diff options
25 files changed, 1166 insertions, 171 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 27e48b2ed9..22aba2d027 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 e13d2df5b3..3d6096f2f1 100644 --- a/build/depends.py +++ b/build/depends.py @@ -768,6 +768,7 @@ class MixxxCore(Feature): "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 @@ class MixxxCore(Feature): "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 @@ class MixxxCore(Feature): "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 @@ class MixxxCore(Feature): '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 0000000000..cb7199750b --- /dev/null +++ b/res/images/preferences/ic_preferences_colors.svg @@ -0,0 +1,7 @@ +<svg width="32" height="32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Mixxx 1.12+ iconset</title> + <g> + <path d="m2.6775373 29.441818c1.2915257 1.276979 3.3854996 1.276979 4.6770264-1e-6.3123328-.310526.5584503-.679879.7236793-1.086207l2.862452-4.243047 4.133113-3.81616 3.933374 3.889081 2.360024-2.333449-11.013445-10.889425-2.3600243 2.333447 3.9333733 3.889083-3.859623 4.08657-4.2806157 2.822624c-.4154472.164357-.7928415.410361-1.109334.723125-1.2915224 1.276982-1.2915236 3.347377 0 4.624359zm19.4763437-8.367599-11.013445-10.889425 8.65342-8.5559755 1.165566 1.1524393 1.395903 1.380184 1.71322 1.6939276-2.926472 3.8589267 4.005054-2.7924897 1.3959 1.3801829 1.395903 1.3801825s-4.876191 5.7519612-4.585379 6.0394992 5.74863-4.889348 5.981281-4.659316l1.472469 1.455888z"/> + <path d="m31.326116 21.55374c.627527 1.301959 1.031435 2.673278 0 3.693101-1.031438 1.01982-2.703725 1.01982-3.735161 0-1.031438-1.019823-.612938-2.384365 0-3.693101 1.840765-3.930379 1.840765-3.930379 1.840765-3.930379s1.262931 2.620252 1.894396 3.930379z" style="paint-order:fill markers stroke"/> + </g> +</svg> diff --git a/res/mixxx.qrc b/res/mixxx.qrc index 545cba1fea..c863791eee 100644 --- a/res/mixxx.qrc +++ b/res/mixxx.qrc @@ -37,6 +37,7 @@ <file>images/preferences/ic_preferences_autodj.svg</file> <file>images/preferences/ic_preferences_bpmdetect.svg</file> <file>images/preferences/ic_preferences_broadcast.svg</file> + <file>images/preferences/ic_preferences_colors.svg</file> <file>images/preferences/ic_preferences_controllers.svg</file> <file>images/preferences/ic_preferences_crossfader.svg</file> <file>images/preferences/ic_preferences_decks.svg</file> diff --git a/src/engine/controls/cuecontrol.cpp b/src/engine/controls/cuecontrol.cpp index d087506dbc..ebb89fd413 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 0000000000..378d6abe57 --- /dev/null +++ b/src/preferences/colorpaletteeditor.cpp @@ -0,0 +1,216 @@ +#include "preferences/colorpaletteeditor.h" + +#include <QColorDialog> +#include <QDialogButtonBox> +#include <QHBoxLayout> +#include <QHeaderView> +#include <QLabel> +#include <QMenu> +#include <QStandardItemModel> +#include <QTableView> + +#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<QComboBox>()), + m_pTableView(make_parented<QTableView>()), + m_pModel(make_parented<ColorPaletteEditorModel>(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 0000000000..9786c10b59 --- /dev/null +++ b/src/preferences/colorpaletteeditor.h @@ -0,0 +1,45 @@ +#pragma once + +#include <QComboBox> +#include <QPushButton> +#include <QTableView> +#include <QWidget> + +#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<QComboBox> m_pPaletteNameComboBox; + parented_ptr<QTableView> m_pTableView; + parented_ptr<ColorPaletteEditorModel> 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 0000000000..62d958fbe1 --- /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<QStandardItem*>{pColorItem, pHotcueIndexItem}); +} + +void ColorPaletteEditorModel::setColorPalette(const ColorPalette& palette) { + // Remove all rows + removeRows(0, rowCount()); + + // Make a map of hotcue indices + QMap<int, int> hotcueColorIndicesMap; + QList<unsigned int> 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<mixxx::RgbColor> colors; + QMap<int, unsigned int> 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 0000000000..b76c7a0053 --- /dev/null +++ b/src/preferences/colorpaletteeditormodel.h @@ -0,0 +1,48 @@ +#pragma once +#include <QStandardItemModel> + +#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 63976e4cbd..fed31b3274 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<mixxx::RgbColor> 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<mixxx::RgbColor> colorList; + QList<unsigned int> hotcueIndices; for (const ConfigKey& key : m_pConfig->getKeysWithGroup(group)) { - mixxx::RgbColor color = mixxx::RgbColor(m_pConfig->getValue<mixxx::RgbColor>(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<unsigned int>(index); + } + } + } else { + mixxx::RgbColor color = mixxx::RgbColor(m_pConfig->getValue<mixxx::RgbColor>(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<mixxx::RgbColor>(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 0000000000..6888e8db98 --- /dev/null +++ b/src/preferences/dialog/dlgprefcolors.cpp @@ -0,0 +1,100 @@ +#include "preferences/dialog/dlgprefcolors.h" + +#include <QColorDialog> +#include <QStandardItemModel> +#include <QtDebug> + +#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; + < |