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 --> 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 @@ 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 --> 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 --> 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