diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ec3eb023f5..d88175b5873 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -466,6 +466,8 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/preferences/dialog/dlgprefautodjdlg.ui src/preferences/dialog/dlgprefbeats.cpp src/preferences/dialog/dlgprefbeatsdlg.ui + src/preferences/dialog/dlgprefcolors.cpp + src/preferences/dialog/dlgprefcolorsdlg.ui src/preferences/dialog/dlgprefcrossfader.cpp src/preferences/dialog/dlgprefcrossfaderdlg.ui src/preferences/dialog/dlgprefdeck.cpp @@ -498,6 +500,8 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/preferences/dialog/dlgprefwaveformdlg.ui src/preferences/dlgpreferencepage.cpp src/preferences/effectsettingsmodel.cpp + src/preferences/colorpaletteeditor.cpp + src/preferences/colorpaletteeditormodel.cpp src/preferences/colorpalettesettings.cpp src/preferences/replaygainsettings.cpp src/preferences/settingsmanager.cpp @@ -562,6 +566,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/util/cmdlineargs.cpp src/util/color/color.cpp src/util/color/colorpalette.cpp + src/util/color/predefinedcolorpalettes.cpp src/util/console.cpp src/util/db/dbconnection.cpp src/util/db/dbconnectionpool.cpp diff --git a/build/depends.py b/build/depends.py index e13d2df5b3b..3d6096f2f13 100644 --- a/build/depends.py +++ b/build/depends.py @@ -768,6 +768,7 @@ def sources(self, build): "src/preferences/configobject.cpp", "src/preferences/dialog/dlgprefautodj.cpp", "src/preferences/dialog/dlgprefdeck.cpp", + "src/preferences/dialog/dlgprefcolors.cpp", "src/preferences/dialog/dlgprefcrossfader.cpp", "src/preferences/dialog/dlgprefeffects.cpp", "src/preferences/dialog/dlgprefeq.cpp", @@ -790,6 +791,8 @@ def sources(self, build): "src/preferences/effectsettingsmodel.cpp", "src/preferences/broadcastprofile.cpp", "src/preferences/upgrade.cpp", + "src/preferences/colorpaletteeditor.cpp", + "src/preferences/colorpaletteeditormodel.cpp", "src/preferences/colorpalettesettings.cpp", "src/preferences/dlgpreferencepage.cpp", @@ -1286,6 +1289,7 @@ def sources(self, build): "src/util/console.cpp", "src/util/color/color.cpp", "src/util/color/colorpalette.cpp", + "src/util/color/predefinedcolorpalettes.cpp", "src/util/db/dbconnection.cpp", "src/util/db/dbconnectionpool.cpp", "src/util/db/dbconnectionpooler.cpp", @@ -1347,6 +1351,7 @@ def sources(self, build): 'src/preferences/dialog/dlgprefautodjdlg.ui', 'src/preferences/dialog/dlgprefbeatsdlg.ui', 'src/preferences/dialog/dlgprefdeckdlg.ui', + 'src/preferences/dialog/dlgprefcolorsdlg.ui', 'src/preferences/dialog/dlgprefcrossfaderdlg.ui', 'src/preferences/dialog/dlgpreflv2dlg.ui', 'src/preferences/dialog/dlgprefeffectsdlg.ui', diff --git a/res/images/preferences/ic_preferences_colors.svg b/res/images/preferences/ic_preferences_colors.svg new file mode 100644 index 00000000000..cb7199750b8 --- /dev/null +++ b/res/images/preferences/ic_preferences_colors.svg @@ -0,0 +1,7 @@ + + Mixxx 1.12+ iconset + + + + + diff --git a/res/mixxx.qrc b/res/mixxx.qrc index 545cba1feac..c863791eee5 100644 --- a/res/mixxx.qrc +++ b/res/mixxx.qrc @@ -37,6 +37,7 @@ images/preferences/ic_preferences_autodj.svg images/preferences/ic_preferences_bpmdetect.svg images/preferences/ic_preferences_broadcast.svg + images/preferences/ic_preferences_colors.svg images/preferences/ic_preferences_controllers.svg images/preferences/ic_preferences_crossfader.svg images/preferences/ic_preferences_decks.svg diff --git a/src/engine/controls/cuecontrol.cpp b/src/engine/controls/cuecontrol.cpp index d087506dbc4..ebb89fd413c 100644 --- a/src/engine/controls/cuecontrol.cpp +++ b/src/engine/controls/cuecontrol.cpp @@ -11,6 +11,7 @@ #include "engine/enginebuffer.h" #include "preferences/colorpalettesettings.h" #include "util/color/color.h" +#include "util/color/predefinedcolorpalettes.h" #include "util/sample.h" #include "vinylcontrol/defs_vinylcontrol.h" @@ -622,7 +623,7 @@ void CueControl::hotcueSet(HotcueControl* pControl, double v) { auto hotcueColorPalette = m_colorPaletteSettings.getHotcueColorPalette(); pCue->setColor(hotcueColorPalette.colorForHotcueIndex(hotcue)); } else { - pCue->setColor(ColorPalette::kDefaultCueColor); + pCue->setColor(mixxx::PredefinedColorPalettes::kDefaultCueColor); } // TODO(XXX) deal with spurious signals diff --git a/src/preferences/colorpaletteeditor.cpp b/src/preferences/colorpaletteeditor.cpp new file mode 100644 index 00000000000..378d6abe576 --- /dev/null +++ b/src/preferences/colorpaletteeditor.cpp @@ -0,0 +1,216 @@ +#include "preferences/colorpaletteeditor.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "preferences/colorpalettesettings.h" +#include "util/color/predefinedcolorpalettes.h" + +namespace { +const QColor kDefaultPaletteColor(0, 0, 0); +} + +ColorPaletteEditor::ColorPaletteEditor(QWidget* parent) + : QWidget(parent), + m_bPaletteExists(false), + m_bPaletteIsReadOnly(false), + m_pPaletteNameComboBox(make_parented()), + m_pTableView(make_parented()), + m_pModel(make_parented(m_pTableView)) { + m_pPaletteNameComboBox->setEditable(true); + + QDialogButtonBox* pButtonBox = new QDialogButtonBox(); + m_pSaveButton = pButtonBox->addButton(QDialogButtonBox::Save); + m_pResetButton = pButtonBox->addButton(QDialogButtonBox::Reset); + m_pDiscardButton = pButtonBox->addButton(QDialogButtonBox::Discard); + + QHBoxLayout* pTopLayout = new QHBoxLayout(); + pTopLayout->addWidget(new QLabel("Name:")); + pTopLayout->addWidget(m_pPaletteNameComboBox, 1); + pTopLayout->addWidget(pButtonBox); + + QVBoxLayout* pLayout = new QVBoxLayout(); + pLayout->addLayout(pTopLayout); + pLayout->addWidget(m_pTableView, 1); + setLayout(pLayout); + setContentsMargins(0, 0, 0, 0); + + // Set up model + m_pModel->setColumnCount(2); + m_pModel->setHeaderData(0, Qt::Horizontal, tr("Color"), Qt::DisplayRole); + m_pModel->setHeaderData(1, Qt::Horizontal, tr("Assign to Hotcue"), Qt::DisplayRole); + connect(m_pModel, + &ColorPaletteEditorModel::dirtyChanged, + this, + &ColorPaletteEditor::slotUpdateButtons); + connect(m_pModel, + &ColorPaletteEditorModel::emptyChanged, + this, + &ColorPaletteEditor::slotUpdateButtons); + + // Setup up table view + m_pTableView->setShowGrid(false); + m_pTableView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_pTableView->setSelectionMode(QAbstractItemView::SingleSelection); + m_pTableView->setDragDropMode(QAbstractItemView::InternalMove); + m_pTableView->setDragDropOverwriteMode(false); + m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu); + m_pTableView->setModel(m_pModel); + + connect(m_pTableView, + &QTableView::doubleClicked, + this, + &ColorPaletteEditor::slotTableViewDoubleClicked); + connect(m_pTableView, + &QTableView::customContextMenuRequested, + this, + &ColorPaletteEditor::slotTableViewContextMenuRequested); + connect(m_pPaletteNameComboBox, + &QComboBox::editTextChanged, + this, + &ColorPaletteEditor::slotPaletteNameChanged); + connect(m_pDiscardButton, + &QPushButton::clicked, + this, + &ColorPaletteEditor::slotDiscardButtonClicked); + connect(m_pSaveButton, + &QPushButton::clicked, + this, + &ColorPaletteEditor::slotSaveButtonClicked); +} + +void ColorPaletteEditor::initialize(UserSettingsPointer pConfig) { + DEBUG_ASSERT(!m_pConfig); + m_pConfig = pConfig; + reset(); +} + +void ColorPaletteEditor::reset() { + m_pPaletteNameComboBox->clear(); + for (const ColorPalette& palette : mixxx::PredefinedColorPalettes::kPalettes) { + m_pPaletteNameComboBox->addItem(palette.getName()); + } + m_pPaletteNameComboBox->insertSeparator(mixxx::PredefinedColorPalettes::kPalettes.size()); + ColorPaletteSettings colorPaletteSettings(m_pConfig); + for (const QString& paletteName : colorPaletteSettings.getColorPaletteNames()) { + m_pPaletteNameComboBox->addItem(paletteName); + } +} + +void ColorPaletteEditor::slotUpdateButtons() { + bool bDirty = m_pModel->isDirty(); + bool bEmpty = m_pModel->isEmpty(); + m_pResetButton->setEnabled(bDirty); + m_pSaveButton->setEnabled(!m_bPaletteExists || (!m_bPaletteIsReadOnly && bDirty && !bEmpty)); + m_pDiscardButton->setEnabled(m_bPaletteExists && !m_bPaletteIsReadOnly); +} + +void ColorPaletteEditor::slotTableViewDoubleClicked(const QModelIndex& index) { + if (index.isValid() && index.column() == 0) { + QColor color = QColorDialog::getColor(); + if (color.isValid()) { + m_pModel->setColor(index.row(), color); + } + } +} + +void ColorPaletteEditor::slotTableViewContextMenuRequested(const QPoint& pos) { + QMenu menu(this); + + QAction* pAddAction = menu.addAction("Add"); + QAction* pRemoveAction = menu.addAction("Remove"); + QAction* pAction = menu.exec(m_pTableView->viewport()->mapToGlobal(pos)); + if (pAction == pAddAction) { + m_pModel->appendRow(kDefaultPaletteColor); + } else if (pAction == pRemoveAction) { + QModelIndexList selection = m_pTableView->selectionModel()->selectedRows(); + + if (selection.count() > 0) { + QModelIndex index = selection.at(0); + + //row selected + int row = index.row(); + m_pModel->removeRow(row); + } + } +} + +void ColorPaletteEditor::slotPaletteNameChanged(const QString& text) { + bool bPaletteIsReadOnly = false; + bool bPaletteExists = false; + for (const ColorPalette& palette : mixxx::PredefinedColorPalettes::kPalettes) { + if (text == palette.getName()) { + bPaletteExists = true; + bPaletteIsReadOnly = true; + break; + } + } + + ColorPaletteSettings colorPaletteSettings(m_pConfig); + if (!bPaletteIsReadOnly) { + bPaletteExists = colorPaletteSettings.getColorPaletteNames().contains(text); + } + + if (bPaletteExists) { + if (!m_pModel->isDirty()) { + bool bPaletteFound = false; + for (const ColorPalette& palette : mixxx::PredefinedColorPalettes::kPalettes) { + if (text == palette.getName()) { + bPaletteFound = true; + m_pModel->setColorPalette(palette); + break; + } + } + if (!bPaletteFound) { + m_pModel->setColorPalette(colorPaletteSettings.getColorPalette(text, mixxx::PredefinedColorPalettes::kDefaultHotcueColorPalette)); + } + } + } + + m_bPaletteExists = bPaletteExists; + m_bPaletteIsReadOnly = bPaletteIsReadOnly; + slotUpdateButtons(); +} + +void ColorPaletteEditor::slotDiscardButtonClicked() { + QString paletteName = m_pPaletteNameComboBox->currentText(); + ColorPaletteSettings colorPaletteSettings(m_pConfig); + colorPaletteSettings.removePalette(paletteName); + reset(); + emit paletteRemoved(paletteName); +} + +void ColorPaletteEditor::slotSaveButtonClicked() { + QString paletteName = m_pPaletteNameComboBox->currentText(); + ColorPaletteSettings colorPaletteSettings(m_pConfig); + colorPaletteSettings.setColorPalette(paletteName, m_pModel->getColorPalette(paletteName)); + m_pModel->setDirty(false); + reset(); + m_pPaletteNameComboBox->setCurrentText(paletteName); + emit paletteChanged(paletteName); +} + +void ColorPaletteEditor::slotResetButtonClicked() { + QString paletteName = m_pPaletteNameComboBox->currentText(); + ColorPaletteSettings colorPaletteSettings(m_pConfig); + bool bPaletteExists = colorPaletteSettings.getColorPaletteNames().contains(paletteName); + if (!bPaletteExists) { + for (const ColorPalette& palette : mixxx::PredefinedColorPalettes::kPalettes) { + if (paletteName == palette.getName()) { + bPaletteExists = true; + break; + } + } + } + m_pModel->setDirty(false); + reset(); + if (bPaletteExists) { + m_pPaletteNameComboBox->setCurrentText(paletteName); + } +} diff --git a/src/preferences/colorpaletteeditor.h b/src/preferences/colorpaletteeditor.h new file mode 100644 index 00000000000..9786c10b592 --- /dev/null +++ b/src/preferences/colorpaletteeditor.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include +#include + +#include "preferences/colorpaletteeditormodel.h" +#include "preferences/usersettings.h" +#include "util/parented_ptr.h" + +// Widget for viewing, adding, editing and removing color palettes that can be +// used for track/hotcue colors. +class ColorPaletteEditor : public QWidget { + Q_OBJECT + public: + ColorPaletteEditor(QWidget* parent = nullptr); + void initialize(UserSettingsPointer pConfig); + void reset(); + + signals: + void paletteChanged(QString name); + void paletteRemoved(QString name); + + private slots: + void slotUpdateButtons(); + void slotTableViewDoubleClicked(const QModelIndex& index); + void slotTableViewContextMenuRequested(const QPoint& pos); + void slotPaletteNameChanged(const QString& text); + void slotDiscardButtonClicked(); + void slotSaveButtonClicked(); + void slotResetButtonClicked(); + + private: + bool m_bPaletteExists; + bool m_bPaletteIsReadOnly; + + UserSettingsPointer m_pConfig; + parented_ptr m_pPaletteNameComboBox; + parented_ptr m_pTableView; + parented_ptr m_pModel; + QPushButton* m_pSaveButton; + QPushButton* m_pDiscardButton; + QPushButton* m_pResetButton; +}; diff --git a/src/preferences/colorpaletteeditormodel.cpp b/src/preferences/colorpaletteeditormodel.cpp new file mode 100644 index 00000000000..62d958fbe16 --- /dev/null +++ b/src/preferences/colorpaletteeditormodel.cpp @@ -0,0 +1,138 @@ +#include "preferences/colorpaletteeditormodel.h" + +namespace { + +QIcon toQIcon(const QColor& color) { + QPixmap pixmap(50, 50); + pixmap.fill(color); + return QIcon(pixmap); +} + +} // namespace + +ColorPaletteEditorModel::ColorPaletteEditorModel(QObject* parent) + : QStandardItemModel(parent), + m_bEmpty(true), + m_bDirty(false) { + connect(this, + &ColorPaletteEditorModel::rowsRemoved, + [this] { + if (rowCount() == 0) { + m_bEmpty = true; + emit emptyChanged(true); + } + setDirty(true); + }); + connect(this, + &ColorPaletteEditorModel::rowsInserted, + [this] { + if (m_bEmpty && rowCount() != 0) { + m_bEmpty = false; + emit emptyChanged(true); + } + setDirty(true); + }); + connect(this, + &ColorPaletteEditorModel::rowsMoved, + [this] { + setDirty(true); + }); +} + +bool ColorPaletteEditorModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) { + // Always move the entire row, and don't allow column "shifting" + Q_UNUSED(column); + return QStandardItemModel::dropMimeData(data, action, row, 0, parent); +} + +bool ColorPaletteEditorModel::setData(const QModelIndex& modelIndex, const QVariant& value, int role) { + setDirty(true); + if (modelIndex.isValid() && modelIndex.column() == 1) { + bool ok; + int hotcueIndex = value.toInt(&ok); + + // Make sure that the value is valid + if (!ok || hotcueIndex <= 0 || hotcueIndex > rowCount()) { + return QStandardItemModel::setData(modelIndex, QVariant(), role); + } + + // Make sure there is no other row with the same hotcue index + for (int i = 0; i < rowCount(); i++) { + QModelIndex otherModelIndex = index(i, 1); + QVariant otherValue = data(otherModelIndex); + int otherHotcueIndex = otherValue.toInt(&ok); + if (ok && otherHotcueIndex == hotcueIndex) { + QStandardItemModel::setData(otherModelIndex, QVariant(), role); + } + } + } + + return QStandardItemModel::setData(modelIndex, value, role); +} + +void ColorPaletteEditorModel::setColor(int row, const QColor& color) { + QStandardItem* pItem = item(row, 0); + if (pItem) { + pItem->setIcon(toQIcon(color)); + pItem->setText(color.name()); + } + setDirty(true); +} + +void ColorPaletteEditorModel::appendRow(const QColor& color, int hotcueIndex) { + QStandardItem* pColorItem = new QStandardItem(toQIcon(color), color.name()); + pColorItem->setEditable(false); + pColorItem->setDropEnabled(false); + + QString hotcueIndexStr; + if (hotcueIndex >= 0) { + hotcueIndexStr = QString::number(hotcueIndex + 1); + } + + QStandardItem* pHotcueIndexItem = new QStandardItem(hotcueIndexStr); + pHotcueIndexItem->setEditable(true); + pHotcueIndexItem->setDropEnabled(false); + + QStandardItemModel::appendRow(QList{pColorItem, pHotcueIndexItem}); +} + +void ColorPaletteEditorModel::setColorPalette(const ColorPalette& palette) { + // Remove all rows + removeRows(0, rowCount()); + + // Make a map of hotcue indices + QMap hotcueColorIndicesMap; + QList hotcueColorIndices = palette.getHotcueIndices(); + for (int i = 0; i < hotcueColorIndices.size(); i++) { + int colorIndex = hotcueColorIndices.at(i); + hotcueColorIndicesMap.insert(colorIndex, i); + } + + for (int i = 0; i < palette.size(); i++) { + QColor color = mixxx::RgbColor::toQColor(palette.at(i)); + int colorIndex = hotcueColorIndicesMap.value(i, kNoHotcueIndex); + appendRow(color, colorIndex); + } + + setDirty(false); +} + +ColorPalette ColorPaletteEditorModel::getColorPalette(const QString& name) const { + QList colors; + QMap hotcueColorIndices; + for (int i = 0; i < rowCount(); i++) { + QStandardItem* pColorItem = item(i, 0); + QStandardItem* pHotcueIndexItem = item(i, 1); + mixxx::RgbColor::optional_t color = mixxx::RgbColor::fromQString(pColorItem->text()); + if (color) { + colors << *color; + + bool ok; + int hotcueIndex = pHotcueIndexItem->text().toInt(&ok); + if (ok) { + hotcueColorIndices.insert(hotcueIndex - 1, colors.size() - 1); + } + } + } + return ColorPalette(name, colors, hotcueColorIndices.values()); +} diff --git a/src/preferences/colorpaletteeditormodel.h b/src/preferences/colorpaletteeditormodel.h new file mode 100644 index 00000000000..b76c7a0053f --- /dev/null +++ b/src/preferences/colorpaletteeditormodel.h @@ -0,0 +1,48 @@ +#pragma once +#include + +#include "util/color/colorpalette.h" + +// Model that is used by the QTableView of the ColorPaletteEditor. +// Takes of displaying palette colors and provides a getter/setter for +// ColorPalette instances. +class ColorPaletteEditorModel : public QStandardItemModel { + Q_OBJECT + public: + static constexpr int kNoHotcueIndex = -1; + + ColorPaletteEditorModel(QObject* parent = nullptr); + + bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + + void setColor(int row, const QColor& color); + void appendRow(const QColor& color, int hotcueIndex = kNoHotcueIndex); + + void setDirty(bool bDirty) { + if (m_bDirty == bDirty) { + return; + } + m_bDirty = bDirty; + emit dirtyChanged(m_bDirty); + } + + bool isDirty() const { + return m_bDirty; + } + + bool isEmpty() const { + return m_bEmpty; + } + + void setColorPalette(const ColorPalette& palette); + ColorPalette getColorPalette(const QString& name) const; + + signals: + void emptyChanged(bool bIsEmpty); + void dirtyChanged(bool bIsDirty); + + private: + bool m_bEmpty; + bool m_bDirty; +}; diff --git a/src/preferences/colorpalettesettings.cpp b/src/preferences/colorpalettesettings.cpp index 63976e4cbdb..fed31b32743 100644 --- a/src/preferences/colorpalettesettings.cpp +++ b/src/preferences/colorpalettesettings.cpp @@ -1,11 +1,16 @@ #include "preferences/colorpalettesettings.h" +#include "util/color/predefinedcolorpalettes.h" + namespace { const mixxx::RgbColor kColorBlack(0x000000); const QString kColorPaletteConfigGroup = QStringLiteral("[Config]"); const QString kColorPaletteGroupStart = QStringLiteral("[ColorPalette "); const QString kColorPaletteGroupEnd = QStringLiteral("]"); const QRegExp kColorPaletteGroupNameRegex(QStringLiteral("^\\[ColorPalette (.+)\\]$")); +const QString kColorPaletteHotcueIndicesConfigItem = QStringLiteral("hotcue_indices"); +const QString kColorPaletteHotcueIndicesConfigSeparator = QStringLiteral(" "); +const QString kColorPaletteGroup = QStringLiteral("[ColorPalette %1]"); const ConfigKey kHotcueColorPaletteConfigKey(kColorPaletteConfigGroup, QStringLiteral("HotcueColorPalette")); const ConfigKey kTrackColorPaletteConfigKey(kColorPaletteConfigGroup, QStringLiteral("TrackColorPalette")); @@ -25,12 +30,35 @@ ConfigKey keyForIndex(const QString& group, int index, int numDigits) { ColorPalette ColorPaletteSettings::getColorPalette( const QString& name, const ColorPalette& defaultPalette) const { - QList colorList; + if (name.isEmpty()) { + return defaultPalette; + } + // If we find a predefined palette with this name, return it + for (const ColorPalette& palette : mixxx::PredefinedColorPalettes::kPalettes) { + if (name == palette.getName()) { + return palette; + } + } + + // Read colors from configuration const QString group = kColorPaletteGroupStart + name + kColorPaletteGroupEnd; + QList colorList; + QList hotcueIndices; for (const ConfigKey& key : m_pConfig->getKeysWithGroup(group)) { - mixxx::RgbColor color = mixxx::RgbColor(m_pConfig->getValue(key, kColorBlack)); - colorList.append(color); + if (key.item == kColorPaletteHotcueIndicesConfigItem) { + for (const QString& stringIndex : + m_pConfig->getValueString(key).split(kColorPaletteHotcueIndicesConfigSeparator, QString::SkipEmptyParts)) { + bool ok; + int index = stringIndex.toInt(&ok); + if (ok && index >= 0) { + hotcueIndices << static_cast(index); + } + } + } else { + mixxx::RgbColor color = mixxx::RgbColor(m_pConfig->getValue(key, kColorBlack)); + colorList.append(color); + } } // If no palette is defined in the settings, we use the default one. @@ -38,7 +66,7 @@ ColorPalette ColorPaletteSettings::getColorPalette( return defaultPalette; } - return ColorPalette(name, colorList); + return ColorPalette(name, colorList, hotcueIndices); } void ColorPaletteSettings::setColorPalette(const QString& name, const ColorPalette& colorPalette) { @@ -47,6 +75,12 @@ void ColorPaletteSettings::setColorPalette(const QString& name, const ColorPalet return; } + for (const ColorPalette& palette : mixxx::PredefinedColorPalettes::kPalettes) { + if (name == palette.getName()) { + qDebug() << "Color Palette" << name << "is a built-in palette, not writing to config!"; + return; + } + } removePalette(name); const QString group = kColorPaletteGroupStart + name + kColorPaletteGroupEnd; @@ -55,6 +89,16 @@ void ColorPaletteSettings::setColorPalette(const QString& name, const ColorPalet mixxx::RgbColor color = colorPalette.at(index); m_pConfig->setValue(keyForIndex(group, index, numDigits), color); } + + QStringList stringIndices; + for (const unsigned int index : colorPalette.getHotcueIndices()) { + stringIndices << QString::number(index); + } + if (!stringIndices.isEmpty()) { + m_pConfig->setValue( + ConfigKey(group, kColorPaletteHotcueIndicesConfigItem), + stringIndices.join(kColorPaletteHotcueIndicesConfigSeparator)); + } } void ColorPaletteSettings::removePalette(const QString& name) { @@ -66,10 +110,7 @@ void ColorPaletteSettings::removePalette(const QString& name) { ColorPalette ColorPaletteSettings::getHotcueColorPalette() const { QString name = m_pConfig->getValueString(kHotcueColorPaletteConfigKey); - if (name.isEmpty()) { - return ColorPalette::mixxxHotcuePalette; - } - return getColorPalette(name, ColorPalette::mixxxHotcuePalette); + return getColorPalette(name, mixxx::PredefinedColorPalettes::kDefaultHotcueColorPalette); } void ColorPaletteSettings::setHotcueColorPalette(const ColorPalette& colorPalette) { @@ -84,10 +125,7 @@ void ColorPaletteSettings::setHotcueColorPalette(const ColorPalette& colorPalett ColorPalette ColorPaletteSettings::getTrackColorPalette() const { QString name = m_pConfig->getValueString(kTrackColorPaletteConfigKey); - if (name.isEmpty()) { - return ColorPalette::mixxxHotcuePalette; - } - return getColorPalette(name, ColorPalette::mixxxHotcuePalette); + return getColorPalette(name, mixxx::PredefinedColorPalettes::kDefaultTrackColorPalette); } void ColorPaletteSettings::setTrackColorPalette(const ColorPalette& colorPalette) { diff --git a/src/preferences/dialog/dlgprefcolors.cpp b/src/preferences/dialog/dlgprefcolors.cpp new file mode 100644 index 00000000000..6888e8db98b --- /dev/null +++ b/src/preferences/dialog/dlgprefcolors.cpp @@ -0,0 +1,100 @@ +#include "preferences/dialog/dlgprefcolors.h" + +#include +#include +#include + +#include "control/controlobject.h" +#include "util/color/predefinedcolorpalettes.h" + +DlgPrefColors::DlgPrefColors( + QWidget* parent, UserSettingsPointer pConfig) + : DlgPreferencePage(parent), + m_pConfig(pConfig), + m_colorPaletteSettings(ColorPaletteSettings(pConfig)) { + setupUi(this); + colorPaletteEditor->initialize(pConfig); + + loadSettings(); + + connect(colorPaletteEditor, + &ColorPaletteEditor::paletteChanged, + [this] { + loadSettings(); + }); + connect(colorPaletteEditor, + &ColorPaletteEditor::paletteRemoved, + [this] { + loadSettings(); + }); +} + +DlgPrefColors::~DlgPrefColors() { +} + +// Loads the config keys and sets the widgets in the dialog to match +void DlgPrefColors::loadSettings() { + comboBoxHotcueColors->clear(); + comboBoxTrackColors->clear(); + foreach (const ColorPalette& palette, mixxx::PredefinedColorPalettes::kPalettes) { + QString paletteName = palette.getName(); + comboBoxHotcueColors->addItem(paletteName); + comboBoxTrackColors->addItem(paletteName); + } + + foreach (const QString& paletteName, m_colorPaletteSettings.getColorPaletteNames()) { + comboBoxHotcueColors->addItem(paletteName); + comboBoxTrackColors->addItem(paletteName); + } + + comboBoxHotcueColors->setCurrentText( + m_colorPaletteSettings.getHotcueColorPalette().getName()); + comboBoxTrackColors->setCurrentText( + m_colorPaletteSettings.getTrackColorPalette().getName()); + + slotApply(); +} + +// Set the default values for all the widgets +void DlgPrefColors::slotResetToDefaults() { + comboBoxHotcueColors->setCurrentText( + mixxx::PredefinedColorPalettes::kDefaultHotcueColorPalette.getName()); + comboBoxTrackColors->setCurrentText( + mixxx::PredefinedColorPalettes::kDefaultTrackColorPalette.getName()); + slotApply(); +} + +// Apply and save any changes made in the dialog +void DlgPrefColors::slotApply() { + QString hotcueColorPaletteName = comboBoxHotcueColors->currentText(); + QString trackColorPaletteName = comboBoxTrackColors->currentText(); + bool bHotcueColorPaletteFound = false; + bool bTrackColorPaletteFound = false; + + foreach (const ColorPalette& palette, mixxx::PredefinedColorPalettes::kPalettes) { + if (!bHotcueColorPaletteFound && hotcueColorPaletteName == palette.getName()) { + m_colorPaletteSettings.setHotcueColorPalette(palette); + bHotcueColorPaletteFound = true; + } + if (!bTrackColorPaletteFound && trackColorPaletteName == palette.getName()) { + m_colorPaletteSettings.setTrackColorPalette(palette); + bTrackColorPaletteFound = true; + } + } + + if (!bHotcueColorPaletteFound) { + m_colorPaletteSettings.setHotcueColorPalette( + m_colorPaletteSettings.getColorPalette(hotcueColorPaletteName, + m_colorPaletteSettings.getHotcueColorPalette())); + } + + if (!bTrackColorPaletteFound) { + m_colorPaletteSettings.setTrackColorPalette( + m_colorPaletteSettings.getColorPalette(trackColorPaletteName, + m_colorPaletteSettings.getTrackColorPalette())); + } + + m_pConfig->setValue( + ConfigKey("[Controls]", "auto_hotcue_colors"), + checkBoxAssignHotcueColors->isChecked()); +} diff --git a/src/preferences/dialog/dlgprefcolors.h b/src/preferences/dialog/dlgprefcolors.h new file mode 100644 index 00000000000..9feb41a873b --- /dev/null +++ b/src/preferences/dialog/dlgprefcolors.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "control/controlproxy.h" +#include "preferences/colorpalettesettings.h" +#include "preferences/dialog/ui_dlgprefcolorsdlg.h" +#include "preferences/dlgpreferencepage.h" +#include "preferences/usersettings.h" + +class DlgPrefColors : public DlgPreferencePage, public Ui::DlgPrefColorsDlg { + Q_OBJECT + public: + DlgPrefColors(QWidget* parent, UserSettingsPointer pConfig); + virtual ~DlgPrefColors(); + + public slots: + // Apply changes to widget + void slotApply(); + void slotResetToDefaults(); + + signals: + void apply(const QString&); + + private: + void loadSettings(); + void loadPaletteIntoEditor(const ColorPalette& palette); + + const UserSettingsPointer m_pConfig; + ColorPaletteSettings m_colorPaletteSettings; +}; diff --git a/src/preferences/dialog/dlgprefcolorsdlg.ui b/src/preferences/dialog/dlgprefcolorsdlg.ui new file mode 100644 index 00000000000..08bf006daa6 --- /dev/null +++ b/src/preferences/dialog/dlgprefcolorsdlg.ui @@ -0,0 +1,110 @@ + + + DlgPrefColorsDlg + + + + 0 + 0 + 524 + 333 + + + + + 0 + 0 + + + + Color Preferences + + + + + + Colors + + + + + + Hotcues: + + + + + + + + + + Track: + + + + + + + + + + Auto hotcue colors + + + checkBoxAssignHotcueColors + + + + + + + Automatically assigns a predefined color to a newly created hotcue point, based on its index. + + + Assign predefined colors to newly created hotcue points + + + + + + + + + + Palette Editor + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + ColorPaletteEditor + QWidget +
preferences/colorpaletteeditor.h
+ 1 +
+
+ + +
diff --git a/src/preferences/dialog/dlgprefdeck.cpp b/src/preferences/dialog/dlgprefdeck.cpp index e6c2ced3be2..1d27be85333 100644 --- a/src/preferences/dialog/dlgprefdeck.cpp +++ b/src/preferences/dialog/dlgprefdeck.cpp @@ -206,14 +206,6 @@ DlgPrefDeck::DlgPrefDeck(QWidget * parent, MixxxMainWindow * mixxx, this, SLOT(slotCloneDeckOnLoadDoubleTapCheckbox(bool))); - // Automatically assign a color to new hot cues - m_bAssignHotcueColors = m_pConfig->getValue(ConfigKey("[Controls]", "auto_hotcue_colors"), false); - checkBoxAssignHotcueColors->setChecked(m_bAssignHotcueColors); - connect(checkBoxAssignHotcueColors, - SIGNAL(toggled(bool)), - this, - SLOT(slotAssignHotcueColorsCheckbox(bool))); - m_bRateInverted = m_pConfig->getValue(ConfigKey("[Controls]", "RateDir"), false); setRateDirectionForAllDecks(m_bRateInverted); checkBoxInvertSpeedSlider->setChecked(m_bRateInverted); @@ -386,9 +378,6 @@ void DlgPrefDeck::slotUpdate() { checkBoxCloneDeckOnLoadDoubleTap->setChecked(m_pConfig->getValue( ConfigKey("[Controls]", "CloneDeckOnLoadDoubleTap"), true)); - checkBoxAssignHotcueColors->setChecked(m_pConfig->getValue( - ConfigKey("[Controls]", "auto_hotcue_colors"), false)); - double deck1RateRange = m_rateRangeControls[0]->get(); int index = ComboBoxRateRange->findData(static_cast(deck1RateRange * 100)); if (index == -1) { @@ -551,10 +540,6 @@ void DlgPrefDeck::slotCloneDeckOnLoadDoubleTapCheckbox(bool checked) { m_bCloneDeckOnLoadDoubleTap = checked; } -void DlgPrefDeck::slotAssignHotcueColorsCheckbox(bool checked) { - m_bAssignHotcueColors = checked; -} - void DlgPrefDeck::slotSetTrackTimeDisplay(QAbstractButton* b) { if (b == radioButtonRemaining) { m_timeDisplayMode = TrackTime::DisplayMode::REMAINING; @@ -642,7 +627,6 @@ void DlgPrefDeck::slotApply() { m_pConfig->setValue(ConfigKey("[Controls]", "CueRecall"), static_cast(m_seekOnLoadMode)); m_pConfig->setValue(ConfigKey("[Controls]", "CloneDeckOnLoadDoubleTap"), m_bCloneDeckOnLoadDoubleTap); - m_pConfig->setValue(ConfigKey("[Controls]", "auto_hotcue_colors"), m_bAssignHotcueColors); // Set rate range setRateRangeForAllDecks(m_iRateRangePercent); diff --git a/src/preferences/dialog/dlgprefdeck.h b/src/preferences/dialog/dlgprefdeck.h index cbc3b5b8688..96bc1914401 100644 --- a/src/preferences/dialog/dlgprefdeck.h +++ b/src/preferences/dialog/dlgprefdeck.h @@ -80,7 +80,6 @@ class DlgPrefDeck : public DlgPreferencePage, public Ui::DlgPrefDeckDlg { void slotCueModeCombobox(int); void slotSetTrackLoadMode(int comboboxIndex); void slotCloneDeckOnLoadDoubleTapCheckbox(bool); - void slotAssignHotcueColorsCheckbox(bool); void slotRateRampingModeLinearButton(bool); void slotRateRampSensitivitySlider(int); diff --git a/src/preferences/dialog/dlgprefdeckdlg.ui b/src/preferences/dialog/dlgprefdeckdlg.ui index e1ca340a60d..927f8aecabf 100644 --- a/src/preferences/dialog/dlgprefdeckdlg.ui +++ b/src/preferences/dialog/dlgprefdeckdlg.ui @@ -23,6 +23,16 @@ 10 + + + + Playing track protection + + + checkBoxDisallowLoadToPlayingDeck + + + @@ -36,6 +46,33 @@ + + + + + + + When the analyzer places the intro start point automatically, +it will place it at the main cue point if the main cue point has been set previously. +This may be helpful for upgrading to Mixxx 2.3 from earlier versions. + +If this option is disabled, the intro start point is automatically placed at the first sound. + + + Set intro start to main cue when analyzing tracks + + + + + + + Intro start + + + ComboBoxCueMode + + + @@ -61,27 +98,30 @@ CUP mode: - - + + - Intro start + Clone deck - ComboBoxCueMode + checkBoxCloneDeckOnLoadDoubleTap - - - - When the analyzer places the intro start point automatically, -it will place it at the main cue point if the main cue point has been set previously. -This may be helpful for upgrading to Mixxx 2.3 from earlier versions. - -If this option is disabled, the intro start point is automatically placed at the first sound. + + + + Time Format + + + + + + + - Set intro start to main cue when analyzing tracks + Track load point @@ -104,6 +144,13 @@ If this option is disabled, the intro start point is automatically placed at the + + + + Do not load tracks into playing decks + + + @@ -138,74 +185,7 @@ If this option is disabled, the intro start point is automatically placed at the - - - - Time Format - - - - - - - - - - Track load point - - - - - - - - - - Auto hotcue colors - - - checkBoxAssignHotcueColors - - - - - - - Automatically assigns a predefined color to a newly created hotcue point, based on its index. - - - Assign predefined colors to newly created hotcue points - - - - - - - Playing track protection - - - checkBoxDisallowLoadToPlayingDeck - - - - - - Do not load tracks into playing decks - - - - - - - Clone deck - - - checkBoxCloneDeckOnLoadDoubleTap - - - - Create a playing clone of the first playing deck by double-tapping a Load button on a controller or keyboard. @@ -822,14 +802,13 @@ You can always drag-and-drop tracks on screen to clone a deck. - + + false - - diff --git a/src/preferences/dialog/dlgpreferences.cpp b/src/preferences/dialog/dlgpreferences.cpp index fc34d5a30bb..61b7b1828e6 100644 --- a/src/preferences/dialog/dlgpreferences.cpp +++ b/src/preferences/dialog/dlgpreferences.cpp @@ -37,11 +37,12 @@ #include "preferences/dialog/dlgprefnovinyl.h" #endif -#include "preferences/dialog/dlgprefinterface.h" -#include "preferences/dialog/dlgprefwaveform.h" +#include "preferences/dialog/dlgprefcolors.h" +#include "preferences/dialog/dlgprefcrossfader.h" #include "preferences/dialog/dlgprefdeck.h" #include "preferences/dialog/dlgprefeq.h" -#include "preferences/dialog/dlgprefcrossfader.h" +#include "preferences/dialog/dlgprefinterface.h" +#include "preferences/dialog/dlgprefwaveform.h" #ifdef __LILV__ #include "preferences/dialog/dlgpreflv2.h" #endif /* __LILV__ */ @@ -121,6 +122,8 @@ DlgPreferences::DlgPreferences(MixxxMainWindow * mixxx, SkinLoader* pSkinLoader, addPageWidget(m_waveformPage); m_deckPage = new DlgPrefDeck(this, mixxx, pPlayerManager, m_pConfig); addPageWidget(m_deckPage); + m_colorsPage = new DlgPrefColors(this, m_pConfig); + addPageWidget(m_colorsPage); m_equalizerPage = new DlgPrefEQ(this, pEffectsManager, m_pConfig); addPageWidget(m_equalizerPage); m_crossfaderPage = new DlgPrefCrossfader(this, m_pConfig); @@ -234,6 +237,12 @@ void DlgPreferences::createIcons() { m_pDecksButton->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter); m_pDecksButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_pColorsButton = new QTreeWidgetItem(contentsTreeWidget, QTreeWidgetItem::Type); + m_pColorsButton->setIcon(0, QIcon(":/images/preferences/ic_preferences_colors.svg")); + m_pColorsButton->setText(0, tr("Colors")); + m_pColorsButton->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter); + m_pColorsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_pEqButton = new QTreeWidgetItem(contentsTreeWidget, QTreeWidgetItem::Type); m_pEqButton->setIcon(0, QIcon(":/images/preferences/ic_preferences_equalizers.svg")); m_pEqButton->setText(0, tr("Equalizers")); @@ -334,6 +343,8 @@ void DlgPreferences::changePage(QTreeWidgetItem* current, QTreeWidgetItem* previ switchToPage(m_waveformPage); } else if (current == m_pDecksButton) { switchToPage(m_deckPage); + } else if (current == m_pColorsButton) { + switchToPage(m_colorsPage); } else if (current == m_pEqButton) { switchToPage(m_equalizerPage); } else if (current == m_pCrossfaderButton) { diff --git a/src/preferences/dialog/dlgpreferences.h b/src/preferences/dialog/dlgpreferences.h index a33b504249a..aa1972f4bd9 100644 --- a/src/preferences/dialog/dlgpreferences.h +++ b/src/preferences/dialog/dlgpreferences.h @@ -40,6 +40,7 @@ class DlgPrefNoVinyl; class DlgPrefInterface; class DlgPrefWaveform; class DlgPrefDeck; +class DlgPrefColors; class DlgPrefEQ; class DlgPrefEffects; class DlgPrefCrossfader; @@ -66,11 +67,16 @@ class DlgPrefModplug; class DlgPreferences : public QDialog, public Ui::DlgPreferencesDlg { Q_OBJECT public: - DlgPreferences(MixxxMainWindow* mixxx, SkinLoader* pSkinLoader, SoundManager* soundman, - PlayerManager* pPlayerManager, ControllerManager* controllers, - VinylControlManager* pVCManager, LV2Backend* pLV2Backend, - EffectsManager* pEffectsManager, - SettingsManager* pSettingsManager, Library *pLibrary); + DlgPreferences(MixxxMainWindow* mixxx, + SkinLoader* pSkinLoader, + SoundManager* soundman, + PlayerManager* pPlayerManager, + ControllerManager* controllers, + VinylControlManager* pVCManager, + LV2Backend* pLV2Backend, + EffectsManager* pEffectsManager, + SettingsManager* pSettingsManager, + Library* pLibrary); virtual ~DlgPreferences(); void addPageWidget(DlgPreferencePage* pWidget); @@ -115,6 +121,7 @@ class DlgPreferences : public QDialog, public Ui::DlgPreferencesDlg { DlgPrefInterface* m_interfacePage; DlgPrefWaveform* m_waveformPage; DlgPrefDeck* m_deckPage; + DlgPrefColors* m_colorsPage; DlgPrefEQ* m_equalizerPage; DlgPrefCrossfader* m_crossfaderPage; DlgPrefEffects* m_effectsPage; @@ -138,6 +145,7 @@ class DlgPreferences : public QDialog, public Ui::DlgPreferencesDlg { QTreeWidgetItem* m_pInterfaceButton; QTreeWidgetItem* m_pWaveformButton; QTreeWidgetItem* m_pDecksButton; + QTreeWidgetItem* m_pColorsButton; QTreeWidgetItem* m_pEqButton; #ifdef __LILV__ QTreeWidgetItem* m_pLV2Button; diff --git a/src/test/colorconfig_test.cpp b/src/test/colorconfig_test.cpp index 58a17f706a2..5ed387161b0 100644 --- a/src/test/colorconfig_test.cpp +++ b/src/test/colorconfig_test.cpp @@ -3,6 +3,7 @@ #include "preferences/colorpalettesettings.h" #include "test/mixxxtest.h" #include "util/color/colorpalette.h" +#include "util/color/predefinedcolorpalettes.h" #include "util/color/rgbcolor.h" class ColorConfigTest : public MixxxTest {}; @@ -99,7 +100,8 @@ TEST_F(ColorConfigTest, LoadSavePalettes) { TEST_F(ColorConfigTest, DefaultColorPalette) { ColorPaletteSettings colorPaletteSettings(config()); - ColorPalette colorPaletteFromConfig = - colorPaletteSettings.getHotcueColorPalette(); - ASSERT_EQ(ColorPalette::mixxxHotcuePalette, colorPaletteFromConfig); + ASSERT_EQ(mixxx::PredefinedColorPalettes::kDefaultHotcueColorPalette, + colorPaletteSettings.getHotcueColorPalette()); + ASSERT_EQ(mixxx::PredefinedColorPalettes::kDefaultTrackColorPalette, + colorPaletteSettings.getTrackColorPalette()); } diff --git a/src/test/colorpalette_test.cpp b/src/test/colorpalette_test.cpp index 77b13d731de..f601259a68c 100644 --- a/src/test/colorpalette_test.cpp +++ b/src/test/colorpalette_test.cpp @@ -3,25 +3,26 @@ #include #include "test/mixxxtest.h" +#include "util/color/predefinedcolorpalettes.h" class ColorPaletteTest : public MixxxTest {}; TEST_F(ColorPaletteTest, NextColor) { - const ColorPalette palette = ColorPalette::mixxxHotcuePalette; + const ColorPalette palette = mixxx::PredefinedColorPalettes::kDefaultHotcueColorPalette; ASSERT_TRUE(palette.size() >= 1); ASSERT_EQ(palette.nextColor(palette.at(0)), palette.at(1)); ASSERT_EQ(palette.nextColor(palette.at(palette.size() - 1)), palette.at(0)); } TEST_F(ColorPaletteTest, PreviousColor) { - const ColorPalette palette = ColorPalette::mixxxHotcuePalette; + const ColorPalette palette = mixxx::PredefinedColorPalettes::kDefaultHotcueColorPalette; ASSERT_TRUE(palette.size() >= 1); ASSERT_EQ(palette.previousColor(palette.at(1)), palette.at(0)); ASSERT_EQ(palette.previousColor(palette.at(0)), palette.at(palette.size() - 1)); } TEST_F(ColorPaletteTest, NextAndPreviousColorRoundtrip) { - const ColorPalette palette = ColorPalette::mixxxHotcuePalette; + const ColorPalette palette = mixxx::PredefinedColorPalettes::kDefaultHotcueColorPalette; ASSERT_TRUE(palette.size() >= 1); ASSERT_EQ(palette.nextColor(palette.previousColor(palette.at(0))), palette.at(0)); ASSERT_EQ(palette.nextColor(palette.previousColor(palette.at(palette.size() - 1))), palette.at(palette.size() - 1)); diff --git a/src/track/cue.cpp b/src/track/cue.cpp index a923ab7a941..7ba0ad99251 100644 --- a/src/track/cue.cpp +++ b/src/track/cue.cpp @@ -9,7 +9,7 @@ #include "engine/engine.h" #include "util/assert.h" #include "util/color/color.h" -#include "util/color/colorpalette.h" +#include "util/color/predefinedcolorpalettes.h" namespace { @@ -54,7 +54,7 @@ Cue::Cue() m_sampleStartPosition(Cue::kNoPosition), m_sampleEndPosition(Cue::kNoPosition), m_iHotCue(Cue::kNoHotCue), - m_color(ColorPalette::kDefaultCueColor) { + m_color(mixxx::PredefinedColorPalettes::kDefaultCueColor) { } Cue::Cue( @@ -101,7 +101,7 @@ Cue::Cue( sampleRate)), m_iHotCue(cueInfo.getHotCueNumber() ? *cueInfo.getHotCueNumber() : kNoHotCue), m_label(cueInfo.getLabel()), - m_color(cueInfo.getColor().value_or(ColorPalette::kDefaultCueColor)) { + m_color(cueInfo.getColor().value_or(mixxx::PredefinedColorPalettes::kDefaultCueColor)) { } mixxx::CueInfo Cue::getCueInfo( diff --git a/src/util/color/colorpalette.cpp b/src/util/color/colorpalette.cpp index a606f8e73b4..f5ff71be249 100644 --- a/src/util/color/colorpalette.cpp +++ b/src/util/color/colorpalette.cpp @@ -1,38 +1,5 @@ #include "colorpalette.h" -namespace { - -constexpr mixxx::RgbColor kColorMixxxRed(0xC50A08); -constexpr mixxx::RgbColor kColorMixxxYellow(0x32BE44); -constexpr mixxx::RgbColor kColorMixxxGreen(0x42D4F4); -constexpr mixxx::RgbColor kColorMixxxCeleste(0xF8D200); -constexpr mixxx::RgbColor kColorMixxxBlue(0x0044FF); -constexpr mixxx::RgbColor kColorMixxxPurple(0xAF00CC); -constexpr mixxx::RgbColor kColorMixxxPink(0xFCA6D7); -constexpr mixxx::RgbColor kColorMixxxWhite(0xF2F2FF); - -// Replaces "no color" values and is used for new cues if auto_hotcue_colors is -// disabled -constexpr mixxx::RgbColor kSchemaMigrationReplacementColor(0xFF8C00); - -} // anonymous namespace - -const ColorPalette ColorPalette::mixxxHotcuePalette = - ColorPalette( - QStringLiteral("Mixxx Hotcue Colors"), - QList{ - kColorMixxxRed, - kColorMixxxYellow, - kColorMixxxGreen, - kColorMixxxCeleste, - kColorMixxxBlue, - kColorMixxxPurple, - kColorMixxxPink, - kColorMixxxWhite, - }); - -const mixxx::RgbColor ColorPalette::kDefaultCueColor = kSchemaMigrationReplacementColor; - mixxx::RgbColor ColorPalette::nextColor(mixxx::RgbColor color) const { // Return first color if color not in palette ((-1 + 1) % size) return at((indexOf(color) + 1) % size()); @@ -49,7 +16,14 @@ mixxx::RgbColor ColorPalette::previousColor(mixxx::RgbColor color) const { return at(iIndex); } -mixxx::RgbColor ColorPalette::colorForHotcueIndex(unsigned int index) const { - // For hotcue n, get nth color from palette - return at(index % size()); +mixxx::RgbColor ColorPalette::colorForHotcueIndex(unsigned int hotcueIndex) const { + int colorIndex; + if (m_hotcueColorIndices.isEmpty()) { + // For hotcue n, get nth color from palette + colorIndex = hotcueIndex; + } else { + // For hotcue n, get nth color from palette + colorIndex = m_hotcueColorIndices.at(hotcueIndex % m_hotcueColorIndices.size()); + } + return at(colorIndex % size()); } diff --git a/src/util/color/colorpalette.h b/src/util/color/colorpalette.h index 1f0165a8b39..1354df10af7 100644 --- a/src/util/color/colorpalette.h +++ b/src/util/color/colorpalette.h @@ -6,9 +6,10 @@ class ColorPalette final { public: - explicit ColorPalette(QString name, QList colorList) + explicit ColorPalette(QString name, QList colorList, QList hotcueColorIndices = {}) : m_name(name), - m_colorList(colorList) { + m_colorList(colorList), + m_hotcueColorIndices(hotcueColorIndices) { DEBUG_ASSERT(m_colorList.size() != 0); } @@ -44,16 +45,18 @@ class ColorPalette final { m_name = name; } - static const ColorPalette mixxxHotcuePalette; - static const mixxx::RgbColor kDefaultCueColor; - const QList& getColorList() const { return m_colorList; } + QList getHotcueIndices() const { + return m_hotcueColorIndices; + } + private: QString m_name; QList m_colorList; + QList m_hotcueColorIndices; }; inline bool operator==( diff --git a/src/util/color/predefinedcolorpalettes.cpp b/src/util/color/predefinedcolorpalettes.cpp new file mode 100644 index 00000000000..db6deb0ed7b --- /dev/null +++ b/src/util/color/predefinedcolorpalettes.cpp @@ -0,0 +1,265 @@ +#include "predefinedcolorpalettes.h" + +namespace { + +// Default Mixxx Hotcue Color Palette +constexpr mixxx::RgbColor kColorMixxxRed(0xC50A08); +constexpr mixxx::RgbColor kColorMixxxYellow(0x32BE44); +constexpr mixxx::RgbColor kColorMixxxGreen(0x42D4F4); +constexpr mixxx::RgbColor kColorMixxxCeleste(0xF8D200); +constexpr mixxx::RgbColor kColorMixxxBlue(0x0044FF); +constexpr mixxx::RgbColor kColorMixxxPurple(0xAF00CC); +constexpr mixxx::RgbColor kColorMixxxPink(0xFCA6D7); +constexpr mixxx::RgbColor kColorMixxxWhite(0xF2F2FF); + +// Rekordbox Track Color Palette +constexpr mixxx::RgbColor kRekordboxTrackColorPink(0xF870F8); +constexpr mixxx::RgbColor kRekordboxTrackColorRed(0xF870900); +constexpr mixxx::RgbColor kRekordboxTrackColorOrange(0xF8A030); +constexpr mixxx::RgbColor kRekordboxTrackColorYellow(0xF8E331); +constexpr mixxx::RgbColor kRekordboxTrackColorGreen(0x1EE000); +constexpr mixxx::RgbColor kRekordboxTrackColorAqua(0x16C0F8); +constexpr mixxx::RgbColor kRekordboxTrackColorBlue(0x0150F8); +constexpr mixxx::RgbColor kRekordboxTrackColorPurple(0x9808F8); + +// Traktor Track Color Palette +constexpr mixxx::RgbColor kTraktorProTrackColorRed(0xFA4B35); +constexpr mixxx::RgbColor kTraktorProTrackColorOrange(0xFF8402); +constexpr mixxx::RgbColor kTraktorProTrackColorYellow(0xFFF700); +constexpr mixxx::RgbColor kTraktorProTrackColorGreen(0x00F329); +constexpr mixxx::RgbColor kTraktorProTrackColorBlue(0x0187FF); +constexpr mixxx::RgbColor kTraktorProTrackColorViolet(0xA669FF); +constexpr mixxx::RgbColor kTraktorProTrackColorMagenta(0xFE55EA); + +// Serato DJ Intro Hotcue Color Palette +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorRed(0xCC0000); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorOrange(0xCC4400); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorBrown(0xCC8800); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorYellow(0xCCCC00); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorEmerald(0x88CC00); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorKelly(0x44CC00); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorGreen(0x00CC00); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorSea(0x00CC44); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorJade(0x00CC88); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorTurquoise(0x00CCCC); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorTeal(0x0088CC); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorBlue(0x0044CC); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorDarkBlue(0x0000CC); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorViolet(0x4400CC); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorPurple(0x8800CC); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorFuchsia(0xCC00CC); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorMagenta(0xCC0088); +constexpr mixxx::RgbColor kSeratoDJIntroHotcueColorCarmine(0xCC0044); + +// Serato DJ Pro Hotcue Color Palette +constexpr mixxx::RgbColor kSeratoDJProHotcueColorRed1(0xC02626); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorOrange1(0xDB4E27); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorOrange2(0xF8821A); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorYellow(0xFAC313); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorGreen1(0x4EB648); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorGreen2(0x006838); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorGreen3(0x1FAD26); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorGreen4(0x8DC63F); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorBlue1(0x2B3673); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorCyan(0x1DBEBD); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorBlue2(0x173BA2); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorDarkBlue1(0x173BA2); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorDarkBlue2(0x173BA2); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorViolet1(0x5C3F97); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorViolet2(0x6823B6); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorMagenta(0xCE359E); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorPurple(0xDC1D49); +constexpr mixxx::RgbColor kSeratoDJProHotcueColorRed2(0xC71136); + +// Serato DJ Pro Track Color Palette (as shown in library column) +constexpr mixxx::RgbColor kSeratoDJProTrackColorGrey1(0x333333); +constexpr mixxx::RgbColor kSeratoDJProTrackColorGrey2(0x555555); +constexpr mixxx::RgbColor kSeratoDJProTrackColorPink1(0x993399); +constexpr mixxx::RgbColor kSeratoDJProTrackColorPink2(0x993377); +constexpr mixxx::RgbColor kSeratoDJProTrackColorRed1(0x993355); +constexpr mixxx::RgbColor kSeratoDJProTrackColorRed2(0x993333); +constexpr mixxx::RgbColor kSeratoDJProTrackColorOrange(0x995533); +constexpr mixxx::RgbColor kSeratoDJProTrackColorBrown1(0x997733); +constexpr mixxx::RgbColor kSeratoDJProTrackColorBrown2(0x999933); +constexpr mixxx::RgbColor kSeratoDJProTrackColorBrown3(0x779933); +constexpr mixxx::RgbColor kSeratoDJProTrackColorGreen1(0x559933); +constexpr mixxx::RgbColor kSeratoDJProTrackColorGreen2(0x339933); +constexpr mixxx::RgbColor kSeratoDJProTrackColorGreen3(0x339955); +constexpr mixxx::RgbColor kSeratoDJProTrackColorTurquoise1(0x339977); +constexpr mixxx::RgbColor kSeratoDJProTrackColorTurquoise2(0x339999); +constexpr mixxx::RgbColor kSeratoDJProTrackColorTurquoise3(0x337799); +constexpr mixxx::RgbColor kSeratoDJProTrackColorBlue(0x335599); +constexpr mixxx::RgbColor kSeratoDJProTrackColorPurple1(0x333399); +constexpr mixxx::RgbColor kSeratoDJProTrackColorPurple2(0x553399); +constexpr mixxx::RgbColor kSeratoDJProTrackColorPurple3(0x773399); + +// VirtualDJ Track Color Palette +constexpr mixxx::RgbColor kVirtualDJTrackColorRed(0xFF0000); +constexpr mixxx::RgbColor kVirtualDJTrackColorYellow(0xFFFF00); +constexpr mixxx::RgbColor kVirtualDJTrackColorGreen(0x00FF00); +constexpr mixxx::RgbColor kVirtualDJTrackColorCyan(0x00FFFF); +constexpr mixxx::RgbColor kVirtualDJTrackColorBlue(0x0000FF); +constexpr mixxx::RgbColor kVirtualDJTrackColorFuchsia(0xFF00FF); +constexpr mixxx::RgbColor kVirtualDJTrackColorWhite(0xFFFFFF); + +// Replaces "no color" values and is used for new cues if auto_hotcue_colors is +// disabled +constexpr mixxx::RgbColor kSchemaMigrationReplacementColor(0xFF8000); + +} // anonymous namespace + +namespace mixxx { + +const ColorPalette PredefinedColorPalettes::kMixxxHotcueColorPalette = + ColorPalette( + QStringLiteral("Mixxx Hotcue Colors"), + QList{ + kColorMixxxRed, + kColorMixxxYellow, + kColorMixxxGreen, + kColorMixxxCeleste, + kColorMixxxBlue, + kColorMixxxPurple, + kColorMixxxPink, + kColorMixxxWhite, + }); + +const ColorPalette PredefinedColorPalettes::kSeratoDJIntroHotcueColorPalette = + ColorPalette( + QStringLiteral("Serato DJ Intro Hotcue Colors"), + QList{ + kSeratoDJIntroHotcueColorRed, + kSeratoDJIntroHotcueColorOrange, + kSeratoDJIntroHotcueColorBrown, + kSeratoDJIntroHotcueColorYellow, + kSeratoDJIntroHotcueColorEmerald, + kSeratoDJIntroHotcueColorKelly, + kSeratoDJIntroHotcueColorGreen, + kSeratoDJIntroHotcueColorSea, + kSeratoDJIntroHotcueColorJade, + kSeratoDJIntroHotcueColorTurquoise, + kSeratoDJIntroHotcueColorTeal, + kSeratoDJIntroHotcueColorBlue, + kSeratoDJIntroHotcueColorDarkBlue, + kSeratoDJIntroHotcueColorViolet, + kSeratoDJIntroHotcueColorPurple, + kSeratoDJIntroHotcueColorFuchsia, + kSeratoDJIntroHotcueColorMagenta, + kSeratoDJIntroHotcueColorCarmine, + }, + QList{0, 2, 12, 3, 6, 15, 9, 14}); + +const ColorPalette PredefinedColorPalettes::kSeratoDJProHotcueColorPalette = + ColorPalette( + QStringLiteral("Serato DJ Pro Hotcue Colors"), + QList{ + kSeratoDJProHotcueColorRed1, + kSeratoDJProHotcueColorOrange1, + kSeratoDJProHotcueColorOrange2, + kSeratoDJProHotcueColorYellow, + kSeratoDJProHotcueColorGreen1, + kSeratoDJProHotcueColorGreen2, + kSeratoDJProHotcueColorGreen3, + kSeratoDJProHotcueColorGreen4, + kSeratoDJProHotcueColorBlue1, + kSeratoDJProHotcueColorCyan, + kSeratoDJProHotcueColorBlue2, + kSeratoDJProHotcueColorDarkBlue1, + kSeratoDJProHotcueColorDarkBlue2, + kSeratoDJProHotcueColorViolet1, + kSeratoDJProHotcueColorViolet2, + kSeratoDJProHotcueColorMagenta, + kSeratoDJProHotcueColorPurple, + kSeratoDJProHotcueColorRed2, + }, + QList{0, 2, 12, 3, 6, 15, 9, 14}); + +const ColorPalette PredefinedColorPalettes::kRekordboxTrackColorPalette = + ColorPalette( + QStringLiteral("Rekordbox Track Colors"), + QList{ + kRekordboxTrackColorPink, + kRekordboxTrackColorRed, + kRekordboxTrackColorOrange, + kRekordboxTrackColorYellow, + kRekordboxTrackColorGreen, + kRekordboxTrackColorAqua, + kRekordboxTrackColorBlue, + kRekordboxTrackColorPurple, + }); + +const ColorPalette PredefinedColorPalettes::kSeratoDJProTrackColorPalette = + ColorPalette( + QStringLiteral("Serato DJ Pro Track Colors"), + QList{ + kSeratoDJProTrackColorGrey1, + kSeratoDJProTrackColorGrey2, + kSeratoDJProTrackColorPink1, + kSeratoDJProTrackColorPink2, + kSeratoDJProTrackColorRed1, + kSeratoDJProTrackColorRed2, + kSeratoDJProTrackColorOrange, + kSeratoDJProTrackColorBrown1, + kSeratoDJProTrackColorBrown2, + kSeratoDJProTrackColorBrown3, + kSeratoDJProTrackColorGreen1, + kSeratoDJProTrackColorGreen2, + kSeratoDJProTrackColorGreen3, + kSeratoDJProTrackColorTurquoise1, + kSeratoDJProTrackColorTurquoise2, + kSeratoDJProTrackColorTurquoise3, + kSeratoDJProTrackColorBlue, + kSeratoDJProTrackColorPurple1, + kSeratoDJProTrackColorPurple2, + kSeratoDJProTrackColorPurple3, + }); + +const ColorPalette PredefinedColorPalettes::kTraktorProTrackColorPalette = + ColorPalette( + QStringLiteral("Traktor Pro Track Colors"), + QList{ + kTraktorProTrackColorRed, + kTraktorProTrackColorOrange, + kTraktorProTrackColorYellow, + kTraktorProTrackColorGreen, + kTraktorProTrackColorBlue, + kTraktorProTrackColorViolet, + kTraktorProTrackColorMagenta, + }); + +const ColorPalette PredefinedColorPalettes::kVirtualDJTrackColorPalette = + ColorPalette( + QStringLiteral("VirtualDJ Track Colors"), + QList{ + kVirtualDJTrackColorRed, + kVirtualDJTrackColorYellow, + kVirtualDJTrackColorGreen, + kVirtualDJTrackColorCyan, + kVirtualDJTrackColorBlue, + kVirtualDJTrackColorFuchsia, + kVirtualDJTrackColorWhite, + }); + +const ColorPalette PredefinedColorPalettes::kDefaultHotcueColorPalette = + mixxx::PredefinedColorPalettes::kMixxxHotcueColorPalette; + +const ColorPalette PredefinedColorPalettes::kDefaultTrackColorPalette = + mixxx::PredefinedColorPalettes::kMixxxHotcueColorPalette; + +const QList PredefinedColorPalettes::kPalettes{ + // Hotcue Color Palettes + mixxx::PredefinedColorPalettes::kMixxxHotcueColorPalette, + mixxx::PredefinedColorPalettes::kSeratoDJProHotcueColorPalette, + mixxx::PredefinedColorPalettes::kSeratoDJIntroHotcueColorPalette, + + // Track Color Palettes + mixxx::PredefinedColorPalettes::kRekordboxTrackColorPalette, + mixxx::PredefinedColorPalettes::kSeratoDJProTrackColorPalette, + mixxx::PredefinedColorPalettes::kTraktorProTrackColorPalette, + mixxx::PredefinedColorPalettes::kVirtualDJTrackColorPalette, +}; + +const mixxx::RgbColor PredefinedColorPalettes::kDefaultCueColor = + kSchemaMigrationReplacementColor; + +} // namespace mixxx diff --git a/src/util/color/predefinedcolorpalettes.h b/src/util/color/predefinedcolorpalettes.h new file mode 100644 index 00000000000..a1f910fc3be --- /dev/null +++ b/src/util/color/predefinedcolorpalettes.h @@ -0,0 +1,24 @@ +#pragma once +#include "util/color/colorpalette.h" + +namespace mixxx { + +class PredefinedColorPalettes { + public: + static const ColorPalette kMixxxHotcueColorPalette; + static const ColorPalette kSeratoDJIntroHotcueColorPalette; + static const ColorPalette kSeratoDJProHotcueColorPalette; + + static const ColorPalette kRekordboxTrackColorPalette; + static const ColorPalette kSeratoDJProTrackColorPalette; + static const ColorPalette kTraktorProTrackColorPalette; + static const ColorPalette kVirtualDJTrackColorPalette; + + static const ColorPalette kDefaultHotcueColorPalette; + static const ColorPalette kDefaultTrackColorPalette; + + static const QList kPalettes; + static const mixxx::RgbColor kDefaultCueColor; +}; + +} // namespace mixxx