diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7959253ab48..e581293c3d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -680,6 +680,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/widget/weffectparameterknobcomposed.cpp
src/widget/weffectpushbutton.cpp
src/widget/weffectselector.cpp
+ src/widget/whotcuebutton.cpp
src/widget/wimagestore.cpp
src/widget/wkey.cpp
src/widget/wknob.cpp
diff --git a/build/depends.py b/build/depends.py
index e13d2df5b3b..eee9463315a 100644
--- a/build/depends.py
+++ b/build/depends.py
@@ -960,6 +960,7 @@ def sources(self, build):
"src/widget/wvumeter.cpp",
"src/widget/wpushbutton.cpp",
"src/widget/weffectpushbutton.cpp",
+ "src/widget/whotcuebutton.cpp",
"src/widget/wslidercomposed.cpp",
"src/widget/wstatuslight.cpp",
"src/widget/woverview.cpp",
diff --git a/res/skins/Deere/hotcue_button.xml b/res/skins/Deere/hotcue_button.xml
index 2712d6eb0f0..bbf386b73c9 100644
--- a/res/skins/Deere/hotcue_button.xml
+++ b/res/skins/Deere/hotcue_button.xml
@@ -8,46 +8,23 @@
SmallSquareButtonSize: the button size
-->
-
+
hotcue
HotcueButton
18,22
22,22
me,f
+
+
+ true
2
-
-
0
-
-
1
-
-
-
- ,hotcue__activate
- true
- LeftButton
- false
-
-
- ,hotcue__clear
- true
- RightButton
- false
-
-
- ,hotcue__enabled
- false
-
-
- ,hotcue__color
- backgroundColorRgba
-
-
+
diff --git a/res/skins/Deere/style.qss b/res/skins/Deere/style.qss
index 5480087178c..ac8d45ef1c2 100644
--- a/res/skins/Deere/style.qss
+++ b/res/skins/Deere/style.qss
@@ -1558,15 +1558,7 @@ WPushButton[value="2"]:hover {
border: 1px solid #0080BE;
}
-#HotcueButton {
- qproperty-shouldHighlightBackgroundOnHover: true;
-}
-
-#HotcueButton[backgroundIsDark=true][hasBackgroundColor=true] {
- color: #FDFDFD;
-}
-
-#HotcueButton[backgroundIsDark=false][hasBackgroundColor=true] {
+#HotcueButton[light="true"] {
color: #1f1e1e;
}
diff --git a/res/skins/LateNight/button_hotcue.xml b/res/skins/LateNight/button_hotcue.xml
index 920ffc05d32..dd4eb7d197c 100644
--- a/res/skins/LateNight/button_hotcue.xml
+++ b/res/skins/LateNight/button_hotcue.xml
@@ -7,12 +7,14 @@
me,f
horizontal
-
+
hotcue
HotcueButton
26,26
26,26
me,f
+
+
2
0
@@ -24,23 +26,7 @@
skin:/buttons_/btn__square_set.svg
skin:/buttons_/btn__square_active.svg
-
- ,hotcue__activate
- LeftButton
-
-
- ,hotcue__clear
- RightButton
-
-
- ,hotcue__enabled
- false
-
-
- ,hotcue__color
- backgroundColorRgba
-
-
+
diff --git a/res/skins/LateNight/style.qss b/res/skins/LateNight/style.qss
index c51102c3e5b..1f07ae4b592 100644
--- a/res/skins/LateNight/style.qss
+++ b/res/skins/LateNight/style.qss
@@ -638,7 +638,7 @@ QPushButton#pushButtonAutoDJ:enabled:!checked,
brighter bg color to enhance contrast in darker containers
and with small size respectively */
#DeckRow_5_LoopCuesTransport WPushButton[value="0"],
-#HotcueButton[displayValue="0"],
+#HotcueButton,
#FxAssignButton[displayValue="0"], #FxFocusButton[displayValue="0"],
#FxToggleButton[displayValue="0"], #FxParameterButton[displayValue="0"],
#SplitCueButton[value="0"],
@@ -684,11 +684,8 @@ QPushButton#pushButtonRecording:checked,
#RecFeedback[displayValue="2"],
#BeatgridButtons WPushButton[value="1"],
#KeyMatchButton[displayValue="1"],
-#KeyUpButton[displayValue="1"], #KeyDownButton[displayValue="1"],
-#HotcueButton[displayValue="1"][highlight="0"],
-#HotcueButton[displayValue="2"][highlight="0"],
-#HotcueButton[displayValue="1"][highlight="1"],
-#HotcueButton[displayValue="2"][highlight="1"] {
+#KeyUpButton[displayValue="1"],
+#KeyDownButton[displayValue="1"] {
background-color: #db0000;
}
@@ -714,8 +711,10 @@ QPushButton#pushButtonAutoDJ:checked,
#MicDuckingButton[value="2"] {
background-color: #d09300;
}
-/* ToDo
- * orange Play button when playing from Cue / Hotcue */
+
+#SpecialCueButton[value="1"] {
+ background-color: #0044ff;
+}
/************** Button icons **************************************************/
diff --git a/res/skins/LateNight/style_flip.qss b/res/skins/LateNight/style_flip.qss
index 1a99ea88c56..23b34f6318b 100644
--- a/res/skins/LateNight/style_flip.qss
+++ b/res/skins/LateNight/style_flip.qss
@@ -290,7 +290,7 @@ WSearchLineEdit {
#GuiToggleButton[displayValue="0"], #RecFeedback[displayValue="0"],
#BroadcastButton[displayValue="0"], #SettingsButton[displayValue="0"],
#DeckRow_5_LoopCuesTransport WPushButton[value="0"],
-#HotcueButton[displayValue="0"],
+#HotcueButton,
#FxAssignButton[displayValue="0"], #FxFocusButton[displayValue="0"],
#FxToggleButton[displayValue="0"], #FxParameterButton[displayValue="0"],
#SplitCueButton[value="0"],
@@ -909,7 +909,7 @@ WEffectSelector {
WLibrary,
#SidebarBox {
/* only 1px padding to compensate the 2px border of inner widgets
- (QTreeView, QTableView, QTextBrowser) */
+ (QTreeView, QTableView, QTextBrowser) */
padding: 1px 1px 0px 1px;
border-bottom: 0px;
border-left: 1px solid qlineargradient(
diff --git a/res/skins/Shade/btn/btn_hotcue_1.png b/res/skins/Shade/btn/btn_hotcue_1.png
index 86f572261d9..bbcc063c525 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_over.png b/res/skins/Shade/btn/btn_hotcue_1_over.png
new file mode 100644
index 00000000000..be7b4dcf962
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_1_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_1_overdown.png b/res/skins/Shade/btn/btn_hotcue_1_overdown.png
new file mode 100644
index 00000000000..99eb9f665f0
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_1_overdown.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_2.png b/res/skins/Shade/btn/btn_hotcue_2.png
index 6c93b48fe2e..f085b9f63a3 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_over.png b/res/skins/Shade/btn/btn_hotcue_2_over.png
new file mode 100644
index 00000000000..45378b2312e
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_2_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_2_overdown.png b/res/skins/Shade/btn/btn_hotcue_2_overdown.png
new file mode 100644
index 00000000000..b9195bb7d20
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_2_overdown.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_3.png b/res/skins/Shade/btn/btn_hotcue_3.png
index b6494126f05..2ccd932a164 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_over.png b/res/skins/Shade/btn/btn_hotcue_3_over.png
new file mode 100644
index 00000000000..37f32b2121f
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_3_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_3_overdown.png b/res/skins/Shade/btn/btn_hotcue_3_overdown.png
new file mode 100644
index 00000000000..3308d3055b1
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_3_overdown.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_4.png b/res/skins/Shade/btn/btn_hotcue_4.png
index f3c47cc7ef8..d973f1eb850 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_over.png b/res/skins/Shade/btn/btn_hotcue_4_over.png
new file mode 100644
index 00000000000..94c3a61dab3
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_4_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_4_overdown.png b/res/skins/Shade/btn/btn_hotcue_4_overdown.png
new file mode 100644
index 00000000000..6c421f86200
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_4_overdown.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_5.png b/res/skins/Shade/btn/btn_hotcue_5.png
index 002cf0cc546..68b74541766 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_over.png b/res/skins/Shade/btn/btn_hotcue_5_over.png
new file mode 100644
index 00000000000..55d1d00cc40
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_5_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_5_overdown.png b/res/skins/Shade/btn/btn_hotcue_5_overdown.png
new file mode 100644
index 00000000000..7e3c06f6f1e
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_5_overdown.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_6.png b/res/skins/Shade/btn/btn_hotcue_6.png
index dffdf0b39c3..6e679a722c3 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_over.png b/res/skins/Shade/btn/btn_hotcue_6_over.png
new file mode 100644
index 00000000000..bb11f9e8b45
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_6_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_6_overdown.png b/res/skins/Shade/btn/btn_hotcue_6_overdown.png
new file mode 100644
index 00000000000..cdfbfb7448c
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_6_overdown.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_7.png b/res/skins/Shade/btn/btn_hotcue_7.png
index 998978cde5e..eeabda86147 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_over.png b/res/skins/Shade/btn/btn_hotcue_7_over.png
new file mode 100644
index 00000000000..d47ca498706
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_7_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_7_overdown.png b/res/skins/Shade/btn/btn_hotcue_7_overdown.png
new file mode 100644
index 00000000000..a2f1bc6cf1b
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_7_overdown.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_8.png b/res/skins/Shade/btn/btn_hotcue_8.png
index 36542964c2e..e99b57e28b5 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_over.png b/res/skins/Shade/btn/btn_hotcue_8_over.png
new file mode 100644
index 00000000000..a735b473929
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_8_over.png differ
diff --git a/res/skins/Shade/btn/btn_hotcue_8_overdown.png b/res/skins/Shade/btn/btn_hotcue_8_overdown.png
new file mode 100644
index 00000000000..41ae9781934
Binary files /dev/null and b/res/skins/Shade/btn/btn_hotcue_8_overdown.png differ
diff --git a/res/skins/Shade/hotcue_button.xml b/res/skins/Shade/hotcue_button.xml
index 40149e41b8d..a357736ce84 100644
--- a/res/skins/Shade/hotcue_button.xml
+++ b/res/skins/Shade/hotcue_button.xml
@@ -1,8 +1,10 @@
-
+
hotcue
HotcueButton
+
+
2
0
@@ -11,24 +13,8 @@
1
- skin:/btn/btn_hotcue_.png
- skin:/btn/btn_hotcue_.png
+ skin:/btn/btn_hotcue__overdown.png
+ skin:/btn/btn_hotcue__over.png
-
- ,hotcue__activate
- LeftButton
-
-
- ,hotcue__clear
- RightButton
-
-
- ,hotcue__enabled
- false
-
-
- ,hotcue__color
- backgroundColorRgba
-
-
+
diff --git a/res/skins/Tango/button_hotcue_deck.xml b/res/skins/Tango/button_hotcue_deck.xml
index eb0785f234c..62edc59087d 100644
--- a/res/skins/Tango/button_hotcue_deck.xml
+++ b/res/skins/Tango/button_hotcue_deck.xml
@@ -8,12 +8,14 @@ Variables:
HotCue: hotcue number
-->
-
+
hotcue
HotcueButton
15,24
23,24
me,f
+
+
2
0
@@ -25,21 +27,5 @@ Variables:
center
-
- ,hotcue__activate
- LeftButton
-
-
- ,hotcue__clear
- RightButton
-
-
- ,hotcue__enabled
- false
-
-
- ,hotcue__color
- backgroundColorRgba
-
-
+
diff --git a/res/skins/Tango/button_hotcue_sam_pre.xml b/res/skins/Tango/button_hotcue_sam_pre.xml
index 5f13a216628..ad95e22a4f3 100644
--- a/res/skins/Tango/button_hotcue_sam_pre.xml
+++ b/res/skins/Tango/button_hotcue_sam_pre.xml
@@ -9,12 +9,14 @@ Variables:
HotCue: hotcue number
-->
-
+
hotcue
HotcueButton
14,18
20,18
me,f
+
+
2
0
@@ -26,17 +28,5 @@ Variables:
center
-
- ,hotcue__activate
- LeftButton
-
-
- ,hotcue__clear
- RightButton
-
-
- ,hotcue__enabled
- false
-
-
+
diff --git a/res/skins/Tango/style.qss b/res/skins/Tango/style.qss
index 0938c92be55..110aa2ca561 100644
--- a/res/skins/Tango/style.qss
+++ b/res/skins/Tango/style.qss
@@ -1006,12 +1006,12 @@ WLabel#TrackComment {
border: 1px solid #eeeeee;
}
-#HotcueButton[backgroundIsDark=true][hasBackgroundColor=true] {
- color: #eeeeee;
+#HotcueButton[light="true"] {
+ color: #0f0f0f;
}
-#HotcueButton[backgroundIsDark=false][hasBackgroundColor=true] {
- color: #0f0f0f;
+#HotcueButton[light="true"]:hover {
+ border: 1px solid #808080;
}
#CueButton {
diff --git a/src/engine/controls/cuecontrol.cpp b/src/engine/controls/cuecontrol.cpp
index d087506dbc4..0d52f3e4ddb 100644
--- a/src/engine/controls/cuecontrol.cpp
+++ b/src/engine/controls/cuecontrol.cpp
@@ -23,8 +23,6 @@ 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;
-constexpr double kNoColorControlValue = -1;
-
namespace {
// Helper function to convert control values (i.e. doubles) into RgbColor
@@ -335,7 +333,6 @@ void CueControl::detachCue(HotcueControl* pControl) {
}
disconnect(pCue.get(), 0, this, 0);
pControl->resetCue();
- pControl->setColor(std::nullopt);
}
void CueControl::trackLoaded(TrackPointer pNewTrack) {
@@ -1769,7 +1766,10 @@ HotcueControl::HotcueControl(QString group, int i)
// The rgba value of the color assigned to this color.
m_hotcueColor = new ControlObject(keyForControl(i, "color"));
- m_hotcueColor->set(kNoColorControlValue);
+ m_hotcueColor->connectValueChangeRequest(
+ this,
+ &HotcueControl::slotHotcueColorChangeRequest,
+ Qt::DirectConnection);
connect(m_hotcueColor,
&ControlObject::valueChanged,
this,
@@ -1858,14 +1858,21 @@ void HotcueControl::slotHotcuePositionChanged(double newPosition) {
emit hotcuePositionChanged(this, newPosition);
}
+void HotcueControl::slotHotcueColorChangeRequest(double color) {
+ if (color < 0 || color > 0xFFFFFF) {
+ qWarning() << "slotHotcueColorChanged got invalid value:" << color;
+ return;
+ }
+ m_hotcueColor->setAndConfirm(color);
+}
+
void HotcueControl::slotHotcueColorChanged(double newColor) {
if (!m_pCue) {
return;
}
mixxx::RgbColor::optional_t color = doubleToRgbColor(newColor);
- if (!color) {
- qWarning() << "slotHotcueColorChanged got invalid value:" << newColor;
+ VERIFY_OR_DEBUG_ASSERT(color) {
return;
}
@@ -1891,8 +1898,6 @@ mixxx::RgbColor::optional_t HotcueControl::getColor() const {
void HotcueControl::setColor(mixxx::RgbColor::optional_t newColor) {
if (newColor) {
m_hotcueColor->set(*newColor);
- } else {
- m_hotcueColor->set(kNoColorControlValue);
}
}
void HotcueControl::resetCue() {
diff --git a/src/engine/controls/cuecontrol.h b/src/engine/controls/cuecontrol.h
index 4c9f0e32a78..2d406a7d439 100644
--- a/src/engine/controls/cuecontrol.h
+++ b/src/engine/controls/cuecontrol.h
@@ -77,6 +77,7 @@ class HotcueControl : public QObject {
void slotHotcueActivatePreview(double v);
void slotHotcueClear(double v);
void slotHotcuePositionChanged(double newPosition);
+ void slotHotcueColorChangeRequest(double newColor);
void slotHotcueColorChanged(double newColor);
signals:
diff --git a/src/skin/legacyskinparser.cpp b/src/skin/legacyskinparser.cpp
index 19ee2fc8574..30cd1c3ae7d 100644
--- a/src/skin/legacyskinparser.cpp
+++ b/src/skin/legacyskinparser.cpp
@@ -32,59 +32,60 @@
#include "recording/recordingmanager.h"
+#include "util/cmdlineargs.h"
+#include "util/timer.h"
+#include "util/valuetransformer.h"
+#include "waveform/waveformwidgetfactory.h"
#include "widget/controlwidgetconnection.h"
#include "widget/wbasewidget.h"
+#include "widget/wbattery.h"
+#include "widget/wbeatspinbox.h"
+#include "widget/wcombobox.h"
#include "widget/wcoverart.h"
-#include "widget/wwidget.h"
+#include "widget/wdisplay.h"
+#include "widget/weffect.h"
+#include "widget/weffectbuttonparameter.h"
+#include "widget/weffectchain.h"
+#include "widget/weffectparameter.h"
+#include "widget/weffectparameterbase.h"
+#include "widget/weffectparameterknob.h"
+#include "widget/weffectparameterknobcomposed.h"
+#include "widget/weffectpushbutton.h"
+#include "widget/weffectselector.h"
+#include "widget/whotcuebutton.h"
+#include "widget/wkey.h"
#include "widget/wknob.h"
#include "widget/wknobcomposed.h"
-#include "widget/wslidercomposed.h"
-#include "widget/wpushbutton.h"
-#include "widget/weffectpushbutton.h"
-#include "widget/wdisplay.h"
-#include "widget/wvumeter.h"
-#include "widget/wstatuslight.h"
#include "widget/wlabel.h"
-#include "widget/wtime.h"
-#include "widget/wrecordingduration.h"
-#include "widget/wtracktext.h"
-#include "widget/wtrackproperty.h"
-#include "widget/wstarrating.h"
+#include "widget/wlibrary.h"
+#include "widget/wlibrarysidebar.h"
#include "widget/wnumber.h"
#include "widget/wnumberdb.h"
#include "widget/wnumberpos.h"
#include "widget/wnumberrate.h"
-#include "widget/weffectchain.h"
-#include "widget/weffect.h"
-#include "widget/weffectselector.h"
-#include "widget/weffectparameter.h"
-#include "widget/weffectparameterknob.h"
-#include "widget/weffectparameterknobcomposed.h"
-#include "widget/weffectbuttonparameter.h"
-#include "widget/weffectparameterbase.h"
-#include "widget/wbeatspinbox.h"
-#include "widget/woverviewlmh.h"
#include "widget/woverviewhsv.h"
+#include "widget/woverviewlmh.h"
#include "widget/woverviewrgb.h"
-#include "widget/wspinny.h"
-#include "widget/wwaveformviewer.h"
-#include "waveform/waveformwidgetfactory.h"
-#include "widget/wsearchlineedit.h"
-#include "widget/wlibrary.h"
-#include "widget/wlibrarysidebar.h"
-#include "widget/wskincolor.h"
#include "widget/wpixmapstore.h"
-#include "widget/wwidgetstack.h"
+#include "widget/wpushbutton.h"
+#include "widget/wrecordingduration.h"
+#include "widget/wsearchlineedit.h"
+#include "widget/wsingletoncontainer.h"
#include "widget/wsizeawarestack.h"
-#include "widget/wwidgetgroup.h"
-#include "widget/wkey.h"
-#include "widget/wbattery.h"
-#include "widget/wcombobox.h"
+#include "widget/wskincolor.h"
+#include "widget/wslidercomposed.h"
+#include "widget/wspinny.h"
#include "widget/wsplitter.h"
-#include "widget/wsingletoncontainer.h"
-#include "util/valuetransformer.h"
-#include "util/cmdlineargs.h"
-#include "util/timer.h"
+#include "widget/wstarrating.h"
+#include "widget/wstatuslight.h"
+#include "widget/wtime.h"
+#include "widget/wtrackproperty.h"
+#include "widget/wtracktext.h"
+#include "widget/wvumeter.h"
+#include "widget/wwaveformviewer.h"
+#include "widget/wwidget.h"
+#include "widget/wwidgetgroup.h"
+#include "widget/wwidgetstack.h"
using mixxx::skin::SkinManifest;
@@ -505,6 +506,8 @@ QList LegacySkinParser::parseNode(const QDomElement& node) {
result = wrapWidget(parseStandardWidget(node));
} else if (nodeName == "EffectPushButton") {
result = wrapWidget(parseEffectPushButton(node));
+ } else if (nodeName == "HotcueButton") {
+ result = wrapWidget(parseStandardWidget(node));
} else if (nodeName == "ComboBox") {
result = wrapWidget(parseStandardWidget(node));
} else if (nodeName == "Overview") {
diff --git a/src/skin/skincontext.h b/src/skin/skincontext.h
index 8898b337f35..2095e26dcaf 100644
--- a/src/skin/skincontext.h
+++ b/src/skin/skincontext.h
@@ -257,6 +257,10 @@ class SkinContext {
return m_scaleFactor;
}
+ UserSettingsPointer getConfig() const {
+ return m_pConfig;
+ }
+
private:
PixmapSource getPixmapSourceInner(const QString& filename) const;
diff --git a/src/skin/tooltips.cpp b/src/skin/tooltips.cpp
index 7bc9234d8c0..cdf68333d41 100644
--- a/src/skin/tooltips.cpp
+++ b/src/skin/tooltips.cpp
@@ -555,8 +555,7 @@ void Tooltips::addStandardTooltips() {
<< QString("%1: %2").arg(leftClick, tr("If hotcue is set, jumps to the hotcue."))
<< tr("If hotcue is not set, sets the hotcue to the current play position.")
<< quantizeSnap
- << QString("%1: %2").arg(rightClick, tr("If hotcue is set, clears the hotcue."))
- << tr("Right click hotcues on the overview waveform to edit their labels and colors.");
+ << QString("%1: %2").arg(rightClick, tr("Opens a menu to clear hotcues or edit their labels and colors."));
// Status displays and toggle buttons
add("toggle_recording")
@@ -962,7 +961,7 @@ void Tooltips::addStandardTooltips() {
add("SaveSamplerBank")
<< tr("Save Sampler Bank")
<< tr("Save the collection of samples loaded in the samplers.");
-
+
add("LoadSamplerBank")
<< tr("Load Sampler Bank")
<< tr("Load a previously saved collection of samples into the samplers.");
diff --git a/src/util/color/color.h b/src/util/color/color.h
index e5196a409e7..7361d5acb87 100644
--- a/src/util/color/color.h
+++ b/src/util/color/color.h
@@ -7,7 +7,7 @@ namespace Color {
int brightness(int red, int green, int blue);
inline int brightness(const QColor& color) {
- return brightness(color.red(), color.green(), color.red());
+ return brightness(color.red(), color.green(), color.blue());
}
inline bool isDimmColor(const QColor& color) {
diff --git a/src/widget/whotcuebutton.cpp b/src/widget/whotcuebutton.cpp
new file mode 100644
index 00000000000..715833d158a
--- /dev/null
+++ b/src/widget/whotcuebutton.cpp
@@ -0,0 +1,141 @@
+#include "widget/whotcuebutton.h"
+
+#include
+#include
+#include
+
+#include "mixer/playerinfo.h"
+
+WHotcueButton::WHotcueButton(QWidget* pParent)
+ : WPushButton(pParent),
+ m_hotcue(Cue::kNoHotCue),
+ m_hoverCueColor(false),
+ m_pCoColor(nullptr),
+ m_cueColorDimmed(false),
+ m_isCueColorLight(false),
+ m_isCueColorDark(false) {
+}
+
+void WHotcueButton::setup(const QDomNode& node, const SkinContext& context) {
+ // Setup parent class.
+ WPushButton::setup(node, context);
+
+ m_group = context.selectString(node, QStringLiteral("Group"));
+ bool ok;
+ int hotcue = context.selectInt(node, QStringLiteral("Hotcue"), &ok);
+ if (ok && hotcue > 0) {
+ m_hotcue = hotcue - 1;
+ } else {
+ SKIN_WARNING(node, context) << "Hotcue value invalid";
+ }
+ m_hoverCueColor = context.selectBool(node, QStringLiteral("Hover"), false);
+
+ m_pCueMenuPopup = make_parented(context.getConfig(), this);
+ ColorPaletteSettings colorPaletteSettings(context.getConfig());
+ auto colorPalette = colorPaletteSettings.getHotcueColorPalette();
+ m_pCueMenuPopup->setColorPalette(colorPalette);
+
+ setFocusPolicy(Qt::NoFocus);
+
+ m_pCoColor = make_parented(createConfigKey(QStringLiteral("color")), this);
+ m_pCoColor->connectValueChanged(this, &WHotcueButton::slotColorChanged);
+ slotColorChanged(m_pCoColor->get());
+
+ auto pLeftConnection = new ControlParameterWidgetConnection(
+ this,
+ createConfigKey(QStringLiteral("activate")),
+ nullptr,
+ ControlParameterWidgetConnection::DIR_FROM_WIDGET,
+ ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE);
+ addLeftConnection(pLeftConnection);
+
+ auto pDisplayConnection = new ControlParameterWidgetConnection(
+ this,
+ createConfigKey(QStringLiteral("enabled")),
+ nullptr,
+ ControlParameterWidgetConnection::DIR_TO_WIDGET,
+ ControlParameterWidgetConnection::EMIT_NEVER);
+ addConnection(pDisplayConnection);
+ setDisplayConnection(pDisplayConnection);
+
+ QDomNode con = context.selectNode(node, QStringLiteral("Connection"));
+ if (!con.isNull()) {
+ SKIN_WARNING(node, context) << "Additional Connections are not allowed";
+ }
+}
+
+void WHotcueButton::mousePressEvent(QMouseEvent* e) {
+ const bool rightClick = e->button() == Qt::RightButton;
+ if (rightClick) {
+ if (readDisplayValue() == 1) {
+ // hot cue is set
+ TrackPointer pTrack = PlayerInfo::instance().getTrackInfo(m_group);
+ if (!pTrack) {
+ return;
+ }
+
+ CuePointer pHotCue;
+ QList cueList = pTrack->getCuePoints();
+ for (const auto& pCue : cueList) {
+ if (pCue->getHotCue() == m_hotcue) {
+ pHotCue = pCue;
+ break;
+ }
+ }
+ if (!pHotCue) {
+ return;
+ }
+ m_pCueMenuPopup->setTrackAndCue(pTrack, pHotCue);
+ m_pCueMenuPopup->popup(e->globalPos());
+ }
+ return;
+ }
+
+ // Pass all other press events to the base class.
+ WPushButton::mousePressEvent(e);
+}
+
+ConfigKey WHotcueButton::createConfigKey(const QString& name) {
+ ConfigKey key;
+ key.group = m_group;
+ // Add one to hotcue so that we don't have a hotcue_0
+ key.item = QStringLiteral("hotcue_") + QString::number(m_hotcue + 1) + QChar('_') + name;
+ return key;
+}
+
+void WHotcueButton::slotColorChanged(double color) {
+ VERIFY_OR_DEBUG_ASSERT(color >= 0 && color <= 0xFFFFFF) {
+ return;
+ }
+ QColor cueColor = QColor::fromRgb(color);
+ m_cueColorDimmed = Color::isDimmColor(cueColor);
+
+ QString style =
+ QStringLiteral("WWidget[displayValue=\"1\"] { background-color: ") +
+ cueColor.name() +
+ QStringLiteral("; }");
+
+ if (m_hoverCueColor) {
+ style +=
+ QStringLiteral("WWidget[displayValue=\"1\"]:hover { background-color: ") +
+ cueColor.lighter(m_cueColorDimmed ? 120 : 80).name() +
+ QStringLiteral("; }");
+ }
+
+ setStyleSheet(style);
+ restyleAndRepaint();
+}
+
+void WHotcueButton::restyleAndRepaint() {
+ if (readDisplayValue()) {
+ // Adjust properties for Qss file
+ m_isCueColorLight = !m_cueColorDimmed;
+ m_isCueColorDark = m_cueColorDimmed;
+ } else {
+ // We are now at the background set by qss.
+ // Since we don't know the color reset both
+ m_isCueColorLight = false;
+ m_isCueColorDark = false;
+ }
+ WPushButton::restyleAndRepaint();
+}
diff --git a/src/widget/whotcuebutton.h b/src/widget/whotcuebutton.h
new file mode 100644
index 00000000000..f53e5cfe3f3
--- /dev/null
+++ b/src/widget/whotcuebutton.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include "skin/skincontext.h"
+#include "util/parented_ptr.h"
+#include "widget/wcuemenupopup.h"
+#include "widget/wpushbutton.h"
+
+class WHotcueButton : public WPushButton {
+ Q_OBJECT
+ public:
+ WHotcueButton(QWidget* pParent);
+
+ void setup(const QDomNode& node, const SkinContext& context) override;
+
+ Q_PROPERTY(bool light MEMBER m_isCueColorLight);
+ Q_PROPERTY(bool dark MEMBER m_isCueColorDark);
+
+ protected:
+ void mousePressEvent(QMouseEvent* e) override;
+ void restyleAndRepaint() override;
+
+ private slots:
+ void slotColorChanged(double color);
+
+ private:
+ ConfigKey createConfigKey(const QString& name);
+ void updateStyleSheet();
+
+ QString m_group;
+ int m_hotcue;
+ bool m_hoverCueColor;
+ parented_ptr m_pCoColor;
+ parented_ptr m_pCueMenuPopup;
+ bool m_cueColorDimmed;
+ bool m_isCueColorLight;
+ bool m_isCueColorDark;
+};
diff --git a/src/widget/woverview.cpp b/src/widget/woverview.cpp
index 4fb65c6fbfe..a6475491f79 100644
--- a/src/widget/woverview.cpp
+++ b/src/widget/woverview.cpp
@@ -54,7 +54,7 @@ WOverview::WOverview(
m_group(group),
m_pConfig(pConfig),
m_endOfTrack(false),
- m_pCueMenuPopup(std::make_unique(pConfig, this)),
+ m_pCueMenuPopup(make_parented(pConfig, this)),
m_bShowCueTimes(true),
m_iPosSeconds(0),
m_bLeftClickDragging(false),
diff --git a/src/widget/woverview.h b/src/widget/woverview.h
index 25ce680bd18..a3e6a93d44b 100644
--- a/src/widget/woverview.h
+++ b/src/widget/woverview.h
@@ -25,6 +25,7 @@
#include "widget/wwidget.h"
#include "util/color/color.h"
+#include "util/parented_ptr.h"
#include "waveform/renderers/waveformsignalcolors.h"
#include "waveform/renderers/waveformmarkset.h"
@@ -141,7 +142,7 @@ class WOverview : public WWidget, public TrackDropTarget {
TrackPointer m_pCurrentTrack;
ConstWaveformPointer m_pWaveform;
- std::unique_ptr m_pCueMenuPopup;
+ parented_ptr m_pCueMenuPopup;
bool m_bShowCueTimes;
int m_iPosSeconds;
diff --git a/src/widget/wpushbutton.h b/src/widget/wpushbutton.h
index 37afd195759..80a51339be6 100644
--- a/src/widget/wpushbutton.h
+++ b/src/widget/wpushbutton.h
@@ -94,7 +94,7 @@ class WPushButton : public WWidget {
void fillDebugTooltip(QStringList* debug) override;
protected:
- void restyleAndRepaint();
+ virtual void restyleAndRepaint();
// Associates a pixmap of a given state of the button with the widget
void setPixmap(int iState, bool bPressed, PixmapSource source,
diff --git a/src/widget/wwidget.cpp b/src/widget/wwidget.cpp
index 801678a107a..364b46280a1 100644
--- a/src/widget/wwidget.cpp
+++ b/src/widget/wwidget.cpp
@@ -26,8 +26,7 @@ WWidget::WWidget(QWidget* parent, Qt::WindowFlags flags)
: QWidget(parent, flags),
WBaseWidget(this),
m_activeTouchButton(Qt::NoButton),
- m_scaleFactor(1.0),
- m_bShouldHighlightBackgroundOnHover(false) {
+ m_scaleFactor(1.0) {
m_pTouchShift = new ControlProxy("[Controls]", "touch_shift");
setAttribute(Qt::WA_StaticContents);
setAttribute(Qt::WA_AcceptTouchEvents);
@@ -38,31 +37,6 @@ WWidget::~WWidget() {
delete m_pTouchShift;
}
-double WWidget::getBackgroundColorRgba() const {
- if (m_backgroundColorRgba < 0) {
- return -1;
- }
- return m_backgroundColorRgba;
-}
-
-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 0fbf10631c2..50e9edee73d 100644
--- a/src/widget/wwidget.h
+++ b/src/widget/wwidget.h
@@ -45,21 +45,6 @@ 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();
@@ -76,9 +61,6 @@ class WWidget : public QWidget, public WBaseWidget {
private:
ControlProxy* m_pTouchShift;
double m_scaleFactor;
- double m_backgroundColorRgba;
- bool m_bBackgroundIsDark;
- bool m_bShouldHighlightBackgroundOnHover;
};
#endif