diff --git a/res/skins/default.qss b/res/skins/default.qss index 5ef73f9cccb8..e9a35ed66305 100644 --- a/res/skins/default.qss +++ b/res/skins/default.qss @@ -34,6 +34,17 @@ WColorPicker QPushButton[noColor="true"] { background-color: black; } +WColorPicker QPushButton[customColor="true"] { + /* Diagonal Rainbow Gradient */ + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, + stop: 0 #FF0000, + stop: 0.2 #FFFF00, + stop: 0.4 #00FF00, + stop: 0.6 #00FFFF, + stop: 0.8 #0000FF, + stop: 1 #FF00FF) +} + WColorPicker QPushButton[checked="false"] { qproperty-icon: none; } diff --git a/src/widget/wcolorpicker.cpp b/src/widget/wcolorpicker.cpp index fb1547206503..0c5fde4a764c 100644 --- a/src/widget/wcolorpicker.cpp +++ b/src/widget/wcolorpicker.cpp @@ -1,5 +1,6 @@ #include "widget/wcolorpicker.h" +#include #include #include #include @@ -35,10 +36,12 @@ inline int idealColumnCount(int numItems) { return numColumns; } -WColorPicker::WColorPicker(ColorOption colorOption, const ColorPalette& palette, QWidget* parent) +WColorPicker::WColorPicker(Options options, const ColorPalette& palette, QWidget* parent) : QWidget(parent), - m_colorOption(colorOption), - m_palette(palette) { + m_options(options), + m_palette(palette), + m_pNoColorButton(nullptr), + m_pCustomColorButton(nullptr) { QGridLayout* pLayout = new QGridLayout(); pLayout->setMargin(0); pLayout->setContentsMargins(0, 0, 0, 0); @@ -57,6 +60,11 @@ WColorPicker::WColorPicker(ColorOption colorOption, const ColorPalette& palette, m_pStyle = QStyleFactory::create(QString("fusion")); setLayout(pLayout); addColorButtons(); + + connect(this, + &WColorPicker::colorPicked, + this, + &WColorPicker::slotColorPicked); } void WColorPicker::removeColorButtons() { @@ -66,11 +74,21 @@ void WColorPicker::removeColorButtons() { return; } + if (m_pCustomColorButton) { + pLayout->removeWidget(m_pCustomColorButton); + delete m_pCustomColorButton; + } + while (!m_colorButtons.isEmpty()) { QPushButton* pColorButton = m_colorButtons.takeLast(); pLayout->removeWidget(pColorButton); delete pColorButton; } + + if (m_pNoColorButton) { + pLayout->removeWidget(m_pNoColorButton); + delete m_pNoColorButton; + } } void WColorPicker::addColorButtons() { @@ -84,13 +102,16 @@ void WColorPicker::addColorButtons() { int column = 0; int numColors = m_palette.size(); - if (m_colorOption == ColorOption::AllowNoColor) { + if (m_options.testFlag(Option::AllowNoColor)) { + numColors++; + } + if (m_options.testFlag(Option::AllowCustomColor)) { numColors++; } int numColumns = idealColumnCount(numColors); - if (m_colorOption == ColorOption::AllowNoColor) { - addColorButton(std::nullopt, pLayout, row, column); + if (m_options.testFlag(Option::AllowNoColor)) { + addNoColorButton(pLayout, row, column); column++; } @@ -102,97 +123,115 @@ void WColorPicker::addColorButtons() { row++; } } -} -void WColorPicker::addColorButton(mixxx::RgbColor::optional_t color, QGridLayout* pLayout, int row, int column) { - parented_ptr pColorButton = make_parented("", this); - if (m_pStyle) { - pColorButton->setStyle(m_pStyle); + if (m_options.testFlag(Option::AllowCustomColor)) { + addCustomColorButton(pLayout, row, column); + column++; } +} - if (color) { - // Set the background color of the button. This can't be overridden in skin stylesheets. - pColorButton->setStyleSheet( - QString("QPushButton { background-color: %1; }").arg(mixxx::RgbColor::toQString(color))); - } else { - pColorButton->setProperty("noColor", true); +void WColorPicker::addColorButton(mixxx::RgbColor color, QGridLayout* pLayout, int row, int column) { + parented_ptr pButton = make_parented("", this); + if (m_pStyle) { + pButton->setStyle(m_pStyle); } - pColorButton->setToolTip(mixxx::RgbColor::toQString(color, tr("No Color"))); - pColorButton->setCheckable(true); - m_colorButtons.append(pColorButton); + // Set the background color of the button. This can't be overridden in skin stylesheets. + pButton->setStyleSheet( + QString("QPushButton { background-color: %1; }").arg(mixxx::RgbColor::toQString(color))); + pButton->setToolTip(mixxx::RgbColor::toQString(color)); + pButton->setCheckable(true); + m_colorButtons.append(pButton); - pLayout->addWidget(pColorButton, row, column); - - connect(this, - &WColorPicker::colorPicked, - this, - &WColorPicker::slotColorPicked); - connect(pColorButton, + connect(pButton, &QPushButton::clicked, this, [this, color]() { - emit colorPicked(color); + emit colorPicked(mixxx::RgbColor::optional(color)); }); + pLayout->addWidget(pButton, row, column); } -void WColorPicker::resetSelectedColor() { - // Unset currently selected color - int i = 0; - if (m_selectedColor) { - i = m_palette.indexOf(*m_selectedColor); - if (i == -1) { - return; - } - if (m_colorOption == ColorOption::AllowNoColor) { - i++; +void WColorPicker::addNoColorButton(QGridLayout* pLayout, int row, int column) { + QPushButton* pButton = m_pNoColorButton; + if (!pButton) { + pButton = make_parented("", this); + if (m_pStyle) { + pButton->setStyle(m_pStyle); } - } else if (m_colorOption != ColorOption::AllowNoColor) { - return; - } - - DEBUG_ASSERT(i < m_colorButtons.size()); - QPushButton* pButton = m_colorButtons.at(i); - VERIFY_OR_DEBUG_ASSERT(pButton != nullptr) { - return; + pButton->setProperty("noColor", true); + pButton->setToolTip(tr("No color")); + pButton->setCheckable(true); + connect(pButton, + &QPushButton::clicked, + this, + [this]() { + emit colorPicked(std::nullopt); + }); + m_pNoColorButton = pButton; } - pButton->setChecked(false); - // This is needed to re-apply skin styles (e.g. to show/hide a checkmark icon) - pButton->style()->unpolish(pButton); - pButton->style()->polish(pButton); + pLayout->addWidget(pButton, row, column); } -void WColorPicker::setSelectedColor(mixxx::RgbColor::optional_t color) { - resetSelectedColor(); +void WColorPicker::addCustomColorButton(QGridLayout* pLayout, int row, int column) { + QPushButton* pButton = m_pCustomColorButton; + if (!pButton) { + pButton = make_parented("", this); + if (m_pStyle) { + pButton->setStyle(m_pStyle); + } - m_selectedColor = color; + pButton->setProperty("customColor", true); + pButton->setToolTip(tr("Custom color")); + pButton->setCheckable(true); + connect(pButton, + &QPushButton::clicked, + this, + [this]() { + QColor color = QColorDialog::getColor(); + if (color.isValid()) { + emit colorPicked(mixxx::RgbColor::fromQColor(color)); + } + }); + m_pCustomColorButton = pButton; + } + pLayout->addWidget(pButton, row, column); +} - int i = 0; +void WColorPicker::setColorButtonChecked(mixxx::RgbColor::optional_t color, bool checked) { + // Unset currently selected color + QPushButton* pButton = nullptr; if (color) { - i = m_palette.indexOf(*color); - if (i == -1) { - return; + int i = m_palette.indexOf(*color); + if (i != -1) { + pButton = m_colorButtons.at(i); } - if (m_colorOption == ColorOption::AllowNoColor) { - i++; - } - } else if (m_colorOption != ColorOption::AllowNoColor) { - return; + } else if (m_options.testFlag(Option::AllowNoColor)) { + pButton = m_pNoColorButton; } - DEBUG_ASSERT(i < m_colorButtons.size()); - - QPushButton* pButton = m_colorButtons.at(i); - VERIFY_OR_DEBUG_ASSERT(pButton != nullptr) { + if (!pButton) { return; } - pButton->setChecked(true); + + pButton->setChecked(checked); // This is needed to re-apply skin styles (e.g. to show/hide a checkmark icon) pButton->style()->unpolish(pButton); pButton->style()->polish(pButton); } +void WColorPicker::resetSelectedColor() { + setColorButtonChecked(m_selectedColor, false); +} + +void WColorPicker::setSelectedColor(mixxx::RgbColor::optional_t color) { + resetSelectedColor(); + + m_selectedColor = color; + setColorButtonChecked(m_selectedColor, true); +} + void WColorPicker::setColorPalette(const ColorPalette& palette) { if (m_palette == palette) { return; diff --git a/src/widget/wcolorpicker.h b/src/widget/wcolorpicker.h index d905e6124623..679f235b5603 100644 --- a/src/widget/wcolorpicker.h +++ b/src/widget/wcolorpicker.h @@ -12,12 +12,14 @@ class WColorPicker : public QWidget { Q_OBJECT public: - enum class ColorOption { - DenyNoColor, - AllowNoColor, + enum class Option { + NoOptions = 0, + AllowNoColor = 1, + AllowCustomColor = 1 << 1, }; + Q_DECLARE_FLAGS(Options, Option); - explicit WColorPicker(ColorOption colorOption, const ColorPalette& palette, QWidget* parent = nullptr); + explicit WColorPicker(Options options, const ColorPalette& palette, QWidget* parent = nullptr); void resetSelectedColor(); void setSelectedColor(mixxx::RgbColor::optional_t color); @@ -30,12 +32,19 @@ class WColorPicker : public QWidget { void slotColorPicked(mixxx::RgbColor::optional_t color); private: + void setColorButtonChecked(mixxx::RgbColor::optional_t color, bool checked); void addColorButtons(); void removeColorButtons(); - void addColorButton(mixxx::RgbColor::optional_t color, QGridLayout* pLayout, int row, int column); - ColorOption m_colorOption; + void addColorButton(mixxx::RgbColor color, QGridLayout* pLayout, int row, int column); + void addNoColorButton(QGridLayout* pLayout, int row, int column); + void addCustomColorButton(QGridLayout* pLayout, int row, int column); + Options m_options; mixxx::RgbColor::optional_t m_selectedColor; ColorPalette m_palette; + QPushButton* m_pNoColorButton; + QPushButton* m_pCustomColorButton; QList m_colorButtons; QStyle* m_pStyle; }; + +Q_DECLARE_OPERATORS_FOR_FLAGS(WColorPicker::Options); diff --git a/src/widget/wcolorpickeraction.cpp b/src/widget/wcolorpickeraction.cpp index 8837695ac616..c1d34d916c9c 100644 --- a/src/widget/wcolorpickeraction.cpp +++ b/src/widget/wcolorpickeraction.cpp @@ -1,8 +1,8 @@ #include "widget/wcolorpickeraction.h" -WColorPickerAction::WColorPickerAction(WColorPicker::ColorOption colorOption, const ColorPalette& palette, QWidget* parent) +WColorPickerAction::WColorPickerAction(WColorPicker::Options options, const ColorPalette& palette, QWidget* parent) : QWidgetAction(parent), - m_pColorPicker(make_parented(colorOption, palette)) { + m_pColorPicker(make_parented(options, palette)) { connect(m_pColorPicker.get(), &WColorPicker::colorPicked, this, &WColorPickerAction::colorPicked); QHBoxLayout* pLayout = new QHBoxLayout(); diff --git a/src/widget/wcolorpickeraction.h b/src/widget/wcolorpickeraction.h index ce222ff49cc8..ca173d5a7d57 100644 --- a/src/widget/wcolorpickeraction.h +++ b/src/widget/wcolorpickeraction.h @@ -11,7 +11,7 @@ class WColorPickerAction : public QWidgetAction { Q_OBJECT public: explicit WColorPickerAction( - WColorPicker::ColorOption colorOption, + WColorPicker::Options options, const ColorPalette& palette, QWidget* parent = nullptr); diff --git a/src/widget/wcuemenupopup.cpp b/src/widget/wcuemenupopup.cpp index ecf3f5cdb776..66bd49d3788e 100644 --- a/src/widget/wcuemenupopup.cpp +++ b/src/widget/wcuemenupopup.cpp @@ -32,7 +32,7 @@ WCueMenuPopup::WCueMenuPopup(UserSettingsPointer pConfig, QWidget* parent) connect(m_pEditLabel, &QLineEdit::textEdited, this, &WCueMenuPopup::slotEditLabel); connect(m_pEditLabel, &QLineEdit::returnPressed, this, &WCueMenuPopup::hide); - m_pColorPicker = new WColorPicker(WColorPicker::ColorOption::DenyNoColor, m_colorPaletteSettings.getHotcueColorPalette(), this); + m_pColorPicker = new WColorPicker(WColorPicker::Option::NoOptions, m_colorPaletteSettings.getHotcueColorPalette(), this); m_pColorPicker->setObjectName("CueColorPicker"); connect(m_pColorPicker, &WColorPicker::colorPicked, this, &WCueMenuPopup::slotChangeCueColor); diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp index 3fc47d469c2a..b3e581d60660 100644 --- a/src/widget/wtracktableview.cpp +++ b/src/widget/wtracktableview.cpp @@ -575,7 +575,7 @@ void WTrackTableView::createActions() { this, [this] { slotScaleBpm(Beats::THREEHALVES); }); ColorPaletteSettings colorPaletteSettings(m_pConfig); - m_pColorPickerAction = new WColorPickerAction(WColorPicker::ColorOption::AllowNoColor, colorPaletteSettings.getTrackColorPalette(), this); + m_pColorPickerAction = new WColorPickerAction(WColorPicker::Option::AllowNoColor, colorPaletteSettings.getTrackColorPalette(), this); m_pColorPickerAction->setObjectName("TrackColorPickerAction"); connect(m_pColorPickerAction, &WColorPickerAction::colorPicked,