Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • seelook/nootka
  • lucas-marques/nootka
2 results
Show changes
Commits on Source (2)
Showing
with 1912 additions and 1184 deletions
This diff is collapsed.
......@@ -2,64 +2,103 @@
* Copyright (C) 2019-2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import QtQuick 2.12
import Qt5Compat.GraphicalEffects
import Nootka 1.0
import Nootka.Charts 1.0
import Qt5Compat.GraphicalEffects
import QtQuick 2.12
Item {
id: barDel
property alias chart: barIt.chart
property alias groupNr: barIt.groupNr
TbarChartDelegate {
id: barIt
x: parent.width * 0.75
y: parent.height * 0.1 + maxDataHeight - (yValue / chartItem.maxYValue()) * maxDataHeight
width: parent.width / 2; height: maxDataHeight * 1.14 - y
visible: false
hovered: barMA.containsMouse
}
DropShadow {
z: 5010
anchors.fill: barIt
horizontalOffset: barDel.width / 30
verticalOffset: horizontalOffset
radius: NOO.factor() * (barIt.hovered ? 2 : 1)
samples: 1 + radius * 2
color: activPal.shadow
source: barIt
Behavior on radius { enabled: GLOB.useAnimations; NumberAnimation { duration: 150 }}
scale: barMA.containsMouse ? 1.1 : 1.0
Behavior on scale { enabled: GLOB.useAnimations; NumberAnimation { duration: 150 }}
MouseArea {
id: barMA
anchors.fill: parent
hoverEnabled: true
id: barDel
property alias chart: barIt.chart
property alias groupNr: barIt.groupNr
TbarChartDelegate {
id: barIt
x: parent.width * 0.75
y: parent.height * 0.1 + maxDataHeight - (yValue / chartItem.maxYValue()) * maxDataHeight
width: parent.width / 2
height: maxDataHeight * 1.14 - y
visible: false
hovered: barMA.containsMouse
}
DropShadow {
z: 5010
anchors.fill: barIt
horizontalOffset: barDel.width / 30
verticalOffset: horizontalOffset
radius: NOO.factor() * (barIt.hovered ? 2 : 1)
samples: 1 + radius * 2
color: activPal.shadow
source: barIt
scale: barMA.containsMouse ? 1.1 : 1
MouseArea {
id: barMA
anchors.fill: parent
hoverEnabled: true
}
Behavior on radius {
enabled: GLOB.useAnimations
NumberAnimation {
duration: 150
}
}
Behavior on scale {
enabled: GLOB.useAnimations
NumberAnimation {
duration: 150
}
}
}
}
Rectangle { // X axis line (partial)
color: activPal.text
y: parent.height - width + lThick / 2
width: parent.width; height: lThick
Rectangle { // X tick
color: activPal.text
x: parent.width - lThick; y: lThick
width: lThick; height: lThick * 2
Column { // X value (description)
y: lThick * 2
anchors.horizontalCenter: parent.horizontalCenter
Text {
text: barIt.xText; font { pixelSize: barDel.width / 5 }
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text; textFormat: Text.RichText; horizontalAlignment: Text.AlignHCenter
// X axis line (partial)
Rectangle {
color: activPal.text
y: parent.height - width + lThick / 2
width: parent.width
height: lThick
// X tick
Rectangle {
color: activPal.text
x: parent.width - lThick
y: lThick
width: lThick
height: lThick * 2
// X value (description)
Column {
y: lThick * 2
anchors.horizontalCenter: parent.horizontalCenter
Text {
text: barIt.xText
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text
textFormat: Text.RichText
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: barDel.width / 5
}
}
}
}
}
}
}
}
......@@ -2,192 +2,306 @@
* Copyright (C) 2019-2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import "../"
import Nootka 1.0
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import Nootka 1.0
import "../"
Drawer {
// Tflickable
id: chartDrawer
Drawer {
id: chartDrawer
property alias pinned: pinBox.checked
visible: true
modal: false
y: analyzeWindow.height / 15 + Screen.pixelDensity * 2
width: parent.height * 0.4; height: parent.height - y
closePolicy: chartItem.keepDrawerOpened() ? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside
background: TipRect { color: activPal.window; radius: 0; verticalOffset: 0; horizontalOffset: pinBox.checked ? 0 : NOO.factor() / 5 }
property int fSize: Math.min(NOO.factor(), width / 25)
Connections {
target: chartItem
onLockXorderList: orderCombo.lock(itNr, state)
}
Tflickable {
height: parent.height
contentHeight: drawCol.height
Column {
id: drawCol
width: parent.width; spacing: fSize / 2
Column {
visible: chartItem.allowOpen
width: parent.width
MenuButton { width: parent.width; action: chartItem.loadExamAct() }
ListView {
id: recentList
width: parent.width; height: Math.min(NOO.factor() * 16.8, NOO.factor() * count * 2.8) // 6 items visible
boundsBehavior: Flickable.StopAtBounds
contentHeight: NOO.factor() * count * 2.8
model: chartItem.recentExamsActions
currentIndex: chartItem.selectedFileId
clip: true
delegate: MenuButton {
width: parent ? parent.width : 0
action: modelData
color: containsPress || recentList.currentIndex === index ? activPal.highlight :
(containsMouse ? NOO.alpha(activPal.highlight, 50) : (index % 2 ? activPal.alternateBase : activPal.base))
textColor: containsPress || recentList.currentIndex === index ? activPal.highlightedText : activPal.text
Rectangle { width: parent.width; height: 1; color: activPal.window; y: parent.height - 1; }
}
ScrollBar.vertical: ScrollBar { active: true; visible: true }
}
MenuButton {
visible: chartItem.exerciseAct(); width: parent.width; action: chartItem.exerciseAct()
Rectangle { width: parent.width; height: 1; color: activPal.dimText; y: parent.height - 1; }
}
}
Item { visible: !chartItem.isMelody; width: parent.width; height: fSize }
Row {
visible: !chartItem.isMelody
spacing: fSize / 4
anchors.horizontalCenter: parent.horizontalCenter
TradioButton {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: fSize
checked: chartItem.chartType === 0
onClicked: chartItem.chartType = checked ? 0 : 1
}
Text {
text: qsTranslate("AnalyzeDialog", "linear chart").replace(" ", "\n")
anchors.verticalCenter: parent.verticalCenter
color: activPal.text; font.pixelSize: fSize
}
Item { width: chartDrawer.width / 10; height: 1 }
TradioButton {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: fSize
onClicked: chartItem.chartType = checked ? 1 : 0
}
Text {
text: qsTranslate("AnalyzeDialog", "bar chart").replace(" ", "\n")
anchors.verticalCenter: parent.verticalCenter
color: activPal.text; font.pixelSize: fSize
}
}
property alias pinned: pinBox.checked
property int fSize: Math.min(NOO.factor(), width / 25)
visible: true
modal: false
y: analyzeWindow.height / 15 + Screen.pixelDensity * 2
width: parent.height * 0.4
height: parent.height - y
closePolicy: chartItem.keepDrawerOpened() ? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside
Connections {
target: chartItem
function onLockXorderList(itNr: int, state: bool) : void { orderCombo.lock(itNr, state) }
}
Tflickable {
height: parent.height
contentHeight: drawCol.height
Column {
id: drawCol
width: parent.width
spacing: fSize / 2
Column {
visible: chartItem.allowOpen
width: parent.width
MenuButton {
width: parent.width
action: chartItem.loadExamAct()
}
ListView {
id: recentList
width: parent.width // 6 items visible
height: Math.min(NOO.factor() * 16.8, NOO.factor() * count * 2.8)
boundsBehavior: Flickable.StopAtBounds
contentHeight: NOO.factor() * count * 2.8
model: chartItem.recentExamsActions
currentIndex: chartItem.selectedFileId
clip: true
delegate: MenuButton {
width: parent ? parent.width : 0
action: modelData
color: containsPress || recentList.currentIndex === index ? activPal.highlight : (containsMouse ? NOO.alpha(activPal.highlight, 50) : (index % 2 ? activPal.alternateBase : activPal.base))
textColor: containsPress || recentList.currentIndex === index ? activPal.highlightedText : activPal.text
Rectangle {
width: parent.width
height: 1
color: activPal.window
y: parent.height - 1
}
}
ScrollBar.vertical: ScrollBar {
active: true
visible: true
}
}
MenuButton {
visible: chartItem.exerciseAct()
width: parent.width
action: chartItem.exerciseAct()
Rectangle {
width: parent.width
height: 1
color: activPal.dimText
y: parent.height - 1
}
}
}
Item {
visible: !chartItem.isMelody
width: parent.width
height: fSize
}
Row {
visible: !chartItem.isMelody
spacing: fSize / 4
anchors.horizontalCenter: parent.horizontalCenter
TradioButton {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: fSize
checked: chartItem.chartType === 0
onClicked: chartItem.chartType = checked ? 0 : 1
}
Text {
text: qsTranslate("AnalyzeDialog", "linear chart").replace(" ", "\n")
anchors.verticalCenter: parent.verticalCenter
color: activPal.text
font.pixelSize: fSize
}
Item {
width: chartDrawer.width / 10
height: 1
}
TradioButton {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: fSize
onClicked: chartItem.chartType = checked ? 1 : 0
}
Text {
text: qsTranslate("AnalyzeDialog", "bar chart").replace(" ", "\n")
anchors.verticalCenter: parent.verticalCenter
color: activPal.text
font.pixelSize: fSize
}
}
Item { width: parent.width; height: fSize }
Item {
width: parent.width
height: fSize
}
Column {
visible: !chartItem.isMelody
width: parent.width
spacing: fSize / 2
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTranslate("AnalyzeDialog", "ordered by:", "Keep a proper form - whole sentence will be: ordered by: question number, key signature, etc...")
color: activPal.text
font.pixelSize: fSize
}
TcomboBox {
id: orderCombo
width: Math.min(parent.width - fSize, NOO.factor() * 20)
font.pixelSize: fSize
anchors.horizontalCenter: parent.horizontalCenter
model: chartItem.xOrderActions
currentIndex: chartItem.xOrder
onActivated: index => { chartItem.xOrder = index }
}
}
Column {
visible: chartItem.isMelody
width: parent.width
spacing: fSize / 2
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTranslate("AnalyzeDialog", "Y value:")
color: activPal.text
font.pixelSize: fSize
}
TcomboBox {
width: Math.min(parent.width - fSize, NOO.factor() * 20)
font.pixelSize: fSize
anchors.horizontalCenter: parent.horizontalCenter
model: chartItem.yValueActions
currentIndex: chartItem.yValue
onActivated: chartItem.yValue = index
}
}
Item {
width: parent.width
height: fSize
}
Column {
width: parent.width
spacing: fSize / 2
Repeater {
model: chartItem.miscSettModel
Row {
spacing: fSize / 2
enabled: modelData.enabled
TcheckBox {
font.pixelSize: fSize
anchors.verticalCenter: parent.verticalCenter
checked: modelData.checked
onClicked: modelData.trigger()
}
Text {
width: chartDrawer.width - fSize * 4
anchors.verticalCenter: parent.verticalCenter
wrapMode: Text.Wrap
text: modelData.text
color: enabled ? activPal.text : disdPal.text
font.pixelSize: fSize
}
}
}
}
Column {
visible: !chartItem.isMelody
width: parent.width; spacing: fSize / 2
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTranslate("AnalyzeDialog", "ordered by:", "Keep a proper form - whole sentence will be: ordered by: question number, key signature, etc...")
color: activPal.text; font.pixelSize: fSize
}
TcomboBox {
id: orderCombo
width: Math.min(parent.width - fSize, NOO.factor() * 20)
font.pixelSize: fSize
anchors.horizontalCenter: parent.horizontalCenter
model: chartItem.xOrderActions
currentIndex: chartItem.xOrder
onActivated: chartItem.xOrder = index
// Column
ScrollBar.horizontal: ScrollBar {
active: true
visible: true
}
}
Column {
visible: chartItem.isMelody
width: parent.width; spacing: fSize / 2
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTranslate("AnalyzeDialog", "Y value:")
color: activPal.text; font.pixelSize: fSize
}
TcheckBox {
id: pinBox
hoverEnabled: true
font.pixelSize: fSize
checked: chartItem.keepDrawerOpened()
onClicked: {
chartDrawer.closePolicy = checked ? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside;
chartItem.setKeepDrawer(checked);
}
TcomboBox {
width: Math.min(parent.width - fSize, NOO.factor() * 20)
font.pixelSize: fSize
anchors.horizontalCenter: parent.horizontalCenter
model: chartItem.yValueActions
currentIndex: chartItem.yValue
onActivated: chartItem.yValue = index
anchors {
right: parent.right
bottom: parent.bottom
}
}
Item { width: parent.width; height: fSize }
ToolTip {
delay: 500
timeout: 5000
visible: pinBox.hovered
Column {
width: parent.width; spacing: fSize / 2
Repeater {
model: chartItem.miscSettModel
Row {
spacing: fSize / 2
enabled: modelData.enabled
TcheckBox {
font.pixelSize: fSize
anchors.verticalCenter: parent.verticalCenter
checked: modelData.checked
onClicked: modelData.trigger()
contentItem: Text {
text: qsTr("keep opened")
color: activPal.highlightedText
}
Text {
width: chartDrawer.width - fSize * 4
anchors.verticalCenter: parent.verticalCenter
wrapMode: Text.Wrap
text: modelData.text
color: enabled ? activPal.text : disdPal.text; font.pixelSize: fSize
enter: Transition {
enabled: GLOB.useAnimations
NumberAnimation {
property: "scale"
to: 1
}
}
}
exit: Transition {
enabled: GLOB.useAnimations
NumberAnimation {
property: "scale"
to: 0
}
}
background: TipRect {
shadowRadius: NOO.factor()
color: activPal.highlight
}
}
}
} // Column
ScrollBar.horizontal: ScrollBar { active: true; visible: true; }
} // Tflickable
TcheckBox {
id: pinBox
hoverEnabled: true
font.pixelSize: fSize
anchors { right: parent.right; bottom: parent.bottom }
checked: chartItem.keepDrawerOpened()
onClicked: {
chartDrawer.closePolicy = checked ? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside
chartItem.setKeepDrawer(checked)
}
ToolTip {
delay: 500
timeout: 5000
visible: pinBox.hovered
contentItem: Text {
text: qsTr("keep opened")
color: activPal.highlightedText
}
enter: Transition { enabled: GLOB.useAnimations; NumberAnimation { property: "scale"; to: 1 }}
exit: Transition { enabled: GLOB.useAnimations; NumberAnimation { property: "scale"; to: 0 }}
background: TipRect { shadowRadius: NOO.factor(); color: activPal.highlight }
background: TipRect {
color: activPal.window
radius: 0
verticalOffset: 0
horizontalOffset: pinBox.checked ? 0 : NOO.factor() / 5
}
}
}
......@@ -2,40 +2,51 @@
* Copyright (C) 2018-2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import "../"
import Nootka 1.0
import QtQuick 2.12
import Nootka 1.0
import "../"
TipRect {
id: helpTip
property alias text: txt.text
property color hintColor: GLOB.correctColor
TipRect {
id: helpTip
property alias text: txt.text
property color hintColor: GLOB.correctColor
shadowRadius: NOO.factor()
width: txt.width + 2 * NOO.factor()
height: txt.height + 2 * NOO.factor()
z: 150
border { color: hintColor; width: 1 }
color: Qt.tint(activPal.base, NOO.alpha(hintColor, 50))
anchors { centerIn: parent }
Column {
padding: NOO.factor()
Text {
z: 200
id: txt
color: activPal.text
textFormat: Text.RichText; horizontalAlignment: Text.AlignHCenter
onLinkActivated: analyzeWindow.openExam()
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
shadowRadius: NOO.factor()
width: txt.width + 2 * NOO.factor()
height: txt.height + 2 * NOO.factor()
z: 150
color: Qt.tint(activPal.base, NOO.alpha(hintColor, 50))
border {
color: hintColor
width: 1
}
anchors {
centerIn: parent
}
}
Column {
padding: NOO.factor()
Text {
id: txt
z: 200
color: activPal.text
textFormat: Text.RichText
horizontalAlignment: Text.AlignHCenter
onLinkActivated: analyzeWindow.openExam()
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}
}
......@@ -2,165 +2,259 @@
* Copyright (C) 2018-2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import QtQuick 2.12
import "../"
import "../score"
import Nootka 1.0
import Nootka.Charts 1.0
import QtQuick 2.12
import Score 1.0
import "../score"
import "../"
TipRect {
id: questTip
property alias tipItem: tipItem
width: tipItem.width; height: tipItem.height
z: 5000
x: NOO.bound(parent.height / 12, tipItem.pos.x - chartView.list.contentX, parent.width - width * 1.2)
y: tipItem.pos.y > parent.height / 2 ? tipItem.pos.y - height - parent.height / 14 : tipItem.pos.y + parent.height / 20
shadowRadius: NOO.factor() * 3; horizontalOffset: NOO.factor() / 3; verticalOffset: horizontalOffset
visible: scale > 0
border { color: tipItem.color; width: NOO.factor() / 7 }
color: Qt.tint(activPal.base, NOO.alpha(tipItem.color, 50))
radius: NOO.factor()
scale: tipItem.show ? 1 : 0
// overlay area to catch when mouse exits a tip and hide it
MouseArea {
id: overArea
parent: questTip.parent
anchors.fill: parent
z: 4999
visible: false
hoverEnabled: true
onEntered: {
visible = false
chartItem.tipExited()
// tipItem
id: questTip
property alias tipItem: tipItem
width: tipItem.width
height: tipItem.height
z: 5000
x: NOO.bound(parent.height / 12, tipItem.pos.x - chartView.list.contentX, parent.width - width * 1.2)
y: tipItem.pos.y > parent.height / 2 ? tipItem.pos.y - height - parent.height / 14 : tipItem.pos.y + parent.height / 20
shadowRadius: NOO.factor() * 3
horizontalOffset: NOO.factor() / 3
verticalOffset: horizontalOffset
visible: scale > 0
color: Qt.tint(activPal.base, NOO.alpha(tipItem.color, 50))
radius: NOO.factor()
scale: tipItem.show ? 1 : 0
border {
color: tipItem.color
width: NOO.factor() / 7
}
}
Behavior on scale { NumberAnimation { duration: 200 }}
Behavior on x { NumberAnimation { duration: 200 }}
Behavior on y { NumberAnimation { duration: 200 }}
TchartTipItem {
id: tipItem
width: (lineCol.visible ? lineCol.width : Math.max(scoreRow.width, headRow.width)) + NOO.factor()
height: (lineCol.visible ? lineCol.height : resultCol.y + resultCol.height) + NOO.factor()
Row {
id: headRow
y: NOO.factor() / 2
visible: tipItem.tipType === 0
spacing: NOO.factor() * 2
anchors.horizontalCenter: parent.horizontalCenter
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.number + "."
font { bold: true; pixelSize: NOO.factor() * 1.6 }
color: activPal.text
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.qaText; horizontalAlignment: Text.AlignHCenter
font { pixelSize: NOO.factor() * 0.8 }
color: activPal.text
}
// overlay area to catch when mouse exits a tip and hide it
MouseArea {
id: overArea
parent: questTip.parent
anchors.fill: parent
z: 4999
visible: false
hoverEnabled: true
onEntered: {
visible = false;
chartItem.tipExited();
}
}
Row {
id: scoreRow
visible: tipItem.tipType === 0
anchors { horizontalCenter: parent.horizontalCenter; top: headRow.bottom }
Item {
anchors.verticalCenter: parent.verticalCenter
visible: tipItem.leftScoreVisible
height: NOO.factor() * 10; width: NOO.factor() * 10
Score {
y: tipItem.yScoreLeftOff / 2
scale: height / firstStaff.linesCount
width: parent.width; height: NOO.factor() * 12
Component.onCompleted: {
bgRect.destroy()
tipItem.leftScore = scoreObj
}
TchartTipItem {
id: tipItem
width: (lineCol.visible ? lineCol.width : Math.max(scoreRow.width, headRow.width)) + NOO.factor()
height: (lineCol.visible ? lineCol.height : resultCol.y + resultCol.height) + NOO.factor()
Row {
id: headRow
y: NOO.factor() / 2
visible: tipItem.tipType === 0
spacing: NOO.factor() * 2
anchors.horizontalCenter: parent.horizontalCenter
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.number + "."
color: activPal.text
font {
bold: true
pixelSize: NOO.factor() * 1.6
}
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.qaText
horizontalAlignment: Text.AlignHCenter
color: activPal.text
font {
pixelSize: NOO.factor() * 0.8
}
}
}
}
Text {
visible: !tipItem.leftScoreVisible; anchors.verticalCenter: parent.verticalCenter
text: tipItem.questionText; textFormat: Text.RichText
color: activPal.text
}
Text { // question mark, visible only for single note questions
anchors.verticalCenter: parent.verticalCenter
text: "?"; font { pixelSize: NOO.factor() * 4; family: "Nootka" }
color: GLOB.wrongColor
}
Text {
visible: !tipItem.rightScoreVisible; anchors.verticalCenter: parent.verticalCenter
text: tipItem.answerText; textFormat: Text.RichText
color: activPal.text
}
Item {
height: NOO.factor() * 10; width: NOO.factor() * 10
anchors.verticalCenter: parent.verticalCenter
visible: tipItem.rightScoreVisible
Score {
y: tipItem.yScoreRightOff / 2
width: parent.width; height: NOO.factor() * 12
scale: height / firstStaff.linesCount
Component.onCompleted: {
bgRect.destroy()
tipItem.secondScore = scoreObj
}
Row {
id: scoreRow
visible: tipItem.tipType === 0
anchors {
horizontalCenter: parent.horizontalCenter
top: headRow.bottom
}
Item {
anchors.verticalCenter: parent.verticalCenter
visible: tipItem.leftScoreVisible
height: NOO.factor() * 10
width: NOO.factor() * 10
Score {
y: tipItem.yScoreLeftOff / 2
scale: height / firstStaff.linesCount
width: parent.width
height: NOO.factor() * 12
Component.onCompleted: {
bgRect.destroy();
tipItem.leftScore = scoreObj;
}
}
}
Text {
visible: !tipItem.leftScoreVisible
anchors.verticalCenter: parent.verticalCenter
text: tipItem.questionText
textFormat: Text.RichText
color: activPal.text
}
// question mark, visible only for single note questions
Text {
anchors.verticalCenter: parent.verticalCenter
text: "?"
color: GLOB.wrongColor
font {
pixelSize: NOO.factor() * 4
family: "Nootka"
}
}
Text {
visible: !tipItem.rightScoreVisible
anchors.verticalCenter: parent.verticalCenter
text: tipItem.answerText
textFormat: Text.RichText
color: activPal.text
}
Item {
height: NOO.factor() * 10
width: NOO.factor() * 10
anchors.verticalCenter: parent.verticalCenter
visible: tipItem.rightScoreVisible
Score {
y: tipItem.yScoreRightOff / 2
width: parent.width
height: NOO.factor() * 12
scale: height / firstStaff.linesCount
Component.onCompleted: {
bgRect.destroy();
tipItem.secondScore = scoreObj;
}
}
}
// score row
}
Column {
id: resultCol
width: parent.width - NOO.factor()
topPadding: NOO.factor() / 2
visible: tipItem.tipType === 0
anchors {
horizontalCenter: parent.horizontalCenter
top: scoreRow.bottom
}
Text {
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.resultText
textFormat: Text.StyledText
color: tipItem.color
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.timeText
textFormat: Text.StyledText
color: activPal.text
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: NOO.factor() * 0.9
}
}
}
// line tip column
Column {
id: lineCol
padding: NOO.factor() / 2
visible: tipItem.tipType === 1
Text {
width: NOO.factor() * 20
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text
textFormat: Text.RichText
text: tipItem.tipText
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
}
}
} // score row
Column {
id: resultCol
anchors { horizontalCenter: parent.horizontalCenter; top: scoreRow.bottom }
width: parent.width - NOO.factor(); topPadding: NOO.factor() / 2
visible: tipItem.tipType === 0
Text {
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.resultText; textFormat: Text.StyledText
color: tipItem.color; horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.timeText; textFormat: Text.StyledText
font { pixelSize: NOO.factor() * 0.9 }
color: activPal.text; horizontalAlignment: Text.AlignHCenter
}
}
Column { // line tip column
id: lineCol
padding: NOO.factor() / 2
visible: tipItem.tipType === 1
Text {
width: NOO.factor() * 20
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text; textFormat: Text.RichText
text: tipItem.tipText; horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
MouseArea {
id: tipArea
anchors.fill: parent
hoverEnabled: true
onEntered: chartItem.tipEntered()
onExited: overArea.visible = true
}
} // tipItem
MouseArea {
id: tipArea
anchors.fill: parent
hoverEnabled: true
onEntered: chartItem.tipEntered()
onExited: overArea.visible = true
}
Behavior on scale {
NumberAnimation {
duration: 200
}
}
Behavior on x {
NumberAnimation {
duration: 200
}
}
Behavior on y {
NumberAnimation {
duration: 200
}
}
}
......@@ -2,238 +2,336 @@
* Copyright (C) 2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import QtQuick 2.12
import "../"
import "../score"
import Nootka.Charts 1.0
import QtQuick 2.12
import Score 1.0
import "../score"
import "../"
TipRect {
id: questTip
property alias tipItem: tipItem
width: tipItem.width; height: tipItem.height
z: 5000
x: NOO.bound(parent.height / 12, tipItem.pos.x - chartView.list.contentX, parent.width - width * 1.2)
y: tipItem.pos.y > parent.height / 2 ? tipItem.pos.y - height - parent.height / 14 : tipItem.pos.y + parent.height / 20
shadowRadius: NOO.factor() * 3; horizontalOffset: NOO.factor() / 3; verticalOffset: horizontalOffset
visible: scale > 0
border { color: tipItem.color; width: NOO.factor() / 7 }
color: Qt.tint(activPal.base, NOO.alpha(tipItem.color, 50))
radius: NOO.factor()
scale: tipItem.show ? 1 : 0
// overlay area to catch when mouse exits a tip and hide it
MouseArea {
id: overArea
parent: questTip.parent
anchors.fill: parent
z: 4999
visible: false
hoverEnabled: true
onEntered: {
visible = false
chartItem.tipExited()
}
}
id: questTip
Behavior on scale { NumberAnimation { duration: 200 }}
Behavior on x { NumberAnimation { duration: 200 }}
Behavior on y { NumberAnimation { duration: 200 }}
property alias tipItem: tipItem
TchartTipItem {
id: tipItem
width: tipItem.width
height: tipItem.height
z: 5000
x: NOO.bound(parent.height / 12, tipItem.pos.x - chartView.list.contentX, parent.width - width * 1.2)
y: tipItem.pos.y > parent.height / 2 ? tipItem.pos.y - height - parent.height / 14 : tipItem.pos.y + parent.height / 20
shadowRadius: NOO.factor() * 3
horizontalOffset: NOO.factor() / 3
verticalOffset: horizontalOffset
visible: scale > 0
color: Qt.tint(activPal.base, NOO.alpha(tipItem.color, 50))
radius: NOO.factor()
scale: tipItem.show ? 1 : 0
property bool prevShown: false /**< @p TRUE when user displayed entire melody */
border {
color: tipItem.color
width: NOO.factor() / 7
}
width: (lineCol.visible ? lineCol.width : Math.max(scoreRow.width, headRow.width)) + NOO.factor()
height: tipCol.height + NOO.factor()
// overlay area to catch when mouse exits a tip and hide it
MouseArea {
id: overArea
onQuestionWasSet: {
attemptSpin.value = 0
prevShown = false
parent: questTip.parent
anchors.fill: parent
z: 4999
visible: false
hoverEnabled: true
onEntered: {
visible = false;
chartItem.tipExited();
}
}
Column {
id: tipCol
spacing: NOO.factor() / 2
Row {
id: headRow
visible: tipItem.tipType === 0
spacing: NOO.factor() * 2
anchors.horizontalCenter: parent.horizontalCenter
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.number + "."
font { bold: true; pixelSize: NOO.factor() * 1.6 }
color: activPal.text
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.qaText; horizontalAlignment: Text.AlignHCenter
font { pixelSize: NOO.factor() * 0.8 }
color: activPal.text
}
}
Rectangle {
id: scoreRow
visible: tipItem.leftScoreVisible && tipItem.tipType === 0
x: NOO.factor() / 2
color: activPal.base
height: tipItem.leftScoreHeight - NOO.factor(); width: NOO.factor() * 40
clip: true
Score {
id: score
y: tipItem.yScoreLeftOff
width: parent.width; height: NOO.factor() * 15
Component.onCompleted: {
bgRect.destroy()
tipItem.leftScore = scoreObj
}
}
Rectangle {
height: parent.height; width: parent.height
rotation: -90
anchors.right: parent.right
visible: tipItem.moreMelody && !tipItem.prevShown
gradient: Gradient {
GradientStop { position: 0.0; color: "transparent" }
GradientStop { position: 0.5; color: activPal.base }
}
RectButton {
anchors.horizontalCenter: parent.horizontalCenter; y: parent.height * 0.66
height: parent.height / 3
rotation: 90
font { family: "Nootka"; pixelSize: parent.height / 3 }
text: "\u0191"
textColor: activPal.text
// onClicked performed by mouse area
}
}
}
TspinBox {
id: attemptSpin
anchors.horizontalCenter: parent.horizontalCenter
visible: tipItem.isMelody && tipItem.tipType === 0
width: NOO.factor() * 15
font.pixelSize: NOO.factor() * 0.8
from: 0; to: tipItem.attempts
textFromValue: function(value) {
return NOO.TR("Texam", "attempt") + " " + value + " " + qsTranslate("ChartTip", "of", "It will give text: 'Attempt x of y'") + " " + to
}
function pressed(m) {
if (m.x > width / 2)
up.pressed = true
else
down.pressed = true
}
function released() {
if (down.pressed || up.pressed) {
var prevV = value
if (up.pressed)
increase()
else
decrease()
if (prevV !== value)
tipItem.setAttemptNr(value)
}
up.pressed = false
down.pressed = false
TchartTipItem {
id: tipItem
property bool prevShown: false //*< @p TRUE when user displayed entire melody
width: (lineCol.visible ? lineCol.width : Math.max(scoreRow.width, headRow.width)) + NOO.factor()
height: tipCol.height + NOO.factor()
onQuestionWasSet: {
attemptSpin.value = 0;
prevShown = false;
}
}
Column {
id: resultCol
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - NOO.factor()
visible: tipItem.tipType === 0
Text {
width: parent.width; visible: text !== ""
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.attemptDetails(attemptSpin.value); textFormat: Text.StyledText
color: activPal.text; horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap; font.pixelSize: NOO.factor() * 0.9
Column {
id: tipCol
spacing: NOO.factor() / 2
Row {
id: headRow
visible: tipItem.tipType === 0
spacing: NOO.factor() * 2
anchors.horizontalCenter: parent.horizontalCenter
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.number + "."
color: activPal.text
font {
bold: true
pixelSize: NOO.factor() * 1.6
}
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: tipItem.qaText
horizontalAlignment: Text.AlignHCenter
color: activPal.text
font {
pixelSize: NOO.factor() * 0.8
}
}
}
Rectangle {
id: scoreRow
visible: tipItem.leftScoreVisible && tipItem.tipType === 0
x: NOO.factor() / 2
color: activPal.base
height: tipItem.leftScoreHeight - NOO.factor()
width: NOO.factor() * 40
clip: true
Score {
id: score
y: tipItem.yScoreLeftOff
width: parent.width
height: NOO.factor() * 15
Component.onCompleted: {
bgRect.destroy();
tipItem.leftScore = scoreObj;
}
}
Rectangle {
height: parent.height
width: parent.height
rotation: -90
anchors.right: parent.right
visible: tipItem.moreMelody && !tipItem.prevShown
RectButton {
// onClicked performed by mouse area
anchors.horizontalCenter: parent.horizontalCenter
y: parent.height * 0.66
height: parent.height / 3
rotation: 90
text: "\u0191"
textColor: activPal.text
font {
family: "Nootka"
pixelSize: parent.height / 3
}
}
gradient: Gradient {
GradientStop {
position: 0
color: "transparent"
}
GradientStop {
position: 0.5
color: activPal.base
}
}
}
}
TspinBox {
id: attemptSpin
function pressed(m) {
if (m.x > width / 2)
up.pressed = true;
else
down.pressed = true;
}
function released() {
if (down.pressed || up.pressed) {
var prevV = value;
if (up.pressed)
increase();
else
decrease();
if (prevV !== value)
tipItem.setAttemptNr(value);
}
up.pressed = false;
down.pressed = false;
}
anchors.horizontalCenter: parent.horizontalCenter
visible: tipItem.isMelody && tipItem.tipType === 0
width: NOO.factor() * 15
font.pixelSize: NOO.factor() * 0.8
from: 0
to: tipItem.attempts
textFromValue: function(value) {
return NOO.TR("Texam", "attempt") + " " + value + " " + qsTranslate("ChartTip", "of", "It will give text: 'Attempt x of y'") + " " + to;
}
}
Column {
id: resultCol
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - NOO.factor()
visible: tipItem.tipType === 0
Text {
width: parent.width
visible: text !== ""
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.attemptDetails(attemptSpin.value)
textFormat: Text.StyledText
color: activPal.text
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: NOO.factor() * 0.9
}
Text {
width: parent.width // visible: text !== ""
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.attemptResult(attemptSpin.value)
textFormat: Text.StyledText
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: NOO.factor() * 0.9
}
Text {
width: parent.width
visible: text !== ""
anchors.horizontalCenter: parent.horizontalCenter
text: attemptSpin.value === 0 ? tipItem.resultText : ""
textFormat: Text.StyledText
color: tipItem.color
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.timeText
textFormat: Text.StyledText
color: activPal.text
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: NOO.factor() * 0.9
}
}
}
// line tip column
Column {
id: lineCol
padding: NOO.factor()
visible: tipItem.tipType === 1
Text {
width: NOO.factor() * 20
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text
textFormat: Text.RichText
text: tipItem.tipText
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
}
}
Text {
width: parent.width;// visible: text !== ""
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.attemptResult(attemptSpin.value); textFormat: Text.StyledText
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap; font.pixelSize: NOO.factor() * 0.9
// tipItem
}
MouseArea {
id: tipArea
property real startPosY: 0
property bool overScore: false
anchors.fill: parent
hoverEnabled: true
onEntered: chartItem.tipEntered()
onExited: overArea.visible = true
onPressed: {
startPosY = mouseY;
if (tipCol.childAt(mouse.x, mouse.y) !== scoreRow)
attemptSpin.pressed(mapToItem(attemptSpin, mouse.x, mouse.y));
else if (tipItem.moreMelody && tipItem.prevShown)
overScore = true;
}
Text {
width: parent.width; visible: text !== ""
anchors.horizontalCenter: parent.horizontalCenter
text: attemptSpin.value === 0 ? tipItem.resultText : ""; textFormat: Text.StyledText
color: tipItem.color; horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
onPositionChanged: {
if (overScore) {
score.contentY -= (mouseY - startPosY);
startPosY = mouseY;
}
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: tipItem.timeText; textFormat: Text.StyledText
font { pixelSize: NOO.factor() * 0.9 }
color: activPal.text; horizontalAlignment: Text.AlignHCenter
onReleased: {
if (tipCol.childAt(mouse.x, mouse.y) === scoreRow) {
if (tipItem.moreMelody && !tipItem.prevShown) {
tipItem.showMelodyPreview();
tipItem.prevShown = true;
}
} else {
attemptSpin.released();
}
if (overScore) {
overScore = false;
score.returnToBounds();
}
}
}
Column { // line tip column
id: lineCol
padding: NOO.factor()
visible: tipItem.tipType === 1
Text {
width: NOO.factor() * 20
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text; textFormat: Text.RichText
text: tipItem.tipText; horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
Behavior on scale {
NumberAnimation {
duration: 200
}
}
}
} // tipItem
MouseArea {
id: tipArea
anchors.fill: parent
hoverEnabled: true
onEntered: chartItem.tipEntered()
onExited: overArea.visible = true
property real startPosY: 0
property bool overScore: false
onPressed: {
startPosY = mouseY
if (tipCol.childAt(mouse.x, mouse.y) !== scoreRow)
attemptSpin.pressed(mapToItem(attemptSpin, mouse.x, mouse.y))
else if (tipItem.moreMelody && tipItem.prevShown)
overScore = true
}
onPositionChanged: {
if (overScore) {
score.contentY -= (mouseY - startPosY)
startPosY = mouseY
}
Behavior on x {
NumberAnimation {
duration: 200
}
}
onReleased: {
if (tipCol.childAt(mouse.x, mouse.y) === scoreRow) {
if (tipItem.moreMelody && !tipItem.prevShown) {
tipItem.showMelodyPreview()
tipItem.prevShown = true
Behavior on y {
NumberAnimation {
duration: 200
}
} else
attemptSpin.released()
if (overScore) {
overScore = false
score.returnToBounds()
}
}
}
}
......@@ -2,57 +2,92 @@
* Copyright (C) 2017-2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import "../"
import Nootka 1.0
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import Nootka 1.0
import "../"
ToolButton {
id: root
property alias pixmap: pix.source
property real factor: analyzeWindow.height / 150
property Taction taction
ToolButton {
id: root
hoverEnabled: true
width: pix.width + (NOO.isAndroid() ? 4 : factor * 2)
height: pix.height + Screen.pixelDensity * 2
enabled: (taction && taction.enabled) || !taction
property alias pixmap: pix.source
property real factor: analyzeWindow.height / 150
property Taction taction
background: Item {}
onClicked: {
if (taction)
taction.trigger()
focus = false
}
Image {
id: pix
mipmap: true
anchors.centerIn: parent
source: taction ? taction.icon : ""
height: factor * 10; width: height * (sourceSize.width / sourceSize.height)
transformOrigin: Image.Center
scale: !enabled || pressed ? 0.6 : (hovered ? 1.1 : 0.8)
Behavior on scale { enabled: GLOB.useAnimations; NumberAnimation { duration: 150 }}
}
ToolTip {
id: toolTip
delay: 750
timeout: 5000
visible: hovered && contentItem.text !== ""
contentItem: Text {
text: taction ? taction.text : ""
color: activPal.highlightedText
hoverEnabled: true
width: pix.width + (NOO.isAndroid() ? 4 : factor * 2)
height: pix.height + Screen.pixelDensity * 2
enabled: (taction && taction.enabled) || !taction
onClicked: {
if (taction)
taction.trigger();
focus = false;
}
enter: Transition { enabled: GLOB.useAnimations; NumberAnimation { property: "scale"; to: 1 }}
exit: Transition { enabled: GLOB.useAnimations; NumberAnimation { property: "scale"; to: 0 }}
background: TipRect { shadowRadius: NOO.factor(); color: activPal.highlight }
}
Image {
id: pix
mipmap: true
anchors.centerIn: parent
source: taction ? taction.icon : ""
height: factor * 10
width: height * (sourceSize.width / sourceSize.height)
transformOrigin: Image.Center
scale: !enabled || pressed ? 0.6 : (hovered ? 1.1 : 0.8)
Behavior on scale {
enabled: GLOB.useAnimations
NumberAnimation {
duration: 150
}
}
}
ToolTip {
id: toolTip
delay: 750
timeout: 5000
visible: hovered && contentItem.text !== ""
contentItem: Text {
text: taction ? taction.text : ""
color: activPal.highlightedText
}
enter: Transition {
enabled: GLOB.useAnimations
NumberAnimation {
property: "scale"
to: 1
}
}
exit: Transition {
enabled: GLOB.useAnimations
NumberAnimation {
property: "scale"
to: 0
}
}
background: TipRect {
shadowRadius: NOO.factor()
color: activPal.highlight
}
}
background: Item {
}
}
......@@ -2,156 +2,234 @@
* Copyright (C) 2019-2020 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import Nootka
import QtQuick 2.12
import QtQuick.Controls 2.12
Flickable {
id: chartView
property alias list: list
property real sc: 1.0
property real lThick: (height / 150.0) * sc
property real maxDataHeight: chartView.height * 0.7333333333333333 *sc
boundsBehavior: Flickable.StopAtBounds
clip: true
contentHeight: height * sc
Timer { id: zoomTimer; interval: 100 }
MouseArea {
anchors.fill: parent
enabled: list.count > 0
onWheel: {
if (wheel.modifiers & Qt.ControlModifier) {
if (wheel.angleDelta.y > 0) {
if (!zoomTimer.running) {
sc = Math.min(2.0, sc * 1.125)
zoomTimer.running = true
}
} else if (wheel.angleDelta.y < 0) {
if (!zoomTimer.running) {
sc = Math.max(0.5, sc * 0.888889)
zoomTimer.running = true
}
}
} else
wheel.accepted = false
}
}
Repeater { // Y grid lines
model: chartItem.yAxisGridModel.length
Rectangle {
visible: list.count > 0; z: 0
y: contentHeight * 0.1 + maxDataHeight - (chartItem.yAxisGridModel[index] / chartItem.maxYValue()) * maxDataHeight
color: NOO.alpha(activPal.text, 100)
width: Math.min(parent.width - list.height / 12, list.contentWidth); height: lThick / 3
x: list.height / 12
}
}
Component {
id: lineComp
LinearDelegate {
chart: chartItem
chartNr: modelIndex
height: chartView.height * sc; width: height / 6
}
}
Component {
id: barComp
BarDelegate {
chart: chartItem
groupNr: modelIndex
height: chartView.height * sc; width: height / 6
}
}
id: chartView
ListView {
id: list
z: 1
width: parent.width; height: chartView.height * sc
property alias list: list
property real sc: 1
property real lThick: (height / 150) * sc
property real maxDataHeight: chartView.height * 0.733333 * sc
orientation: ListView.Horizontal
boundsBehavior: Flickable.StopAtBounds
clip: true
contentHeight: height * sc
model: chartItem.chartModel
Timer {
id: zoomTimer
delegate: Component {
Loader {
property int modelIndex: index
z: 2000 - modelIndex; // for proper overlapping keep 'z' stack in reverse order as delegates are created
sourceComponent: chartItem.chartType === 0 ? lineComp : barComp
}
interval: 100
}
header: Item { // fake, just to force space on the chart left
visible: list.count > 0
height: list.height; width: height / 12
MouseArea {
anchors.fill: parent
enabled: list.count > 0
onWheel: wheel => {
if (wheel.modifiers & Qt.ControlModifier) {
if (wheel.angleDelta.y > 0) {
if (!zoomTimer.running) {
sc = Math.min(2, sc * 1.125);
zoomTimer.running = true;
}
} else if (wheel.angleDelta.y < 0) {
if (!zoomTimer.running) {
sc = Math.max(0.5, sc * 0.888889);
zoomTimer.running = true;
}
}
} else {
wheel.accepted = false;
}
}
}
footer: Item {
visible: list.count > 0
height: list.height; width: height / 6
Rectangle {
color: activPal.text
y: parent.height - parent.width + lThick / 2
width: parent.width / 1.3; height: lThick
Repeater { // X arrow
model: 2
Rectangle {
x: parent.width
color: activPal.text; radius: width / 2
height: lThick; width: lThick * 5
rotation: index === 0 ? 155 : -155; transformOrigin: Item.Left
}
// Y grid lines
Repeater {
model: chartItem.yAxisGridModel.length
Rectangle {
visible: list.count > 0
z: 0
y: contentHeight * 0.1 + maxDataHeight - (chartItem.yAxisGridModel[index] / chartItem.maxYValue()) * maxDataHeight
color: NOO.alpha(activPal.text, 100)
width: Math.min(parent.width - list.height / 12, list.contentWidth)
height: lThick / 3
x: list.height / 12
}
}
}
Rectangle { // Y axis (over that fake header)
visible: list.count > 0
color: NOO.alpha(activPal.base, 200)
height: list.height; width: height / 12
Rectangle { // Y axis line
color: activPal.text
x: parent.width; y: parent.height * 0.01 + lThick / 2
width: lThick; height: parent.height * 0.8233333333333333
Repeater { // Y arrow
model: 2
Rectangle {
color: activPal.text; radius: width / 2
width: lThick; height: lThick * 5
rotation: index === 0 ? 25 : -25; transformOrigin: Item.Top
}
Component {
id: lineComp
LinearDelegate {
chart: chartItem
chartNr: modelIndex
height: chartView.height * sc
width: height / 6
}
Text { // Y label
font { pixelSize: lThick * 5; bold: true }
y: (parent.height - height) / 2; x: -width / 2 - height
color: activPal.text
text: chartItem.yAxisLabel
rotation: -90
}
Component {
id: barComp
BarDelegate {
chart: chartItem
groupNr: modelIndex
height: chartView.height * sc
width: height / 6
}
}
Repeater { // ticks and Y values (text)
model: chartItem.yAxisGridModel.length
}
ListView {
id: list
z: 1
width: parent.width
height: chartView.height * sc
orientation: ListView.Horizontal
boundsBehavior: Flickable.StopAtBounds
model: chartItem.chartModel
// Y axis (over that fake header)
Rectangle {
y: contentHeight * 0.1 + maxDataHeight - (chartItem.yAxisGridModel[index] / chartItem.maxYValue()) * maxDataHeight - lThick / 4
color: activPal.text
width: lThick * 1.5; height: lThick
x: parent.width - width
Text {
color: activPal.text; text: index < chartItem.yAxisGridModel.length ? chartItem.yAxisTickText(index) : ""
font { pixelSize: lThick * 3.5 }
y: -height + lThick / 2; x: lThick * 3
}
visible: list.count > 0
color: NOO.alpha(activPal.base, 200)
height: list.height
width: height / 12
// Y axis line
Rectangle {
color: activPal.text
x: parent.width
y: parent.height * 0.01 + lThick / 2
width: lThick
height: parent.height * 0.823333
// Y arrow
Repeater {
model: 2
Rectangle {
color: activPal.text
radius: width / 2
width: lThick
height: lThick * 5
rotation: index === 0 ? 25 : -25
transformOrigin: Item.Top
}
}
// Y label
Text {
y: (parent.height - height) / 2
x: -width / 2 - height
color: activPal.text
text: chartItem.yAxisLabel
rotation: -90
font {
pixelSize: lThick * 5
bold: true
}
}
}
// ticks and Y values (text)
Repeater {
model: chartItem.yAxisGridModel.length
Rectangle {
y: contentHeight * 0.1 + maxDataHeight - (chartItem.yAxisGridModel[index] / chartItem.maxYValue()) * maxDataHeight - lThick / 4
color: activPal.text
width: lThick * 1.5
height: lThick
x: parent.width - width
Text {
color: activPal.text
text: index < chartItem.yAxisGridModel.length ? chartItem.yAxisTickText(index) : ""
y: -height + lThick / 2
x: lThick * 3
font {
pixelSize: lThick * 3.5
}
}
}
}
}
delegate: Component {
Loader {
property int modelIndex: index
z: 2000 - modelIndex // for proper overlapping keep 'z' stack in reverse order as delegates are created
sourceComponent: chartItem.chartType === 0 ? lineComp : barComp
}
}
}
// fake, just to force space on the chart left
header: Item {
visible: list.count > 0
height: list.height
width: height / 12
}
footer: Item {
visible: list.count > 0
height: list.height
width: height / 6
Rectangle {
color: activPal.text
y: parent.height - parent.width + lThick / 2
width: parent.width / 1.3
height: lThick
// X arrow
Repeater {
model: 2
Rectangle {
x: parent.width
color: activPal.text
radius: width / 2
height: lThick
width: lThick * 5
rotation: index === 0 ? 155 : -155
transformOrigin: Item.Left
}
}
}
}
ScrollBar.horizontal: ScrollBar {
active: true
visible: true
}
}
ScrollBar.vertical: ScrollBar {
active: true
visible: true
}
ScrollBar.horizontal: ScrollBar { active: true; visible: true }
}
ScrollBar.vertical: ScrollBar { active: true; visible: true }
}
......@@ -2,26 +2,33 @@
* Copyright (C) 2018-2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import QtQuick 2.12
import "../"
import "../level"
import QtQuick 2.12
Tmenu {
id: lPop
property alias levelPreview: levelPreview
width: NOO.factor() * 40; height: parent.height / 2
x: (parent.width - width) / 2; y: parent.height / 12
visible: true
Column {
width: parent.width; padding: NOO.factor() / 2
LevelPreview {
id: levelPreview
width: parent.width - NOO.factor(); height: lPop.height - NOO.factor()
id: lPop
property alias levelPreview: levelPreview
width: NOO.factor() * 40
height: parent.height / 2
x: (parent.width - width) / 2
y: parent.height / 12
visible: true
onClosed: destroy()
Column {
width: parent.width
padding: NOO.factor() / 2
LevelPreview {
id: levelPreview
width: parent.width - NOO.factor()
height: lPop.height - NOO.factor()
}
}
}
onClosed: destroy()
}
......@@ -2,120 +2,201 @@
* Copyright (C) 2019-2021 by Tomasz Bojczuk (seelook@gmail.com) *
* on the terms of GNU GPLv3 license (http://www.gnu.org/licenses) */
import QtQuick 2.12
import Nootka
import Nootka.Charts
import Qt5Compat.GraphicalEffects
import QtQuick 2.12
import Nootka.Charts 1.0
TlinChartDelegate {
id: lineDel
property var hintText: null
TlinChartDelegate {
id: lineDel
Rectangle { // average line
visible: averageY > 0.0
color: chartItem.averLineGroup === groupNr ? "#00c0c0" : (groupNr % 2 ? "#008080" : "#00a0a0")
x: width / 2; z: 1
y: parent.height * 0.1 + maxDataHeight - (averageY / chartItem.maxYValue()) * maxDataHeight - height / 2
width: parent.width; height: lThick / 2
MouseArea {
id: averMa
width: parent.width; height: parent.height * 5; y: -2 * parent.height
hoverEnabled: true
onEntered: lineEntered(mouseX, parent.y)
onExited: lineExited()
}
}
Rectangle { // X axis line (partial)
color: activPal.text
y: parent.height - width + lThick / 2
width: parent.width; height: lThick
Rectangle { // X tick
color: activPal.text
x: parent.width - lThick; y: lThick
width: lThick; height: lThick * 2
Column { // X value (description)
y: lThick * 2
anchors.horizontalCenter: parent.horizontalCenter
Text { // question number
text: nrText; font { pixelSize: lineDel.width / 7 }
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text; textFormat: Text.StyledText; horizontalAlignment: Text.AlignHCenter
}
Item { // note name
width: childrenRect.width; height: lineDel.width / 4
anchors.horizontalCenter: parent.horizontalCenter
Text {
y: -lineDel.width / (nrText === "" ? 5 : 4.5)
text: noteText; font { pixelSize: lineDel.width / 5; family: "Scorek" }
color: activPal.text; textFormat: Text.StyledText
}
}
Text { // position on instrument
text: posText; font { pixelSize: lineDel.width / 6 }
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text; textFormat: Text.RichText
onNrChanged: {
if (groupNr > -1) {
var h = getHintText();
if (h !== "") {
if (!hintText)
hintText = hintComp.createObject(lineDel);
hintText.text = h;
} else {
if (hintText)
hintText.destroy();
}
}
Text { // key signature
text: keyText; font { pixelSize: lineDel.width / 7; italic: true }
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text; textFormat: Text.PlainText
}
// average line
Rectangle {
visible: averageY > 0
color: chartItem.averLineGroup === groupNr ? "#00c0c0" : (groupNr % 2 ? "#008080" : "#00a0a0")
x: width / 2
z: 1
y: parent.height * 0.1 + maxDataHeight - (averageY / chartItem.maxYValue()) * maxDataHeight - height / 2
width: parent.width
height: lThick / 2
MouseArea {
id: averMa
width: parent.width
height: parent.height * 5
y: -2 * parent.height
hoverEnabled: true
onEntered: lineEntered(mouseX, parent.y)
onExited: lineExited()
}
}
}
}
Text {
id: nText
color: pointColor; text: pointSymbol
y: pointY - (pointSymbol === "M" ? height * 0.3 : height * 0.8)
x: parent.width - (pointSymbol === "M" ? width * 0.5 : width / 3)
font { pixelSize: lineDel.width / 2; family: "Nootka" }
visible: false
}
DropShadow {
z: 5010
anchors.fill: nText
horizontalOffset: lineDel.width / 35
verticalOffset: horizontalOffset
radius: NOO.factor()
samples: 1 + radius * 2
color: activPal.shadow
source: nText
scale: ma.containsMouse ? 1.4 : 1.0
Behavior on scale { enabled: GLOB.useAnimations; NumberAnimation { duration: 150 }}
MouseArea {
id: ma
anchors.fill: parent
hoverEnabled: true
onEntered: pointEntered()
onExited: pointExited()
// X axis line (partial)
Rectangle {
color: activPal.text
y: parent.height - width + lThick / 2
width: parent.width
height: lThick
// X tick
Rectangle {
color: activPal.text
x: parent.width - lThick
y: lThick
width: lThick
height: lThick * 2
// X value (description)
Column {
y: lThick * 2
anchors.horizontalCenter: parent.horizontalCenter
// question number
Text {
text: nrText
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text
textFormat: Text.StyledText
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: lineDel.width / 7
}
}
// note name
Item {
width: childrenRect.width
height: lineDel.width / 4
anchors.horizontalCenter: parent.horizontalCenter
Text {
y: -lineDel.width / (nrText === "" ? 5 : 4.5)
text: noteText
color: activPal.text
textFormat: Text.StyledText
font {
pixelSize: lineDel.width / 5
family: "Scorek"
}
}
}
// position on instrument
Text {
text: posText
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text
textFormat: Text.RichText
font {
pixelSize: lineDel.width / 6
}
}
// key signature
Text {
text: keyText
anchors.horizontalCenter: parent.horizontalCenter
color: activPal.text
textFormat: Text.PlainText
font {
pixelSize: lineDel.width / 7
italic: true
}
}
}
}
}
}
Component {
id: hintComp
Text {
z: -1
x: (parent.width - width) / 2; y: parent.height * 0.05
color: NOO.alpha(activPal.text, 75)
textFormat: Text.RichText
id: nText
color: pointColor
text: pointSymbol
y: pointY - (pointSymbol === "M" ? height * 0.3 : height * 0.8)
x: parent.width - (pointSymbol === "M" ? width * 0.5 : width / 3)
visible: false
font {
pixelSize: lineDel.width / 2
family: "Nootka"
}
}
}
property var hintText: null
onNrChanged: {
if (groupNr > -1) {
var h = getHintText()
if (h !== "") {
if (!hintText)
hintText = hintComp.createObject(lineDel)
hintText.text = h
} else {
if (hintText)
hintText.destroy()
}
DropShadow {
z: 5010
anchors.fill: nText
horizontalOffset: lineDel.width / 35
verticalOffset: horizontalOffset
radius: NOO.factor()
samples: 1 + radius * 2
color: activPal.shadow
source: nText
scale: ma.containsMouse ? 1.4 : 1
MouseArea {
id: ma
anchors.fill: parent
hoverEnabled: true
onEntered: pointEntered()
onExited: pointExited()
}
Behavior on scale {
enabled: GLOB.useAnimations
NumberAnimation {
duration: 150
}
}
}
}
Component {
id: hintComp
Text {
z: -1
x: (parent.width - width) / 2
y: parent.height * 0.05
color: NOO.alpha(activPal.text, 75)
textFormat: Text.RichText
}
}
}
......@@ -39,7 +39,7 @@ TnameItem {
Connections {
target: score
enabled: !GLOB.isExam
onNoteChanged: noteName.note = score.note
function onNoteChanged() : void { noteName.note = score.note }
}
Rectangle {
......
......@@ -68,60 +68,67 @@ Texecutor {
Connections {
target: tipHandler
onWantStartTip: {
var s = Qt.createComponent("qrc:/exam/ExamTip.qml");
function onWantStartTip(text: string, color: color, pos: point) : void {
let s = Qt.createComponent("qrc:/exam/ExamTip.qml");
tipHandler.startTip = s.createObject(executor, {
"text": text,
"offX": pos.x,
"offY": pos.y,
"bg": color
text: text,
offX: pos.x,
offY: pos.y,
bg: color
});
}
onWantQuestionTip: {
var s = Qt.createComponent("qrc:/exam/QuestionTip.qml");
function onWantQuestionTip(text: string, pos: point) : void {
let s = Qt.createComponent("qrc:/exam/QuestionTip.qml");
tipHandler.questionTip = s.createObject(executor, {
"text": text,
"offX": pos.x,
"offY": pos.y
text: text,
offX: pos.x,
offY: pos.y
});
}
onWantConfirmTip: {
var s = Qt.createComponent("qrc:/exam/ExamTip.qml");
function onWantConfirmTip(text: string, color: color, pos: point) : void {
let s = Qt.createComponent("qrc:/exam/ExamTip.qml");
tipHandler.confirmTip = s.createObject(executor, {
"text": text,
"offX": pos.x,
"offY": pos.y,
"bg": color,
"showExit": !NOO.isAndroid()
text: text,
offX: pos.x,
offY: pos.y,
bg: color,
showExit: !NOO.isAndroid()
});
}
onWantResultTip: {
var r = Qt.createComponent("qrc:/exam/ResultTip.qml");
function onWantResultTip(text: string, color: color) : void {
let r = Qt.createComponent("qrc:/exam/ResultTip.qml");
tipHandler.resultTip = r.createObject(executor.parent, {
"text": text,
"color": color
text: text,
color: color
});
}
onWantTryAgainTip: {
var a = Qt.createComponent("qrc:/exam/ResultTip.qml");
function onWantTryAgainTip() : void {
let a = Qt.createComponent("qrc:/exam/ResultTip.qml");
tipHandler.tryAgainTip = a.createObject(executor.parent, {
"text": qsTranslate("TtipHandler", "Try again!"),
"color": GLOB.wrongColor,
"targetY": Math.min(executor.width, executor.height) / 12
text: qsTranslate("TtipHandler", "Try again!"),
color: GLOB.wrongColor,
targetY: Math.min(executor.width, executor.height) / 12
});
}
onWantWhatNextTip: {
var s = Qt.createComponent("qrc:/exam/ExamTip.qml");
function onWantWhatNextTip(text: string, color: color, pos: point) : void {
let s = Qt.createComponent("qrc:/exam/ExamTip.qml");
tipHandler.whatNextTip = s.createObject(executor, {
"text": text,
"offX": pos.x,
"offY": pos.y,
"bg": color
text: text,
offX: pos.x,
offY: pos.y,
bg: color
});
}
onWantCertificate: {
function onWantCertificate() : void {
tipHandler.certTip = Qt.createComponent("qrc:/exam/Certificate.qml").createObject(nootkaWindow.contentItem.parent);
}
}
}
......@@ -31,12 +31,12 @@ GlowRect {
width: text.width
height: text.height
scale: GLOB.useAnimations ? 0 : 1
Component.onCompleted: {
eW = executor.width;
eH = executor.height;
if (GLOB.useAnimations)
scale = 1;
}
border {
......@@ -50,7 +50,7 @@ GlowRect {
color: activPal.text
textFormat: Text.RichText
padding: NOO.factor()
onLinkActivated: {
onLinkActivated: link => {
executor.tipLink(link);
tip.destroy();
}
......@@ -60,7 +60,6 @@ GlowRect {
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
Image {
......@@ -85,12 +84,12 @@ GlowRect {
Connections {
target: executor
onWidthChanged: {
function onWidthChanged() : void {
scale = (executor.width / eW) * scale;
offX = offX * (executor.width / eW);
eW = executor.width;
}
onHeightChanged: {
function onHeightChanged() : void {
offY = offY * (executor.height / eH);
eH = executor.height;
}
......
......@@ -50,7 +50,7 @@ TlevelCreatorItem {
pages.pages[2].saveLevel();
}
onWantValidationMessage: {
onWantValidationMessage: title, message, accent => {
var c = Qt.createComponent("qrc:/level/LevelValidationMessage.qml");
c.createObject(creator, {
"caption": title,
......
......@@ -72,12 +72,12 @@ Column {
Connections {
target: creator
onSaveNewLevel: {
function onSaveNewLevel(name: string, desc: string) : void {
newLevelPopup.name = name === "" ? qsTr("new level") : name;
newLevelPopup.desc = desc;
newLevelPopup.open();
}
onWantNotSavedMessage: {
function onWantNotSavedMessage(title: string, message: string) : void {
if (!notSavedMess) {
notSavedMess = Qt.createComponent("qrc:/Tmessage.qml").createObject(creator, {
"accent": "#ff557f"
......
......@@ -17,7 +17,7 @@ Tflickable {
Connections {
target: creator
onUpdateLevel: {
function onUpdateLevel() : void {
rangeScore.setNote(0, creator.loNote);
rangeScore.setNote(1, creator.hiNote);
}
......@@ -65,12 +65,12 @@ Tflickable {
Connections {
target: rangeScore.firstStaff.clef
onClicked: creator.clef = rangeScore.clef
function onClicked() : void { creator.clef = rangeScore.clef }
}
Connections {
target: rangeScore.scoreObj
onClicked: {
function onClicked() : void {
creator.loNote = rangeScore.scoreObj.noteAt(0);
creator.hiNote = rangeScore.scoreObj.noteAt(1);
}
......