diff -urN mixxx-20161215/build/depends.py mixxx-20161215-librarytrackcolors/build/depends.py --- mixxx-20161215/build/depends.py 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/build/depends.py 2016-12-21 10:44:47.871845688 +0100 @@ -931,6 +931,8 @@ "library/starrating.cpp", "library/stardelegate.cpp", "library/stareditor.cpp", + "library/colordelegate.cpp", + "library/trackcolorpicker.cpp", "library/bpmdelegate.cpp", "library/previewbuttondelegate.cpp", "library/coverartdelegate.cpp", diff -urN mixxx-20161215/res/schema.xml mixxx-20161215-librarytrackcolors/res/schema.xml --- mixxx-20161215/res/schema.xml 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/res/schema.xml 2016-12-21 10:44:47.871845688 +0100 @@ -426,4 +426,12 @@ ALTER TABLE cues ADD COLUMN color INTEGER DEFAULT 4294901760 NOT NULL; + + + Add track color support. Default color is transparent. + + + ALTER TABLE library ADD COLUMN color INTEGER DEFAULT 0 NOT NULL; + + diff -urN mixxx-20161215/src/library/basesqltablemodel.cpp mixxx-20161215-librarytrackcolors/src/library/basesqltablemodel.cpp --- mixxx-20161215/src/library/basesqltablemodel.cpp 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/basesqltablemodel.cpp 2016-12-21 10:44:47.872845693 +0100 @@ -9,6 +9,7 @@ #include "library/coverartdelegate.h" #include "library/stardelegate.h" #include "library/starrating.h" +#include "library/colordelegate.h" #include "library/bpmdelegate.h" #include "library/previewbuttondelegate.h" #include "library/queryutil.h" @@ -60,6 +61,8 @@ // TODO(owilliams): Clean this up to make it readable. setHeaderProperties(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED, tr("Played"), 50); + setHeaderProperties(ColumnCache::COLUMN_LIBRARYTABLE_COLOR, + tr("Color"), 25); setHeaderProperties(ColumnCache::COLUMN_LIBRARYTABLE_ARTIST, tr("Artist"), 200); setHeaderProperties(ColumnCache::COLUMN_LIBRARYTABLE_TITLE, @@ -611,6 +614,15 @@ // role switch (role) { case Qt::ToolTipRole: + if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COLOR)) { + for (int i=0; i < QColor::colorNames().size(); i++) { + if (QColor(QColor::colorNames().at(i)) == QColor::fromRgba(value.toUInt())) { + value = QColor::colorNames().at(i); + break; + } + } + } + break; case Qt::DisplayRole: if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DURATION)) { int duration = value.toInt(); @@ -921,6 +933,8 @@ mixxx::track::io::key::USER); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK) == column) { pTrack->setBpmLocked(value.toBool()); + } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COLOR) == column) { + pTrack->setColor(value.toUInt()); } else { // We never should get up to this point! DEBUG_ASSERT_AND_HANDLE(false) { @@ -1028,6 +1042,8 @@ connect(pCoverDelegate, SIGNAL(coverReadyForCell(int, int)), this, SLOT(refreshCell(int, int))); return pCoverDelegate; + } else if (i == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COLOR)) { + return new ColorDelegate(pParent); } return NULL; } diff -urN mixxx-20161215/src/library/basetrackcache.cpp mixxx-20161215-librarytrackcolors/src/library/basetrackcache.cpp --- mixxx-20161215/src/library/basetrackcache.cpp 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/basetrackcache.cpp 2016-12-21 10:44:47.872845693 +0100 @@ -336,6 +336,8 @@ trackValue.setValue(static_cast(pTrack->getCoverInfo().source)); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_TYPE) == column) { trackValue.setValue(static_cast(pTrack->getCoverInfo().type)); + } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COLOR) == column) { + trackValue.setValue(pTrack->getColor()); } } diff -urN mixxx-20161215/src/library/colordelegate.cpp mixxx-20161215-librarytrackcolors/src/library/colordelegate.cpp --- mixxx-20161215/src/library/colordelegate.cpp 1970-01-01 01:00:00.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/colordelegate.cpp 2016-12-21 10:45:39.149129722 +0100 @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include + +#include "library/colordelegate.h" +#include "library/trackcolorpicker.h" + +ColorDelegate::ColorDelegate(QObject* pParent) + : QItemDelegate(pParent) { +} + +void ColorDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const { + QColor color = QColor::fromRgba(qVariantValue(index.data())); + painter->save(); + painter->setClipRect(option.rect); + painter->fillRect(option.rect, color); + painter->restore(); +} + +QSize ColorDelegate::sizeHint(const QStyleOptionViewItem& option, + const QModelIndex& index) const { + Q_UNUSED(option); + Q_UNUSED(index); + return QSize(25, 25); +} + +bool ColorDelegate::editorEvent(QEvent* event, + QAbstractItemModel* model, + const QStyleOptionViewItem& option, + const QModelIndex& index) { + QMouseEvent* mouseEvent = NULL; + if (event->type() == QEvent::MouseButtonPress) { + mouseEvent = static_cast(event); + } + if (mouseEvent && mouseEvent->button() == Qt::LeftButton) { + TrackColorPicker* colordialog = new TrackColorPicker(QColor::fromRgba(qVariantValue(index.data()))); + m_index = index; + m_pModel = model; + connect(colordialog, SIGNAL(currentColorChanged(const QColor &)), + this, SLOT(colorSelect(const QColor &))); + colordialog->show(); + return true; + } + return QAbstractItemDelegate::editorEvent(event, model, option, index); +} + +void ColorDelegate::colorSelect(const QColor& color) { + TrackColorPicker* colordialog = qobject_cast(sender()); +// TODO(XXX): this is a workaround when color is set to 0/transparent, +// won't set until you set it to another value first + m_pModel->setData(m_index, qVariantValue(1)); + m_pModel->setData(m_index, color.rgba()); + delete colordialog; +} diff -urN mixxx-20161215/src/library/colordelegate.h mixxx-20161215-librarytrackcolors/src/library/colordelegate.h --- mixxx-20161215/src/library/colordelegate.h 1970-01-01 01:00:00.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/colordelegate.h 2016-12-21 10:43:56.990563847 +0100 @@ -0,0 +1,30 @@ +#ifndef COLORDELEGATE_H +#define COLORDELEGATE_H + +#include +#include + +class ColorDelegate : public QItemDelegate { + Q_OBJECT + public: + explicit ColorDelegate(QObject* pParent = 0); + + void paint(QPainter* painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const; + + QSize sizeHint(const QStyleOptionViewItem& option, + const QModelIndex& index) const; + + virtual bool editorEvent(QEvent* event, QAbstractItemModel* model, + const QStyleOptionViewItem& option, + const QModelIndex& index); + + public slots: + void colorSelect(const QColor& color); + + private: + QModelIndex m_index; + QAbstractItemModel* m_pModel; +}; + +#endif diff -urN mixxx-20161215/src/library/columncache.cpp mixxx-20161215-librarytrackcolors/src/library/columncache.cpp --- mixxx-20161215/src/library/columncache.cpp 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/columncache.cpp 2016-12-21 10:44:47.872845693 +0100 @@ -33,6 +33,7 @@ } m_columnIndexByEnum[COLUMN_LIBRARYTABLE_ID] = fieldIndex(LIBRARYTABLE_ID); + m_columnIndexByEnum[COLUMN_LIBRARYTABLE_COLOR] = fieldIndex(LIBRARYTABLE_COLOR); m_columnIndexByEnum[COLUMN_LIBRARYTABLE_ARTIST] = fieldIndex(LIBRARYTABLE_ARTIST); m_columnIndexByEnum[COLUMN_LIBRARYTABLE_TITLE] = fieldIndex(LIBRARYTABLE_TITLE); m_columnIndexByEnum[COLUMN_LIBRARYTABLE_ALBUM] = fieldIndex(LIBRARYTABLE_ALBUM); diff -urN mixxx-20161215/src/library/columncache.h mixxx-20161215-librarytrackcolors/src/library/columncache.h --- mixxx-20161215/src/library/columncache.h 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/columncache.h 2016-12-21 10:44:47.873845699 +0100 @@ -19,6 +19,7 @@ enum Column { COLUMN_LIBRARYTABLE_INVALID = -1, COLUMN_LIBRARYTABLE_ID = 0, + COLUMN_LIBRARYTABLE_COLOR, COLUMN_LIBRARYTABLE_ARTIST, COLUMN_LIBRARYTABLE_TITLE, COLUMN_LIBRARYTABLE_ALBUM, diff -urN mixxx-20161215/src/library/dao/trackdao.cpp mixxx-20161215-librarytrackcolors/src/library/dao/trackdao.cpp --- mixxx-20161215/src/library/dao/trackdao.cpp 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/dao/trackdao.cpp 2016-12-21 10:44:47.873845699 +0100 @@ -395,7 +395,7 @@ "timesplayed,channels,mixxx_deleted,header_parsed," "beats_version,beats_sub_version,beats,bpm_lock," "keys_version,keys_sub_version,keys," - "coverart_source,coverart_type,coverart_location,coverart_hash" + "coverart_source,coverart_type,coverart_location,coverart_hash,color" ") VALUES (" ":artist,:title,:album,:album_artist,:year,:genre,:tracknumber,:tracktotal,:composer," ":grouping,:filetype,:location,:comment,:url,:duration,:rating,:key,:key_id," @@ -403,7 +403,7 @@ ":timesplayed,:channels,:mixxx_deleted,:header_parsed," ":beats_version,:beats_sub_version,:beats,:bpm_lock," ":keys_version,:keys_sub_version,:keys," - ":coverart_source,:coverart_type,:coverart_location,:coverart_hash" + ":coverart_source,:coverart_type,:coverart_location,:coverart_hash,:color" ")"); m_pQueryLibraryUpdate->prepare("UPDATE library SET mixxx_deleted = 0 " @@ -486,6 +486,7 @@ pTrackLibraryQuery->bindValue(":coverart_type", coverInfo.type); pTrackLibraryQuery->bindValue(":coverart_location", coverInfo.coverLocation); pTrackLibraryQuery->bindValue(":coverart_hash", coverInfo.hash); + pTrackLibraryQuery->bindValue(":color", track.getColor()); QByteArray beatsBlob; QString beatsVersion; @@ -1014,6 +1015,12 @@ const int column, TrackPointer pTrack); +bool setTrackColor(const QSqlRecord& record, const int column, + TrackPointer pTrack) { + pTrack->setColor(record.value(column).toUInt()); + return false; +} + bool setTrackArtist(const QSqlRecord& record, const int column, TrackPointer pTrack) { pTrack->setArtist(record.value(column).toString()); @@ -1265,6 +1272,7 @@ ColumnPopulator columns[] = { // Location must be first. { "track_locations.location", nullptr }, + { "color", setTrackColor }, { "artist", setTrackArtist }, { "title", setTrackTitle }, { "album", setTrackAlbum }, @@ -1565,7 +1573,8 @@ "coverart_source=:coverart_source," "coverart_type=:coverart_type," "coverart_location=:coverart_location," - "coverart_hash=:coverart_hash" + "coverart_hash=:coverart_hash," + "color=:color" " WHERE id=:track_id"); query.bindValue(":track_id", trackId.toVariant()); diff -urN mixxx-20161215/src/library/dao/trackdao.h mixxx-20161215-librarytrackcolors/src/library/dao/trackdao.h --- mixxx-20161215/src/library/dao/trackdao.h 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/dao/trackdao.h 2016-12-21 10:44:47.873845699 +0100 @@ -57,6 +57,7 @@ const QString LIBRARYTABLE_COVERART_TYPE = "coverart_type"; const QString LIBRARYTABLE_COVERART_LOCATION = "coverart_location"; const QString LIBRARYTABLE_COVERART_HASH = "coverart_hash"; +const QString LIBRARYTABLE_COLOR = "color"; const QString TRACKLOCATIONSTABLE_ID = "id"; const QString TRACKLOCATIONSTABLE_LOCATION = "location"; diff -urN mixxx-20161215/src/library/mixxxlibraryfeature.cpp mixxx-20161215-librarytrackcolors/src/library/mixxxlibraryfeature.cpp --- mixxx-20161215/src/library/mixxxlibraryfeature.cpp 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/mixxxlibraryfeature.cpp 2016-12-21 10:44:47.873845699 +0100 @@ -34,6 +34,7 @@ m_pTrackCollection(pTrackCollection) { QStringList columns; columns << "library." + LIBRARYTABLE_ID + << "library." + LIBRARYTABLE_COLOR << "library." + LIBRARYTABLE_PLAYED << "library." + LIBRARYTABLE_TIMESPLAYED //has to be up here otherwise Played and TimesPlayed are not show diff -urN mixxx-20161215/src/library/trackcollection.cpp mixxx-20161215-librarytrackcolors/src/library/trackcollection.cpp --- mixxx-20161215/src/library/trackcollection.cpp 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/trackcollection.cpp 2016-12-21 10:44:47.874845704 +0100 @@ -14,7 +14,7 @@ #include "util/assert.h" // static -const int TrackCollection::kRequiredSchemaVersion = 27; +const int TrackCollection::kRequiredSchemaVersion = 28; TrackCollection::TrackCollection(UserSettingsPointer pConfig) : m_pConfig(pConfig), diff -urN mixxx-20161215/src/library/trackcolorpicker.cpp mixxx-20161215-librarytrackcolors/src/library/trackcolorpicker.cpp --- mixxx-20161215/src/library/trackcolorpicker.cpp 1970-01-01 01:00:00.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/trackcolorpicker.cpp 2016-12-21 10:44:10.406638161 +0100 @@ -0,0 +1,110 @@ +#include +#include + +#include "library/trackcolorpicker.h" + +namespace { + const int iColorButtonsInRow = 6; + const int iColorButtonHeight = 15; + const int iColorButtonLength = 25; +// Too many colors for the dialog +// const QStringList colors = QColor::colorNames(); + const QStringList colors = QStringList() << "white" << "black" + << "cyan" << "darkCyan" << "red" << "darkRed" << "magenta" + << "darkMagenta" << "green" << "darkGreen" << "yellow" + << "blue" << "darkBlue" << "grey" << "darkGrey" + << "lightgrey" << "orange" << "lightblue"; +} + +TrackColorPicker::TrackColorPicker(QColor color) + : m_selectedColor(color) +{ + int widgetHeight; + int widgetLength = iColorButtonsInRow*(iColorButtonLength+6)+4;; + if ((colors.size()+1) % iColorButtonsInRow == 0) { + widgetHeight = (15+5)*(colors.size()/iColorButtonsInRow)+5; + } else { + widgetHeight = (15+5)*(colors.size()/iColorButtonsInRow+1)+5; + } + this->resize(widgetLength, widgetHeight); + this->move(QCursor::pos() - QPoint(widgetLength/2,widgetHeight/2)); + this->setWindowFlags(Qt::CustomizeWindowHint); + this->setStyleSheet("background-color: darkgrey;"); + this->setModal(true); +} + +void TrackColorPicker::paintEvent(QPaintEvent *) { + QPainter painter(this); + int x = 5; int y = 5; + for (int i=0; i < colors.size(); i++) { + if (m_selectedColor == QColor(colors.at(i))) { + painter.fillRect(x-3, y-3, iColorButtonLength+6, iColorButtonHeight+6, QColor("black")); + painter.fillRect(x-1, y-1, iColorButtonLength+2, iColorButtonHeight+2, QColor("lightgrey")); + } else { + painter.fillRect(x-1, y-1, iColorButtonLength+2, iColorButtonHeight+2, QColor("black")); + } + painter.fillRect(x, y, iColorButtonLength, iColorButtonHeight, QColor(colors.at(i))); + x += iColorButtonLength+6; + if (x >= iColorButtonsInRow*(iColorButtonLength+6)) { + x = 5; + y += iColorButtonHeight+5; + } + } + if (m_selectedColor == QColor(Qt::transparent)) { + painter.fillRect(x-3, y-3, iColorButtonLength+6, iColorButtonHeight+6, QColor("black")); + painter.fillRect(x-1, y-1, iColorButtonLength+2, iColorButtonHeight+2, QColor("lightgrey")); + } else { + painter.fillRect(x-1, y-1, iColorButtonLength+2, iColorButtonHeight+2, QColor("black")); + } + for (int i=x; i < x+iColorButtonLength; i+=5) { + for (int j=y; j < y+iColorButtonHeight; j+=5) { + painter.fillRect(i, j, 5, 5, (i+j)%2 == 0 ? QColor("darkgrey") : QColor("grey")); + } + } +} + +QColor TrackColorPicker::hoverColor(QPoint pos) +{ + int x = 5; int y = 5; + QColor returnColor; + for (int i=0; i < colors.size(); i++) { + QRect rect(x, y, iColorButtonLength, iColorButtonHeight); + if (rect.contains(pos)) { + returnColor.setNamedColor(colors.at(i)); + return returnColor; + } + x += iColorButtonLength+6; + if (x >= iColorButtonsInRow*(iColorButtonLength+6)) { + x = 5; + y += iColorButtonHeight+5; + } + } + QRect rect(x, y, iColorButtonLength, iColorButtonHeight); + if (rect.contains(pos)) { + return Qt::transparent; + } + return returnColor; +} + +void TrackColorPicker::mousePressEvent(QMouseEvent *event) { + if (hoverColor(event->pos()).isValid()) { + m_selectedColor = hoverColor(event->pos()); + update(); + } +} + +void TrackColorPicker::mouseMoveEvent(QMouseEvent *event) { + if (event->buttons() == Qt::LeftButton && + hoverColor(event->pos()).isValid()) { + m_selectedColor = hoverColor(event->pos()); + update(); + } +} + +void TrackColorPicker::mouseReleaseEvent(QMouseEvent *event) { + if (event->button() == Qt::LeftButton) { + if (hoverColor(event->pos()).isValid()) { + emit currentColorChanged(hoverColor(event->pos())); + } + } +} diff -urN mixxx-20161215/src/library/trackcolorpicker.h mixxx-20161215-librarytrackcolors/src/library/trackcolorpicker.h --- mixxx-20161215/src/library/trackcolorpicker.h 1970-01-01 01:00:00.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/library/trackcolorpicker.h 2016-12-21 10:44:10.406638161 +0100 @@ -0,0 +1,28 @@ +#ifndef TRACKCOLORPICKER_H +#define TRACKCOLORPICKER_H + +#include +#include +#include +#include + +class TrackColorPicker : public QDialog { + Q_OBJECT + public: + TrackColorPicker(QColor defaultColor = QColor(Qt::transparent)); + + protected: + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event); + + signals: + void currentColorChanged(const QColor &); + + private: + QColor hoverColor(QPoint pos); + QColor m_selectedColor; +}; + +#endif diff -urN mixxx-20161215/src/track/track.cpp mixxx-20161215-librarytrackcolors/src/track/track.cpp --- mixxx-20161215/src/track/track.cpp 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/track/track.cpp 2016-12-21 10:44:47.874845704 +0100 @@ -48,6 +48,7 @@ m_qMutex(QMutex::Recursive), m_id(trackId), m_bDirty(false), + m_color(0), m_iRating(0), m_fCuePoint(0.0f), m_dateAdded(QDateTime::currentDateTime()), @@ -666,6 +667,18 @@ return m_sURL; } +unsigned int Track::getColor() const { + QMutexLocker lock(&m_qMutex); + return m_color; +} + +void Track::setColor(const unsigned int color) { + QMutexLocker lock(&m_qMutex); + if (compareAndSet(&m_color, color)) { + markDirtyAndUnlock(&lock); + } +} + ConstWaveformPointer Track::getWaveform() const { return m_waveform; } diff -urN mixxx-20161215/src/track/track.h mixxx-20161215-librarytrackcolors/src/track/track.h --- mixxx-20161215/src/track/track.h 2016-12-14 21:50:29.000000000 +0100 +++ mixxx-20161215-librarytrackcolors/src/track/track.h 2016-12-21 10:44:47.874845704 +0100 @@ -231,6 +231,11 @@ // Set URL for track void setURL(const QString& url); + // Returns the track color + unsigned int getColor() const; + // Sets the track color + void setColor(const unsigned int); + // Output a formatted string with artist and title. QString getInfo() const; @@ -379,6 +384,9 @@ // URL (used in promo track) QString m_sURL; + // Track color + unsigned int m_color; + // Track rating int m_iRating;