summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Klotz <uklotz@mixxx.org>2020-03-20 13:40:25 +0100
committerGitHub <noreply@github.com>2020-03-20 13:40:25 +0100
commita189892a486608c80fd94dd81b8c7ee89cdcf573 (patch)
treec02f101bc7af5aca866b031f62010ec2134723d3
parent7f6fd5a2e1a18f3a969ee6b71940f039a4881355 (diff)
parenta3b356af1a4d681dd5a87e7a1284bea2a36b962d (diff)
Merge pull request #2530 from Holzhaus/hotcue-rgb-color-picker
Make Hotcue RGB colors configurable
-rw-r--r--CMakeLists.txt5
-rw-r--r--build/depends.py5
-rw-r--r--res/images/preferences/ic_preferences_colors.svg7
-rw-r--r--res/mixxx.qrc1
-rw-r--r--src/engine/controls/cuecontrol.cpp3
-rw-r--r--src/preferences/colorpaletteeditor.cpp216
-rw-r--r--src/preferences/colorpaletteeditor.h45
-rw-r--r--src/preferences/colorpaletteeditormodel.cpp138
-rw-r--r--src/preferences/colorpaletteeditormodel.h48
-rw-r--r--src/preferences/colorpalettesettings.cpp62
-rw-r--r--src/preferences/dialog/dlgprefcolors.cpp100
-rw-r--r--src/preferences/dialog/dlgprefcolors.h31
-rw-r--r--src/preferences/dialog/dlgprefcolorsdlg.ui110
-rw-r--r--src/preferences/dialog/dlgprefdeck.cpp16
-rw-r--r--src/preferences/dialog/dlgprefdeck.h1
-rw-r--r--src/preferences/dialog/dlgprefdeckdlg.ui145
-rw-r--r--src/preferences/dialog/dlgpreferences.cpp17
-rw-r--r--src/preferences/dialog/dlgpreferences.h18
-rw-r--r--src/test/colorconfig_test.cpp8
-rw-r--r--src/test/colorpalette_test.cpp7
-rw-r--r--src/track/cue.cpp6
-rw-r--r--src/util/color/colorpalette.cpp46
-rw-r--r--src/util/color/colorpalette.h13
-rw-r--r--src/util/color/predefinedcolorpalettes.cpp265
-rw-r--r--src/util/color/predefinedcolorpalettes.h24
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);
+ }
+