Skip to content

Commit aecc34e

Browse files
authored
Merge pull request mixxxdj#14887 from acolombier/feat/qml-settings-interface
feat(QML): add interface settings
2 parents 7a8cc3c + 4bf12d5 commit aecc34e

24 files changed

Lines changed: 3388 additions & 365 deletions

res/qml/Deck/TrackTime.qml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import ".." as Skin
2+
import Mixxx 1.0 as Mixxx
3+
import QtQuick 2.12
4+
5+
Skin.EmbeddedText {
6+
id: root
7+
8+
enum Display {
9+
Elapsed,
10+
Remaining,
11+
Both
12+
}
13+
enum Mode {
14+
Traditional,
15+
TraditionalCoarse,
16+
Seconds,
17+
SecondsLong,
18+
KiloSeconds,
19+
HectoSeconds
20+
}
21+
22+
property var display: TrackTime.Mode.Display
23+
property double elapsed: durationControl.value
24+
property string group: "[Channel1]"
25+
property var mode: TrackTime.Mode.Traditional
26+
property double remaining: durationControl.value * (1 - playPositionControl.value)
27+
28+
function toTime(value) {
29+
let result = "";
30+
switch (root.mode) {
31+
case TrackTime.Mode.Seconds:
32+
case TrackTime.Mode.SecondsLong:
33+
{
34+
let seconds = parseInt(value).toString();
35+
let subs = value % 1;
36+
return `${seconds.padStart(root.mode === TrackTime.Mode.SecondsLong ? 3 : 0, '0')}.${subs.toFixed(2).slice(-2)}`;
37+
}
38+
case TrackTime.Mode.KiloSeconds:
39+
{
40+
let kilos = parseInt(value / 1000);
41+
let seconds = parseInt(value % 1000).toString();
42+
let subs = value % 1;
43+
return `${kilos}.${seconds.padStart(3, '0')} ${subs.toFixed(2).slice(-2)}`;
44+
}
45+
case TrackTime.Mode.HectoSeconds:
46+
return `???`;
47+
default:
48+
console.warn(`Unsupported track time mode: ${root.mode}. Defaulting to traditional`);
49+
case TrackTime.Mode.Traditional:
50+
case TrackTime.Mode.TraditionalCoarse:
51+
{
52+
let component = [];
53+
if (remaining + elapsed > 3600) {
54+
component.push(parseInt(value / 3600).toString().padStart(2, '0'));
55+
}
56+
component.push(parseInt(value / 60).toString().padStart(2, '0'));
57+
component.push(parseInt(value % 60).toString().padStart(2, '0'));
58+
if (root.mode !== TrackTime.Mode.TraditionalCoarse) {
59+
component[component.length - 1] += `.${(value % 1).toFixed(2).slice(-2)}`;
60+
}
61+
return component.join(':');
62+
}
63+
}
64+
}
65+
66+
text: {
67+
switch (root.display) {
68+
case TrackTime.Display.Remaining:
69+
return `-${toTime(root.remaining)}`;
70+
case TrackTime.Display.Both:
71+
return `${toTime(root.elapsed)} -${toTime(root.remaining)}`;
72+
default:
73+
console.warn(`Unsupported track time display: ${root.display}. Defaulting to elapsed`);
74+
case TrackTime.Display.Elapsed:
75+
return toTime(root.elapsed);
76+
}
77+
}
78+
79+
Mixxx.ControlProxy {
80+
id: durationControl
81+
82+
group: root.group
83+
key: "duration"
84+
}
85+
Mixxx.ControlProxy {
86+
id: playPositionControl
87+
88+
group: root.group
89+
key: "playposition"
90+
}
91+
}

