diff --git a/build/depends.py b/build/depends.py
index 3cafd41f9af..ac5e778feee 100644
--- a/build/depends.py
+++ b/build/depends.py
@@ -776,6 +776,7 @@ def sources(self, build):
"src/preferences/effectsettingsmodel.cpp",
"src/preferences/broadcastprofile.cpp",
"src/preferences/upgrade.cpp",
+ "src/preferences/hotcuecolorpalettesettings.cpp",
"src/preferences/dlgpreferencepage.cpp",
"src/effects/effectmanifest.cpp",
@@ -912,6 +913,8 @@ def sources(self, build):
"src/controllers/softtakeover.cpp",
"src/controllers/keyboard/keyboardeventfilter.cpp",
"src/controllers/colorjsproxy.cpp",
+ "src/controllers/colormapper.cpp",
+ "src/controllers/colormapperjsproxy.cpp",
"src/main.cpp",
"src/mixxx.cpp",
@@ -1254,6 +1257,7 @@ def sources(self, build):
"src/util/movinginterquartilemean.cpp",
"src/util/console.cpp",
"src/util/color/color.cpp",
+ "src/util/color/colorpalette.cpp",
"src/util/db/dbconnection.cpp",
"src/util/db/dbconnectionpool.cpp",
"src/util/db/dbconnectionpooler.cpp",
@@ -1280,8 +1284,7 @@ def sources(self, build):
"src/util/desktophelper.cpp",
"src/util/widgetrendertimer.cpp",
"src/util/workerthread.cpp",
- "src/util/workerthreadscheduler.cpp",
- "src/util/color/predefinedcolor.cpp"
+ "src/util/workerthreadscheduler.cpp"
]
proto_args = {
diff --git a/res/controllers/Roland_DJ-505-scripts.js b/res/controllers/Roland_DJ-505-scripts.js
index e2600dacbaa..25efbbfb523 100644
--- a/res/controllers/Roland_DJ-505-scripts.js
+++ b/res/controllers/Roland_DJ-505-scripts.js
@@ -941,17 +941,24 @@ DJ505.PadColor = {
DIM_MODIFIER: 0x10,
};
-DJ505.PadColorMap = [
- DJ505.PadColor.OFF,
- DJ505.PadColor.RED,
- DJ505.PadColor.GREEN,
- DJ505.PadColor.BLUE,
- DJ505.PadColor.YELLOW,
- DJ505.PadColor.CELESTE,
- DJ505.PadColor.PURPLE,
- DJ505.PadColor.APRICOT,
- DJ505.PadColor.WHITE,
-];
+DJ505.PadColorMap = new ColorMapper({
+ '#FFCC0000': DJ505.PadColor.RED,
+ '#FFCC4400': DJ505.PadColor.CORAL,
+ '#FFCC8800': DJ505.PadColor.ORANGE,
+ '#FFCCCC00': DJ505.PadColor.YELLOW,
+ '#FF88CC00': DJ505.PadColor.GREEN,
+ '#FF00CC00': DJ505.PadColor.APPLEGREEN,
+ '#FF00CC88': DJ505.PadColor.AQUAMARINE,
+ '#FF00CCCC': DJ505.PadColor.TURQUOISE,
+ '#FF0088CC': DJ505.PadColor.CELESTE,
+ '#FF0000CC': DJ505.PadColor.BLUE,
+ '#FF4400CC': DJ505.PadColor.AZURE,
+ '#FF8800CC': DJ505.PadColor.PURPLE,
+ '#FFCC00CC': DJ505.PadColor.MAGENTA,
+ '#FFCC0044': DJ505.PadColor.RED,
+ '#FFFFCCCC': DJ505.PadColor.APRICOT,
+ '#FFFFFFFF': DJ505.PadColor.WHITE,
+});
DJ505.PadSection = function (deck, offset) {
// TODO: Add support for missing modes (flip, slicer, slicerloop)
@@ -1190,7 +1197,6 @@ DJ505.HotcueMode = function (deck, offset) {
this.ledControl = DJ505.PadMode.HOTCUE;
this.color = DJ505.PadColor.WHITE;
- var hotcueColors = [this.color].concat(DJ505.PadColorMap.slice(1));
this.pads = new components.ComponentContainer();
for (var i = 0; i <= 7; i++) {
this.pads[i] = new components.HotcueButton({
@@ -1202,7 +1208,7 @@ DJ505.HotcueMode = function (deck, offset) {
group: deck.currentDeck,
on: this.color,
off: this.color + DJ505.PadColor.DIM_MODIFIER,
- colors: hotcueColors,
+ colorMapper: DJ505.PadColorMap,
outConnect: false,
});
}
@@ -1226,7 +1232,6 @@ DJ505.CueLoopMode = function (deck, offset) {
this.ledControl = DJ505.PadMode.HOTCUE;
this.color = DJ505.PadColor.BLUE;
- var cueloopColors = [this.color].concat(DJ505.PadColorMap.slice(1));
this.PerformancePad = function(n) {
this.midi = [0x94 + offset, 0x14 + n];
this.number = n + 1;
@@ -1241,7 +1246,7 @@ DJ505.CueLoopMode = function (deck, offset) {
group: deck.currentDeck,
on: this.color,
off: this.color + DJ505.PadColor.DIM_MODIFIER,
- colors: cueloopColors,
+ colorMapper: DJ505.PadColorMap,
outConnect: false,
unshift: function() {
this.input = function (channel, control, value, status, group) {
@@ -1492,14 +1497,13 @@ DJ505.PitchPlayMode = function (deck, offset) {
this.color = DJ505.PadColor.GREEN;
this.cuepoint = 1;
this.range = PitchPlayRange.MID;
- var pitchplayColors = [this.color].concat(DJ505.PadColorMap.slice(1));
this.PerformancePad = function(n) {
this.midi = [0x94 + offset, 0x14 + n];
this.number = n + 1;
this.on = this.color + DJ505.PadColor.DIM_MODIFIER;
- this.colors = pitchplayColors;
- this.colorIdKey = 'hotcue_' + this.number + '_color_id';
+ this.colorMapper = DJ505.PadColorMap;
+ this.colorKey = 'hotcue_' + this.number + '_color';
components.Button.call(this);
};
this.PerformancePad.prototype = new components.Button({
@@ -1510,10 +1514,10 @@ DJ505.PitchPlayMode = function (deck, offset) {
mode: this,
outConnect: false,
off: DJ505.PadColor.OFF,
- outputColor: function(id) {
+ outputColor: function(colorCode) {
// For colored hotcues (shifted only)
- var color = this.colors[id];
- this.send((this.mode.cuepoint === this.number) ? color : (color + DJ505.PadColor.DIM_MODIFIER));
+ var midiColor = this.colorMapper.getNearestValue(colorCode);
+ this.send((this.mode.cuepoint === this.number) ? midiColor : (midiColor + DJ505.PadColor.DIM_MODIFIER));
},
unshift: function() {
this.outKey = "pitch_adjust";
@@ -1561,8 +1565,8 @@ DJ505.PitchPlayMode = function (deck, offset) {
this.outKey = "hotcue_" + this.number + "_enabled";
this.output = function (value, group, control) {
var outval = this.outValueScale(value);
- if (this.colorIdKey !== undefined && outval !== this.off) {
- this.outputColor(engine.getValue(this.group, this.colorIdKey));
+ if (this.colorKey !== undefined && outval !== this.off) {
+ this.outputColor(engine.getValue(this.group, this.colorKey));
} else {
this.send(DJ505.PadColor.OFF);
}
@@ -1572,13 +1576,13 @@ DJ505.PitchPlayMode = function (deck, offset) {
var previous_cuepoint = this.mode.cuepoint;
this.mode.cuepoint = this.number;
this.mode.pads[previous_cuepoint - 1].trigger();
- this.outputColor(engine.getValue(this.group, this.colorIdKey));
+ this.outputColor(engine.getValue(this.group, this.colorKey));
}
};
this.connect = function() {
components.Button.prototype.connect.call(this); // call parent connect
- if (undefined !== this.group && this.colorIdKey !== undefined) {
- this.connections[1] = engine.makeConnection(this.group, this.colorIdKey, function (id) {
+ if (undefined !== this.group && this.colorKey !== undefined) {
+ this.connections[1] = engine.makeConnection(this.group, this.colorKey, function (id) {
if (engine.getValue(this.group, this.outKey)) {
this.outputColor(id);
}
diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js
index 7bb5c009578..c4685e75ea5 100644
--- a/res/controllers/midi-components-0.0.js
+++ b/res/controllers/midi-components-0.0.js
@@ -294,11 +294,8 @@
print('ERROR: No hotcue number specified for new HotcueButton.');
return;
}
- if (options.colors !== undefined || options.sendRGB !== undefined) {
- this.colorIdKey = 'hotcue_' + options.number + '_color_id';
- if (options.colors === undefined) {
- options.colors = color.predefinedColorsList();
- }
+ if (options.colorMapper !== undefined || options.sendRGB !== undefined) {
+ this.colorKey = 'hotcue_' + options.number + '_color';
}
this.number = options.number;
this.outKey = 'hotcue_' + this.number + '_enabled';
@@ -312,8 +309,8 @@
this.inKey = 'hotcue_' + this.number + '_clear';
},
getColor: function() {
- if (this.colorIdKey !== undefined) {
- return color.predefinedColorFromId(engine.getValue(this.group,this.colorIdKey));
+ if (this.colorKey !== undefined) {
+ return color.colorFromHexCode(engine.getValue(this.group,this.colorKey));
} else {
return null;
}
@@ -324,32 +321,29 @@
// and there is no hotcueColor for turning the LED
// off. So the `send()` function is responsible for turning the
// actual LED off.
- if (this.colorIdKey !== undefined && outval !== this.off) {
- this.outputColor(engine.getValue(this.group, this.colorIdKey));
+ if (this.colorKey !== undefined && outval !== this.off) {
+ this.outputColor(engine.getValue(this.group, this.colorKey));
} else {
this.send(outval);
}
},
- outputColor: function (id) {
- var color = this.colors[id];
- if (color instanceof Array) {
- if (color.length !== 3) {
- print("ERROR: invalid color array for id: " + id);
- return;
- }
+ outputColor: function (colorCode) {
+ if (this.colorMapper !== undefined) {
+ var nearestColorValue = this.colorMapper.getNearestValue(colorCode);
+ print("COLOR = "+nearestColorValue);
+ this.send(nearestColorValue);
+ } else {
if (this.sendRGB === undefined) {
print("ERROR: no function defined for sending RGB colors");
return;
}
- this.sendRGB(color);
- } else if (typeof color === 'number') {
- this.send(color);
+ this.sendRGB(color.colorFromHexCode(colorCode));
}
},
connect: function() {
Button.prototype.connect.call(this); // call parent connect
- if (undefined !== this.group && this.colorIdKey !== undefined) {
- this.connections[1] = engine.makeConnection(this.group, this.colorIdKey, function (id) {
+ if (undefined !== this.group && this.colorKey !== undefined) {
+ this.connections[1] = engine.makeConnection(this.group, this.colorKey, function (id) {
if (engine.getValue(this.group,this.outKey)) {
this.outputColor(id);
}
diff --git a/res/schema.xml b/res/schema.xml
index d5babba85aa..4940729fe1c 100644
--- a/res/schema.xml
+++ b/res/schema.xml
@@ -480,5 +480,30 @@ METADATA
position INTEGER
);
-
+
+
+
+ Convert the PredefinedColor id to the actual RGBA value.
+
+
+
+ UPDATE cues SET color=4278190080 WHERE color=0;
+
+ UPDATE cues SET color=4291103240 WHERE color=1;
+
+ UPDATE cues SET color=4281515588 WHERE color=2;
+
+ UPDATE cues SET color=4278207743 WHERE color=3;
+
+ UPDATE cues SET color=4294496768 WHERE color=4;
+
+ UPDATE cues SET color=4282569972 WHERE color=5;
+
+ UPDATE cues SET color=4289659084 WHERE color=6;
+
+ UPDATE cues SET color=4294747863 WHERE color=7;
+
+ UPDATE cues SET color=4294111999 WHERE color=8;
+
+
diff --git a/res/skins/Deere/hotcue_button.xml b/res/skins/Deere/hotcue_button.xml
index f5e47776226..19ba4bb08b4 100644
--- a/res/skins/Deere/hotcue_button.xml
+++ b/res/skins/Deere/hotcue_button.xml
@@ -46,8 +46,8 @@
false
- ,hotcue__color_id
- highlight
+ ,hotcue__color
+ backgroundColorRgba
diff --git a/res/skins/Deere/style.qss b/res/skins/Deere/style.qss
index c89a5eca6b4..944870dd38d 100644
--- a/res/skins/Deere/style.qss
+++ b/res/skins/Deere/style.qss
@@ -1583,7 +1583,6 @@ WPushButton:hover {
/*"Pressed" state*/
WPushButton[value="1"],
WPushButton[value="2"] {
- /*color: #FDFDFD;*/
color: #FDFDFD;
background-color: #006596;
border: 0px solid #006596;
@@ -1596,129 +1595,17 @@ WPushButton[value="2"]:hover {
border: 0px solid #0080BE;
}
-/* Hotcue Color: No Color */
-#HotcueButton[value="1"][highlight="0"],
-#HotcueButton[value="2"][highlight="0"] {
- background-color: #006596;
-}
-
-#HotcueButton[value="1"][highlight="0"]:hover,
-#HotcueButton[value="2"][highlight="0"]:hover {
- background-color: #0080BE;
-}
-
-/* Hotcue Color: Red */
-#HotcueButton[value="1"][highlight="1"],
-#HotcueButton[value="2"][highlight="1"] {
- background-color: #c50a08;
-}
-
-#HotcueButton[value="1"][highlight="1"]:hover,
-#HotcueButton[value="2"][highlight="1"]:hover {
- background-color: #e50c08;
-}
-
-/* Hotcue Color: Green */
-#HotcueButton[value="1"][highlight="2"],
-#HotcueButton[value="2"][highlight="2"] {
- background-color: #32be44;
-}
-
-#HotcueButton[value="1"][highlight="2"]:hover,
-#HotcueButton[value="2"][highlight="2"]:hover {
- background-color: #52de64;
-}
-
-/* Hotcue Color: Blue */
-#HotcueButton[value="1"][highlight="3"],
-#HotcueButton[value="2"][highlight="3"] {
- background-color: #0044ff;
-}
-
-#HotcueButton[value="1"][highlight="3"]:hover,
-#HotcueButton[value="2"][highlight="3"]:hover {
- background-color: #0064ff;
-}
-
-/* Hotcue Color: Yellow */
-#HotcueButton[value="1"][highlight="4"],
-#HotcueButton[value="2"][highlight="4"] {
- color: #4B4B4B;
- background-color: #f8d200;
-}
-
-#HotcueButton[value="1"][highlight="4"]:hover,
-#HotcueButton[value="2"][highlight="4"]:hover {
- color: #4B4B4B;
- background-color: #f8f200;
-}
-
-/* Hotcue Color: Celeste */
-#HotcueButton[value="1"][highlight="5"],
-#HotcueButton[value="2"][highlight="5"] {
- color: #4B4B4B;
- background-color: #42d4f4;
+#HotcueButton {
+ qproperty-shouldHighlightBackgroundOnHover: true;
}
-#HotcueButton[value="1"][highlight="5"]:hover,
-#HotcueButton[value="2"][highlight="5"]:hover {
- color: #4B4B4B;
- background-color: #62f4f4;
-}
-
-/* Hotcue Color: Purple */
-#HotcueButton[value="1"][highlight="6"],
-#HotcueButton[value="2"][highlight="6"] {
- background-color: #af00cc;
-}
-
-#HotcueButton[value="1"][highlight="6"]:hover,
-#HotcueButton[value="2"][highlight="6"]:hover {
- background-color: #cf00ec;
-}
-
-/* Hotcue Color: Pink */
-#HotcueButton[value="1"][highlight="7"],
-#HotcueButton[value="2"][highlight="7"] {
- color: #4B4B4B;
- background-color: #fca6d7;
-}
-
-#HotcueButton[value="1"][highlight="7"]:hover,
-#HotcueButton[value="2"][highlight="7"]:hover {
- color: #4B4B4B;
- background-color: #fcc6f7;
-}
-
-/* Hotcue Color: White */
-#HotcueButton[value="1"][highlight="8"],
-#HotcueButton[value="2"][highlight="8"] {
- color: #4B4B4B;
- background-color: #f2f2ff;
-}
-
-#HotcueButton[value="1"][highlight="8"]:hover,
-#HotcueButton[value="2"][highlight="8"]:hover {
- color: #4B4B4B;
- background-color: #ffffff;
-}
-
-/*"Enabled" state, e.g. for recording status
- 0 -- disconnected / off
- 1 -- connecting / enabling
- 2 -- connected / enabled
-WPushButton[value="2"] {
+#HotcueButton[backgroundIsDark=true][hasBackgroundColor=true] {
color: #FDFDFD;
- background-color: #4B4B4B;
- border: 0px solid #006596;
}
-WPushButton[value="2"]:hover {
- color: #FDFDFD;
- background-color: #4B4B4B;
- border: 0px solid #0080BE;
+#HotcueButton[backgroundIsDark=false][hasBackgroundColor=true] {
+ color: #1f1e1e;
}
-*/
#PlayToggle[value="0"] {
image: url(skin:/icon/ic_play_48px.svg) no-repeat center center;
diff --git a/res/skins/LateNight/button_hotcue.xml b/res/skins/LateNight/button_hotcue.xml
index 481b1ab72d7..88b031eabb2 100644
--- a/res/skins/LateNight/button_hotcue.xml
+++ b/res/skins/LateNight/button_hotcue.xml
@@ -28,8 +28,8 @@
false
- ,hotcue__color_id
- highlight
+ ,hotcue__color
+ backgroundColorRgba
diff --git a/res/skins/LateNight/style.qss b/res/skins/LateNight/style.qss
index b2101872d4e..1627fd42022 100644
--- a/res/skins/LateNight/style.qss
+++ b/res/skins/LateNight/style.qss
@@ -356,50 +356,6 @@ QHeaderView::down-arrow {
#SpecialCueButton[displayValue="1"] {
background-color: #0000D4;
}
-/* Hotcue Color: Red
- this is also the default color if Auto-Color
- in Preferences > Decks is Off */
-#HotcueButton[displayValue="1"][highlight="0"],
-#HotcueButton[displayValue="2"][highlight="0"],
-#HotcueButton[displayValue="1"][highlight="1"],
-#HotcueButton[displayValue="2"][highlight="1"] {
- background-color: #db0000;
-}
-/* Hotcue Color: Green */
-#HotcueButton[displayValue="1"][highlight="2"],
-#HotcueButton[displayValue="2"][highlight="2"] {
- background-color: #32be44;
-}
-/* Hotcue Color: Blue */
-#HotcueButton[displayValue="1"][highlight="3"],
-#HotcueButton[displayValue="2"][highlight="3"] {
- background-color: #0044ff;
-}
-/* Hotcue Color: Yellow */
-#HotcueButton[displayValue="1"][highlight="4"],
-#HotcueButton[displayValue="2"][highlight="4"] {
- background-color: #f8d200;
-}
-/* Hotcue Color: Celeste */
-#HotcueButton[displayValue="1"][highlight="5"],
-#HotcueButton[displayValue="2"][highlight="5"] {
- background-color: #42d4f4;
-}
-/* Hotcue Color: Purple */
-#HotcueButton[displayValue="1"][highlight="6"],
-#HotcueButton[displayValue="2"][highlight="6"] {
- background-color: #af00cc;
-}
-/* Hotcue Color: Pink */
-#HotcueButton[displayValue="1"][highlight="7"],
-#HotcueButton[displayValue="2"][highlight="7"] {
- background-color: #fca6d7;
-}
-/* Hotcue Color: White */
-#HotcueButton[displayValue="1"][highlight="8"],
-#HotcueButton[displayValue="2"][highlight="8"] {
- background-color: #f2f2ff;
-}
#BeatgridButtonsToggle {
image: url(skin:/buttons/btn_beatgrid_buttons_toggle.svg) no-repeat center center;
diff --git a/res/skins/Shade/btn/btn_hotcue_1.png b/res/skins/Shade/btn/btn_hotcue_1.png
index bbcc063c525..86f572261d9 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_1.png and b/res/skins/Shade/btn/btn_hotcue_1.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_1_down.png b/res/skins/Shade/btn/btn_hotcue_1_down.png
deleted file mode 100644
index b2b78e0b2cd..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_1_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_1_over.png b/res/skins/Shade/btn/btn_hotcue_1_over.png
deleted file mode 100644
index 079f132f1da..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_1_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_1_overdown.png b/res/skins/Shade/btn/btn_hotcue_1_overdown.png
deleted file mode 100644
index 78137be3a27..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_1_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_2.png b/res/skins/Shade/btn/btn_hotcue_2.png
index f085b9f63a3..6c93b48fe2e 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_2.png and b/res/skins/Shade/btn/btn_hotcue_2.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_2_down.png b/res/skins/Shade/btn/btn_hotcue_2_down.png
deleted file mode 100644
index 93b227bafe4..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_2_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_2_over.png b/res/skins/Shade/btn/btn_hotcue_2_over.png
deleted file mode 100644
index 248fb1ea957..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_2_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_2_overdown.png b/res/skins/Shade/btn/btn_hotcue_2_overdown.png
deleted file mode 100644
index a89346b0e30..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_2_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_3.png b/res/skins/Shade/btn/btn_hotcue_3.png
index 2ccd932a164..b6494126f05 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_3.png and b/res/skins/Shade/btn/btn_hotcue_3.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_3_down.png b/res/skins/Shade/btn/btn_hotcue_3_down.png
deleted file mode 100644
index 96b06c76596..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_3_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_3_over.png b/res/skins/Shade/btn/btn_hotcue_3_over.png
deleted file mode 100644
index bc39f10974a..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_3_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_3_overdown.png b/res/skins/Shade/btn/btn_hotcue_3_overdown.png
deleted file mode 100644
index 87587d95efa..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_3_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_4.png b/res/skins/Shade/btn/btn_hotcue_4.png
index d973f1eb850..f3c47cc7ef8 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_4.png and b/res/skins/Shade/btn/btn_hotcue_4.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_4_down.png b/res/skins/Shade/btn/btn_hotcue_4_down.png
deleted file mode 100644
index da33bba1f70..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_4_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_4_over.png b/res/skins/Shade/btn/btn_hotcue_4_over.png
deleted file mode 100644
index 944eef1c632..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_4_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_4_overdown.png b/res/skins/Shade/btn/btn_hotcue_4_overdown.png
deleted file mode 100644
index 6dd65f063cc..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_4_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_5.png b/res/skins/Shade/btn/btn_hotcue_5.png
index dab5e3ce7b0..002cf0cc546 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_5.png and b/res/skins/Shade/btn/btn_hotcue_5.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_5_down.png b/res/skins/Shade/btn/btn_hotcue_5_down.png
deleted file mode 100644
index b893778f314..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_5_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_5_over.png b/res/skins/Shade/btn/btn_hotcue_5_over.png
deleted file mode 100644
index 6b9e23bedb8..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_5_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_5_overdown.png b/res/skins/Shade/btn/btn_hotcue_5_overdown.png
deleted file mode 100644
index 8eaf2454685..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_5_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_6.png b/res/skins/Shade/btn/btn_hotcue_6.png
index be5e45c35f8..dffdf0b39c3 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_6.png and b/res/skins/Shade/btn/btn_hotcue_6.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_6_down.png b/res/skins/Shade/btn/btn_hotcue_6_down.png
deleted file mode 100644
index 22a37ba05d8..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_6_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_6_over.png b/res/skins/Shade/btn/btn_hotcue_6_over.png
deleted file mode 100644
index 9e71774a01b..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_6_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_6_overdown.png b/res/skins/Shade/btn/btn_hotcue_6_overdown.png
deleted file mode 100644
index 3dc5b66bd29..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_6_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_7.png b/res/skins/Shade/btn/btn_hotcue_7.png
index f0821440d8c..998978cde5e 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_7.png and b/res/skins/Shade/btn/btn_hotcue_7.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_7_down.png b/res/skins/Shade/btn/btn_hotcue_7_down.png
deleted file mode 100644
index c6da80d83a1..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_7_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_7_over.png b/res/skins/Shade/btn/btn_hotcue_7_over.png
deleted file mode 100644
index b69e204f631..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_7_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_7_overdown.png b/res/skins/Shade/btn/btn_hotcue_7_overdown.png
deleted file mode 100644
index 6090eb34550..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_7_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_8.png b/res/skins/Shade/btn/btn_hotcue_8.png
index d4261196257..36542964c2e 100644
Binary files a/res/skins/Shade/btn/btn_hotcue_8.png and b/res/skins/Shade/btn/btn_hotcue_8.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_8_down.png b/res/skins/Shade/btn/btn_hotcue_8_down.png
deleted file mode 100644
index 9644ffd1ca1..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_8_down.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_8_over.png b/res/skins/Shade/btn/btn_hotcue_8_over.png
deleted file mode 100644
index 62eee604366..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_8_over.png and /dev/null differ
diff --git a/res/skins/Shade/btn/btn_hotcue_8_overdown.png b/res/skins/Shade/btn/btn_hotcue_8_overdown.png
deleted file mode 100644
index 3f67c1fb925..00000000000
Binary files a/res/skins/Shade/btn/btn_hotcue_8_overdown.png and /dev/null differ
diff --git a/res/skins/Shade/deck_hotcue_button.xml b/res/skins/Shade/deck_hotcue_button.xml
index 69c10a0fac1..f45560d2555 100644
--- a/res/skins/Shade/deck_hotcue_button.xml
+++ b/res/skins/Shade/deck_hotcue_button.xml
@@ -8,13 +8,13 @@
true
0
- skin:/btn/btn_hotcue__down.png
+ skin:/btn/btn_hotcue_.png
skin:/btn/btn_hotcue_.png
1
- skin:/btn/btn_hotcue__overdown.png
- skin:/btn/btn_hotcue__over.png
+ skin:/btn/btn_hotcue_.png
+ skin:/btn/btn_hotcue_.png
[Channel],hotcue__activate
@@ -33,8 +33,8 @@
false
- [Channel],hotcue__color_id
- highlight
+ [Channel],hotcue__color
+ backgroundColorRgba
diff --git a/res/skins/Shade/style.qss b/res/skins/Shade/style.qss
index 158e25eb970..07da25f2396 100644
--- a/res/skins/Shade/style.qss
+++ b/res/skins/Shade/style.qss
@@ -553,47 +553,6 @@ QPushButton#pushButtonRepeatPlaylist {
}
/* AutoDJ button icons */
-/* Hotcue Color: No Color */
-#HotcueButton[highlight="0"] {
- background-color: #fd0564;
-}
-
-/* Hotcue Color: Red */
-#HotcueButton[highlight="1"] {
- background-color: #c50a08;
-}
-
-/* Hotcue Color: Green */
-#HotcueButton[highlight="2"] {
- background-color: #32be44;
-}
-
-/* Hotcue Color: Blue */
-#HotcueButton[highlight="3"] {
- background-color: #0044ff;
-}
-
-/* Hotcue Color: Yellow */
-#HotcueButton[highlight="4"] {
- background-color: #f8d200;
-}
-
-/* Hotcue Color: Celeste */
-#HotcueButton[highlight="5"] {
- background-color: #42d4f4;
-}
-
-/* Hotcue Color: Purple */
-#HotcueButton[highlight="6"] {
- background-color: #af00cc;
-}
-
-/* Hotcue Color: Pink */
-#HotcueButton[highlight="7"] {
- background-color: #fca6d7;
-}
-
-/* Hotcue Color: White */
-#HotcueButton[highlight="8"] {
- background-color: #f2f2ff;
+#HotcueButton {
+ background-color: #aab2b7;
}
diff --git a/res/skins/Shade/style_dark.qss b/res/skins/Shade/style_dark.qss
index fda2ce766cb..f9f10fc77fe 100644
--- a/res/skins/Shade/style_dark.qss
+++ b/res/skins/Shade/style_dark.qss
@@ -83,8 +83,3 @@ WLibrary QPushButton {
WLibrary QRadioButton::indicator:checked {
background: url(skin:/btn/btn_lib_radio_button_on_dark.svg) center center;
}
-
-/* Hotcue Color: No Color */
-#HotcueButton[highlight="0"] {
- background-color: #b39a00;
-}
diff --git a/res/skins/Shade/style_summer_sunset.qss b/res/skins/Shade/style_summer_sunset.qss
index 903adc42713..e3d04bed986 100644
--- a/res/skins/Shade/style_summer_sunset.qss
+++ b/res/skins/Shade/style_summer_sunset.qss
@@ -71,8 +71,3 @@ WLibrary QPushButton {
QPushButton#pushButtonAnalyze:hover {
border: 1px solid #52F904;
}
-
-/* Hotcue Color: No Color */
-#HotcueButton[highlight="0"] {
- background-color: #52f904;
-}
diff --git a/res/skins/Tango/button_hotcue_deck.xml b/res/skins/Tango/button_hotcue_deck.xml
index bb1009dbf42..eb0785f234c 100644
--- a/res/skins/Tango/button_hotcue_deck.xml
+++ b/res/skins/Tango/button_hotcue_deck.xml
@@ -38,8 +38,8 @@ Variables:
false
- ,hotcue__color_id
- highlight
+ ,hotcue__color
+ backgroundColorRgba
diff --git a/res/skins/Tango/style.qss b/res/skins/Tango/style.qss
index dbde02e6c39..0b5b879dc8e 100644
--- a/res/skins/Tango/style.qss
+++ b/res/skins/Tango/style.qss
@@ -985,62 +985,12 @@ WLabel#TrackComment {
border: 1px solid #eeeeee;
}
-/* Hotcue Color: No Color */
-#HotcueButton[displayValue="1"][highlight="0"],
-#HotcueButton[displayValue="2"][highlight="0"] {
- background-color: #666;
-}
-
-/* Hotcue Color: Red */
-#HotcueButton[displayValue="1"][highlight="1"],
-#HotcueButton[displayValue="2"][highlight="1"] {
- background-color: #c50a08;
-}
-
-/* Hotcue Color: Green */
-#HotcueButton[displayValue="1"][highlight="2"],
-#HotcueButton[displayValue="2"][highlight="2"] {
- background-color: #32be44;
-}
-
-/* Hotcue Color: Blue */
-#HotcueButton[displayValue="1"][highlight="3"],
-#HotcueButton[displayValue="2"][highlight="3"] {
- background-color: #0044ff;
-}
-
-/* Hotcue Color: Yellow */
-#HotcueButton[displayValue="1"][highlight="4"],
-#HotcueButton[displayValue="2"][highlight="4"] {
- color: #333;
- background-color: #f8d200;
-}
-
-/* Hotcue Color: Celeste */
-#HotcueButton[displayValue="1"][highlight="5"],
-#HotcueButton[displayValue="2"][highlight="5"] {
- color: #333;
- background-color: #42d4f4;
-}
-
-/* Hotcue Color: Purple */
-#HotcueButton[displayValue="1"][highlight="6"],
-#HotcueButton[displayValue="2"][highlight="6"] {
- background-color: #af00cc;
-}
-
-/* Hotcue Color: Pink */
-#HotcueButton[displayValue="1"][highlight="7"],
-#HotcueButton[displayValue="2"][highlight="7"] {
- color: #333;
- background-color: #fca6d7;
+#HotcueButton[backgroundIsDark=true][hasBackgroundColor=true] {
+ color: #eeeeee;
}
-/* Hotcue Color: White */
-#HotcueButton[displayValue="1"][highlight="8"],
-#HotcueButton[displayValue="2"][highlight="8"] {
- color: #333;
- background-color: #f2f2ff;
+#HotcueButton[backgroundIsDark=false][hasBackgroundColor=true] {
+ color: #0f0f0f;
}
#CueButton {
diff --git a/src/controllers/bulk/bulkcontroller.cpp b/src/controllers/bulk/bulkcontroller.cpp
index d178d084877..01853742be4 100644
--- a/src/controllers/bulk/bulkcontroller.cpp
+++ b/src/controllers/bulk/bulkcontroller.cpp
@@ -68,15 +68,15 @@ static QString get_string(libusb_device_handle *handle, u_int8_t id) {
return QString::fromLatin1((char*)buf);
}
-
-BulkController::BulkController(libusb_context* context,
- libusb_device_handle *handle,
- struct libusb_device_descriptor *desc)
- : m_context(context),
+BulkController::BulkController(UserSettingsPointer pConfig,
+ libusb_context* context,
+ libusb_device_handle* handle,
+ struct libusb_device_descriptor* desc)
+ : Controller(pConfig),
+ m_context(context),
m_phandle(handle),
in_epaddr(0),
- out_epaddr(0)
-{
+ out_epaddr(0) {
vendor_id = desc->idVendor;
product_id = desc->idProduct;
diff --git a/src/controllers/bulk/bulkcontroller.h b/src/controllers/bulk/bulkcontroller.h
index 480aa084a69..9d67c1041ea 100644
--- a/src/controllers/bulk/bulkcontroller.h
+++ b/src/controllers/bulk/bulkcontroller.h
@@ -42,8 +42,10 @@ class BulkReader : public QThread {
class BulkController : public Controller {
Q_OBJECT
public:
- BulkController(libusb_context* context, libusb_device_handle *handle,
- struct libusb_device_descriptor *desc);
+ BulkController(UserSettingsPointer pConfig,
+ libusb_context* context,
+ libusb_device_handle* handle,
+ struct libusb_device_descriptor* desc);
~BulkController() override;
QString presetExtension() override;
diff --git a/src/controllers/bulk/bulkenumerator.cpp b/src/controllers/bulk/bulkenumerator.cpp
index 2942c5b3ac7..27b5eea15d3 100644
--- a/src/controllers/bulk/bulkenumerator.cpp
+++ b/src/controllers/bulk/bulkenumerator.cpp
@@ -11,9 +11,8 @@
#include "controllers/bulk/bulkenumerator.h"
#include "controllers/bulk/bulksupported.h"
-BulkEnumerator::BulkEnumerator()
- : ControllerEnumerator(),
- m_context(NULL) {
+BulkEnumerator::BulkEnumerator(UserSettingsPointer pConfig)
+ : ControllerEnumerator(), m_context(NULL), m_pConfig(pConfig) {
libusb_init(&m_context);
}
@@ -55,7 +54,8 @@ QList BulkEnumerator::queryDevices() {
continue;
}
- BulkController* currentDevice = new BulkController(m_context, handle, &desc);
+ BulkController* currentDevice =
+ new BulkController(m_pConfig, m_context, handle, &desc);
m_devices.push_back(currentDevice);
}
}
diff --git a/src/controllers/bulk/bulkenumerator.h b/src/controllers/bulk/bulkenumerator.h
index 5e16dd67d11..2018a4a1181 100644
--- a/src/controllers/bulk/bulkenumerator.h
+++ b/src/controllers/bulk/bulkenumerator.h
@@ -14,7 +14,7 @@ struct libusb_context;
class BulkEnumerator : public ControllerEnumerator {
public:
- BulkEnumerator();
+ BulkEnumerator(UserSettingsPointer pConfig);
virtual ~BulkEnumerator();
QList queryDevices();
@@ -22,6 +22,7 @@ class BulkEnumerator : public ControllerEnumerator {
private:
QList m_devices;
libusb_context* m_context;
+ UserSettingsPointer m_pConfig;
};
#endif
diff --git a/src/controllers/colorjsproxy.cpp b/src/controllers/colorjsproxy.cpp
index 4147cdcc124..f7ef331f704 100644
--- a/src/controllers/colorjsproxy.cpp
+++ b/src/controllers/colorjsproxy.cpp
@@ -1,36 +1,40 @@
#include "controllers/colorjsproxy.h"
+#include "preferences/hotcuecolorpalettesettings.h"
-ColorJSProxy::ColorJSProxy(QScriptEngine* pScriptEngine)
- : m_pScriptEngine(pScriptEngine),
- m_predefinedColorsList(makePredefinedColorsList(pScriptEngine)){};
-
-ColorJSProxy::~ColorJSProxy() {};
+ColorJSProxy::ColorJSProxy(QScriptEngine* pScriptEngine,
+ HotcueColorPaletteSettings colorPaletteSettings)
+ : m_pScriptEngine(pScriptEngine),
+ m_JsHotcueColorPalette(
+ makeHotcueColorPalette(pScriptEngine, colorPaletteSettings)),
+ m_colorPaletteSettings(colorPaletteSettings) {
+}
-QScriptValue ColorJSProxy::predefinedColorFromId(int iId) {
- PredefinedColorPointer color(Color::kPredefinedColorsSet.predefinedColorFromId(iId));
- return jsColorFrom(color);
-};
+ColorJSProxy::~ColorJSProxy() = default;
-Q_INVOKABLE QScriptValue ColorJSProxy::predefinedColorsList() {
- return m_predefinedColorsList;
+Q_INVOKABLE QScriptValue ColorJSProxy::hotcueColorPalette() {
+ return m_JsHotcueColorPalette;
}
-QScriptValue ColorJSProxy::jsColorFrom(PredefinedColorPointer predefinedColor) {
+QScriptValue ColorJSProxy::colorFromHexCode(uint colorCode) {
+ QColor color = QColor::fromRgba(colorCode);
QScriptValue jsColor = m_pScriptEngine->newObject();
- jsColor.setProperty("red", predefinedColor->m_defaultRgba.red());
- jsColor.setProperty("green", predefinedColor->m_defaultRgba.green());
- jsColor.setProperty("blue", predefinedColor->m_defaultRgba.blue());
- jsColor.setProperty("alpha", predefinedColor->m_defaultRgba.alpha());
- jsColor.setProperty("id", predefinedColor->m_iId);
+ jsColor.setProperty("red", color.red());
+ jsColor.setProperty("green", color.green());
+ jsColor.setProperty("blue", color.blue());
+ jsColor.setProperty("alpha", color.alpha());
return jsColor;
}
-QScriptValue ColorJSProxy::makePredefinedColorsList(QScriptEngine* pScriptEngine) {
- int numColors = Color::kPredefinedColorsSet.allColors.length();
- QScriptValue colorList = pScriptEngine->newArray(numColors);
+QScriptValue ColorJSProxy::makeHotcueColorPalette(QScriptEngine* pScriptEngine,
+ HotcueColorPaletteSettings colorPaletteSettings) {
+ // TODO: make sure we get notified when the palette changes
+ QList colorList =
+ colorPaletteSettings.getHotcueColorPalette().m_colorList;
+ int numColors = colorList.length();
+ QScriptValue jsColorList = pScriptEngine->newArray(numColors);
for (int i = 0; i < numColors; ++i) {
- PredefinedColorPointer color = Color::kPredefinedColorsSet.allColors.at(i);
- colorList.setProperty(i, jsColorFrom(color));
+ QColor color = colorList.at(i);
+ jsColorList.setProperty(i, colorFromHexCode(color.rgba()));
}
- return colorList;
+ return jsColorList;
}
diff --git a/src/controllers/colorjsproxy.h b/src/controllers/colorjsproxy.h
index e6ebeda1d9b..dda4d693798 100644
--- a/src/controllers/colorjsproxy.h
+++ b/src/controllers/colorjsproxy.h
@@ -5,23 +5,29 @@
#include
#include
+#include "preferences/hotcuecolorpalettesettings.h"
#include "util/color/color.h"
-class ColorJSProxy: public QObject {
+class ColorJSProxy final : public QObject {
Q_OBJECT
public:
- ColorJSProxy(QScriptEngine* pScriptEngine);
+ ColorJSProxy(QScriptEngine* pScriptEngine,
+ HotcueColorPaletteSettings colorPaletteSettings);
- virtual ~ColorJSProxy();
+ ~ColorJSProxy() override;
- Q_INVOKABLE QScriptValue predefinedColorFromId(int iId);
- Q_INVOKABLE QScriptValue predefinedColorsList();
+ Q_INVOKABLE QScriptValue hotcueColorPalette();
+ // Return a JS object with the red, green, blue and alpha components
+ // of a color. The parameter is the hexadecimal representation of the color
+ // i.e. 0xAARRGGBB
+ Q_INVOKABLE QScriptValue colorFromHexCode(uint colorCode);
private:
- QScriptValue jsColorFrom(PredefinedColorPointer predefinedColor);
- QScriptValue makePredefinedColorsList(QScriptEngine* pScriptEngine);
+ QScriptValue makeHotcueColorPalette(QScriptEngine* pScriptEngine,
+ HotcueColorPaletteSettings colorPaletteSettings);
QScriptEngine* m_pScriptEngine;
- QScriptValue m_predefinedColorsList;
+ QScriptValue m_JsHotcueColorPalette;
+ HotcueColorPaletteSettings m_colorPaletteSettings;
};
#endif /* COLORJSPROXY_H */
diff --git a/src/controllers/colormapper.cpp b/src/controllers/colormapper.cpp
new file mode 100644
index 00000000000..3caa515806e
--- /dev/null
+++ b/src/controllers/colormapper.cpp
@@ -0,0 +1,59 @@
+#include "controllers/colormapper.h"
+
+#include
+#include
+
+#include "util/debug.h"
+
+namespace {
+double colorDistance(QRgb a, QRgb b) {
+ // This algorithm calculates the distance between two colors. In
+ // contrast to the L2 norm, this also tries take the human perception
+ // of colors into account. More accurate algorithms like the CIELAB2000
+ // Delta-E rely on sophisticated color space conversions and need a lot
+ // of costly computations. In contrast, this is a low-cost
+ // approximation and should be sufficently accurate.
+ // More details: https://www.compuphase.com/cmetric.htm
+ long mean_red = ((long)qRed(a) + (long)qRed(b)) / 2;
+ long delta_red = (long)qRed(a) - (long)qRed(b);
+ long delta_green = (long)qGreen(a) - (long)qGreen(b);
+ long delta_blue = (long)qBlue(a) - (long)qBlue(b);
+ return sqrt(
+ (((512 + mean_red) * delta_red * delta_red) >> 8) +
+ (4 * delta_green * delta_green) +
+ (((767 - mean_red) * delta_blue * delta_blue) >> 8));
+}
+} // namespace
+
+QPair ColorMapper::getNearestColor(QRgb desiredColor) {
+ // If desired color is already in cache, use cache entry
+ QMap::const_iterator i = m_cache.find(desiredColor);
+ QMap::const_iterator j;
+ if (i != m_cache.constEnd()) {
+ j = m_availableColors.find(i.value());
+ DEBUG_ASSERT(j != m_availableColors.constEnd());
+ qDebug() << "ColorMapper cache hit for" << desiredColor << ":"
+ << "Color =" << j.key() << ","
+ << "Value =" << j.value();
+ return QPair(j.key(), j.value());
+ }
+
+ // Color is not cached
+ QMap::const_iterator nearestColorIterator;
+ double nearestColorDistance = qInf();
+ for (j = m_availableColors.constBegin(); j != m_availableColors.constEnd(); j++) {
+ QRgb availableColor = j.key();
+ double distance = colorDistance(desiredColor, availableColor);
+ if (distance < nearestColorDistance) {
+ nearestColorDistance = distance;
+ nearestColorIterator = j;
+ }
+ }
+
+ DEBUG_ASSERT(nearestColorDistance < qInf());
+ qDebug() << "ColorMapper found matching color for" << desiredColor << ":"
+ << "Color =" << nearestColorIterator.key() << ","
+ << "Value =" << nearestColorIterator.value();
+ m_cache.insert(desiredColor, nearestColorIterator.key());
+ return QPair(nearestColorIterator.key(), nearestColorIterator.value());
+}
diff --git a/src/controllers/colormapper.h b/src/controllers/colormapper.h
new file mode 100644
index 00000000000..c138edbf38d
--- /dev/null
+++ b/src/controllers/colormapper.h
@@ -0,0 +1,30 @@
+#ifndef COLORMAPPER_H
+#define COLORMAPPER_H
+
+#include
+#include
+#include
+#include
+#include
+
+#include "util/assert.h"
+
+class ColorMapper final : public QObject {
+ Q_OBJECT
+ public:
+ ColorMapper() = delete;
+ ColorMapper(const QMap availableColors)
+ : m_availableColors(availableColors) {
+ DEBUG_ASSERT(!m_availableColors.isEmpty());
+ }
+
+ ~ColorMapper() = default;
+
+ QPair getNearestColor(QRgb desiredColor);
+
+ private:
+ const QMap m_availableColors;
+ QMap m_cache;
+};
+
+#endif /* COLORMAPPER_H */
diff --git a/src/controllers/colormapperjsproxy.cpp b/src/controllers/colormapperjsproxy.cpp
new file mode 100644
index 00000000000..f806cb9752e
--- /dev/null
+++ b/src/controllers/colormapperjsproxy.cpp
@@ -0,0 +1,47 @@
+#include
+
+#include "controllers/colormapperjsproxy.h"
+
+ColorMapperJSProxy::ColorMapperJSProxy(QScriptEngine* pScriptEngine, QMap availableColors)
+ : m_pScriptEngine(pScriptEngine) {
+ m_colorMapper = new ColorMapper(availableColors);
+}
+
+QScriptValue ColorMapperJSProxy::getNearestColor(uint colorCode) {
+ QPair result = m_colorMapper->getNearestColor(static_cast(colorCode));
+ QScriptValue jsColor = m_pScriptEngine->newObject();
+ jsColor.setProperty("red", qRed(result.first));
+ jsColor.setProperty("green", qGreen(result.first));
+ jsColor.setProperty("blue", qBlue(result.first));
+ jsColor.setProperty("alpha", qAlpha(result.first));
+ return jsColor;
+}
+
+QScriptValue ColorMapperJSProxy::getNearestValue(uint colorCode) {
+ QPair result = m_colorMapper->getNearestColor(static_cast(colorCode));
+ return m_pScriptEngine->toScriptValue(result.second);
+}
+
+QScriptValue ColorMapperJSProxyConstructor(QScriptContext* pScriptContext, QScriptEngine* pScriptEngine) {
+ QMap availableColors;
+ DEBUG_ASSERT(pScriptContext->argumentCount() == 1);
+ QScriptValueIterator it(pScriptContext->argument(0));
+ while (it.hasNext()) {
+ it.next();
+ DEBUG_ASSERT(!it.value().isObject());
+ QColor color(it.name());
+ VERIFY_OR_DEBUG_ASSERT(color.isValid()) {
+ qWarning() << "Received invalid color name from controller script:" << it.name();
+ continue;
+ }
+ availableColors.insert(color.rgb(), it.value().toVariant());
+ }
+
+ if (availableColors.isEmpty()) {
+ qWarning() << "Failed to create ColorMapper object: available colors mustn't be empty!";
+ return pScriptEngine->undefinedValue();
+ }
+
+ QObject* colorMapper = new ColorMapperJSProxy(pScriptEngine, availableColors);
+ return pScriptEngine->newQObject(colorMapper, QScriptEngine::ScriptOwnership);
+}
diff --git a/src/controllers/colormapperjsproxy.h b/src/controllers/colormapperjsproxy.h
new file mode 100644
index 00000000000..367d13bba3e
--- /dev/null
+++ b/src/controllers/colormapperjsproxy.h
@@ -0,0 +1,30 @@
+#ifndef COLORMAPPERJS_H
+#define COLORMAPPERJS_H
+
+#include
+#include
+
+#include "controllers/colormapper.h"
+
+class ColorMapperJSProxy final : public QObject {
+ Q_OBJECT
+ public:
+ ColorMapperJSProxy() = delete;
+ ColorMapperJSProxy(QScriptEngine* pScriptEngine, QMap availableColors);
+
+ ~ColorMapperJSProxy() {
+ delete m_colorMapper;
+ };
+
+ public slots:
+ QScriptValue getNearestColor(uint ColorCode);
+ QScriptValue getNearestValue(uint ColorCode);
+
+ private:
+ QScriptEngine* m_pScriptEngine;
+ ColorMapper* m_colorMapper;
+};
+
+QScriptValue ColorMapperJSProxyConstructor(QScriptContext* context, QScriptEngine* engine);
+
+#endif /* COLORMAPPER_H */
diff --git a/src/controllers/controller.cpp b/src/controllers/controller.cpp
index e30ff7a5f63..15a1e1dd5ec 100644
--- a/src/controllers/controller.cpp
+++ b/src/controllers/controller.cpp
@@ -13,14 +13,15 @@
#include "controllers/defs_controllers.h"
#include "util/screensaver.h"
-Controller::Controller()
+Controller::Controller(UserSettingsPointer pConfig)
: QObject(),
m_pEngine(NULL),
m_bIsOutputDevice(false),
m_bIsInputDevice(false),
m_bIsOpen(false),
- m_bLearning(false) {
- m_userActivityInhibitTimer.start();
+ m_bLearning(false),
+ m_pConfig(pConfig) {
+ m_userActivityInhibitTimer.start();
}
Controller::~Controller() {
@@ -35,7 +36,7 @@ void Controller::startEngine()
qWarning() << "Controller: Engine already exists! Restarting:";
stopEngine();
}
- m_pEngine = new ControllerEngine(this);
+ m_pEngine = new ControllerEngine(this, m_pConfig);
}
void Controller::stopEngine() {
diff --git a/src/controllers/controller.h b/src/controllers/controller.h
index 9cc6be386ce..44a5218e2ae 100644
--- a/src/controllers/controller.h
+++ b/src/controllers/controller.h
@@ -23,7 +23,7 @@
class Controller : public QObject, ConstControllerPresetVisitor {
Q_OBJECT
public:
- Controller();
+ Controller(UserSettingsPointer pConfig);
~Controller() override; // Subclass should call close() at minimum.
// Returns the extension for the controller (type) preset files. This is
@@ -162,6 +162,8 @@ class Controller : public QObject, ConstControllerPresetVisitor {
bool m_bLearning;
QTime m_userActivityInhibitTimer;
+ UserSettingsPointer m_pConfig;
+
// accesses lots of our stuff, but in the same thread
friend class ControllerManager;
// For testing
diff --git a/src/controllers/controllerengine.cpp b/src/controllers/controllerengine.cpp
index 1d09be74657..e01e8943a1c 100644
--- a/src/controllers/controllerengine.cpp
+++ b/src/controllers/controllerengine.cpp
@@ -6,8 +6,8 @@
email : spappalardo@mixxx.org
***************************************************************************/
+#include "controllers/colormapperjsproxy.h"
#include "controllers/controllerengine.h"
-
#include "controllers/controller.h"
#include "controllers/controllerdebug.h"
#include "control/controlobject.h"
@@ -29,9 +29,11 @@ const int kDecks = 16;
const int kScratchTimerMs = 1;
const double kAlphaBetaDt = kScratchTimerMs / 1000.0;
-ControllerEngine::ControllerEngine(Controller* controller)
+ControllerEngine::ControllerEngine(
+ Controller* controller, UserSettingsPointer pConfig)
: m_pEngine(nullptr),
m_pController(controller),
+ m_pConfig(pConfig),
m_bPopups(false),
m_pBaClass(nullptr) {
// Handle error dialog buttons
@@ -213,9 +215,14 @@ void ControllerEngine::initializeScriptEngine() {
engineGlobalObject.setProperty("midi", m_pEngine->newQObject(m_pController));
}
- m_pColorJSProxy = std::make_unique(m_pEngine);
+ m_pColorJSProxy = std::make_unique(
+ m_pEngine, HotcueColorPaletteSettings(m_pConfig));
engineGlobalObject.setProperty("color", m_pEngine->newQObject(m_pColorJSProxy.get()));
+ QScriptValue constructor = m_pEngine->newFunction(ColorMapperJSProxyConstructor);
+ QScriptValue metaObject = m_pEngine->newQMetaObject(&ColorMapperJSProxy::staticMetaObject, constructor);
+ engineGlobalObject.setProperty("ColorMapper", metaObject);
+
m_pBaClass = new ByteArrayClass(m_pEngine);
engineGlobalObject.setProperty("ByteArray", m_pBaClass->constructor());
}
diff --git a/src/controllers/controllerengine.h b/src/controllers/controllerengine.h
index 2359a0bcbb3..7eafb1763ea 100644
--- a/src/controllers/controllerengine.h
+++ b/src/controllers/controllerengine.h
@@ -80,7 +80,7 @@ class ScriptConnectionInvokableWrapper : public QObject {
class ControllerEngine : public QObject {
Q_OBJECT
public:
- ControllerEngine(Controller* controller);
+ ControllerEngine(Controller* controller, UserSettingsPointer pConfig);
virtual ~ControllerEngine();
bool isReady();
@@ -198,6 +198,7 @@ class ControllerEngine : public QObject {
double getDeckRate(const QString& group);
Controller* m_pController;
+ UserSettingsPointer m_pConfig;
bool m_bPopups;
QList m_scriptFunctionPrefixes;
QMap m_scriptErrors;
diff --git a/src/controllers/controllermanager.cpp b/src/controllers/controllermanager.cpp
index 54029398d48..397a9c7dc84 100644
--- a/src/controllers/controllermanager.cpp
+++ b/src/controllers/controllermanager.cpp
@@ -127,15 +127,15 @@ void ControllerManager::slotInitialize() {
// Instantiate all enumerators. Enumerators can take a long time to
// construct since they interact with host MIDI APIs.
- m_enumerators.append(new PortMidiEnumerator());
+ m_enumerators.append(new PortMidiEnumerator(m_pConfig));
#ifdef __HSS1394__
m_enumerators.append(new Hss1394Enumerator());
#endif
#ifdef __BULK__
- m_enumerators.append(new BulkEnumerator());
+ m_enumerators.append(new BulkEnumerator(m_pConfig));
#endif
#ifdef __HID__
- m_enumerators.append(new HidEnumerator());
+ m_enumerators.append(new HidEnumerator(m_pConfig));
#endif
}
diff --git a/src/controllers/hid/hidcontroller.cpp b/src/controllers/hid/hidcontroller.cpp
index b07b5167c5e..094e31cae3f 100644
--- a/src/controllers/hid/hidcontroller.cpp
+++ b/src/controllers/hid/hidcontroller.cpp
@@ -47,8 +47,9 @@ void HidReader::run() {
delete [] data;
}
-HidController::HidController(const hid_device_info deviceInfo)
- : m_pHidDevice(NULL) {
+HidController::HidController(
+ const hid_device_info deviceInfo, UserSettingsPointer pConfig)
+ : Controller(pConfig), m_pHidDevice(NULL) {
// Copy required variables from deviceInfo, which will be freed after
// this class is initialized by caller.
hid_vendor_id = deviceInfo.vendor_id;
diff --git a/src/controllers/hid/hidcontroller.h b/src/controllers/hid/hidcontroller.h
index ac44aa9998b..0cefb8670d8 100644
--- a/src/controllers/hid/hidcontroller.h
+++ b/src/controllers/hid/hidcontroller.h
@@ -41,7 +41,8 @@ class HidReader : public QThread {
class HidController final : public Controller {
Q_OBJECT
public:
- HidController(const hid_device_info deviceInfo);
+ HidController(
+ const hid_device_info deviceInfo, UserSettingsPointer pConfig);
~HidController() override;
QString presetExtension() override;
diff --git a/src/controllers/hid/hidenumerator.cpp b/src/controllers/hid/hidenumerator.cpp
index c1c2dc27834..802459f3c02 100644
--- a/src/controllers/hid/hidenumerator.cpp
+++ b/src/controllers/hid/hidenumerator.cpp
@@ -11,7 +11,8 @@
#include "controllers/hid/hidenumerator.h"
#include "controllers/hid/hidblacklist.h"
-HidEnumerator::HidEnumerator() : ControllerEnumerator() {
+HidEnumerator::HidEnumerator(UserSettingsPointer pConfig)
+ : ControllerEnumerator(), m_pConfig(pConfig) {
}
HidEnumerator::~HidEnumerator() {
@@ -98,7 +99,7 @@ QList HidEnumerator::queryDevices() {
continue;
}
- HidController* currentDevice = new HidController(*cur_dev);
+ HidController* currentDevice = new HidController(*cur_dev, m_pConfig);
m_devices.push_back(currentDevice);
}
hid_free_enumeration(devs);
diff --git a/src/controllers/hid/hidenumerator.h b/src/controllers/hid/hidenumerator.h
index 351e972beb1..9b39b75c947 100644
--- a/src/controllers/hid/hidenumerator.h
+++ b/src/controllers/hid/hidenumerator.h
@@ -12,13 +12,14 @@
class HidEnumerator : public ControllerEnumerator {
public:
- HidEnumerator();
+ HidEnumerator(UserSettingsPointer pConfig);
virtual ~HidEnumerator();
QList queryDevices();
private:
QList m_devices;
+ UserSettingsPointer m_pConfig;
};
#endif
diff --git a/src/controllers/midi/midicontroller.cpp b/src/controllers/midi/midicontroller.cpp
index 0176aa653ec..43dbaa65bed 100644
--- a/src/controllers/midi/midicontroller.cpp
+++ b/src/controllers/midi/midicontroller.cpp
@@ -17,8 +17,8 @@
#include "util/math.h"
#include "util/screensaver.h"
-MidiController::MidiController()
- : Controller() {
+MidiController::MidiController(UserSettingsPointer pConfig)
+ : Controller(pConfig) {
setDeviceCategory(tr("MIDI Controller"));
}
diff --git a/src/controllers/midi/midicontroller.h b/src/controllers/midi/midicontroller.h
index 93d91fdf443..b8ebb8b94b4 100644
--- a/src/controllers/midi/midicontroller.h
+++ b/src/controllers/midi/midicontroller.h
@@ -23,7 +23,7 @@
class MidiController : public Controller {
Q_OBJECT
public:
- MidiController();
+ MidiController(UserSettingsPointer pConfig);
~MidiController() override;
QString presetExtension() override;
diff --git a/src/controllers/midi/portmidicontroller.cpp b/src/controllers/midi/portmidicontroller.cpp
index c4479a1ae68..4be78583c78 100644
--- a/src/controllers/midi/portmidicontroller.cpp
+++ b/src/controllers/midi/portmidicontroller.cpp
@@ -12,12 +12,11 @@
#include "controllers/controllerdebug.h"
PortMidiController::PortMidiController(const PmDeviceInfo* inputDeviceInfo,
- const PmDeviceInfo* outputDeviceInfo,
- int inputDeviceIndex,
- int outputDeviceIndex)
- : MidiController(),
- m_cReceiveMsg_index(0),
- m_bInSysex(false) {
+ const PmDeviceInfo* outputDeviceInfo,
+ int inputDeviceIndex,
+ int outputDeviceIndex,
+ UserSettingsPointer pConfig)
+ : MidiController(pConfig), m_cReceiveMsg_index(0), m_bInSysex(false) {
for (unsigned int k = 0; k < MIXXX_PORTMIDI_BUFFER_LEN; ++k) {
// Can be shortened to `m_midiBuffer[k] = {}` with C++11.
m_midiBuffer[k].message = 0;
diff --git a/src/controllers/midi/portmidicontroller.h b/src/controllers/midi/portmidicontroller.h
index 96da9afce1a..92d2954e18f 100644
--- a/src/controllers/midi/portmidicontroller.h
+++ b/src/controllers/midi/portmidicontroller.h
@@ -60,9 +60,10 @@ class PortMidiController : public MidiController {
Q_OBJECT
public:
PortMidiController(const PmDeviceInfo* inputDeviceInfo,
- const PmDeviceInfo* outputDeviceInfo,
- int inputDeviceIndex,
- int outputDeviceIndex);
+ const PmDeviceInfo* outputDeviceInfo,
+ int inputDeviceIndex,
+ int outputDeviceIndex,
+ UserSettingsPointer pConfig);
~PortMidiController() override;
private slots:
diff --git a/src/controllers/midi/portmidienumerator.cpp b/src/controllers/midi/portmidienumerator.cpp
index 47e6a23a829..ba525ddeb73 100644
--- a/src/controllers/midi/portmidienumerator.cpp
+++ b/src/controllers/midi/portmidienumerator.cpp
@@ -21,7 +21,8 @@ bool shouldBlacklistDevice(const PmDeviceInfo* device) {
deviceName.startsWith("Midi Through Port", Qt::CaseInsensitive);
}
-PortMidiEnumerator::PortMidiEnumerator() : MidiEnumerator() {
+PortMidiEnumerator::PortMidiEnumerator(UserSettingsPointer pConfig)
+ : MidiEnumerator(), m_pConfig(pConfig) {
PmError err = Pm_Initialize();
// Based on reading the source, it's not possible for this to fail.
if (err != pmNoError) {
@@ -257,9 +258,12 @@ QList PortMidiEnumerator::queryDevices() {
// device (outputDeviceInfo != NULL).
//.... so create our (aggregate) MIDI device!
- PortMidiController *currentDevice = new PortMidiController(
- inputDeviceInfo, outputDeviceInfo,
- inputDevIndex, outputDevIndex);
+ PortMidiController* currentDevice =
+ new PortMidiController(inputDeviceInfo,
+ outputDeviceInfo,
+ inputDevIndex,
+ outputDevIndex,
+ m_pConfig);
m_devices.push_back(currentDevice);
}
diff --git a/src/controllers/midi/portmidienumerator.h b/src/controllers/midi/portmidienumerator.h
index 606c4feb4de..9566b54df1b 100644
--- a/src/controllers/midi/portmidienumerator.h
+++ b/src/controllers/midi/portmidienumerator.h
@@ -13,13 +13,14 @@
class PortMidiEnumerator : public MidiEnumerator {
Q_OBJECT
public:
- PortMidiEnumerator();
+ PortMidiEnumerator(UserSettingsPointer pConfig);
virtual ~PortMidiEnumerator();
QList queryDevices();
private:
QList m_devices;
+ UserSettingsPointer m_pConfig;
};
// For testing.
diff --git a/src/database/mixxxdb.cpp b/src/database/mixxxdb.cpp
index 5a18ff73526..6dcd79a0a52 100644
--- a/src/database/mixxxdb.cpp
+++ b/src/database/mixxxdb.cpp
@@ -11,7 +11,7 @@
const QString MixxxDb::kDefaultSchemaFile(":/schema.xml");
//static
-const int MixxxDb::kRequiredSchemaVersion = 30;
+const int MixxxDb::kRequiredSchemaVersion = 31;
namespace {
diff --git a/src/engine/controls/cuecontrol.cpp b/src/engine/controls/cuecontrol.cpp
index 3a160eded79..312ba3f3223 100644
--- a/src/engine/controls/cuecontrol.cpp
+++ b/src/engine/controls/cuecontrol.cpp
@@ -7,12 +7,13 @@
#include "engine/enginebuffer.h"
#include "engine/controls/cuecontrol.h"
+#include "control/controlindicator.h"
#include "control/controlobject.h"
#include "control/controlpushbutton.h"
-#include "control/controlindicator.h"
-#include "vinylcontrol/defs_vinylcontrol.h"
-#include "util/sample.h"
+#include "preferences/hotcuecolorpalettesettings.h"
#include "util/color/color.h"
+#include "util/sample.h"
+#include "vinylcontrol/defs_vinylcontrol.h"
// TODO: Convert these doubles to a standard enum
// and convert elseif logic to switch statements
@@ -23,19 +24,19 @@ static const double CUE_MODE_NUMARK = 3.0;
static const double CUE_MODE_MIXXX_NO_BLINK = 4.0;
static const double CUE_MODE_CUP = 5.0;
-CueControl::CueControl(QString group,
- UserSettingsPointer pConfig) :
- EngineControl(group, pConfig),
- m_bPreviewing(false),
- // m_pPlay->toBoo() -> engine play state
- // m_pPlay->set(1.0) -> emulate play button press
- m_pPlay(ControlObject::getControl(ConfigKey(group, "play"))),
- m_pStopButton(ControlObject::getControl(ConfigKey(group, "stop"))),
- m_iCurrentlyPreviewingHotcues(0),
- m_bypassCueSetByPlay(false),
- m_iNumHotCues(NUM_HOT_CUES),
- m_pLoadedTrack(),
- m_mutex(QMutex::Recursive) {
+CueControl::CueControl(QString group, UserSettingsPointer pConfig)
+ : EngineControl(group, pConfig),
+ m_colorPaletteSettings(HotcueColorPaletteSettings(pConfig)),
+ m_bPreviewing(false),
+ // m_pPlay->toBoo() -> engine play state
+ // m_pPlay->set(1.0) -> emulate play button press
+ m_pPlay(ControlObject::getControl(ConfigKey(group, "play"))),
+ m_pStopButton(ControlObject::getControl(ConfigKey(group, "stop"))),
+ m_iCurrentlyPreviewingHotcues(0),
+ m_bypassCueSetByPlay(false),
+ m_iNumHotCues(NUM_HOT_CUES),
+ m_pLoadedTrack(),
+ m_mutex(QMutex::Recursive) {
// To silence a compiler warning about CUE_MODE_PIONEER.
Q_UNUSED(CUE_MODE_PIONEER);
createControls();
@@ -297,6 +298,8 @@ void CueControl::detachCue(HotcueControl* pControl) {
}
disconnect(pCue.get(), 0, this, 0);
pControl->resetCue();
+ // Reset the color CO to -1
+ pControl->setColor(QColor());
}
void CueControl::trackLoaded(TrackPointer pNewTrack) {
@@ -579,14 +582,19 @@ void CueControl::hotcueSet(HotcueControl* pControl, double v) {
pCue->setHotCue(hotcue);
pCue->setLabel("");
pCue->setType(Cue::Type::HotCue);
- // TODO(XXX) deal with spurious signals
- attachCue(pCue, pControl);
- if (getConfig()->getValue(ConfigKey("[Controls]", "auto_hotcue_colors"), false)) {
- const QList predefinedColors = Color::kPredefinedColorsSet.allColors;
- pCue->setColor(predefinedColors.at((hotcue % (predefinedColors.count() - 1)) + 1));
+ auto hotcueColorPalette = m_colorPaletteSettings.getHotcueColorPalette();
+ ConfigKey autoHotcueColorsKey("[Controls]", "auto_hotcue_colors");
+ if (getConfig()->getValue(autoHotcueColorsKey, false)) {
+ auto colors = hotcueColorPalette.m_colorList;
+ pCue->setColor(colors.at((hotcue % (colors.count() - 1)) + 1));
+ } else {
+ pCue->setColor(hotcueColorPalette.m_colorList.first());
};
+ // TODO(XXX) deal with spurious signals
+ attachCue(pCue, pControl);
+
// If quantize is enabled and we are not playing, jump to the cue point
// since it's not necessarily where we currently are. TODO(XXX) is this
// potentially invalid for vinyl control?
@@ -1734,8 +1742,9 @@ HotcueControl::HotcueControl(QString group, int i)
m_hotcueEnabled = new ControlObject(keyForControl(i, "enabled"));
m_hotcueEnabled->setReadOnly();
- // The id of the predefined color assigned to this color.
- m_hotcueColor = new ControlObject(keyForControl(i, "color_id"));
+ // The rgba value of the color assigned to this color.
+ m_hotcueColor = new ControlObject(keyForControl(i, "color"));
+ m_hotcueColor->set(-1);
connect(m_hotcueColor,
&ControlObject::valueChanged,
this,
@@ -1824,9 +1833,9 @@ void HotcueControl::slotHotcuePositionChanged(double newPosition) {
emit(hotcuePositionChanged(this, newPosition));
}
-void HotcueControl::slotHotcueColorChanged(double newColorId) {
- m_pCue->setColor(Color::kPredefinedColorsSet.predefinedColorFromId(newColorId));
- emit(hotcueColorChanged(this, newColorId));
+void HotcueControl::slotHotcueColorChanged(double newColor) {
+ m_pCue->setColor(QColor::fromRgba(newColor));
+ emit(hotcueColorChanged(this, newColor));
}
double HotcueControl::getPosition() const {
@@ -1840,12 +1849,16 @@ void HotcueControl::setCue(CuePointer pCue) {
// because we have a null check for valid data else where in the code
m_pCue = pCue;
}
-PredefinedColorPointer HotcueControl::getColor() const {
- return Color::kPredefinedColorsSet.predefinedColorFromId(m_hotcueColor->get());
+QColor HotcueControl::getColor() const {
+ return QColor::fromRgba(m_hotcueColor->get());
}
-void HotcueControl::setColor(PredefinedColorPointer newColor) {
- m_hotcueColor->set(static_cast(newColor->m_iId));
+void HotcueControl::setColor(const QColor& newColor) {
+ if (newColor.isValid()) {
+ m_hotcueColor->set(newColor.rgba());
+ } else {
+ m_hotcueColor->set(-1);
+ }
}
void HotcueControl::resetCue() {
// clear pCue first because we have a null check for valid data else where
diff --git a/src/engine/controls/cuecontrol.h b/src/engine/controls/cuecontrol.h
index ee9ce2412d4..eada3678368 100644
--- a/src/engine/controls/cuecontrol.h
+++ b/src/engine/controls/cuecontrol.h
@@ -7,9 +7,10 @@
#include
#include
+#include "control/controlproxy.h"
#include "engine/controls/enginecontrol.h"
+#include "preferences/hotcuecolorpalettesettings.h"
#include "preferences/usersettings.h"
-#include "control/controlproxy.h"
#include "track/track.h"
#define NUM_HOT_CUES 37
@@ -51,8 +52,8 @@ class HotcueControl : public QObject {
void setCue(CuePointer pCue);
void resetCue();
void setPosition(double position);
- void setColor(PredefinedColorPointer newColor);
- PredefinedColorPointer getColor() const;
+ void setColor(const QColor& newColor);
+ QColor getColor() const;
// Used for caching the preview state of this hotcue control.
inline bool isPreviewing() {
@@ -77,7 +78,7 @@ class HotcueControl : public QObject {
void slotHotcueActivatePreview(double v);
void slotHotcueClear(double v);
void slotHotcuePositionChanged(double newPosition);
- void slotHotcueColorChanged(double newColorId);
+ void slotHotcueColorChanged(double newColor);
signals:
void hotcueSet(HotcueControl* pHotcue, double v);
@@ -88,7 +89,7 @@ class HotcueControl : public QObject {
void hotcueActivatePreview(HotcueControl* pHotcue, double v);
void hotcueClear(HotcueControl* pHotcue, double v);
void hotcuePositionChanged(HotcueControl* pHotcue, double newPosition);
- void hotcueColorChanged(HotcueControl* pHotcue, double newColorId);
+ void hotcueColorChanged(HotcueControl* pHotcue, double newColor);
void hotcuePlay(double v);
private:
@@ -197,6 +198,7 @@ class CueControl : public EngineControl {
double quantizeCurrentPosition(QuantizeMode mode);
TrackAt getTrackAt() const;
+ HotcueColorPaletteSettings m_colorPaletteSettings;
bool m_bPreviewing;
ControlObject* m_pPlay;
ControlObject* m_pStopButton;
diff --git a/src/library/dao/cuedao.cpp b/src/library/dao/cuedao.cpp
index 5d81c215615..e43859645ee 100644
--- a/src/library/dao/cuedao.cpp
+++ b/src/library/dao/cuedao.cpp
@@ -11,8 +11,6 @@
#include "library/queryutil.h"
#include "util/assert.h"
#include "util/performancetimer.h"
-#include "util/color/color.h"
-#include "util/color/predefinedcolor.h"
int CueDAO::cueCount() {
qDebug() << "CueDAO::cueCount" << QThread::currentThread() << m_database.connectionName();
@@ -53,9 +51,16 @@ CuePointer CueDAO::cueFromRow(const QSqlQuery& query) const {
int length = record.value(record.indexOf("length")).toInt();
int hotcue = record.value(record.indexOf("hotcue")).toInt();
QString label = record.value(record.indexOf("label")).toString();
- int iColorId = record.value(record.indexOf("color")).toInt();
- PredefinedColorPointer color = Color::kPredefinedColorsSet.predefinedColorFromId(iColorId);
- CuePointer pCue(new Cue(id, trackId, (Cue::Type)type, position, length, hotcue, label, color));
+ uint colorValue = record.value(record.indexOf("color")).toUInt();
+ QColor color = QColor::fromRgba(colorValue);
+ CuePointer pCue(new Cue(id,
+ trackId,
+ (Cue::Type)type,
+ position,
+ length,
+ hotcue,
+ label,
+ color));
m_cues[id] = pCue;
return pCue;
}
@@ -147,7 +152,7 @@ bool CueDAO::saveCue(Cue* cue) {
query.bindValue(":length", cue->getLength());
query.bindValue(":hotcue", cue->getHotCue());
query.bindValue(":label", cue->getLabel());
- query.bindValue(":color", cue->getColor()->m_iId);
+ query.bindValue(":color", cue->getColor().rgba());
if (query.exec()) {
int id = query.lastInsertId().toInt();
@@ -175,7 +180,7 @@ bool CueDAO::saveCue(Cue* cue) {
query.bindValue(":length", cue->getLength());
query.bindValue(":hotcue", cue->getHotCue());
query.bindValue(":label", cue->getLabel());
- query.bindValue(":color", cue->getColor()->m_iId);
+ query.bindValue(":color", cue->getColor().rgba());
if (query.exec()) {
cue->setDirty(false);
diff --git a/src/library/dlgtrackinfo.cpp b/src/library/dlgtrackinfo.cpp
index 6fafc712dbe..ab665aaffdf 100644
--- a/src/library/dlgtrackinfo.cpp
+++ b/src/library/dlgtrackinfo.cpp
@@ -1,17 +1,18 @@
+#include
#include
-#include
#include
-#include
+#include
#include "library/coverartcache.h"
#include "library/coverartutils.h"
#include "library/dlgtrackinfo.h"
+#include "preferences/hotcuecolorpalettesettings.h"
#include "sources/soundsourceproxy.h"
#include "track/beatfactory.h"
#include "track/cue.h"
#include "track/keyfactory.h"
#include "track/keyutils.h"
-#include "util/color/color.h"
+#include "util/color/colorpalette.h"
#include "util/compatibility.h"
#include "util/desktophelper.h"
#include "util/duration.h"
@@ -22,11 +23,12 @@ const int kMinBpm = 30;
// Maximum allowed interval between beats (calculated from kMinBpm).
const mixxx::Duration kMaxInterval = mixxx::Duration::fromMillis(1000.0 * (60.0 / kMinBpm));
-DlgTrackInfo::DlgTrackInfo(QWidget* parent)
- : QDialog(parent),
- m_pTapFilter(new TapFilter(this, kFilterLength, kMaxInterval)),
- m_dLastTapedBpm(-1.),
- m_pWCoverArtLabel(new WCoverArtLabel(this)) {
+DlgTrackInfo::DlgTrackInfo(QWidget* parent, UserSettingsPointer pConfig)
+ : QDialog(parent),
+ m_pTapFilter(new TapFilter(this, kFilterLength, kMaxInterval)),
+ m_dLastTapedBpm(-1.),
+ m_pWCoverArtLabel(new WCoverArtLabel(this)),
+ m_pConfig(pConfig) {
init();
}
@@ -37,7 +39,6 @@ DlgTrackInfo::~DlgTrackInfo() {
void DlgTrackInfo::init() {
setupUi(this);
- cueTable->hideColumn(0);
coverBox->insertWidget(1, m_pWCoverArtLabel);
connect(btnNext, &QPushButton::clicked, this, &DlgTrackInfo::slotNext);
@@ -90,14 +91,6 @@ void DlgTrackInfo::init() {
this,
&DlgTrackInfo::slotKeyTextChanged);
- connect(btnCueActivate,
- &QPushButton::clicked,
- this,
- &DlgTrackInfo::cueActivate);
- connect(btnCueDelete,
- &QPushButton::clicked,
- this,
- &DlgTrackInfo::cueDelete);
connect(bpmTap,
&QPushButton::pressed,
m_pTapFilter.data(),
@@ -163,30 +156,6 @@ void DlgTrackInfo::slotPrev() {
emit(previous());
}
-void DlgTrackInfo::cueActivate() {
-
-}
-
-void DlgTrackInfo::cueDelete() {
- QList selected = cueTable->selectedItems();
- QListIterator item_it(selected);
-
- QSet rowsToDelete;
- while(item_it.hasNext()) {
- QTableWidgetItem* item = item_it.next();
- rowsToDelete.insert(item->row());
- }
-
- QList rowsList = QList::fromSet(rowsToDelete);
- std::sort(rowsList.begin(), rowsList.end());
-
- QListIterator it(rowsList);
- it.toBack();
- while (it.hasPrevious()) {
- cueTable->removeRow(it.previous());
- }
-}
-
void DlgTrackInfo::populateFields(const Track& track) {
setWindowTitle(track.getArtist() % " - " % track.getTitle());
@@ -255,7 +224,6 @@ void DlgTrackInfo::loadTrack(TrackPointer pTrack) {
m_pLoadedTrack = pTrack;
populateFields(*m_pLoadedTrack);
- populateCues(m_pLoadedTrack);
m_pWCoverArtLabel->loadTrack(m_pLoadedTrack);
// We already listen to changed() so we don't need to listen to individual
@@ -307,130 +275,6 @@ void DlgTrackInfo::slotOpenInFileBrowser() {
mixxx::DesktopHelper::openInFileBrowser(QStringList(m_pLoadedTrack->getLocation()));
}
-void DlgTrackInfo::populateCues(TrackPointer pTrack) {
- int sampleRate = pTrack->getSampleRate();
-
- QList listPoints;
- const QList cuePoints = pTrack->getCuePoints();
- QListIterator it(cuePoints);
- while (it.hasNext()) {
- CuePointer pCue = it.next();
- Cue::Type type = pCue->getType();
- if (type == Cue::Type::HotCue || type == Cue::Type::MainCue || type == Cue::Type::Intro
- || type == Cue::Type::Outro) {
- listPoints.push_back(pCue);
- }
- }
- it = QListIterator(listPoints);
- cueTable->setSortingEnabled(false);
- int row = 0;
-
- while (it.hasNext()) {
- CuePointer pCue(it.next());
-
- QString rowStr = QString("%1").arg(row);
-
- // All hotcues are stored in Cue's as 0-indexed, but the GUI presents
- // them to the user as 1-indexex. Add 1 here. rryan 9/2010
- int iHotcue = pCue->getHotCue() + 1;
- QString hotcue = "";
- hotcue = QString("%1").arg(iHotcue);
- double position = pCue->getPosition();
- if (position == -1) {
- continue;
- }
-
- double totalSeconds = position / sampleRate / 2.0;
-
- bool negative = false;
- if (totalSeconds < 0) {
- totalSeconds *= -1;
- negative = true;
- }
-
- int iTotalSeconds = static_cast(totalSeconds);
- int fraction = 100 * (totalSeconds - iTotalSeconds);
- int seconds = iTotalSeconds % 60;
- int mins = iTotalSeconds / 60;
- //int hours = mins / 60; //Not going to worry about this for now. :)
-
- //Construct a nicely formatted duration string now.
- QString duration = QString("%1%2:%3.%4").arg(
- negative ? QString("-") : QString(),
- QString::number(mins),
- QString("%1").arg(seconds, 2, 10, QChar('0')),
- QString("%1").arg(fraction, 2, 10, QChar('0')));
-
- QTableWidgetItem* durationItem = new QTableWidgetItem(duration);
- // Make the duration read only
- durationItem->setFlags(Qt::NoItemFlags);
-
- // Decode cue type to display text
- QString cueType;
- switch (pCue->getType()) {
- case Cue::Type::Invalid:
- cueType = "?";
- break;
- case Cue::Type::HotCue:
- cueType = "Hotcue";
- break;
- case Cue::Type::MainCue:
- cueType = "Main Cue";
- break;
- case Cue::Type::Beat:
- cueType = "Beat";
- break;
- case Cue::Type::Loop:
- cueType = "Loop";
- break;
- case Cue::Type::Jump:
- cueType = "Jump";
- break;
- case Cue::Type::Intro:
- cueType = "Intro";
- break;
- case Cue::Type::Outro:
- cueType = "Outro";
- break;
- default:
- break;
- }
-
- QTableWidgetItem* typeItem = new QTableWidgetItem(cueType);
- // Make the type read only
- typeItem->setFlags(Qt::NoItemFlags);
-
- QComboBox* colorComboBox = new QComboBox();
- const QList predefinedColors = Color::kPredefinedColorsSet.allColors;
- for (int i = 0; i < predefinedColors.count(); i++) {
- PredefinedColorPointer color = predefinedColors.at(i);
- QColor defaultRgba = color->m_defaultRgba;
- colorComboBox->addItem(color->m_sDisplayName, defaultRgba);
- if (*color != *Color::kPredefinedColorsSet.noColor) {
- QPixmap pixmap(80, 80);
- pixmap.fill(defaultRgba);
- QIcon icon(pixmap);
- colorComboBox->setItemIcon(i, icon);
- }
- }
- PredefinedColorPointer cueColor = pCue->getColor();
- colorComboBox->setCurrentIndex(Color::kPredefinedColorsSet.predefinedColorIndex(cueColor));
-
- m_cueMap[row] = pCue;
- cueTable->insertRow(row);
- cueTable->setItem(row, 0, new QTableWidgetItem(rowStr));
- cueTable->setItem(row, 1, durationItem);
- cueTable->setItem(row, 2, typeItem);
- cueTable->setItem(row, 3, new QTableWidgetItem(hotcue));
- cueTable->setCellWidget(row, 4, colorComboBox);
- cueTable->setItem(row, 5, new QTableWidgetItem(pCue->getLabel()));
- row += 1;
- }
- cueTable->setSortingEnabled(true);
- cueTable->horizontalHeader()->setStretchLastSection(true);
- cueTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
-}
-
void DlgTrackInfo::saveTrack() {
if (!m_pLoadedTrack)
return;
@@ -466,66 +310,6 @@ void DlgTrackInfo::saveTrack() {
m_pLoadedTrack->setKeys(m_keysClone);
- QSet updatedRows;
- for (int row = 0; row < cueTable->rowCount(); ++row) {
- QTableWidgetItem* rowItem = cueTable->item(row, 0);
- QTableWidgetItem* hotcueItem = cueTable->item(row, 3);
- QWidget* colorWidget = cueTable->cellWidget(row, 4);
- QTableWidgetItem* labelItem = cueTable->item(row, 5);
-
- VERIFY_OR_DEBUG_ASSERT(rowItem && hotcueItem && colorWidget && labelItem) {
- qWarning() << "unable to retrieve cells from cueTable row";
- continue;
- }
-
- int oldRow = rowItem->data(Qt::DisplayRole).toInt();
- CuePointer pCue(m_cueMap.value(oldRow, CuePointer()));
- if (!pCue) {
- continue;
- }
- updatedRows.insert(oldRow);
-
- QVariant vHotcue = hotcueItem->data(Qt::DisplayRole);
- bool ok;
- int iTableHotcue = vHotcue.toInt(&ok);
- if (ok) {
- // The GUI shows hotcues as 1-indexed, but they are actually
- // 0-indexed, so subtract 1
- pCue->setHotCue(iTableHotcue - 1);
- } else {
- pCue->setHotCue(-1);
- }
-
- if (pCue->getType() == Cue::Type::HotCue) {
- auto colorComboBox = qobject_cast(colorWidget);
- if (colorComboBox) {
- PredefinedColorPointer color = Color::kPredefinedColorsSet.allColors.at(colorComboBox->currentIndex());
- pCue->setColor(color);
- }
- }
- // do nothing for now.
-
- QString label = labelItem->data(Qt::DisplayRole).toString();
- pCue->setLabel(label);
- }
-
- QMutableHashIterator it(m_cueMap);
- // Everything that was not processed above was removed.
- while (it.hasNext()) {
- it.next();
- int oldRow = it.key();
-
- // If cue's old row is not in updatedRows then it must have been
- // deleted.
- if (updatedRows.contains(oldRow)) {
- continue;
- }
- CuePointer pCue(it.value());
- it.remove();
- qDebug() << "Deleting cue" << pCue->getId() << pCue->getHotCue();
- m_pLoadedTrack->removeCue(pCue);
- }
-
m_pLoadedTrack->setCoverInfo(m_loadedCoverInfo);
// Reconnect changed signals now.
@@ -575,10 +359,6 @@ void DlgTrackInfo::clear() {
txtKey->setText("");
txtReplayGain->setText("");
- m_cueMap.clear();
- cueTable->clearContents();
- cueTable->setRowCount(0);
-
m_loadedCoverInfo = CoverInfo();
m_pWCoverArtLabel->setCoverArt(m_loadedCoverInfo, QPixmap());
}
diff --git a/src/library/dlgtrackinfo.h b/src/library/dlgtrackinfo.h
index 0ca2a44a292..9856dcbeeb3 100644
--- a/src/library/dlgtrackinfo.h
+++ b/src/library/dlgtrackinfo.h
@@ -18,7 +18,7 @@
class DlgTrackInfo : public QDialog, public Ui::DlgTrackInfo {
Q_OBJECT
public:
- DlgTrackInfo(QWidget* parent);
+ DlgTrackInfo(QWidget* parent, UserSettingsPointer pConfig);
virtual ~DlgTrackInfo();
public slots:
@@ -39,9 +39,6 @@ class DlgTrackInfo : public QDialog, public Ui::DlgTrackInfo {
void cancel();
void trackUpdated();
- void cueActivate();
- void cueDelete();
-
void slotBpmDouble();
void slotBpmHalve();
void slotBpmTwoThirds();
@@ -69,12 +66,10 @@ class DlgTrackInfo : public QDialog, public Ui::DlgTrackInfo {
private:
void populateFields(const Track& track);
void reloadTrackBeats(const Track& track);
- void populateCues(TrackPointer pTrack);
void saveTrack();
void unloadTrack(bool save);
void clear();
void init();
- QHash m_cueMap;
TrackPointer m_pLoadedTrack;
BeatsPointer m_pBeatsClone;
Keys m_keysClone;
@@ -85,6 +80,7 @@ class DlgTrackInfo : public QDialog, public Ui::DlgTrackInfo {
CoverInfo m_loadedCoverInfo;
WCoverArtLabel* m_pWCoverArtLabel;
+ UserSettingsPointer m_pConfig;
};
#endif /* DLGTRACKINFO_H */
diff --git a/src/library/dlgtrackinfo.ui b/src/library/dlgtrackinfo.ui
index 4435134c7a0..caf42ac2c25 100644
--- a/src/library/dlgtrackinfo.ui
+++ b/src/library/dlgtrackinfo.ui
@@ -7,7 +7,7 @@
0
0
700
- 588
+ 595
@@ -41,7 +41,7 @@
- 0
+ 2
@@ -376,7 +376,16 @@
QLayout::SetDefaultConstraint
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
-
@@ -798,90 +807,6 @@ Often results in higher quality beatgrids, but will not do well on tracks that h
-
-
- Cuepoints
-
-
- -
-
-
-
- Cue Id
-
-
-
-
- Position
-
-
-
-
- Type
-
-
-
-
- Hotcue
-
-
-
-
- Color
-
-
-
-
- Label
-
-
-
-
- -
-
-
-
-
-
-
- 125
- 0
-
-
-
- Delete Cue
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 125
- 0
-
-
-
- Activate Cue
-
-
-
-
-
-
-
-
@@ -1030,9 +955,6 @@ Often results in higher quality beatgrids, but will not do well on tracks that h
bpmThreeFourth
bpmThreeHalves
bpmFourThirds
- cueTable
- btnCueDelete
- btnCueActivate
diff --git a/src/preferences/configobject.cpp b/src/preferences/configobject.cpp
index 6eecb2bb991..22900ac4e48 100644
--- a/src/preferences/configobject.cpp
+++ b/src/preferences/configobject.cpp
@@ -215,6 +215,18 @@ template void ConfigObject::save() {
}
}
+template
+QList ConfigObject::getKeysWithGroup(QString group) {
+ QWriteLocker lock(&m_valuesLock);
+ QList filteredList;
+ for (const ConfigKey& key : m_values.uniqueKeys()) {
+ if (key.group == group) {
+ filteredList.append(key);
+ }
+ }
+ return filteredList;
+}
+
template ConfigObject::ConfigObject(const QDomNode& node) {
if (!node.isNull() && node.isElement()) {
QDomNode ctrl = node.firstChild();
@@ -270,6 +282,13 @@ void ConfigObject::setValue(
set(key, ConfigValue(QString::number(value)));
}
+template<>
+template<>
+void ConfigObject::setValue(
+ const ConfigKey& key, const QColor& value) {
+ set(key, ConfigValue(value.name(QColor::NameFormat::HexArgb)));
+}
+
template <> template <>
bool ConfigObject::getValue(
const ConfigKey& key, const bool& default_value) const {
@@ -306,6 +325,24 @@ double ConfigObject::getValue(
return ok ? result : default_value;
}
+template<>
+template<>
+QColor ConfigObject::getValue(
+ const ConfigKey& key, const QColor& default_value) const {
+ const ConfigValue value = get(key);
+ if (value.isNull()) {
+ return default_value;
+ }
+ auto color = QColor(value.value);
+ return color.isValid() ? color : default_value;
+}
+
+template<>
+template<>
+QColor ConfigObject::getValue(const ConfigKey& key) const {
+ return getValue(key, QColor());
+}
+
// For string literal default
template <>
QString ConfigObject::getValue(
diff --git a/src/preferences/configobject.h b/src/preferences/configobject.h
index 3e4ba6aa20e..3791de6ecd7 100644
--- a/src/preferences/configobject.h
+++ b/src/preferences/configobject.h
@@ -187,6 +187,8 @@ template class ConfigObject {
return m_settingsPath;
}
+ QList getKeysWithGroup(QString group);
+
protected:
// We use QMap because we want a sorted list in mixxx.cfg
QMap m_values;
diff --git a/src/preferences/hotcuecolorpalettesettings.cpp b/src/preferences/hotcuecolorpalettesettings.cpp
new file mode 100644
index 00000000000..1da25a868f2
--- /dev/null
+++ b/src/preferences/hotcuecolorpalettesettings.cpp
@@ -0,0 +1,36 @@
+#include "preferences/hotcuecolorpalettesettings.h"
+
+const QString HotcueColorPaletteSettings::sGroup = "[HotcueColorPalette]";
+
+ColorPalette HotcueColorPaletteSettings::getHotcueColorPalette() const {
+ QList colorList;
+ for (const ConfigKey& key : m_pConfig->getKeysWithGroup(sGroup)) {
+ QColor color = m_pConfig->getValue(key);
+ if (color.isValid()) {
+ colorList.append(color);
+ }
+ }
+
+ // If no palette is defined in the settings, we use the default one.
+ if (colorList.isEmpty()) {
+ return ColorPalette::mixxxHotcuesPalette;
+ }
+
+ return colorList;
+}
+
+void HotcueColorPaletteSettings::setHotcueColorPalette(
+ const ColorPalette& colorPalette) {
+ removePalette();
+
+ for (int index = 0; index < colorPalette.m_colorList.count(); ++index) {
+ QColor color = colorPalette.m_colorList[index];
+ m_pConfig->setValue(keyForIndex(index), color);
+ }
+}
+
+void HotcueColorPaletteSettings::removePalette() {
+ for (const ConfigKey& key : m_pConfig->getKeysWithGroup(sGroup)) {
+ m_pConfig->remove(key);
+ }
+}
diff --git a/src/preferences/hotcuecolorpalettesettings.h b/src/preferences/hotcuecolorpalettesettings.h
new file mode 100644
index 00000000000..9ed134146a2
--- /dev/null
+++ b/src/preferences/hotcuecolorpalettesettings.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "preferences/usersettings.h"
+#include "util/color/colorpalette.h"
+
+class HotcueColorPaletteSettings {
+ public:
+ explicit HotcueColorPaletteSettings(UserSettingsPointer pConfig)
+ : m_pConfig(pConfig) {
+ }
+
+ ColorPalette getHotcueColorPalette() const;
+
+ void setHotcueColorPalette(const ColorPalette& colorPalette);
+
+ private:
+ static const QString sGroup;
+
+ void removePalette();
+
+ ConfigKey keyForIndex(int index) {
+ return ConfigKey(sGroup, QString::number(index));
+ }
+
+ UserSettingsPointer m_pConfig;
+};
diff --git a/src/skin/skincontext.h b/src/skin/skincontext.h
index 7a81d296318..9c3f86f1918 100644
--- a/src/skin/skincontext.h
+++ b/src/skin/skincontext.h
@@ -12,7 +12,6 @@
#include
#include
-#include "../util/color/predefinedcolorsrepresentation.h"
#include "preferences/usersettings.h"
#include "skin/pixmapsource.h"
#include "util/color/color.h"
@@ -247,20 +246,6 @@ class SkinContext {
return m_scaleFactor;
}
- PredefinedColorsRepresentation getCueColorRepresentation(const QDomNode& node, QColor defaultColor) const {
- PredefinedColorsRepresentation colorRepresentation = Color::kPredefinedColorsSet.defaultRepresentation();
- for (PredefinedColorPointer color : Color::kPredefinedColorsSet.allColors) {
- QString sColorName(color->m_sName);
- QColor skinRgba = selectColor(node, "Cue" + sColorName);
- if (skinRgba.isValid()) {
- PredefinedColorPointer originalColor = Color::kPredefinedColorsSet.predefinedColorFromName(sColorName);
- colorRepresentation.setCustomRgba(originalColor, skinRgba);
- }
- }
- colorRepresentation.setCustomRgba(Color::kPredefinedColorsSet.noColor, defaultColor);
- return colorRepresentation;
- }
-
private:
PixmapSource getPixmapSourceInner(const QString& filename) const;
diff --git a/src/test/colorconfig_test.cpp b/src/test/colorconfig_test.cpp
new file mode 100644
index 00000000000..477bab40a52
--- /dev/null
+++ b/src/test/colorconfig_test.cpp
@@ -0,0 +1,79 @@
+#include
+#include
+
+#include "test/mixxxtest.h"
+
+#include
+#include
+
+class ColorConfigTest : public MixxxTest {};
+
+TEST_F(ColorConfigTest, SavingColorWithoutAlpha) {
+ ConfigKey key("[Color]", "color");
+ QColor originalColor("#FF9900");
+ config()->setValue(key, originalColor);
+ saveAndReloadConfig();
+ QColor colorFromConfig = config()->getValue(key);
+ ASSERT_EQ(originalColor, colorFromConfig);
+}
+
+TEST_F(ColorConfigTest, SavingColorWithAlpha) {
+ ConfigKey key("[Color]", "color");
+ QColor originalColor("#66FF9900");
+ config()->setValue(key, originalColor);
+ saveAndReloadConfig();
+ QColor colorFromConfig = config()->getValue(key);
+ ASSERT_EQ(originalColor, colorFromConfig);
+}
+
+TEST_F(ColorConfigTest, GetDefaultColorWhenNoStoredColor) {
+ ConfigKey key("[Color]", "color");
+ QColor defaultColor("#66FF9900");
+ QColor colorFromConfig = config()->getValue(key, defaultColor);
+ ASSERT_EQ(defaultColor, colorFromConfig);
+}
+
+TEST_F(ColorConfigTest, SaveColorPalette) {
+ HotcueColorPaletteSettings colorPaletteSettings(config());
+ ColorPalette originalColorPalette(QList{
+ QColor("#66FF9900"),
+ QColor("#FF9900"),
+ QColor("#00000000"),
+ QColor("#FFFFFF"),
+ });
+ ConfigKey key("[ColorPalette]", "colorPalette");
+ colorPaletteSettings.setHotcueColorPalette(originalColorPalette);
+ saveAndReloadConfig();
+ ColorPalette colorPaletteFromConfig =
+ colorPaletteSettings.getHotcueColorPalette();
+ ASSERT_EQ(originalColorPalette, colorPaletteFromConfig);
+}
+
+TEST_F(ColorConfigTest, ReplaceColorPalette) {
+ HotcueColorPaletteSettings colorPaletteSettings(config());
+ ColorPalette colorPalette1(QList{
+ QColor("#66FF9900"),
+ QColor("#FF9900"),
+ QColor("#00000000"),
+ QColor("#FFFFFF"),
+ });
+ ColorPalette colorPalette2(QList{
+ QColor("#0000FF"),
+ QColor("#FF0000"),
+ });
+ ConfigKey key("[ColorPalette]", "colorPalette");
+ colorPaletteSettings.setHotcueColorPalette(colorPalette1);
+ saveAndReloadConfig();
+ colorPaletteSettings.setHotcueColorPalette(colorPalette2);
+ saveAndReloadConfig();
+ ColorPalette colorPaletteFromConfig =
+ colorPaletteSettings.getHotcueColorPalette();
+ ASSERT_EQ(colorPalette2, colorPaletteFromConfig);
+}
+
+TEST_F(ColorConfigTest, DefaultColorPalette) {
+ HotcueColorPaletteSettings colorPaletteSettings(config());
+ ColorPalette colorPaletteFromConfig =
+ colorPaletteSettings.getHotcueColorPalette();
+ ASSERT_EQ(ColorPalette::mixxxHotcuesPalette, colorPaletteFromConfig);
+}
diff --git a/src/test/controller_preset_validation_test.cpp b/src/test/controller_preset_validation_test.cpp
index d49ee3e50ba..970cf0158c9 100644
--- a/src/test/controller_preset_validation_test.cpp
+++ b/src/test/controller_preset_validation_test.cpp
@@ -15,7 +15,7 @@
class FakeController : public Controller {
public:
- FakeController();
+ FakeController(UserSettingsPointer pConfig);
~FakeController() override;
QString presetExtension() override {
@@ -112,9 +112,8 @@ class FakeController : public Controller {
HidControllerPreset m_hidPreset;
};
-FakeController::FakeController()
- : m_bMidiPreset(false),
- m_bHidPreset(false) {
+FakeController::FakeController(UserSettingsPointer pConfig)
+ : Controller(pConfig), m_bMidiPreset(false), m_bHidPreset(false) {
}
FakeController::~FakeController() {
@@ -135,7 +134,7 @@ class ControllerPresetValidationTest : public MixxxTest {
return false;
}
- FakeController controller;
+ FakeController controller(config());
controller.setDeviceName("Test Controller");
controller.startEngine();
controller.setPreset(*pPreset);
diff --git a/src/test/controllerengine_test.cpp b/src/test/controllerengine_test.cpp
index d84f736a6ff..ade6169ca5a 100644
--- a/src/test/controllerengine_test.cpp
+++ b/src/test/controllerengine_test.cpp
@@ -1,13 +1,14 @@
-#include
#include
+#include
#include "control/controlobject.h"
#include "control/controlpotmeter.h"
-#include "preferences/usersettings.h"
-#include "controllers/controllerengine.h"
#include "controllers/controllerdebug.h"
+#include "controllers/controllerengine.h"
#include "controllers/softtakeover.h"
+#include "preferences/usersettings.h"
#include "test/mixxxtest.h"
+#include "util/color/colorpalette.h"
#include "util/memory.h"
#include "util/time.h"
@@ -17,7 +18,7 @@ class ControllerEngineTest : public MixxxTest {
mixxx::Time::setTestMode(true);
mixxx::Time::setTestElapsedTime(mixxx::Duration::fromMillis(10));
QThread::currentThread()->setObjectName("Main");
- cEngine = new ControllerEngine(nullptr);
+ cEngine = new ControllerEngine(nullptr, config());
pScriptEngine = cEngine->m_pEngine;
ControllerDebug::enable();
cEngine->setPopups(false);
@@ -618,24 +619,24 @@ TEST_F(ControllerEngineTest, connectionExecutesWithCorrectThisObject) {
EXPECT_DOUBLE_EQ(1.0, pass->get());
}
-TEST_F(ControllerEngineTest, colorProxy) {
- QList allColors = Color::kPredefinedColorsSet.allColors;
+TEST_F(ControllerEngineTest, colorProxyTestMixxxPalette) {
+ QList allColors = ColorPalette::mixxxHotcuesPalette.m_colorList;
for (int i = 0; i < allColors.length(); ++i) {
- PredefinedColorPointer color = allColors[i];
- qDebug() << "Testing color " << color->m_sName;
- QScriptValue jsColor = pScriptEngine->evaluate("color.predefinedColorFromId(" + QString::number(color->m_iId) + ")");
- EXPECT_EQ(jsColor.property("red").toInt32(), color->m_defaultRgba.red());
- EXPECT_EQ(jsColor.property("green").toInt32(), color->m_defaultRgba.green());
- EXPECT_EQ(jsColor.property("blue").toInt32(), color->m_defaultRgba.blue());
- EXPECT_EQ(jsColor.property("alpha").toInt32(), color->m_defaultRgba.alpha());
- EXPECT_EQ(jsColor.property("id").toInt32(), color->m_iId);
-
- QScriptValue jsColor2 = pScriptEngine->evaluate("color.predefinedColorsList()["
- + QString::number(i) + "]");
- EXPECT_EQ(jsColor2.property("red").toInt32(), color->m_defaultRgba.red());
- EXPECT_EQ(jsColor2.property("green").toInt32(), color->m_defaultRgba.green());
- EXPECT_EQ(jsColor2.property("blue").toInt32(), color->m_defaultRgba.blue());
- EXPECT_EQ(jsColor2.property("alpha").toInt32(), color->m_defaultRgba.alpha());
- EXPECT_EQ(jsColor2.property("id").toInt32(), color->m_iId);
+ QColor color = allColors[i];
+ qDebug() << "Testing color " << color.name();
+ QString colorCode = QString::number(color.rgba());
+ QScriptValue jsColor = pScriptEngine->evaluate(
+ "color.colorFromHexCode(" + colorCode + ")");
+ EXPECT_EQ(jsColor.property("red").toInt32(), color.red());
+ EXPECT_EQ(jsColor.property("green").toInt32(), color.green());
+ EXPECT_EQ(jsColor.property("blue").toInt32(), color.blue());
+ EXPECT_EQ(jsColor.property("alpha").toInt32(), color.alpha());
+
+ QScriptValue jsColor2 = pScriptEngine->evaluate(
+ "color.hotcueColorPalette()[" + QString::number(i) + "]");
+ EXPECT_EQ(jsColor2.property("red").toInt32(), color.red());
+ EXPECT_EQ(jsColor2.property("green").toInt32(), color.green());
+ EXPECT_EQ(jsColor2.property("blue").toInt32(), color.blue());
+ EXPECT_EQ(jsColor2.property("alpha").toInt32(), color.alpha());
}
}
diff --git a/src/test/midicontrollertest.cpp b/src/test/midicontrollertest.cpp
index 696483c05fd..0d10c4c54a0 100644
--- a/src/test/midicontrollertest.cpp
+++ b/src/test/midicontrollertest.cpp
@@ -12,7 +12,8 @@
class MockMidiController : public MidiController {
public:
- MockMidiController() { }
+ MockMidiController(UserSettingsPointer pConfig) : MidiController(pConfig) {
+ }
~MockMidiController() override { }
MOCK_METHOD0(open, int());
@@ -27,7 +28,7 @@ class MockMidiController : public MidiController {
class MidiControllerTest : public MixxxTest {
protected:
void SetUp() override {
- m_pController.reset(new MockMidiController());
+ m_pController.reset(new MockMidiController(config()));
}
void addMapping(MidiInputMapping mapping) {
diff --git a/src/test/portmidicontroller_test.cpp b/src/test/portmidicontroller_test.cpp
index b8b9cb63594..8daf1f43d99 100644
--- a/src/test/portmidicontroller_test.cpp
+++ b/src/test/portmidicontroller_test.cpp
@@ -16,11 +16,15 @@ using ::testing::SetArrayArgument;
class MockPortMidiController : public PortMidiController {
public:
MockPortMidiController(const PmDeviceInfo* inputDeviceInfo,
- const PmDeviceInfo* outputDeviceInfo,
- int inputDeviceIndex,
- int outputDeviceIndex) : PortMidiController(
- inputDeviceInfo, outputDeviceInfo,
- inputDeviceIndex, outputDeviceIndex) {
+ const PmDeviceInfo* outputDeviceInfo,
+ int inputDeviceIndex,
+ int outputDeviceIndex,
+ UserSettingsPointer pConfig)
+ : PortMidiController(inputDeviceInfo,
+ outputDeviceInfo,
+ inputDeviceIndex,
+ outputDeviceIndex,
+ pConfig) {
}
~MockPortMidiController() override {
}
@@ -71,9 +75,8 @@ class PortMidiControllerTest : public MixxxTest {
m_outputDeviceInfo.output = 1;
m_outputDeviceInfo.opened = 0;
- m_pController.reset(new MockPortMidiController(&m_inputDeviceInfo,
- &m_outputDeviceInfo,
- 0, 0));
+ m_pController.reset(new MockPortMidiController(
+ &m_inputDeviceInfo, &m_outputDeviceInfo, 0, 0, config()));
m_pController->setPortMidiInputDevice(m_mockInput);
m_pController->setPortMidiOutputDevice(m_mockOutput);
}
diff --git a/src/track/cue.cpp b/src/track/cue.cpp
index f4d8711f85d..2c34957a2f2 100644
--- a/src/track/cue.cpp
+++ b/src/track/cue.cpp
@@ -28,12 +28,18 @@ Cue::Cue(TrackId trackId)
m_sampleEndPosition(Cue::kNoPosition),
m_iHotCue(-1),
m_label(kDefaultLabel),
- m_color(Color::kPredefinedColorsSet.noColor) {
+ m_color(QColor()) {
DEBUG_ASSERT(!m_label.isNull());
}
-Cue::Cue(int id, TrackId trackId, Cue::Type type, double position, double length,
- int hotCue, QString label, PredefinedColorPointer color)
+Cue::Cue(int id,
+ TrackId trackId,
+ Cue::Type type,
+ double position,
+ double length,
+ int hotCue,
+ QString label,
+ QColor color)
: m_bDirty(false),
m_iId(id),
m_trackId(trackId),
@@ -153,12 +159,12 @@ void Cue::setLabel(const QString label) {
emit(updated());
}
-PredefinedColorPointer Cue::getColor() const {
+QColor Cue::getColor() const {
QMutexLocker lock(&m_mutex);
return m_color;
}
-void Cue::setColor(const PredefinedColorPointer color) {
+void Cue::setColor(const QColor& color) {
QMutexLocker lock(&m_mutex);
m_color = color;
m_bDirty = true;
diff --git a/src/track/cue.h b/src/track/cue.h
index ffc1c814690..9b6d133766a 100644
--- a/src/track/cue.h
+++ b/src/track/cue.h
@@ -6,7 +6,6 @@
#include
#include "track/trackid.h"
-#include "util/color/predefinedcolor.h"
#include "util/memory.h"
class CuePosition;
@@ -54,8 +53,8 @@ class Cue : public QObject {
QString getLabel() const;
void setLabel(QString label);
- PredefinedColorPointer getColor() const;
- void setColor(PredefinedColorPointer color);
+ QColor getColor() const;
+ void setColor(const QColor& color);
double getEndPosition() const;
@@ -64,8 +63,14 @@ class Cue : public QObject {
private:
explicit Cue(TrackId trackId);
- Cue(int id, TrackId trackId, Cue::Type type, double position, double length,
- int hotCue, QString label, PredefinedColorPointer color);
+ Cue(int id,
+ TrackId trackId,
+ Cue::Type type,
+ double position,
+ double length,
+ int hotCue,
+ QString label,
+ QColor color);
void setDirty(bool dirty);
void setId(int id);
void setTrackId(TrackId trackId);
@@ -80,7 +85,7 @@ class Cue : public QObject {
double m_sampleEndPosition;
int m_iHotCue;
QString m_label;
- PredefinedColorPointer m_color;
+ QColor m_color;
friend class Track;
friend class CueDAO;
diff --git a/src/util/color/color.cpp b/src/util/color/color.cpp
index 4627fdf3d9a..92116acb748 100644
--- a/src/util/color/color.cpp
+++ b/src/util/color/color.cpp
@@ -4,8 +4,6 @@
namespace Color {
-const PredefinedColorsSet kPredefinedColorsSet = PredefinedColorsSet();
-
// algorithm by http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
// NOTE(Swiftb0y): please suggest if I should you use other methods
// (like the W3C algorithm) or if this approach is to to performance hungry
diff --git a/src/util/color/color.h b/src/util/color/color.h
index 13401e05254..e5196a409e7 100644
--- a/src/util/color/color.h
+++ b/src/util/color/color.h
@@ -1,11 +1,9 @@
#pragma once
-#include "util/color/predefinedcolorsset.h"
+#include
namespace Color {
-extern const PredefinedColorsSet kPredefinedColorsSet;
-
int brightness(int red, int green, int blue);
inline int brightness(const QColor& color) {
diff --git a/src/util/color/colorpalette.cpp b/src/util/color/colorpalette.cpp
new file mode 100644
index 00000000000..7334763b6f1
--- /dev/null
+++ b/src/util/color/colorpalette.cpp
@@ -0,0 +1,18 @@
+//
+// Created by Ferran Pujol Camins on 27/10/2019.
+//
+
+#include "colorpalette.h"
+
+ColorPalette::ColorPalette(QList colorList) : m_colorList(colorList) {
+}
+
+const ColorPalette ColorPalette::mixxxHotcuesPalette =
+ ColorPalette(QList{QColor("#c50a08"),
+ QColor("#32be44"),
+ QColor("#0044ff"),
+ QColor("#f8d200"),
+ QColor("#42d4f4"),
+ QColor("#af00cc"),
+ QColor("#fca6d7"),
+ QColor("#f2f2ff")});
diff --git a/src/util/color/colorpalette.h b/src/util/color/colorpalette.h
new file mode 100644
index 00000000000..eb276a2fecd
--- /dev/null
+++ b/src/util/color/colorpalette.h
@@ -0,0 +1,21 @@
+//
+// Created by Ferran Pujol Camins on 27/10/2019.
+//
+
+#pragma once
+
+#include
+#include "QList"
+
+class ColorPalette {
+ public:
+ ColorPalette(QList);
+
+ static const ColorPalette mixxxHotcuesPalette;
+
+ QList m_colorList;
+};
+
+inline bool operator==(const ColorPalette& lhs, const ColorPalette& rhs) {
+ return lhs.m_colorList == rhs.m_colorList;
+}
diff --git a/src/util/color/predefinedcolor.cpp b/src/util/color/predefinedcolor.cpp
deleted file mode 100644
index 2a5db56e987..00000000000
--- a/src/util/color/predefinedcolor.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "util/color/predefinedcolor.h"
-
-#include "util/color/color.h"
-
-PredefinedColor::PredefinedColor(QColor defaultRgba, QString sName, QString sDisplayName, int iId)
- : m_defaultRgba(defaultRgba),
- m_sName(sName),
- m_sDisplayName(sDisplayName),
- m_iId(iId) {
-}
diff --git a/src/util/color/predefinedcolor.h b/src/util/color/predefinedcolor.h
deleted file mode 100644
index 4e5745c0883..00000000000
--- a/src/util/color/predefinedcolor.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-
-#include
-
-#include "util/memory.h"
-
-// The PredefinedColor class is used to represent a Mixxx identificable color.
-// A PredefinedColor can be uniquely identified with its m_iId property.
-//
-// PredefinedColors have a default Rgba value. A PredefinedColorsMap can provide with an alternative
-// Rgba value for each PredefinedColor. Thus, a PredefinedColorsMap defines a particular way to render
-// the PredefinedColors.
-class PredefinedColor final {
- public:
- PredefinedColor(QColor defaultRgba, QString sName, QString sDisplayName, int iId);
-
- inline bool operator==(const PredefinedColor& other) const {
- return m_iId == other.m_iId;
- }
-
- inline bool operator!=(const PredefinedColor& other) const {
- return m_iId != other.m_iId;
- }
-
- // The QColor that is used by default to render this PredefinedColor.
- const QColor m_defaultRgba;
- // The name of the color used programmatically, e.g. on skin files.
- const QString m_sName;
- // The name of the color used on UI.
- const QString m_sDisplayName;
- // An Id uniquely identifying this predefined color.
- // This value is used to identify a color on the DB and control objects.
- const int m_iId;
-};
-typedef std::shared_ptr PredefinedColorPointer;
diff --git a/src/util/color/predefinedcolorsrepresentation.h b/src/util/color/predefinedcolorsrepresentation.h
deleted file mode 100644
index 83f16405447..00000000000
--- a/src/util/color/predefinedcolorsrepresentation.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef PREDEFINEDCOLORSREPRESENTATION_H
-#define PREDEFINEDCOLORSREPRESENTATION_H
-
-#include
-#include
-
-#include "util/color/predefinedcolor.h"
-
-// PredefinedColorsRepresentation defines a particular way to render Mixxx PredefinedColors.
-//
-// PredefinedColorsRepresentation maps a PredefinedColor to a custom Rgba color.
-// Initially no color has a custom Rgba set.
-// Call setCustomRgba(PredefinedColorPointer, QColor) to add a custom Rgba for a predefined color
-// and customize the color map.
-//
-// This class uses the color's name() property as key, e.g. "#A9A9A9"
-// Since QHash has copy-on-write, making a copy of PredefinedColorsRepresentation is fast.
-// A deep copy of the QHash will be made when a copy is modified.
-class PredefinedColorsRepresentation final {
- public:
- // Set a custom Rgba for a given color
- void setCustomRgba(PredefinedColorPointer color, QColor cutomizedRgba) {
- m_colorNameMap[color->m_defaultRgba.name()] = cutomizedRgba.name();
- }
-
- // Returns the custom Rgba of a color.
- // If no custom Rgba is set for color, returns color->m_defaultRgba.
- QColor representationFor(PredefinedColorPointer color) const {
- QColor defaultRgba = color->m_defaultRgba;
- if (m_colorNameMap.contains(defaultRgba.name())) {
- return QColor(m_colorNameMap[defaultRgba.name()]);
- }
- return defaultRgba;
- }
-
-
- private:
- QHash m_colorNameMap;
-};
-
-#endif /* PREDEFINEDCOLORSREPRESENTATION_H */
diff --git a/src/util/color/predefinedcolorsset.h b/src/util/color/predefinedcolorsset.h
deleted file mode 100644
index f2dbff29ee2..00000000000
--- a/src/util/color/predefinedcolorsset.h
+++ /dev/null
@@ -1,120 +0,0 @@
-#pragma once
-
-#include
-#include
-
-#include "predefinedcolorsrepresentation.h"
-#include "util/color/predefinedcolor.h"
-
-// This class defines a set of predefined colors and provides some handy functions to work with them.
-// A single global instance is create in the Color namespace.
-// This class is thread-safe because all its methods and public properties are const.
-class PredefinedColorsSet final {
- public:
- const PredefinedColorPointer noColor = std::make_shared(
- QColor(),
- QLatin1String("No Color"),
- QObject::tr("No Color"),
- 0);
- const PredefinedColorPointer red = std::make_shared(
- QColor("#c50a08"),
- QLatin1String("Red"),
- QObject::tr("Red"),
- 1);
- const PredefinedColorPointer green = std::make_shared(
- QColor("#32be44"),
- QLatin1String("Green"),
- QObject::tr("Green"),
- 2);
- const PredefinedColorPointer blue = std::make_shared(
- QColor("#0044ff"),
- QLatin1String("Blue"),
- QObject::tr("Blue"),
- 3);
- const PredefinedColorPointer yellow = std::make_shared(
- QColor("#f8d200"),
- QLatin1String("Yellow"),
- QObject::tr("Yellow"),
- 4);
- const PredefinedColorPointer cyan = std::make_shared(
- QColor("#42d4f4"),
- QLatin1String("Celeste"),
- QObject::tr("Celeste"),
- 5);
- const PredefinedColorPointer magenta = std::make_shared(
- QColor("#af00cc"),
- QLatin1String("Purple"),
- QObject::tr("Purple"),
- 6);
- const PredefinedColorPointer pink = std::make_shared(
- QColor("#fca6d7"),
- QLatin1String("Pink"),
- QObject::tr("Pink"),
- 7);
- const PredefinedColorPointer white = std::make_shared(
- QColor("#f2f2ff"),
- QLatin1String("White"),
- QObject::tr("White"),
- 8);
-
- // The list of the predefined colors.
- const QList allColors{
- noColor,
- red,
- green,
- yellow,
- blue,
- cyan,
- magenta,
- pink,
- white,
- };
-
- PredefinedColorsSet()
- : m_defaultRepresentation() {
- for (PredefinedColorPointer color : allColors) {
- m_defaultRepresentation.setCustomRgba(color, color->m_defaultRgba);
- }
- }
-
- // Returns the position of a PredefinedColor in the allColors list.
- int predefinedColorIndex(PredefinedColorPointer searchedColor) const {
- for (int position = 0; position < allColors.count(); ++position) {
- PredefinedColorPointer color(allColors.at(position));
- if (*color == *searchedColor) {
- return position;
- }
- }
- return 0;
- };
-
- // Return a predefined color from its name.
- // Return noColor if there's no color with such name.
- PredefinedColorPointer predefinedColorFromName(QString name) const {
- for (PredefinedColorPointer color : allColors) {
- if (color->m_sName == name) {
- return color;
- }
- }
- return noColor;
- };
-
- // Return a predefined color from its id.
- // Return noColor if there's no color with iId.
- PredefinedColorPointer predefinedColorFromId(int iId) const {
- for (PredefinedColorPointer color : allColors) {
- if (color->m_iId == iId) {
- return color;
- }
- }
- return noColor;
- };
-
- // The default color representation, i.e. maps each predefined color to its default Rgba.
- PredefinedColorsRepresentation defaultRepresentation() const {
- return m_defaultRepresentation;
- };
-
- private:
- PredefinedColorsRepresentation m_defaultRepresentation;
-};
diff --git a/src/waveform/renderers/waveformrendermark.cpp b/src/waveform/renderers/waveformrendermark.cpp
index 1d338688e08..26a840e8974 100644
--- a/src/waveform/renderers/waveformrendermark.cpp
+++ b/src/waveform/renderers/waveformrendermark.cpp
@@ -27,11 +27,6 @@ WaveformRenderMark::WaveformRenderMark(
void WaveformRenderMark::setup(const QDomNode& node, const SkinContext& context) {
WaveformSignalColors signalColors = *m_waveformRenderer->getWaveformSignalColors();
m_marks.setup(m_waveformRenderer->getGroup(), node, context, signalColors);
- WaveformMarkPointer defaultMark(m_marks.getDefaultMark());
- QColor defaultColor = defaultMark
- ? defaultMark->fillColor()
- : signalColors.getAxesColor();
- m_predefinedColorsRepresentation = context.getCueColorRepresentation(node, defaultColor);
}
void WaveformRenderMark::draw(QPainter* painter, QPaintEvent* /*event*/) {
@@ -128,7 +123,7 @@ void WaveformRenderMark::slotCuesUpdated() {
}
QString newLabel = pCue->getLabel();
- QColor newColor = m_predefinedColorsRepresentation.representationFor(pCue->getColor());
+ QColor newColor = pCue->getColor();
if (pMark->m_text.isNull() || newLabel != pMark->m_text ||
!pMark->fillColor().isValid() || newColor != pMark->fillColor()) {
pMark->m_text = newLabel;
diff --git a/src/waveform/renderers/waveformrendermark.h b/src/waveform/renderers/waveformrendermark.h
index 693332c8162..dc0fad17c90 100644
--- a/src/waveform/renderers/waveformrendermark.h
+++ b/src/waveform/renderers/waveformrendermark.h
@@ -35,8 +35,6 @@ class WaveformRenderMark : public QObject, public WaveformRendererAbstract {
private:
void generateMarkImage(WaveformMarkPointer pMark);
- PredefinedColorsRepresentation m_predefinedColorsRepresentation;
-
WaveformMarkSet m_marks;
DISALLOW_COPY_AND_ASSIGN(WaveformRenderMark);
};
diff --git a/src/widget/colormenu.cpp b/src/widget/colormenu.cpp
index 543b2710842..1ceabc888fe 100644
--- a/src/widget/colormenu.cpp
+++ b/src/widget/colormenu.cpp
@@ -1,39 +1,78 @@
#include "widget/colormenu.h"
+
#include "util/color/color.h"
-ColorMenu::ColorMenu(QWidget *parent)
- : QMenu(parent) {
+ColorMenu::ColorMenu(QWidget* parent)
+ : QMenu(parent), m_pColorDialog(new QColorDialog(this)) {
// If another title would be more appropriate in some context, setTitle
// can be called again after construction.
setTitle(tr("Set color"));
- for (const auto& pColor : Color::kPredefinedColorsSet.allColors) {
- if (*pColor == *Color::kPredefinedColorsSet.noColor) {
- continue;
- }
+ useColorPalette(ColorPalette::mixxxHotcuesPalette);
+
+ connect(m_pColorDialog,
+ &QColorDialog::colorSelected,
+ this,
+ [this](const QColor& newColor) {
+ if (newColor.isValid()) {
+ emit(colorPicked(newColor));
+ }
+ });
+}
+
+void ColorMenu::useColorPalette(const ColorPalette& colorPalette) {
+ clear();
+ m_pActionGroup = new QActionGroup(this);
+ m_pActionGroup->setExclusive(true);
+
+ createPaletteColorsActions(colorPalette);
+ createColorPickerAction();
+}
- QAction* pColorAction = new QAction(pColor->m_sDisplayName, this);
+void ColorMenu::setCurrentColor(QColor currentColor) {
+ m_currentColor = currentColor;
+ selectCurrentColorAction(currentColor);
+}
+
+void ColorMenu::openColorDialog() {
+ m_pColorDialog->setCurrentColor(m_currentColor);
+ m_pColorDialog->open();
+}
+
+void ColorMenu::createPaletteColorsActions(const ColorPalette& colorPalette) {
+ for (const auto& color : colorPalette.m_colorList) {
+ QAction* pColorAction = new QAction(m_pActionGroup);
QPixmap pixmap(80, 80);
- pixmap.fill(pColor->m_defaultRgba);
+ pixmap.fill(color);
pColorAction->setIcon(QIcon(pixmap));
+ pColorAction->setCheckable(true);
+ pColorAction->setData(color);
- m_pColorActions.insert(pColor, pColorAction);
addAction(pColorAction);
- connect(pColorAction, &QAction::triggered, this, [pColor, this]() {
- emit(colorPicked(pColor));
+ connect(pColorAction, &QAction::triggered, this, [color, this]() {
+ emit(colorPicked(color));
});
}
}
-void ColorMenu::useColorSet(PredefinedColorsRepresentation* pColorRepresentation) {
- QMapIterator i(m_pColorActions);
- while (i.hasNext()) {
- i.next();
- QPixmap pixmap(80, 80);
- if (pColorRepresentation == nullptr) {
- pixmap.fill(i.key()->m_defaultRgba);
- } else {
- pixmap.fill(pColorRepresentation->representationFor(i.key()));
+void ColorMenu::createColorPickerAction() {
+ m_pColorPickerAction = new QAction(m_pActionGroup);
+ m_pColorPickerAction->setText(tr("Other") + "…");
+ m_pColorPickerAction->setCheckable(true);
+ addAction(m_pColorPickerAction);
+ connect(m_pColorPickerAction,
+ &QAction::triggered,
+ this,
+ &ColorMenu::openColorDialog);
+}
+
+void ColorMenu::selectCurrentColorAction(const QColor& currentColor) const {
+ for (QAction* pAction : actions()) {
+ QColor color = pAction->data().value();
+ // Other color action is the last one, if we find it, we didn't
+ // matched to any color action.
+ if (color == currentColor || pAction == m_pColorPickerAction) {
+ pAction->setChecked(true);
+ return;
}
- i.value()->setIcon(QIcon(pixmap));
}
}
diff --git a/src/widget/colormenu.h b/src/widget/colormenu.h
index 4c82943cbb8..e661a8996f4 100644
--- a/src/widget/colormenu.h
+++ b/src/widget/colormenu.h
@@ -1,19 +1,31 @@
#pragma once
+#include
#include
-#include "util/color/color.h"
+#include "util/color/colorpalette.h"
class ColorMenu : public QMenu {
Q_OBJECT
public:
ColorMenu(QWidget *parent = nullptr);
- void useColorSet(PredefinedColorsRepresentation* pColorRepresentation);
+ void useColorPalette(const ColorPalette& colorPalette);
+ void setCurrentColor(QColor currentColor);
signals:
- void colorPicked(PredefinedColorPointer pColor);
+ void colorPicked(QColor pColor);
+
+ private slots:
+ void openColorDialog();
private:
- QMap m_pColorActions;
+ void createPaletteColorsActions(const ColorPalette& colorPalette);
+ void createColorPickerAction();
+ void selectCurrentColorAction(const QColor& currentColor) const;
+
+ QColor m_currentColor;
+ QAction* m_pColorPickerAction;
+ QActionGroup* m_pActionGroup;
+ QColorDialog* m_pColorDialog;
};
diff --git a/src/widget/cuemenu.cpp b/src/widget/cuemenu.cpp
index b9d62a30911..53d88736e8a 100644
--- a/src/widget/cuemenu.cpp
+++ b/src/widget/cuemenu.cpp
@@ -37,14 +37,8 @@ void CueMenu::slotEditLabel() {
}
}
-void CueMenu::slotChangeCueColor(PredefinedColorPointer pColor) {
- VERIFY_OR_DEBUG_ASSERT(m_pCue != nullptr) {
- return;
- }
- VERIFY_OR_DEBUG_ASSERT(pColor != nullptr) {
- return;
- }
- m_pCue->setColor(pColor);
+void CueMenu::slotChangeCueColor(QColor color) {
+ m_pCue->setColor(color);
}
void CueMenu::slotRemoveCue() {
diff --git a/src/widget/cuemenu.h b/src/widget/cuemenu.h
index 3802292e44a..5bf1a080649 100644
--- a/src/widget/cuemenu.h
+++ b/src/widget/cuemenu.h
@@ -14,22 +14,23 @@ class CueMenu : public QMenu {
void setCue(CuePointer pCue) {
m_pCue = pCue;
+ m_pColorMenu->setCurrentColor(m_pCue->getColor());
}
void setTrack(TrackPointer pTrack) {
m_pTrack = pTrack;
}
- void useColorSet(PredefinedColorsRepresentation* pColorRepresentation) {
+ void useColorSet(const ColorPalette& colorPalette) {
if (m_pColorMenu != nullptr) {
- m_pColorMenu->useColorSet(pColorRepresentation);
+ m_pColorMenu->useColorPalette(colorPalette);
}
}
private slots:
void slotEditLabel();
void slotRemoveCue();
- void slotChangeCueColor(PredefinedColorPointer pColor);
+ void slotChangeCueColor(QColor color);
private:
CuePointer m_pCue;
diff --git a/src/widget/woverview.cpp b/src/widget/woverview.cpp
index 62697f2ae01..e543197fa68 100644
--- a/src/widget/woverview.cpp
+++ b/src/widget/woverview.cpp
@@ -25,6 +25,7 @@
#include "control/controlproxy.h"
#include "engine/engine.h"
#include "mixer/playermanager.h"
+#include "preferences/hotcuecolorpalettesettings.h"
#include "track/track.h"
#include "util/color/color.h"
#include "util/compatibility.h"
@@ -131,12 +132,9 @@ void WOverview::setup(const QDomNode& node, const SkinContext& context) {
// setup hotcues and cue and loop(s)
m_marks.setup(m_group, node, context, m_signalColors);
- WaveformMarkPointer defaultMark(m_marks.getDefaultMark());
- QColor defaultColor = defaultMark
- ? defaultMark->fillColor()
- : m_signalColors.getAxesColor();
- m_predefinedColorsRepresentation = context.getCueColorRepresentation(node, defaultColor);
- m_pCueMenu->useColorSet(&m_predefinedColorsRepresentation);
+ HotcueColorPaletteSettings colorPaletteSettings(m_pConfig);
+ auto colorPalette = colorPaletteSettings.getHotcueColorPalette();
+ m_pCueMenu->useColorSet(colorPalette);
for (const auto& pMark: m_marks) {
if (pMark->isValid()) {
@@ -339,7 +337,7 @@ void WOverview::updateCues(const QList &loadedCues) {
const WaveformMarkPointer pMark = m_marks.getHotCueMark(currentCue->getHotCue());
if (pMark != nullptr && pMark->isValid() && pMark->isVisible() && pMark->getSamplePosition() != Cue::kNoPosition) {
- QColor newColor = m_predefinedColorsRepresentation.representationFor(currentCue->getColor());
+ QColor newColor = currentCue->getColor();
if (newColor != pMark->fillColor() || newColor != pMark->m_textColor) {
pMark->setBaseColor(newColor);
}
diff --git a/src/widget/woverview.h b/src/widget/woverview.h
index d5bcc4792ac..eaf5dca108c 100644
--- a/src/widget/woverview.h
+++ b/src/widget/woverview.h
@@ -167,7 +167,6 @@ class WOverview : public WWidget, public TrackDropTarget {
QColor m_labelBackgroundColor;
QColor m_endOfTrackColor;
- PredefinedColorsRepresentation m_predefinedColorsRepresentation;
// All WaveformMarks
WaveformMarkSet m_marks;
// List of visible WaveformMarks sorted by the order they appear in the track
diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp
index 271dd42be02..ac8ce5a9103 100644
--- a/src/widget/wtracktableview.cpp
+++ b/src/widget/wtracktableview.cpp
@@ -764,7 +764,7 @@ void WTrackTableView::showTrackInfo(QModelIndex index) {
if (m_pTrackInfo.isNull()) {
// Give a NULL parent because otherwise it inherits our style which can
// make it unreadable. Bug #673411
- m_pTrackInfo.reset(new DlgTrackInfo(nullptr));
+ m_pTrackInfo.reset(new DlgTrackInfo(nullptr, m_pConfig));
connect(m_pTrackInfo.data(), SIGNAL(next()),
this, SLOT(slotNextTrackInfo()));
diff --git a/src/widget/wwidget.cpp b/src/widget/wwidget.cpp
index 364b46280a1..5d523663139 100644
--- a/src/widget/wwidget.cpp
+++ b/src/widget/wwidget.cpp
@@ -26,7 +26,8 @@ WWidget::WWidget(QWidget* parent, Qt::WindowFlags flags)
: QWidget(parent, flags),
WBaseWidget(this),
m_activeTouchButton(Qt::NoButton),
- m_scaleFactor(1.0) {
+ m_scaleFactor(1.0),
+ m_bShouldHighlightBackgroundOnHover(false) {
m_pTouchShift = new ControlProxy("[Controls]", "touch_shift");
setAttribute(Qt::WA_StaticContents);
setAttribute(Qt::WA_AcceptTouchEvents);
@@ -37,6 +38,31 @@ WWidget::~WWidget() {
delete m_pTouchShift;
}
+double WWidget::getBackgroundColorRgba() const {
+ if (m_backgroundColorRgba >= 0) {
+ return m_backgroundColorRgba;
+ }
+ return -1;
+}
+
+void WWidget::setBackgroundColorRgba(double rgba) {
+ QColor backgroundColor = QColor::fromRgba(rgba);
+ QColor highlightedBackgroundColor = backgroundColor.lighter();
+ QString style = QString("WWidget { background-color: %1; }");
+ if (m_bShouldHighlightBackgroundOnHover) {
+ style += "WWidget:hover { background-color: %2; }";
+ }
+
+ if (rgba >= 0) {
+ setStyleSheet(style.arg(backgroundColor.name())
+ .arg(highlightedBackgroundColor.name()));
+ } else {
+ setStyleSheet("");
+ }
+ m_backgroundColorRgba = rgba;
+ m_bBackgroundIsDark = Color::isDimmColor(backgroundColor);
+}
+
bool WWidget::touchIsRightButton() {
return (m_pTouchShift->get() != 0.0);
}
diff --git a/src/widget/wwidget.h b/src/widget/wwidget.h
index cbadf8ab2fe..0fbf10631c2 100644
--- a/src/widget/wwidget.h
+++ b/src/widget/wwidget.h
@@ -23,6 +23,7 @@
#include
#include "preferences/usersettings.h"
+#include "util/color/color.h"
#include "widget/wbasewidget.h"
class ControlProxy;
@@ -44,6 +45,21 @@ class WWidget : public QWidget, public WBaseWidget {
~WWidget() override;
Q_PROPERTY(double value READ getControlParameterDisplay);
+ Q_PROPERTY(double backgroundColorRgba READ getBackgroundColorRgba WRITE
+ setBackgroundColorRgba);
+ Q_PROPERTY(bool shouldHighlightBackgroundOnHover MEMBER
+ m_bShouldHighlightBackgroundOnHover);
+ Q_PROPERTY(bool hasBackgroundColor READ hasBackgroundColor);
+ Q_PROPERTY(bool backgroundIsDark READ backgroundIsDark);
+
+ double getBackgroundColorRgba() const;
+ void setBackgroundColorRgba(double rgba);
+ bool hasBackgroundColor() const {
+ return m_backgroundColorRgba >= 0;
+ }
+ bool backgroundIsDark() const {
+ return m_bBackgroundIsDark;
+ }
protected:
bool touchIsRightButton();
@@ -60,6 +76,9 @@ class WWidget : public QWidget, public WBaseWidget {
private:
ControlProxy* m_pTouchShift;
double m_scaleFactor;
+ double m_backgroundColorRgba;
+ bool m_bBackgroundIsDark;
+ bool m_bShouldHighlightBackgroundOnHover;
};
#endif