diff --git a/res/skins/QMLDemo/Button.qml b/res/skins/QMLDemo/Button.qml
new file mode 100644
index 00000000000..f667a118512
--- /dev/null
+++ b/res/skins/QMLDemo/Button.qml
@@ -0,0 +1,128 @@
+import "." as Skin
+import QtGraphicalEffects 1.12
+import QtQml 2.12
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import "Theme"
+
+AbstractButton {
+ id: root
+
+ property color normalColor: Theme.buttonNormalColor
+ property color activeColor // required
+ property color pressedColor: activeColor
+ property bool highlight: false
+
+ implicitWidth: 52
+ implicitHeight: 26
+ states: [
+ State {
+ name: "pressed"
+ when: root.pressed
+
+ PropertyChanges {
+ target: backgroundImage
+ source: "images/button_pressed.svg"
+ }
+
+ PropertyChanges {
+ target: label
+ color: root.pressedColor
+ }
+
+ PropertyChanges {
+ target: labelGlow
+ visible: true
+ }
+
+ },
+ State {
+ name: "active"
+ when: (root.highlight || root.checked) && !root.pressed
+
+ PropertyChanges {
+ target: backgroundImage
+ source: "images/button.svg"
+ }
+
+ PropertyChanges {
+ target: label
+ color: root.activeColor
+ }
+
+ PropertyChanges {
+ target: labelGlow
+ visible: true
+ }
+
+ },
+ State {
+ name: "inactive"
+ when: !root.checked && !root.highlight && !root.pressed
+
+ PropertyChanges {
+ target: backgroundImage
+ source: "images/button.svg"
+ }
+
+ PropertyChanges {
+ target: label
+ color: root.normalColor
+ }
+
+ PropertyChanges {
+ target: labelGlow
+ visible: false
+ }
+
+ }
+ ]
+
+ background: BorderImage {
+ id: backgroundImage
+
+ anchors.fill: parent
+ horizontalTileMode: BorderImage.Stretch
+ verticalTileMode: BorderImage.Stretch
+ source: "images/button.svg"
+
+ border {
+ top: 10
+ left: 10
+ right: 10
+ bottom: 10
+ }
+
+ }
+
+ contentItem: Item {
+ anchors.fill: parent
+
+ Glow {
+ id: labelGlow
+
+ anchors.fill: parent
+ radius: 5
+ spread: 0.1
+ samples: 1 + radius * 2
+ color: label.color
+ source: label
+ }
+
+ Label {
+ id: label
+
+ anchors.fill: parent
+ text: root.text
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ font.family: Theme.fontFamily
+ font.capitalization: Font.AllUppercase
+ font.bold: true
+ font.pixelSize: Theme.buttonFontPixelSize
+ color: root.normalColor
+ }
+
+ }
+
+}
diff --git a/res/skins/QMLDemo/ControlButton.qml b/res/skins/QMLDemo/ControlButton.qml
new file mode 100644
index 00000000000..eb7a15ddf6a
--- /dev/null
+++ b/res/skins/QMLDemo/ControlButton.qml
@@ -0,0 +1,16 @@
+import "." as Skin
+import Mixxx 0.1 as Mixxx
+
+Skin.Button {
+ id: root
+
+ property string group // required
+ property string key // required
+
+ Mixxx.ControlProxy {
+ group: root.group
+ key: root.key
+ value: root.checked || root.down
+ }
+
+}
diff --git a/res/skins/QMLDemo/CrossfaderRow.qml b/res/skins/QMLDemo/CrossfaderRow.qml
new file mode 100644
index 00000000000..559f187cd52
--- /dev/null
+++ b/res/skins/QMLDemo/CrossfaderRow.qml
@@ -0,0 +1,49 @@
+import "." as Skin
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import "Theme"
+
+Item {
+ id: root
+
+ property real crossfaderWidth // required
+
+ implicitHeight: crossfaderSlider.width
+
+ Item {
+ id: effectUnitLeftPlaceholder
+
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ }
+
+ Skin.Slider {
+ id: crossfaderSlider
+
+ anchors.centerIn: parent
+ height: root.crossfaderWidth
+ group: "[Master]"
+ key: "crossfader"
+ barColor: Theme.crossfaderBarColor
+ barStart: 0.5
+ fg: "images/slider_handle_crossfader.svg"
+ bg: "images/slider_crossfader.svg"
+
+ transform: Rotation {
+ origin.x: crossfaderSlider.width / 2
+ origin.y: crossfaderSlider.height / 2
+ angle: 90
+ }
+
+ }
+
+ Item {
+ id: effectUnitRightPlaceholder
+
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ }
+
+}
diff --git a/res/skins/QMLDemo/Deck.qml b/res/skins/QMLDemo/Deck.qml
index 2cbe3c6544f..58a86a615f8 100644
--- a/res/skins/QMLDemo/Deck.qml
+++ b/res/skins/QMLDemo/Deck.qml
@@ -1,400 +1,357 @@
+import "." as Skin
import Mixxx 0.1 as Mixxx
import Mixxx.Controls 0.1 as MixxxControls
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.11
+import "Theme"
Item {
id: root
- required property string group
+ property string group // required
- ColumnLayout {
- anchors.fill: parent
+ Skin.DeckInfoBar {
+ id: infoBar
- RowLayout {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- ColumnLayout {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- Rectangle {
- id: trackInfo
-
- Layout.fillWidth: true
- height: 60
- color: "#121213"
-
- Rectangle {
- id: coverArt
-
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.bottom: parent.bottom
- width: height
- color: "black"
- }
-
- Item {
- id: spinny
-
- anchors.fill: coverArt
-
- // The Spinnies are automatically hidden if the track
- // is stopped. This is not really useful, but is nice for
- // demo'ing transitions.
- Mixxx.ControlProxy {
- group: root.group
- key: "play"
- onValueChanged: spinnyIndicator.indicatorVisible = (value > 0)
- }
-
- MixxxControls.Spinny {
- id: spinnyIndicator
-
- anchors.fill: parent
- group: root.group
- indicatorVisible: false
-
- indicatorDelegate: Image {
- mipmap: true
- width: spinnyIndicator.width
- height: spinnyIndicator.height
- source: "../LateNight/palemoon/style/spinny_indicator.svg"
- }
-
- }
-
- }
-
- Item {
- id: trackText
-
- anchors.top: parent.top
- anchors.left: coverArt.right
- anchors.right: parent.right
- anchors.bottom: parent.bottom
-
- ColumnLayout {
- anchors.fill: parent
- anchors.margins: 5
-
- Text {
- id: trackTitle
-
- Layout.fillWidth: true
- Layout.fillHeight: true
- text: "Title Placeholder"
- elide: Text.ElideRight
- color: "#c2b3a5"
- }
-
- Rectangle {
- id: trackColor
-
- Layout.fillWidth: true
- implicitHeight: 3
- color: "black"
- }
-
- Text {
- id: trackArtist
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ color: Theme.deckBackgroundColor
+ group: root.group
+ }
- Layout.fillWidth: true
- Layout.fillHeight: true
- text: "Artist Placeholder"
- elide: Text.ElideRight
- color: "#c2b3a5"
- }
+ Skin.Slider {
+ id: rateSlider
+
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ anchors.top: infoBar.bottom
+ anchors.right: parent.right
+ anchors.bottom: buttonBar.top
+ width: syncButton.width
+ group: root.group
+ key: "rate"
+ barStart: 0.5
+ barColor: Theme.bpmSliderBarColor
+ bg: "images/slider_bpm.svg"
+ }
- }
+ Rectangle {
+ id: overview
+
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ anchors.rightMargin: 5
+ anchors.top: infoBar.bottom
+ anchors.bottom: buttonBar.top
+ anchors.left: parent.left
+ anchors.right: rateSlider.left
+ radius: 5
+ color: Theme.deckBackgroundColor
+ height: 56
+
+ Skin.WaveformOverview {
+ group: root.group
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: parent.height - 26
+ }
- }
+ Item {
+ id: waveformBar
- }
+ height: 26
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+
+ Rectangle {
+ id: waveformBarVSeparator
+
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ anchors.leftMargin: 5
+ height: 2
+ color: infoBar.lineColor
+ }
- WaveformOverview {
- Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter
- Layout.fillWidth: true
- Layout.fillHeight: true
- group: root.group
+ InfoBarButton {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ width: rateSlider.width
+ group: "[EffectRack1_EffectUnit1]"
+ key: "group_" + root.group + "_enable"
+ checkable: true
+ activeColor: Theme.deckActiveColor
+
+ foreground: Text {
+ anchors.centerIn: parent
+ text: "FX 1"
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ font.family: Theme.fontFamily
+ font.bold: true
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
}
}
- Item {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- Layout.fillHeight: true
- implicitWidth: 50
-
- MixxxControls.ToggleButton {
- id: syncButton
+ Rectangle {
+ id: waveformBarHSeparator1
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- height: 24
- group: root.group
- key: "sync_enabled"
- icon.width: 50
- icon.height: 24
-
- State {
- name: "0"
-
- PropertyChanges {
- target: syncButton
- icon.source: "../LateNight/palemoon/buttons/btn__sync_deck.svg"
- icon.color: "#777777"
- background.color: "transparent"
- background.border.width: 2
- }
-
- PropertyChanges {
- target: syncButtonBgImage
- source: "../LateNight/palemoon/buttons/btn_embedded_sync.svg"
- }
-
- }
-
- State {
- name: "1"
-
- PropertyChanges {
- target: syncButton
- icon.source: "../LateNight/palemoon/buttons/btn__sync_deck_active.svg"
- icon.color: "transparent"
- background.color: "#b24c12"
- background.border.width: 2
- }
-
- PropertyChanges {
- target: syncButtonBgImage
- source: "../LateNight/palemoon/buttons/btn_embedded_sync_active.svg"
- }
-
- }
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: waveformBarVSeparator.left
+ anchors.leftMargin: rateSlider.width
+ width: 2
+ color: infoBar.lineColor
+ }
- background: Rectangle {
- anchors.fill: parent
+ InfoBarButton {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: waveformBarHSeparator1.left
+ width: rateSlider.width
+ group: "[EffectRack1_EffectUnit2]"
+ key: "group_" + root.group + "_enable"
+ checkable: true
+ activeColor: Theme.deckActiveColor
+
+ foreground: Text {
+ anchors.centerIn: parent
+ text: "FX 2"
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ font.family: Theme.fontFamily
+ font.bold: true
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
+ }
- data: Image {
- id: syncButtonBgImage
+ }
- anchors.fill: parent
- }
+ Rectangle {
+ id: waveformBarHSeparator2
- }
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: waveformBarHSeparator1.right
+ anchors.leftMargin: rateSlider.width
+ width: 2
+ color: infoBar.lineColor
+ }
+ Text {
+ id: waveformBarPosition
+
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: waveformBarHSeparator2.right
+ anchors.leftMargin: 5
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignLeft
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
+ text: {
+ const positionSeconds = samplesControl.value / 2 / sampleRateControl.value * playPositionControl.value;
+ if (isNaN(positionSeconds))
+ return "";
+
+ let minutes = Math.floor(positionSeconds / 60);
+ let seconds = positionSeconds - (minutes * 60);
+ let centiseconds = Math.trunc((seconds - Math.trunc(seconds)) * 100);
+ seconds = Math.trunc(seconds);
+ if (minutes < 10)
+ minutes = "0" + minutes;
+
+ if (seconds < 10)
+ seconds = "0" + seconds;
+
+ if (centiseconds < 10)
+ centiseconds = "0" + centiseconds;
+
+ return minutes + ':' + seconds + "." + centiseconds;
}
Mixxx.ControlProxy {
- id: bpmControl
+ id: playPositionControl
group: root.group
- key: "bpm"
- }
-
- Text {
- id: bpmText
-
- anchors.top: syncButton.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- height: contentHeight
- text: bpmControl.value.toFixed(2)
- horizontalAlignment: Text.AlignHCenter
- font.family: "Open Sans"
- font.bold: true
- font.pixelSize: 11
- color: "#777"
+ key: "playposition"
}
Mixxx.ControlProxy {
- id: rateRatioControl
+ id: sampleRateControl
group: root.group
- key: "rate_ratio"
+ key: "track_samplerate"
}
- Text {
- id: bpmRatioText
-
- property real ratio: ((rateRatioControl.value - 1) * 100).toPrecision(2)
-
- anchors.top: bpmText.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- height: contentHeight
- text: (ratio > 0) ? "+" + ratio.toFixed(2) : ratio.toFixed(2)
- horizontalAlignment: Text.AlignHCenter
- font.family: "Open Sans"
- font.bold: true
- font.pixelSize: 10
- color: "#404040"
- }
-
- MixxxControls.Slider {
- id: rateSlider
+ Mixxx.ControlProxy {
+ id: samplesControl
- anchors.top: bpmRatioText.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
group: root.group
- key: "rate"
- bar: true
- barColor: "#257b82"
- barMargin: 10
- barStart: 0.5
-
- handle: Image {
- source: "../LateNight/palemoon/sliders/knob_volume_deck.svg"
- width: 42
- height: 19
- }
-
- background: Image {
- anchors.fill: parent
- source: "../LateNight/palemoon/sliders/slider_volume_deck.svg"
- }
-
+ key: "track_samples"
}
}
- }
-
- Rectangle {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- Layout.fillWidth: true
- height: 26
- color: "transparent"
+ Item {
+ id: waveformBarRightSpace
- RowLayout {
- anchors.fill: parent
+ anchors.top: waveformBar.top
+ anchors.bottom: waveformBar.bottom
+ anchors.right: waveformBar.right
+ width: rateSlider.width
+ }
- Rectangle {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
- implicitWidth: 68
- implicitHeight: 26
- color: "#121213"
+ Rectangle {
+ id: waveformBarHSeparator
- MixxxControls.ToggleButton {
- id: playButton
+ anchors.top: waveformBar.top
+ anchors.bottom: waveformBar.bottom
+ anchors.right: waveformBarRightSpace.left
+ anchors.bottomMargin: 5
+ width: 2
+ color: infoBar.lineColor
+ }
- anchors.fill: parent
- group: root.group
- key: "play"
- icon.width: 50
- icon.height: 24
+ InfoBarButton {
+ anchors.top: waveformBarVSeparator.bottom
+ anchors.bottom: waveformBar.bottom
+ anchors.left: waveformBarRightSpace.left
+ anchors.right: waveformBarRightSpace.right
+ group: root.group
+ key: "quantize"
+ checkable: true
+ activeColor: Theme.deckActiveColor
+
+ foreground: Image {
+ anchors.centerIn: parent
+ source: "images/icon_quantize.svg"
+ }
- State {
- name: "0"
+ }
- PropertyChanges {
- target: playButton
- icon.source: "../LateNight/palemoon/buttons/btn__play_deck.svg"
- icon.color: "#777777"
- background.color: "transparent"
- background.border.width: 2
- }
+ Item {
+ id: waveformBarLeftSpace
- PropertyChanges {
- target: playButtonBgImage
- source: "../LateNight/palemoon/buttons/btn_embedded_play.svg"
- }
+ anchors.top: waveformBar.top
+ anchors.bottom: waveformBar.bottom
+ anchors.right: waveformBarHSeparator.left
+ width: rateSlider.width
+ }
- }
+ Rectangle {
+ id: waveformBarHSeparator3
- State {
- name: "1"
+ anchors.top: waveformBar.top
+ anchors.bottom: waveformBar.bottom
+ anchors.right: waveformBarLeftSpace.left
+ anchors.bottomMargin: 5
+ width: 2
+ color: infoBar.lineColor
+ }
- PropertyChanges {
- target: playButton
- icon.source: "../LateNight/palemoon/buttons/btn__play_deck_active.svg"
- icon.color: "transparent"
- background.color: "#b24c12"
- background.border.width: 2
- }
+ InfoBarButton {
+ anchors.top: waveformBarVSeparator.bottom
+ anchors.bottom: waveformBar.bottom
+ anchors.left: waveformBarLeftSpace.left
+ anchors.right: waveformBarLeftSpace.right
+ group: root.group
+ key: "passthrough"
+ checkable: true
+ activeColor: Theme.deckActiveColor
+
+ foreground: Image {
+ anchors.centerIn: parent
+ source: "images/icon_passthrough.svg"
+ }
- PropertyChanges {
- target: playButtonBgImage
- source: "../LateNight/palemoon/buttons/btn_embedded_play_active.svg"
- }
+ }
- }
+ }
- background: Rectangle {
- anchors.fill: parent
+ }
- data: Image {
- id: playButtonBgImage
+ Item {
+ id: buttonBar
- anchors.fill: parent
- }
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 56
- }
+ Skin.ControlButton {
+ id: cueButton
- }
+ anchors.left: parent.left
+ anchors.top: parent.top
+ group: root.group
+ key: "cue_default"
+ text: "Cue"
+ activeColor: Theme.deckActiveColor
+ }
- }
+ Skin.ControlButton {
+ id: playButton
+
+ anchors.top: cueButton.bottom
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ anchors.topMargin: 5
+ group: root.group
+ key: "play"
+ text: "Play"
+ checkable: true
+ activeColor: Theme.deckActiveColor
+ }
- Item {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
- Layout.fillWidth: true
- Layout.fillHeight: true
+ Row {
+ anchors.left: cueButton.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: 10
+ spacing: -1
+
+ Repeater {
+ model: 8
+
+ Skin.HotcueButton {
+ // TODO: Once we require Qt >= 5.14, we're going to re-add
+ // the `required` keyword. If the component has any
+ // required properties, we'll stumble over a Qt bug and
+ // need the following workaround:
+ // required property int index
+ // See this for details:
+ // https://bugreports.qt.io/browse/QTBUG-86009, and need
+
+ hotcueNumber: index + 1
+ group: root.group
}
- Item {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- implicitWidth: 50
- implicitHeight: 20
-
- Mixxx.ControlProxy {
- id: passthroughControl
-
- group: root.group
- key: "passthrough"
- }
-
- Switch {
- id: passthroughSwitch
-
- width: parent.implicitWidth
- height: 18
- anchors.margins: 5
- text: "Passthrough"
- checked: passthroughControl.value
- onCheckedChanged: passthroughControl.value = checked
-
- indicator: Rectangle {
- anchors.fill: parent
- x: passthroughSwitch.leftPadding
- y: parent.height / 2 - height / 2
- radius: height / 2
- color: passthroughSwitch.checked ? "#202020" : "#121213"
- border.color: "#404040"
-
- Rectangle {
- x: passthroughSwitch.checked ? parent.width - width : 0
- height: passthroughSwitch.height
- width: height
- radius: height / 2
- color: passthroughSwitch.checked ? "#777" : "#404040"
- border.color: "#404040"
- }
-
- }
-
- }
+ }
- }
+ }
- }
+ Skin.ControlButton {
+ id: syncButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ text: "Sync"
+ group: root.group
+ key: "sync_enabled"
+ checkable: true
+ activeColor: Theme.deckActiveColor
}
}
diff --git a/res/skins/QMLDemo/DeckInfoBar.qml b/res/skins/QMLDemo/DeckInfoBar.qml
new file mode 100644
index 00000000000..ee897b247ef
--- /dev/null
+++ b/res/skins/QMLDemo/DeckInfoBar.qml
@@ -0,0 +1,200 @@
+import "." as Skin
+import Mixxx 0.1 as Mixxx
+import Mixxx.Controls 0.1 as MixxxControls
+import QtQuick 2.12
+import "Theme"
+
+Rectangle {
+ id: root
+
+ property string group // required
+ property color textColor: Theme.deckTextColor
+ property color lineColor: Theme.deckLineColor
+
+ radius: 5
+ height: 56
+
+ Rectangle {
+ id: coverArt
+
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ anchors.margins: 5
+ width: height
+ radius: height / 2
+ border.width: 2
+ border.color: Theme.deckLineColor
+ color: "transparent"
+ }
+
+ Item {
+ id: spinny
+
+ anchors.fill: coverArt
+
+ // The Spinnies are automatically hidden if the track
+ // is stopped. This is not really useful, but is nice for
+ // demo'ing transitions.
+ Mixxx.ControlProxy {
+ group: root.group
+ key: "play"
+ onValueChanged: spinnyIndicator.indicatorVisible = (value > 0)
+ }
+
+ MixxxControls.Spinny {
+ id: spinnyIndicator
+
+ anchors.fill: parent
+ group: root.group
+ indicatorVisible: false
+
+ indicator: Item {
+ width: spinnyIndicator.width
+ height: spinnyIndicator.height
+
+ Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 2
+ height: parent.height / 2
+ color: Theme.deckTextColor
+ }
+
+ }
+
+ }
+
+ }
+
+ Text {
+ id: infoBarTitle
+
+ text: "Title Placeholder"
+ anchors.top: infoBarHSeparator1.top
+ anchors.left: infoBarVSeparator.left
+ anchors.right: infoBarHSeparator1.left
+ anchors.bottom: infoBarVSeparator.bottom
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
+ }
+
+ Rectangle {
+ id: infoBarVSeparator
+
+ anchors.left: coverArt.right
+ anchors.right: infoBar.right
+ anchors.verticalCenter: infoBar.verticalCenter
+ anchors.margins: 5
+ height: 2
+ color: infoBar.lineColor
+ }
+
+ Text {
+ id: infoBarArtist
+
+ text: "Artist Placeholder"
+ anchors.top: infoBarVSeparator.bottom
+ anchors.left: infoBarVSeparator.left
+ anchors.right: infoBarHSeparator1.left
+ anchors.bottom: infoBarHSeparator1.bottom
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
+ }
+
+ Rectangle {
+ id: infoBarHSeparator1
+
+ anchors.top: infoBar.top
+ anchors.bottom: infoBar.bottom
+ anchors.right: infoBarKey.left
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ width: 2
+ color: infoBar.lineColor
+ }
+
+ Text {
+ id: infoBarKey
+
+ anchors.top: infoBarHSeparator1.top
+ anchors.bottom: infoBarVSeparator.top
+ width: rateSlider.width
+ anchors.right: infoBarHSeparator2.left
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ text: "KEY"
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
+ }
+
+ Rectangle {
+ id: infoBarHSeparator2
+
+ anchors.top: infoBar.top
+ anchors.bottom: infoBar.bottom
+ anchors.right: infoBarRateRatio.left
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ width: 2
+ color: infoBar.lineColor
+ }
+
+ Text {
+ id: infoBarRate
+
+ anchors.top: infoBarHSeparator2.top
+ anchors.bottom: infoBarVSeparator.top
+ width: rateSlider.width
+ anchors.right: infoBar.right
+ anchors.rightMargin: 5
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ text: bpmControl.value.toFixed(2)
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
+
+ Mixxx.ControlProxy {
+ id: bpmControl
+
+ group: root.group
+ key: "bpm"
+ }
+
+ }
+
+ Text {
+ id: infoBarRateRatio
+
+ property real ratio: ((rateRatioControl.value - 1) * 100).toPrecision(2)
+
+ anchors.top: infoBarVSeparator.bottom
+ anchors.bottom: infoBarHSeparator1.bottom
+ width: rateSlider.width
+ anchors.right: infoBar.right
+ anchors.rightMargin: 5
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: infoBar.textColor
+ text: (ratio > 0) ? "+" + ratio.toFixed(2) : ratio.toFixed(2)
+
+ Mixxx.ControlProxy {
+ id: rateRatioControl
+
+ group: root.group
+ key: "rate_ratio"
+ }
+
+ }
+
+}
diff --git a/res/skins/QMLDemo/DeckRow.qml b/res/skins/QMLDemo/DeckRow.qml
index f6725626bd8..e33d8e7d30d 100644
--- a/res/skins/QMLDemo/DeckRow.qml
+++ b/res/skins/QMLDemo/DeckRow.qml
@@ -1,72 +1,44 @@
-import Mixxx 0.1 as Mixxx
-import Mixxx.Controls 0.1 as MixxxControls
import QtQuick 2.12
import QtQuick.Controls 2.12
-import QtQuick.Layouts 1.11
Item {
id: root
- required property string leftDeck
- required property string rightDeck
+ property string leftDeckGroup // required
+ property string rightDeckGroup // required
+ property alias mixer: mixer
- RowLayout {
- anchors.fill: parent
- anchors.leftMargin: 10
- anchors.rightMargin: 10
- Layout.margins: 10
+ implicitHeight: mixer.height
- Deck {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
- Layout.fillWidth: true
- Layout.fillHeight: true
- group: root.leftDeck
- }
+ Deck {
+ id: leftDeck
- Rectangle {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
- implicitWidth: 200
- Layout.fillHeight: true
- color: "#1e1e20"
- border.color: "#121213"
- border.width: 2
- radius: 1
-
- RowLayout {
- anchors.fill: parent
- anchors.margins: 10
-
- EqColumn {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
- group: root.leftDeck
- }
-
- MixerColumn {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
- group: root.leftDeck
- }
-
- MixerColumn {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
- group: root.rightDeck
- }
-
- EqColumn {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
- group: root.rightDeck
- }
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: mixer.left
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 5
+ group: root.leftDeckGroup
+ }
- }
+ Mixer {
+ id: mixer
- }
+ anchors.top: parent.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ leftDeckGroup: root.leftDeckGroup
+ rightDeckGroup: root.rightDeckGroup
+ }
- Deck {
- Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
- Layout.fillWidth: true
- Layout.fillHeight: true
- group: root.rightDeck
- }
+ Deck {
+ id: rightDeck
+ anchors.top: parent.top
+ anchors.left: mixer.right
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: 5
+ group: root.rightDeckGroup
}
}
diff --git a/res/skins/QMLDemo/EqColumn.qml b/res/skins/QMLDemo/EqColumn.qml
index bf3af882c4a..cc82669640b 100644
--- a/res/skins/QMLDemo/EqColumn.qml
+++ b/res/skins/QMLDemo/EqColumn.qml
@@ -1,57 +1,51 @@
+import "." as Skin
import Mixxx.Controls 0.1 as MixxxControls
import QtQuick 2.12
-import QtQuick.Layouts 1.11
+import QtQuick.Shapes 1.12
+import "Theme"
-Item {
+Column {
id: root
- required property string group
-
- implicitWidth: 35
- implicitHeight: 150
-
- ColumnLayout {
- EqKnob {
- channelGroup: root.group
- key: "parameter3"
- }
-
- EqKnob {
- channelGroup: root.group
- key: "parameter2"
- }
-
- EqKnob {
- channelGroup: root.group
- key: "parameter1"
- }
-
- MixxxControls.Knob {
- id: filterKnob
-
- width: 35
- height: width
- group: "[QuickEffectRack1_" + root.group + "]"
- key: "super1"
- arc: true
- arcRadius: 15
- arcColor: "#518f00"
- arcWidth: 2
-
- background: Image {
- source: "../LateNight/palemoon/knobs/knob_bg_master.svg"
- width: filterKnob.width
- height: filterKnob.width / 7 * 6
- }
-
- foreground: Image {
- source: "../LateNight/palemoon/knobs/knob_indicator_regular_green.svg"
- width: filterKnob.width
- height: filterKnob.width / 7 * 6
- }
-
- }
+ property string group // required
+ spacing: 4
+
+ EqKnob {
+ group: "[EqualizerRack1_" + root.group + "_Effect1]"
+ key: "parameter3"
+ statusKey: "button_parameter3"
+ color: Theme.eqHighColor
+ }
+
+ EqKnob {
+ group: "[EqualizerRack1_" + root.group + "_Effect1]"
+ key: "parameter2"
+ statusKey: "button_parameter2"
+ color: Theme.eqMidColor
+ }
+
+ EqKnob {
+ group: "[EqualizerRack1_" + root.group + "_Effect1]"
+ key: "parameter1"
+ statusKey: "button_parameter1"
+ color: Theme.eqLowColor
+ }
+
+ EqKnob {
+ group: "[QuickEffectRack1_" + root.group + "]"
+ key: "super1"
+ statusGroup: "[QuickEffectRack1_" + root.group + "_Effect1]"
+ statusKey: "enabled"
+ arcStyle: ShapePath.DashLine
+ arcStylePattern: [2, 2]
+ color: Theme.eqFxColor
+ }
+
+ Skin.OrientationToggleButton {
+ group: root.group
+ key: "orientation"
+ color: Theme.crossfaderOrientationColor
}
}
diff --git a/res/skins/QMLDemo/EqKnob.qml b/res/skins/QMLDemo/EqKnob.qml
index d00d7de8ca6..171c65d9192 100644
--- a/res/skins/QMLDemo/EqKnob.qml
+++ b/res/skins/QMLDemo/EqKnob.qml
@@ -1,35 +1,39 @@
+import "." as Skin
+import Mixxx 0.1 as Mixxx
import Mixxx.Controls 0.1 as MixxxControls
import QtQuick 2.12
+import "Theme"
-Item {
+Skin.Knob {
id: root
- required property string channelGroup
- property alias key: knob.key
+ property string statusGroup: root.group // required
+ property string statusKey // required
- width: 35
- height: 35
+ Mixxx.ControlProxy {
+ id: statusControl
- MixxxControls.Knob {
- id: knob
-
- anchors.fill: parent
- group: "[EqualizerRack1_" + channelGroup + "_Effect1]"
- arc: true
- arcRadius: 15
- arcColor: "#858585"
- arcWidth: 2
-
- background: Image {
- source: "../LateNight/palemoon/knobs/knob_bg_master.svg"
- width: 35
- height: 30
- }
+ group: root.statusGroup
+ key: root.statusKey
+ }
- foreground: Image {
- source: "../LateNight/palemoon/knobs/knob_indicator_regular_red.svg"
- width: 35
- height: 30
+ Rectangle {
+ id: statusButton
+
+ anchors.left: root.left
+ anchors.bottom: root.bottom
+ anchors.leftMargin: 6
+ anchors.bottomMargin: 2
+ width: 8
+ height: width
+ radius: width / 2
+ border.width: 1
+ border.color: Theme.buttonNormalColor
+ color: statusControl.value ? root.color : "transparent"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: statusControl.value = !statusControl.value
}
}
diff --git a/res/skins/QMLDemo/HiddenState.qml b/res/skins/QMLDemo/HiddenState.qml
new file mode 100644
index 00000000000..19435a9b3e3
--- /dev/null
+++ b/res/skins/QMLDemo/HiddenState.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.12
+
+State {
+ property alias target: changes.target
+
+ name: "hidden"
+
+ PropertyChanges {
+ id: changes
+
+ opacity: 0
+ visible: false
+ }
+
+}
diff --git a/res/skins/QMLDemo/HiddenTransition.qml b/res/skins/QMLDemo/HiddenTransition.qml
new file mode 100644
index 00000000000..65379d70b53
--- /dev/null
+++ b/res/skins/QMLDemo/HiddenTransition.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.12
+
+Transition {
+ id: root
+
+ property var target // required
+
+ to: "hidden"
+ reversible: true
+
+ SequentialAnimation {
+ NumberAnimation {
+ target: root.target
+ property: "opacity"
+ duration: 150
+ }
+
+ PropertyAction {
+ target: root.target
+ property: "visible"
+ }
+
+ }
+
+}
diff --git a/res/skins/QMLDemo/HotcueButton.qml b/res/skins/QMLDemo/HotcueButton.qml
new file mode 100644
index 00000000000..c5aec57558e
--- /dev/null
+++ b/res/skins/QMLDemo/HotcueButton.qml
@@ -0,0 +1,97 @@
+import "." as Skin
+import Mixxx 0.1 as Mixxx
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import "Theme"
+
+Skin.Button {
+ id: root
+
+ property int hotcueNumber // required
+ property string group // required
+
+ text: hotcueNumber
+ width: playButton.height
+ height: playButton.height
+ activeColor: {
+ if (hotcueColorControl.value < 0)
+ return Theme.deckActiveColor;
+
+ return "#" + hotcueColorControl.value.toString(16).padStart(6, "0");
+ }
+ highlight: hotcueControl.value
+
+ Mixxx.ControlProxy {
+ id: hotcueColorControl
+
+ group: root.group
+ key: "hotcue_" + hotcueNumber + "_color"
+ }
+
+ Mixxx.ControlProxy {
+ group: root.group
+ key: "hotcue_" + hotcueNumber + "_activate"
+ value: root.down
+ }
+
+ Mixxx.ControlProxy {
+ id: hotcueControl
+
+ group: root.group
+ key: "hotcue_" + hotcueNumber + "_enabled"
+ }
+
+ Mixxx.ControlProxy {
+ id: hotcueClearControl
+
+ group: root.group
+ key: "hotcue_" + hotcueNumber + "_clear"
+ }
+
+ MouseArea {
+ id: mousearea
+
+ anchors.fill: parent
+ acceptedButtons: Qt.RightButton
+ onClicked: {
+ popup.x = mouse.x;
+ popup.y = mouse.y;
+ popup.open();
+ }
+ }
+
+ Popup {
+ id: popup
+
+ modal: true
+ focus: true
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
+
+ Text {
+ text: "Cue Popup Placeholder"
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: Theme.deckTextColor
+ anchors.centerIn: parent
+ }
+
+ background: BorderImage {
+ id: backgroundImage
+
+ anchors.fill: parent
+ horizontalTileMode: BorderImage.Stretch
+ verticalTileMode: BorderImage.Stretch
+ source: "images/button.svg"
+
+ border {
+ top: 10
+ left: 20
+ right: 20
+ bottom: 10
+ }
+
+ }
+
+ }
+
+}
diff --git a/res/skins/QMLDemo/InfoBarButton.qml b/res/skins/QMLDemo/InfoBarButton.qml
new file mode 100644
index 00000000000..c252b57066f
--- /dev/null
+++ b/res/skins/QMLDemo/InfoBarButton.qml
@@ -0,0 +1,71 @@
+import "." as Skin
+import Mixxx 0.1 as Mixxx
+import QtGraphicalEffects 1.12
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import "Theme"
+
+AbstractButton {
+ id: root
+
+ property string group // required
+ property string key // required
+ property alias foreground: foreground.data
+ property color normalColor: Theme.buttonNormalColor
+ property color activeColor // required
+ property color pressedColor: activeColor
+
+ states: [
+ State {
+ name: "pressed"
+ when: root.pressed
+
+ PropertyChanges {
+ target: colorOverlay
+ color: root.pressedColor
+ }
+
+ },
+ State {
+ name: "active"
+ when: root.checked && !root.pressed
+
+ PropertyChanges {
+ target: colorOverlay
+ color: root.activeColor
+ }
+
+ },
+ State {
+ name: "inactive"
+ when: !root.checked && !root.pressed
+
+ PropertyChanges {
+ target: colorOverlay
+ color: root.normalColor
+ }
+
+ }
+ ]
+
+ Mixxx.ControlProxy {
+ group: root.group
+ key: root.key
+ value: root.checked || root.down
+ }
+
+ Item {
+ id: foreground
+
+ anchors.fill: parent
+ }
+
+ ColorOverlay {
+ id: colorOverlay
+
+ anchors.fill: foreground
+ source: foreground
+ color: root.normalColor
+ }
+
+}
diff --git a/res/skins/QMLDemo/Knob.qml b/res/skins/QMLDemo/Knob.qml
new file mode 100644
index 00000000000..5d8acdc0c96
--- /dev/null
+++ b/res/skins/QMLDemo/Knob.qml
@@ -0,0 +1,38 @@
+import Mixxx.Controls 0.1 as MixxxControls
+import QtQuick 2.12
+import "Theme"
+
+MixxxControls.Knob {
+ id: root
+
+ property color color // required
+
+ implicitWidth: 56
+ implicitHeight: implicitWidth
+ arc: true
+ arcRadius: 20
+ arcColor: root.color
+ arcWidth: 2
+ angle: 117
+
+ background: Image {
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.right: parent.right
+ source: "images/knob.svg"
+ }
+
+ foreground: Item {
+ anchors.fill: parent
+
+ Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: root.width / 30
+ height: root.width / 7
+ y: parent.height / 4
+ color: root.color
+ }
+
+ }
+
+}
diff --git a/res/skins/QMLDemo/Library.qml b/res/skins/QMLDemo/Library.qml
index ee0ad35b48d..f8437c5813f 100644
--- a/res/skins/QMLDemo/Library.qml
+++ b/res/skins/QMLDemo/Library.qml
@@ -1,15 +1,19 @@
+import "." as Skin
import Qt.labs.qmlmodels 1.0
import QtQuick 2.12
import QtQuick.Controls 1.4
+import "Theme"
Item {
Rectangle {
- color: "#121213"
+ color: Theme.deckBackgroundColor
anchors.fill: parent
Text {
text: "Library Placeholder"
- color: "white"
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: Theme.deckTextColor
anchors.centerIn: parent
}
diff --git a/res/skins/QMLDemo/Mixer.qml b/res/skins/QMLDemo/Mixer.qml
new file mode 100644
index 00000000000..11ecd0390e0
--- /dev/null
+++ b/res/skins/QMLDemo/Mixer.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+
+Row {
+ id: mixer
+
+ property string leftDeckGroup // required
+ property string rightDeckGroup // required
+ property bool show4decks: false
+
+ EqColumn {
+ group: root.leftDeckGroup
+ }
+
+ MixerColumn {
+ width: 56
+ height: parent.height
+ group: root.leftDeckGroup
+ }
+
+ MixerColumn {
+ width: 56
+ height: parent.height
+ group: root.rightDeckGroup
+ }
+
+ EqColumn {
+ width: 56
+ height: parent.height
+ group: root.rightDeckGroup
+ }
+
+}
diff --git a/res/skins/QMLDemo/MixerColumn.qml b/res/skins/QMLDemo/MixerColumn.qml
index 94d18a13384..580bffc374f 100644
--- a/res/skins/QMLDemo/MixerColumn.qml
+++ b/res/skins/QMLDemo/MixerColumn.qml
@@ -1,69 +1,50 @@
-import Mixxx.Controls 0.1 as MixxxControls
+import "." as Skin
import QtQuick 2.12
import QtQuick.Layouts 1.11
+import "Theme"
Item {
id: root
- required property string group
+ property string group // required
- implicitWidth: 47
- implicitHeight: 150
+ Knob {
+ id: gainKnob
- ColumnLayout {
- MixxxControls.Knob {
- id: gainKnob
-
- Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
- width: 35
- height: width
- group: root.group
- key: "pregain"
- arc: true
- arcRadius: 15
- arcColor: "#b96300"
- arcWidth: 2
-
- background: Image {
- source: "../LateNight/palemoon/knobs/knob_bg_master.svg"
- width: gainKnob.width
- height: gainKnob.width / 7 * 6
- }
-
- foreground: Image {
- source: "../LateNight/palemoon/knobs/knob_indicator_regular_orange.svg"
- width: gainKnob.width
- height: gainKnob.width / 7 * 6
- }
-
- }
-
- MixxxControls.Slider {
- id: volumeSlider
-
- Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
- width: root.width
- height: 107
- group: root.group
- key: "volume"
- bar: true
- barColor: "#257b82"
- barMargin: 10
-
- handle: Image {
- source: "../LateNight/palemoon/sliders/knob_volume_deck.svg"
- width: 42
- height: 19
- }
-
- background: Image {
- width: volumeSlider.width
- height: volumeSlider.height
- source: "../LateNight/palemoon/sliders/slider_volume_deck.svg"
- }
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: width
+ group: root.group
+ key: "pregain"
+ color: Theme.gainKnobColor
+ }
- }
+ Slider {
+ id: volumeSlider
+
+ anchors.top: gainKnob.bottom
+ anchors.topMargin: 5
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: pflButton.top
+ group: root.group
+ key: "volume"
+ barColor: Theme.volumeSliderBarColor
+ bg: "images/slider_volume.svg"
+ }
+ Skin.ControlButton {
+ id: pflButton
+
+ group: root.group
+ key: "pfl"
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ text: "PFL"
+ activeColor: Theme.pflActiveButtonColor
+ checkable: true
}
}
diff --git a/res/skins/QMLDemo/Mixxx/Controls/Knob.qml b/res/skins/QMLDemo/Mixxx/Controls/Knob.qml
index 28bae664e85..c69bfb9f86f 100644
--- a/res/skins/QMLDemo/Mixxx/Controls/Knob.qml
+++ b/res/skins/QMLDemo/Mixxx/Controls/Knob.qml
@@ -32,22 +32,16 @@ Item {
key: root.key + "_set_default"
}
- Rectangle {
+ Item {
id: background
- width: root.width
- height: root.height
- anchors.centerIn: root
- color: "transparent"
+ anchors.fill: parent
}
- Rectangle {
+ Item {
id: foreground
- width: root.width
- height: root.height
- anchors.centerIn: root
- color: "transparent"
+ anchors.fill: parent
rotation: (control.parameter - (root.max - root.min) / 2) * 2 * root.angle
}
@@ -84,9 +78,9 @@ Item {
anchors.fill: root
onWheel: {
if (wheel.angleDelta.y < 0)
- control.parameter = control.parameter + 0.1;
+ control.parameter = Math.min(root.max, control.parameter + 0.1);
else
- control.parameter = control.parameter - 0.1;
+ control.parameter = Math.max(root.min, control.parameter - 0.1);
}
onDoubleClicked: resetcontrol.value = 1
onPressed: {
@@ -94,8 +88,9 @@ Item {
}
onPositionChanged: {
if (mousearea.pressed) {
- var dy = mousearea.posy - mouse.y;
- control.parameter += Math.max(Math.min(dy, 100), -100) / 100;
+ const dy = mousearea.posy - mouse.y;
+ let parameter = control.parameter + Math.max(Math.min(dy, 100), -100) / 100;
+ control.parameter = Math.max(root.min, Math.min(root.max, parameter));
mousearea.posy = mouse.y;
}
}
diff --git a/res/skins/QMLDemo/Mixxx/Controls/Spinny.qml b/res/skins/QMLDemo/Mixxx/Controls/Spinny.qml
index d95d0516a8d..07c8012cb7b 100644
--- a/res/skins/QMLDemo/Mixxx/Controls/Spinny.qml
+++ b/res/skins/QMLDemo/Mixxx/Controls/Spinny.qml
@@ -1,13 +1,14 @@
import Mixxx 0.1 as Mixxx
import QtQuick 2.12
+import QtQuick.Controls 2.12
Item {
id: root
- required property string group
+ property string group // required
property real rpm: 33
property bool indicatorVisible: true
- property alias indicatorDelegate: indicatorContainer.data
+ property alias indicator: indicatorContainer.contentItem
// Avoid animation short blinking of spinny during startup
Component.onCompleted: indicatorTransition.enabled = true
@@ -33,22 +34,17 @@ Item {
key: "playposition"
}
- Item {
+ Control {
id: indicatorContainer
anchors.fill: parent
visible: opacity > 0
- Item {
- anchors.fill: parent
-
- data: Rectangle {
- height: root.height / 2
- width: height / 12
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- }
-
+ contentItem: Rectangle {
+ height: root.height / 2
+ width: height / 12
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
}
transform: Rotation {
diff --git a/res/skins/QMLDemo/Mixxx/Controls/ToggleButton.qml b/res/skins/QMLDemo/Mixxx/Controls/ToggleButton.qml
deleted file mode 100644
index f029bcc642c..00000000000
--- a/res/skins/QMLDemo/Mixxx/Controls/ToggleButton.qml
+++ /dev/null
@@ -1,37 +0,0 @@
-import Mixxx 0.1 as Mixxx
-import QtQuick 2.12
-import QtQuick.Controls 2.12
-
-Item {
- id: root
-
- property alias group: control.group
- property alias key: control.key
- property alias icon: button.icon
- property alias background: button.background
- property alias state: buttonRect.state
- default property alias states: buttonRect.states
-
- Rectangle {
- id: buttonRect
-
- anchors.fill: parent
- color: "transparent"
-
- Button {
- id: button
-
- anchors.fill: parent
- onPressed: control.value ? control.value = 0 : control.value = 1
-
- Mixxx.ControlProxy {
- id: control
-
- onValueChanged: root.state = control.value
- }
-
- }
-
- }
-
-}
diff --git a/res/skins/QMLDemo/OrientationToggleButton.qml b/res/skins/QMLDemo/OrientationToggleButton.qml
new file mode 100644
index 00000000000..c255bf96b56
--- /dev/null
+++ b/res/skins/QMLDemo/OrientationToggleButton.qml
@@ -0,0 +1,92 @@
+import "." as Skin
+import Mixxx 0.1 as Mixxx
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+
+AbstractButton {
+ id: root
+
+ property string group // required
+ property string key // required
+ property alias orientation: control.value
+ property color color: "white"
+
+ implicitWidth: 56
+ implicitHeight: 26
+ onClicked: control.value = Math.trunc(3 * pressX / root.width)
+ states: [
+ State {
+ name: "left"
+ when: orientation == 0
+
+ PropertyChanges {
+ target: indicator
+ x: 0
+ }
+
+ },
+ State {
+ name: "right"
+ when: orientation == 2
+
+ PropertyChanges {
+ target: indicator
+ x: parent.width - width
+ }
+
+ },
+ State {
+ name: "mid"
+ when: orientation == 1
+
+ PropertyChanges {
+ target: indicator
+ x: parent.width / 2 - width / 2
+ }
+
+ }
+ ]
+
+ Mixxx.ControlProxy {
+ id: control
+
+ group: root.group
+ key: root.key
+ }
+
+ Item {
+ anchors.fill: root
+ anchors.leftMargin: 10
+ anchors.rightMargin: 10
+ anchors.topMargin: 2
+ anchors.bottomMargin: 2
+
+ Rectangle {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ height: 2
+ color: root.color
+ }
+
+ Rectangle {
+ id: indicator
+
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 5
+ width: 3
+ color: root.color
+
+ Behavior on x {
+ NumberAnimation {
+ duration: 150
+ }
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/res/skins/QMLDemo/Slider.qml b/res/skins/QMLDemo/Slider.qml
new file mode 100644
index 00000000000..be1786dee65
--- /dev/null
+++ b/res/skins/QMLDemo/Slider.qml
@@ -0,0 +1,32 @@
+import "." as Skin
+import Mixxx.Controls 0.1 as MixxxControls
+import QtQuick 2.12
+import "Theme"
+
+MixxxControls.Slider {
+ id: root
+
+ property alias fg: handleImage.source
+ property alias bg: backgroundImage.source
+
+ bar: true
+ barColor: Theme.sliderBarColor
+ barMargin: 10
+ implicitWidth: handleImage.implicitWidth + 10
+ implicitHeight: handleImage.implicitHeight + 10
+
+ handle: Image {
+ id: handleImage
+
+ anchors.top: parent.top
+ source: "images/slider_handle.svg"
+ }
+
+ background: Image {
+ id: backgroundImage
+
+ anchors.fill: parent
+ anchors.margins: 10
+ }
+
+}
diff --git a/res/skins/QMLDemo/Theme/Theme.qml b/res/skins/QMLDemo/Theme/Theme.qml
new file mode 100644
index 00000000000..1b9b678acbb
--- /dev/null
+++ b/res/skins/QMLDemo/Theme/Theme.qml
@@ -0,0 +1,37 @@
+import QtQuick 2.12
+pragma Singleton
+
+QtObject {
+ property color white: "#e3d7fb"
+ property color yellow: "#fca001"
+ property color red: "#ea2a4e"
+ property color blue: "#01dcfc"
+ property color green: "#85c85b"
+ property color lightGray: "#747474"
+ property color lightGray2: "#b0b0b0"
+ property color midGray: "#696969"
+ property color darkGray: "#0f0f0f"
+ property color darkGray2: "#2e2e2e"
+ property color eqHighColor: white
+ property color eqMidColor: white
+ property color eqLowColor: white
+ property color eqFxColor: red
+ property color bpmSliderBarColor: green
+ property color volumeSliderBarColor: blue
+ property color gainKnobColor: blue
+ property color crossfaderOrientationColor: lightGray
+ property color crossfaderBarColor: red
+ property color toolbarBackgroundColor: darkGray2
+ property color pflActiveButtonColor: blue
+ property color backgroundColor: "#1e1e20"
+ property color deckActiveColor: green
+ property color deckBackgroundColor: darkGray
+ property color deckLineColor: darkGray2
+ property color deckTextColor: lightGray2
+ property color buttonNormalColor: midGray
+ property color textColor: lightGray2
+ property color toolbarActiveColor: white
+ property string fontFamily: "Open Sans"
+ property int textFontPixelSize: 14
+ property int buttonFontPixelSize: 10
+}
diff --git a/res/skins/QMLDemo/Theme/qmldir b/res/skins/QMLDemo/Theme/qmldir
new file mode 100644
index 00000000000..5023b9dc1c4
--- /dev/null
+++ b/res/skins/QMLDemo/Theme/qmldir
@@ -0,0 +1 @@
+singleton Theme 0.1 Theme.qml
diff --git a/res/skins/QMLDemo/WaveformOverview.qml b/res/skins/QMLDemo/WaveformOverview.qml
index 8ed1da2f170..37690f74f94 100644
--- a/res/skins/QMLDemo/WaveformOverview.qml
+++ b/res/skins/QMLDemo/WaveformOverview.qml
@@ -1,11 +1,12 @@
import Mixxx 0.1 as Mixxx
import QtQuick 2.12
import QtQuick.Shapes 1.12
+import "Theme"
Item {
id: root
- required property string group
+ property string group // required
states: [
State {
@@ -119,14 +120,13 @@ Item {
id: waveformContainer
anchors.fill: parent
- color: "#121213"
+ color: Theme.deckBackgroundColor
Text {
anchors.centerIn: parent
- font.family: "Open Sans"
- font.bold: true
- font.pixelSize: 11
- color: "#777777"
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: Theme.deckTextColor
text: "Waveform Placeholder"
}
@@ -140,10 +140,9 @@ Item {
Text {
anchors.centerIn: parent
- font.family: "Open Sans"
- font.bold: true
- font.pixelSize: 11
- color: "#777777"
+ font.family: Theme.fontFamily
+ font.pixelSize: Theme.textFontPixelSize
+ color: Theme.deckTextColor
text: "Passthrough Enabled"
}
diff --git a/res/skins/QMLDemo/images/button.svg b/res/skins/QMLDemo/images/button.svg
new file mode 100644
index 00000000000..c7f76d1717e
--- /dev/null
+++ b/res/skins/QMLDemo/images/button.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/res/skins/QMLDemo/images/button_pressed.svg b/res/skins/QMLDemo/images/button_pressed.svg
new file mode 100644
index 00000000000..1c669f0ab31
--- /dev/null
+++ b/res/skins/QMLDemo/images/button_pressed.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/res/skins/QMLDemo/images/icon_passthrough.svg b/res/skins/QMLDemo/images/icon_passthrough.svg
new file mode 100644
index 00000000000..cd74c2b7f2d
--- /dev/null
+++ b/res/skins/QMLDemo/images/icon_passthrough.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/res/skins/QMLDemo/images/icon_quantize.svg b/res/skins/QMLDemo/images/icon_quantize.svg
new file mode 100644
index 00000000000..63d974c43c9
--- /dev/null
+++ b/res/skins/QMLDemo/images/icon_quantize.svg
@@ -0,0 +1,35 @@
+
+
diff --git a/res/skins/QMLDemo/images/knob.svg b/res/skins/QMLDemo/images/knob.svg
new file mode 100644
index 00000000000..d75a207454f
--- /dev/null
+++ b/res/skins/QMLDemo/images/knob.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/res/skins/QMLDemo/images/slider_bpm.svg b/res/skins/QMLDemo/images/slider_bpm.svg
new file mode 100644
index 00000000000..bdeb7176abb
--- /dev/null
+++ b/res/skins/QMLDemo/images/slider_bpm.svg
@@ -0,0 +1,1812 @@
+
+
diff --git a/res/skins/QMLDemo/images/slider_crossfader.svg b/res/skins/QMLDemo/images/slider_crossfader.svg
new file mode 100644
index 00000000000..4f9f28ad4cf
--- /dev/null
+++ b/res/skins/QMLDemo/images/slider_crossfader.svg
@@ -0,0 +1,360 @@
+
+
diff --git a/res/skins/QMLDemo/images/slider_handle.svg b/res/skins/QMLDemo/images/slider_handle.svg
new file mode 100644
index 00000000000..58d3f8ae294
--- /dev/null
+++ b/res/skins/QMLDemo/images/slider_handle.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/res/skins/QMLDemo/images/slider_handle_crossfader.svg b/res/skins/QMLDemo/images/slider_handle_crossfader.svg
new file mode 100644
index 00000000000..4ceec575bd2
--- /dev/null
+++ b/res/skins/QMLDemo/images/slider_handle_crossfader.svg
@@ -0,0 +1,163 @@
+
+
diff --git a/res/skins/QMLDemo/images/slider_volume.svg b/res/skins/QMLDemo/images/slider_volume.svg
new file mode 100644
index 00000000000..e9999d57630
--- /dev/null
+++ b/res/skins/QMLDemo/images/slider_volume.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/res/skins/QMLDemo/main.qml b/res/skins/QMLDemo/main.qml
index 275d50af2bd..1369972ccda 100644
--- a/res/skins/QMLDemo/main.qml
+++ b/res/skins/QMLDemo/main.qml
@@ -1,13 +1,17 @@
+import "." as Skin
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.11
+import "Theme"
Rectangle {
id: root
+ property alias show4decks: show4DecksButton.checked
+
width: 1920
height: 1080
- color: "#1e1e20"
+ color: Theme.backgroundColor
visible: true
Column {
@@ -19,165 +23,59 @@ Rectangle {
width: parent.width
height: 36
- color: "#151517"
- border.color: "#020202"
- border.width: 1
+ color: Theme.toolbarBackgroundColor
radius: 1
Row {
padding: 5
spacing: 5
- Button {
- id: decksCDToggle
-
- width: 100
- height: 26
- text: "4 DECKS"
- font.family: "Open Sans"
- font.bold: true
- font.pixelSize: 11
- onClicked: decksCD.stateHidden = !decksCD.stateHidden
- states: [
- State {
- when: decksCD.stateHidden
-
- PropertyChanges {
- target: decksCDToggle
- background.color: "#151517"
- contentItem.color: "#777777"
- }
-
- PropertyChanges {
- target: decksCDToggleBgImage
- source: "../LateNight/palemoon/buttons/btn___active.svg"
- }
-
- },
- State {
- when: !decksCD.stateHidden
-
- PropertyChanges {
- target: decksCDToggle
- background.color: "#777777"
- contentItem.color: "#000000"
- }
-
- PropertyChanges {
- target: decksCDToggleBgImage
- source: "../LateNight/palemoon/buttons/btn__.svg"
- }
-
- }
- ]
-
- contentItem: Text {
- text: decksCDToggle.text
- font: decksCDToggle.font
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- }
-
- background: Rectangle {
- anchors.fill: parent
- border.width: 2
-
- Image {
- id: decksCDToggleBgImage
-
- anchors.fill: parent
- }
-
- }
+ Skin.Button {
+ id: show4DecksButton
+ text: "4 Decks"
+ activeColor: Theme.white
+ checkable: true
}
}
}
- DeckRow {
- id: decksAB
+ Skin.DeckRow {
+ id: decks12
- width: root.width
- height: 180
- leftDeck: "[Channel1]"
- rightDeck: "[Channel2]"
+ leftDeckGroup: "[Channel1]"
+ rightDeckGroup: "[Channel2]"
+ width: parent.width - 10
+ x: 5
}
- DeckRow {
- id: decksCD
+ Skin.CrossfaderRow {
+ id: crossfader
- property bool stateHidden: true
+ crossfaderWidth: decks12.mixer.width
+ width: parent.width - 10
+ x: 5
+ }
- function toggle() {
- stateHidden = !stateHidden;
- }
+ Skin.DeckRow {
+ id: decks34
- width: root.width
- height: 180
- leftDeck: "[Channel3]"
- rightDeck: "[Channel4]"
- states: [
- State {
- when: !decksCD.stateHidden
-
- PropertyChanges {
- target: decksCD
- opacity: 1
- visible: true
- }
-
- },
- State {
- when: decksCD.stateHidden
-
- PropertyChanges {
- target: decksCD
- opacity: 0
- visible: false
- }
+ leftDeckGroup: "[Channel3]"
+ rightDeckGroup: "[Channel4]"
+ width: parent.width - 10
+ x: 5
- }
- ]
- transitions: [
- Transition {
- enabled: !decksCD.stateHidden
-
- SequentialAnimation {
- NumberAnimation {
- target: decksCD
- property: "opacity"
- duration: 150
- }
-
- PropertyAction {
- target: decksCD
- property: "visible"
- }
-
- }
-
- },
- Transition {
- enabled: decksCD.stateHidden
-
- SequentialAnimation {
- PropertyAction {
- target: decksCD
- property: "visible"
- }
-
- NumberAnimation {
- target: decksCD
- property: "opacity"
- duration: 150
- }
-
- }
+ states: Skin.HiddenState {
+ when: !root.show4decks
+ target: decks34
+ }
+
+ transitions: Skin.HiddenTransition {
+ target: decks34
+ }
- }
- ]
}
Library {
diff --git a/src/skin/qml/qmlcontrolproxy.h b/src/skin/qml/qmlcontrolproxy.h
index 8ecedee1f62..1e62590b0ee 100644
--- a/src/skin/qml/qmlcontrolproxy.h
+++ b/src/skin/qml/qmlcontrolproxy.h
@@ -14,14 +14,11 @@ namespace qml {
class QmlControlProxy : public QObject, public QQmlParserStatus {
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
- // The REQUIRED flag only exists in Qt 5.14 and later.
-#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
- Q_PROPERTY(QString group READ getGroup WRITE setGroup NOTIFY groupChanged REQUIRED)
- Q_PROPERTY(QString key READ getKey WRITE setKey NOTIFY keyChanged REQUIRED)
-#else
+ // TODO: The REQUIRED flag only exists in Qt 5.14 and later. Once we
+ // require that as minimum dependency, add it to the group and key
+ // properties.
Q_PROPERTY(QString group READ getGroup WRITE setGroup NOTIFY groupChanged)
Q_PROPERTY(QString key READ getKey WRITE setKey NOTIFY keyChanged)
-#endif
Q_PROPERTY(QString keyValid READ isKeyValid NOTIFY keyValidChanged)
Q_PROPERTY(QString initialized READ isInitialized NOTIFY initializedChanged)
Q_PROPERTY(double value READ getValue WRITE setValue NOTIFY valueChanged)