res/qml/HotcuePopup.qml

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,44 @@ Popup {
99

1010
required property Hotcue hotcue
1111

12-
dim: false
13-
modal: true
14-
focus: true
1512
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
16-
contentWidth: colorGrid.implicitWidth
1713
contentHeight: colorGrid.implicitHeight + clearButton.implicitHeight
14+
contentWidth: colorGrid.implicitWidth
15+
dim: false
16+
focus: true
17+
modal: true
18+
19+
background: BorderImage {
20+
id: backgroundImage
21+
22+
anchors.fill: parent
23+
horizontalTileMode: BorderImage.Stretch
24+
source: Theme.imgPopupBackground
25+
verticalTileMode: BorderImage.Stretch
26+
27+
border {
28+
bottom: 10
29+
left: 20
30+
right: 20
31+
top: 10
32+
}
33+
}
34+
enter: Transition {
35+
NumberAnimation {
36+
duration: 100
37+
from: 0
38+
properties: "opacity"
39+
to: 1
40+
}
41+
}
42+
exit: Transition {
43+
NumberAnimation {
44+
duration: 100
45+
from: 1
46+
properties: "opacity"
47+
to: 0
48+
}
49+
}
1850

1951
Grid {
2052
id: colorGrid
@@ -23,17 +55,18 @@ Popup {
2355
spacing: 2
2456

2557
Repeater {
26-
model: Mixxx.Config.getHotcueColorPalette()
58+
model: Mixxx.Config.hotcueColorPalette
2759

2860
Rectangle {
2961
required property color modelData
3062

63+
color: modelData
3164
height: 24
3265
width: 24
33-
color: modelData
3466

3567
MouseArea {
3668
anchors.fill: parent
69+
3770
onClicked: {
3871
root.hotcue.setColor(parent.color);
3972
root.close();
@@ -42,50 +75,16 @@ Popup {
4275
}
4376
}
4477
}
45-
4678
Skin.Button {
4779
id: clearButton
4880

49-
anchors.top: colorGrid.bottom
81+
activeColor: Theme.deckActiveColor
5082
anchors.left: parent.left
83+
anchors.top: colorGrid.bottom
5184
anchors.topMargin: 5
5285
text: "Clear"
53-
activeColor: Theme.deckActiveColor
86+
5487
onPressed: root.hotcue.clear = 1
5588
onReleased: root.hotcue.clear = 0
5689
}
57-
58-
enter: Transition {
59-
NumberAnimation {
60-
properties: "opacity"
61-
from: 0
62-
to: 1
63-
duration: 100
64-
}
65-
}
66-
67-
exit: Transition {
68-
NumberAnimation {
69-
properties: "opacity"
70-
from: 1
71-
to: 0
72-
duration: 100
73-
}
74-
}
75-
76-
background: BorderImage {
77-
id: backgroundImage
78-
79-
anchors.fill: parent
80-
horizontalTileMode: BorderImage.Stretch
81-
verticalTileMode: BorderImage.Stretch
82-
source: Theme.imgPopupBackground
83-
84-
border {
85-
top: 10
86-
left: 20
87-
right: 20
88-
bottom: 10
89-
}
90-
}
9190
}

res/qml/Mixxx/Controls/Knob.qml

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,33 @@ Item {
1212
Maximum
1313
}
1414

15-
property real value: min
16-
property alias background: background.data
17-
property alias foreground: foreground.data
18-
property real min: 0
19-
property real max: 1
20-
property real wheelStepSize: (root.max - root.min) / 100
2115
property real angle: 130
2216
property bool arc: false
23-
property int arcStart: Knob.Center
17+
property alias arcColor: arcPath.strokeColor
18+
property real arcOffsetX: 0
19+
property real arcOffsetY: 0
2420
property real arcRadius: width / 2
21+
property int arcStart: Knob.Center
2522
readonly property real arcStartValue: {
2623
switch (arcStart) {
27-
case Knob.ArcStart.Minimum:
28-
return min;
29-
case Knob.ArcStart.Maximum:
30-
return max;
31-
default:
32-
return valueCenter;
24+
case Knob.ArcStart.Minimum:
25+
return min;
26+
case Knob.ArcStart.Maximum:
27+
return max;
28+
default:
29+
return valueCenter;
3330
}
3431
}
35-
property real arcOffsetX: 0
36-
property real arcOffsetY: 0
37-
property alias arcColor: arcPath.strokeColor
38-
property alias arcWidth: arcPath.strokeWidth
3932
property alias arcStyle: arcPath.strokeStyle
4033
property alias arcStylePattern: arcPath.dashPattern
34+
property alias arcWidth: arcPath.strokeWidth
35+
property alias background: background.data
36+
property alias foreground: foreground.data
37+
property real max: 1
38+
property real min: 0
39+
property real value: min
4140
readonly property real valueCenter: (max - min) / 2
41+
property real wheelStepSize: (root.max - root.min) / 100
4242

4343
signal turned(real value)
4444

@@ -51,51 +51,49 @@ Item {
5151

5252
anchors.fill: parent
5353
}
54-
5554
Item {
5655
id: foreground
5756

5857
anchors.fill: parent
5958
rotation: root.angleFrom(root.value - root.valueCenter)
6059
}
61-
6260
Shape {
63-
anchors.fill: parent
64-
antialiasing: true
65-
visible: root.arc
6661
// Enable smooth curves. For QtQuick Shapes, this currently only works
6762
// by enabling multisampling, so we use 4xMSAA here.
68-
//
6963
// See https://www.qt.io/blog/2017/07/07/let-there-be-shapes for details.
70-
property int multiSamplingLevel: Mixxx.Config.getMultiSamplingLevel()
64+
property int multiSamplingLevel: Mixxx.Config.multiSamplingLevel
65+
66+
anchors.fill: parent
67+
antialiasing: true
7168
layer.enabled: multiSamplingLevel > 1
7269
layer.samples: multiSamplingLevel
70+
visible: root.arc
7371

7472
ShapePath {
7573
id: arcPath
7674

75+
fillColor: "transparent"
7776
strokeColor: "transparent"
7877
strokeWidth: 2
79-
fillColor: "transparent"
8078

8179
PathAngleArc {
82-
startAngle: root.angleFrom(root.arcStartValue - root.valueCenter) - 90
83-
sweepAngle: root.angleFrom(root.value - root.arcStartValue)
84-
radiusX: root.arcRadius
85-
radiusY: root.arcRadius
8680
centerX: root.width / 2 + root.arcOffsetX
8781
centerY: root.width / 2 + root.arcOffsetY
82+
radiusX: root.arcRadius
83+
radiusY: root.arcRadius
84+
startAngle: root.angleFrom(root.arcStartValue - root.valueCenter) - 90
85+
sweepAngle: root.angleFrom(root.value - root.arcStartValue)
8886
}
8987
}
9088
}
91-
9289
DragHandler {
9390
id: dragHandler
9491

95-
property real value
9692
property vector2d lastTranslation: Qt.vector2d(0, 0)
93+
property real value
9794

9895
target: null
96+
9997
onActiveChanged: {
10098
dragHandler.value = root.value;
10199
lastTranslation = Qt.vector2d(0, 0);
@@ -120,12 +118,11 @@ Item {
120118
dragHandler.value = value;
121119
}
122120
}
123-
124121
Binding {
125-
when: dragHandler.active
126-
target: root
127122
property: "value"
123+
target: root
128124
value: dragHandler.value
125+
when: dragHandler.active
129126
}
130127

131128
// TODO: Replace this with a WheelHandler once we switch to Qt >= 5.14.
@@ -134,19 +131,19 @@ Item {
134131

135132
property real value
136133

137-
anchors.fill: parent
138134
acceptedButtons: Qt.NoButton
135+
anchors.fill: parent
136+
139137
onWheel: {
140138
const value = (wheel.angleDelta.y < 0) ? Math.min(root.max, root.value + root.wheelStepSize) : Math.max(root.min, root.value - root.wheelStepSize);
141139
root.turned(value);
142140
dragHandler.value = value;
143141
}
144142
}
145-
146143
Binding {
147-
when: wheelHandler.drag.active
148-
target: root
149144
property: "value"
145+
target: root
150146
value: wheelHandler.value
147+
when: wheelHandler.drag.active
151148
}
152149
}

0 commit comments

Comments
 (0)