diff --git a/src/library/basesqltablemodel.cpp b/src/library/basesqltablemodel.cpp index 7d8300a818c..415d2fa618e 100644 --- a/src/library/basesqltablemodel.cpp +++ b/src/library/basesqltablemodel.cpp @@ -114,6 +114,41 @@ void BaseSqlTableModel::initHeaderData() { tr("ReplayGain"), 50); } +void BaseSqlTableModel::initSortColumnMapping() { + // Add a bijective mapping between the SortColumnIds and column indices + for (int i = 0; i < TrackModel::SortColumnId::NUM_SORTCOLUMNIDS; ++i) { + m_columnIndexBySortColumnId[i] = -1; + } + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ARTIST] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ARTIST); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TITLE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TITLE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ALBUM] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUM); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ALBUMARTIST] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUMARTIST); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_YEAR] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_YEAR); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_GENRE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_GENRE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COMPOSER] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COMPOSER); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_GROUPING] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_GROUPING); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TRACKNUMBER] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TRACKNUMBER); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_FILETYPE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_FILETYPE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_NATIVELOCATION] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_NATIVELOCATION); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COMMENT] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COMMENT); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_DURATION] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DURATION); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_BITRATE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BITRATE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_BPM] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_REPLAYGAIN] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_REPLAYGAIN); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_DATETIMEADDED] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DATETIMEADDED); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TIMESPLAYED] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_RATING] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_RATING); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_KEY] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_KEY); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_PREVIEW] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COVERART] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART); + + m_sortColumnIdByColumnIndex.clear(); + for (int i = 0; i < TrackModel::SortColumnId::NUM_SORTCOLUMNIDS; ++i) { + TrackModel::SortColumnId sortColumn = static_cast(i); + m_sortColumnIdByColumnIndex.insert(m_columnIndexBySortColumnId[sortColumn], sortColumn); + } +} + void BaseSqlTableModel::setHeaderProperties( ColumnCache::Column column, QString title, int defaultWidth) { int fi = fieldIndex(column); @@ -399,10 +434,24 @@ void BaseSqlTableModel::setTable(const QString& tableName, m_tableColumnCache.setColumns(m_tableColumns); initHeaderData(); + initSortColumnMapping(); m_bInitialized = true; } +int BaseSqlTableModel::columnIndexFromSortColumnId(TrackModel::SortColumnId column) { + if (column == TrackModel::SortColumnId::SORTCOLUMN_INVALID) { + return -1; + } + + return m_columnIndexBySortColumnId[column]; +} + +TrackModel::SortColumnId BaseSqlTableModel::sortColumnIdFromColumnIndex(int index) { + return m_sortColumnIdByColumnIndex.value(index, TrackModel::SortColumnId::SORTCOLUMN_INVALID); +} + + const QString BaseSqlTableModel::currentSearch() const { return m_currentSearch; } diff --git a/src/library/basesqltablemodel.h b/src/library/basesqltablemodel.h index 5c5d036c800..b98588d3605 100644 --- a/src/library/basesqltablemodel.h +++ b/src/library/basesqltablemodel.h @@ -76,6 +76,8 @@ class BaseSqlTableModel : public QAbstractTableModel, public TrackModel { void search(const QString& searchText, const QString& extraFilter = QString()) override; const QString currentSearch() const override; QAbstractItemDelegate* delegateForColumn(const int i, QObject* pParent) override; + TrackModel::SortColumnId sortColumnIdFromColumnIndex(int column) override; + int columnIndexFromSortColumnId(TrackModel::SortColumnId sortColumn) override; /////////////////////////////////////////////////////////////////////////// // Inherited from QAbstractItemModel @@ -90,6 +92,7 @@ class BaseSqlTableModel : public QAbstractTableModel, public TrackModel { const QStringList& tableColumns, QSharedPointer trackSource); void initHeaderData(); + virtual void initSortColumnMapping(); // Use this if you want a model that is read-only. virtual Qt::ItemFlags readOnlyFlags(const QModelIndex &index) const; @@ -102,6 +105,8 @@ class BaseSqlTableModel : public QAbstractTableModel, public TrackModel { QString m_previewDeckGroup; TrackId m_previewDeckTrackId; QString m_tableOrderBy; + int m_columnIndexBySortColumnId[NUM_SORTCOLUMNIDS]; + QMap m_sortColumnIdByColumnIndex; private slots: virtual void tracksChanged(QSet trackIds); diff --git a/src/library/browse/browsetablemodel.cpp b/src/library/browse/browsetablemodel.cpp index 594d73d9720..fe9679b43e7 100644 --- a/src/library/browse/browsetablemodel.cpp +++ b/src/library/browse/browsetablemodel.cpp @@ -62,6 +62,41 @@ BrowseTableModel::BrowseTableModel(QObject* parent, setDefaultSort(COLUMN_FILENAME, Qt::AscendingOrder); + for (int i = 0; i < TrackModel::SortColumnId::NUM_SORTCOLUMNIDS; ++i) { + m_columnIndexBySortColumnId[i] = -1; + } + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_FILENAME] = COLUMN_FILENAME; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ARTIST] = COLUMN_ARTIST; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TITLE] = COLUMN_TITLE; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ALBUM] = COLUMN_ALBUM; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ALBUMARTIST] = COLUMN_ALBUMARTIST; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_YEAR] = COLUMN_YEAR; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_GENRE] = COLUMN_GENRE; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COMPOSER] = COLUMN_COMPOSER; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_GROUPING] = COLUMN_GROUPING; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TRACKNUMBER] = COLUMN_TRACK_NUMBER; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_FILETYPE] = COLUMN_TYPE; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_NATIVELOCATION] = COLUMN_NATIVELOCATION; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COMMENT] = COLUMN_COMMENT; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_DURATION] = COLUMN_DURATION; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_BITRATE] = COLUMN_BITRATE; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_BPM] = COLUMN_BPM; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_REPLAYGAIN] = COLUMN_REPLAYGAIN; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_KEY] = COLUMN_KEY; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_PREVIEW] = COLUMN_PREVIEW; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_GROUPING] = COLUMN_GROUPING; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_FILE_MODIFIED_TIME] = COLUMN_FILE_MODIFIED_TIME; + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_FILE_CREATION_TIME] = COLUMN_FILE_CREATION_TIME; + + m_sortColumnIdByColumnIndex.clear(); + for (int i = 0; i < TrackModel::SortColumnId::NUM_SORTCOLUMNIDS; ++i) { + TrackModel::SortColumnId sortColumn = static_cast(i); + int columnIndex = m_columnIndexBySortColumnId[sortColumn]; + if (columnIndex >= 0) { + m_sortColumnIdByColumnIndex.insert(columnIndex, sortColumn); + } + } + setHorizontalHeaderLabels(header_data); // register the QList as a metatype since we use QueuedConnection below qRegisterMetaType< QList< QList > >( @@ -87,6 +122,19 @@ BrowseTableModel::BrowseTableModel(QObject* parent, BrowseTableModel::~BrowseTableModel() { } +int BrowseTableModel::columnIndexFromSortColumnId(TrackModel::SortColumnId column) { + if (column == TrackModel::SortColumnId::SORTCOLUMN_INVALID || + column >= TrackModel::SortColumnId::NUM_SORTCOLUMNIDS) { + return -1; + } + + return m_columnIndexBySortColumnId[column]; +} + +TrackModel::SortColumnId BrowseTableModel::sortColumnIdFromColumnIndex(int index) { + return m_sortColumnIdByColumnIndex.value(index, TrackModel::SortColumnId::SORTCOLUMN_INVALID); +} + const QList& BrowseTableModel::searchColumns() const { return m_searchColumns; } diff --git a/src/library/browse/browsetablemodel.h b/src/library/browse/browsetablemodel.h index a68507133b0..35a479071b8 100644 --- a/src/library/browse/browsetablemodel.h +++ b/src/library/browse/browsetablemodel.h @@ -69,6 +69,8 @@ class BrowseTableModel final : public QStandardItemModel, public virtual TrackMo bool setData(const QModelIndex& index, const QVariant& value, int role=Qt::EditRole) override; QAbstractItemDelegate* delegateForColumn(const int i, QObject* pParent) override; bool isColumnSortable(int column) override; + TrackModel::SortColumnId sortColumnIdFromColumnIndex(int index) override; + int columnIndexFromSortColumnId(TrackModel::SortColumnId sortColumn) override; public slots: void slotClear(BrowseTableModel*); @@ -84,6 +86,9 @@ class BrowseTableModel final : public QStandardItemModel, public virtual TrackMo RecordingManager* m_pRecordingManager; BrowseThreadPointer m_pBrowseThread; QString m_previewDeckGroup; + int m_columnIndexBySortColumnId[TrackModel::SortColumnId::NUM_SORTCOLUMNIDS]; + QMap m_sortColumnIdByColumnIndex; + }; #endif diff --git a/src/library/librarycontrol.cpp b/src/library/librarycontrol.cpp index 76ebb89268c..7f6cb473355 100644 --- a/src/library/librarycontrol.cpp +++ b/src/library/librarycontrol.cpp @@ -106,6 +106,16 @@ LibraryControl::LibraryControl(Library* pLibrary) connect(m_pAutoDjAddBottom.get(), SIGNAL(valueChanged(double)), this, SLOT(slotAutoDjAddBottom(double))); + // Sort controls + m_pSortColumn = std::make_unique(ConfigKey("[Library]", "sort_column")); + m_pSortOrder = std::make_unique(ConfigKey("[Library]", "sort_order")); + m_pSortOrder->setButtonMode(ControlPushButton::TOGGLE); + m_pSortColumnToggle = std::make_unique(ConfigKey("[Library]", "sort_column_toggle"), false); + connect(m_pSortColumn.get(), SIGNAL(valueChanged(double)), + this, SLOT(slotSortColumn(double))); + connect(m_pSortColumnToggle.get(), SIGNAL(valueChanged(double)), + this, SLOT(slotSortColumnToggle(double))); + // Font sizes m_pFontSizeKnob = std::make_unique( ConfigKey("[Library]", "font_size_knob"), false); @@ -478,6 +488,20 @@ void LibraryControl::slotGoToItem(double v) { //emitKeyEvent(QKeyEvent{QEvent::KeyPress, Qt::Key_Return, Qt::AltModifier}); } +void LibraryControl::slotSortColumn(double v) { + m_pSortColumnToggle->set(v); +} + +void LibraryControl::slotSortColumnToggle(double v) { + int column = static_cast(v); + if (static_cast(m_pSortColumn->get()) == column) { + m_pSortOrder->set(!m_pSortOrder->get()); + } else { + m_pSortColumn->set(v); + m_pSortOrder->set(0); + } +} + void LibraryControl::slotFontSize(double v) { if (v == 0.0) { return; diff --git a/src/library/librarycontrol.h b/src/library/librarycontrol.h index dea3028493a..e2efd831aaa 100644 --- a/src/library/librarycontrol.h +++ b/src/library/librarycontrol.h @@ -78,6 +78,9 @@ class LibraryControl : public QObject { void slotNumSamplersChanged(double v); void slotNumPreviewDecksChanged(double v); + void slotSortColumn(double v); + void slotSortColumnToggle(double v); + void slotFontSize(double v); void slotIncrementFontSize(double v); void slotDecrementFontSize(double v); @@ -117,6 +120,11 @@ class LibraryControl : public QObject { std::unique_ptr m_pAutoDjAddTop; std::unique_ptr m_pAutoDjAddBottom; + // Controls to sort the track view + std::unique_ptr m_pSortColumn; + std::unique_ptr m_pSortColumnToggle; + std::unique_ptr m_pSortOrder; + // Font sizes std::unique_ptr m_pFontSizeIncrement; std::unique_ptr m_pFontSizeDecrement; diff --git a/src/library/playlisttablemodel.cpp b/src/library/playlisttablemodel.cpp index e1bc686c7d3..b77d48e5451 100644 --- a/src/library/playlisttablemodel.cpp +++ b/src/library/playlisttablemodel.cpp @@ -15,6 +15,42 @@ PlaylistTableModel::PlaylistTableModel(QObject* parent, PlaylistTableModel::~PlaylistTableModel() { } +void PlaylistTableModel::initSortColumnMapping() { + // Add a bijective mapping between the SortColumnIds and column indices + for (int i = 0; i < TrackModel::SortColumnId::NUM_SORTCOLUMNIDS; ++i) { + m_columnIndexBySortColumnId[i] = -1; + } + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ARTIST] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ARTIST); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TITLE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TITLE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ALBUM] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUM); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_ALBUMARTIST] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUMARTIST); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_YEAR] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_YEAR); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_GENRE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_GENRE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COMPOSER] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COMPOSER); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_GROUPING] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_GROUPING); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TRACKNUMBER] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TRACKNUMBER); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_FILETYPE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_FILETYPE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_NATIVELOCATION] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_NATIVELOCATION); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COMMENT] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COMMENT); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_DURATION] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DURATION); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_BITRATE] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BITRATE); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_BPM] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_REPLAYGAIN] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_REPLAYGAIN); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_DATETIMEADDED] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DATETIMEADDED); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_TIMESPLAYED] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_RATING] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_RATING); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_KEY] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_KEY); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_PREVIEW] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_COVERART] = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART); + m_columnIndexBySortColumnId[TrackModel::SortColumnId::SORTCOLUMN_POSITION] = fieldIndex(ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_POSITION); + + m_sortColumnIdByColumnIndex.clear(); + for (int i = 0; i < TrackModel::SortColumnId::NUM_SORTCOLUMNIDS; ++i) { + TrackModel::SortColumnId sortColumn = static_cast(i); + m_sortColumnIdByColumnIndex.insert(m_columnIndexBySortColumnId[sortColumn], sortColumn); + } +} + void PlaylistTableModel::setTableModel(int playlistId) { //qDebug() << "PlaylistTableModel::setTableModel" << playlistId; if (m_iPlaylistId == playlistId) { diff --git a/src/library/playlisttablemodel.h b/src/library/playlisttablemodel.h index 070a187f269..18fa3320be4 100644 --- a/src/library/playlisttablemodel.h +++ b/src/library/playlisttablemodel.h @@ -36,6 +36,8 @@ class PlaylistTableModel : public BaseSqlTableModel { void playlistChanged(int playlistId); private: + void initSortColumnMapping() override; + int m_iPlaylistId; bool m_showAll; }; diff --git a/src/library/proxytrackmodel.cpp b/src/library/proxytrackmodel.cpp index 3504557b1a7..969b721bf85 100644 --- a/src/library/proxytrackmodel.cpp +++ b/src/library/proxytrackmodel.cpp @@ -23,6 +23,16 @@ ProxyTrackModel::ProxyTrackModel(QAbstractItemModel* pTrackModel, ProxyTrackModel::~ProxyTrackModel() { } +TrackModel::SortColumnId ProxyTrackModel::sortColumnIdFromColumnIndex(int index) { + return (m_pTrackModel ? m_pTrackModel->sortColumnIdFromColumnIndex(index) + : TrackModel::sortColumnIdFromColumnIndex(index)); +} + +int ProxyTrackModel::columnIndexFromSortColumnId(TrackModel::SortColumnId sortColumn) { + return (m_pTrackModel ? m_pTrackModel->columnIndexFromSortColumnId(sortColumn) + : TrackModel::columnIndexFromSortColumnId(sortColumn)); +} + TrackId ProxyTrackModel::getTrackId(const QModelIndex& index) const { QModelIndex indexSource = mapToSource(index); return m_pTrackModel ? m_pTrackModel->getTrackId(indexSource) : TrackId(); diff --git a/src/library/proxytrackmodel.h b/src/library/proxytrackmodel.h index 716a5680929..8b4b097be86 100644 --- a/src/library/proxytrackmodel.h +++ b/src/library/proxytrackmodel.h @@ -37,6 +37,8 @@ class ProxyTrackModel : public QSortFilterProxyModel, public TrackModel { QAbstractItemDelegate* delegateForColumn(const int i, QObject* pParent) final; QString getModelSetting(QString name) final; bool setModelSetting(QString name, QVariant value) final; + TrackModel::SortColumnId sortColumnIdFromColumnIndex(int index) override; + int columnIndexFromSortColumnId(TrackModel::SortColumnId sortColumn) override; // Inherited from QSortFilterProxyModel bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const final; diff --git a/src/library/trackmodel.h b/src/library/trackmodel.h index 1c4a17fb490..be47da248da 100644 --- a/src/library/trackmodel.h +++ b/src/library/trackmodel.h @@ -49,6 +49,41 @@ class TrackModel { }; typedef int CapabilitiesFlags; /** Enables us to do ORing */ + enum SortColumnId { + SORTCOLUMN_INVALID = -1, + SORTCOLUMN_ARTIST = 0, + SORTCOLUMN_TITLE, + SORTCOLUMN_ALBUM, + SORTCOLUMN_ALBUMARTIST, + SORTCOLUMN_YEAR, + SORTCOLUMN_GENRE, + SORTCOLUMN_COMPOSER, + SORTCOLUMN_GROUPING, + SORTCOLUMN_TRACKNUMBER, + SORTCOLUMN_FILETYPE, + SORTCOLUMN_NATIVELOCATION, + SORTCOLUMN_COMMENT, + SORTCOLUMN_DURATION, + SORTCOLUMN_BITRATE, + SORTCOLUMN_BPM, + SORTCOLUMN_REPLAYGAIN, + SORTCOLUMN_DATETIMEADDED, + SORTCOLUMN_TIMESPLAYED, + SORTCOLUMN_RATING, + SORTCOLUMN_KEY, + SORTCOLUMN_PREVIEW, + SORTCOLUMN_COVERART, + SORTCOLUMN_POSITION, + SORTCOLUMN_PLAYLISTID, + SORTCOLUMN_LOCATION, + SORTCOLUMN_FILENAME, + SORTCOLUMN_FILE_MODIFIED_TIME, + SORTCOLUMN_FILE_CREATION_TIME, + + // NUM_SORTCOLUMNS should always be the last item. + NUM_SORTCOLUMNIDS + }; + // Deserialize and return the track at the given QModelIndex in this result // set. virtual TrackPointer getTrack(const QModelIndex& index) const = 0; @@ -138,6 +173,17 @@ class TrackModel { return true; } + virtual SortColumnId sortColumnIdFromColumnIndex(int index) { + Q_UNUSED(index); + return SORTCOLUMN_INVALID; + + } + + virtual int columnIndexFromSortColumnId(TrackModel::SortColumnId sortColumn) { + Q_UNUSED(sortColumn); + return -1; + } + virtual int fieldIndex(const QString& fieldName) const { Q_UNUSED(fieldName); return -1; diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp index 85024eb6847..fb0e53d52b9 100644 --- a/src/widget/wtracktableview.cpp +++ b/src/widget/wtracktableview.cpp @@ -127,6 +127,10 @@ WTrackTableView::WTrackTableView(QWidget * parent, m_pKeyNotation = new ControlProxy("[Library]", "key_notation", this); m_pKeyNotation->connectValueChanged(this, &WTrackTableView::keyNotationChanged); + m_pSortColumn = new ControlProxy("[Library]", "sort_column", this); + m_pSortColumn->connectValueChanged(this, &WTrackTableView::applySortingIfVisible); + m_pSortOrder = new ControlProxy("[Library]", "sort_order", this); + m_pSortOrder->connectValueChanged(this, &WTrackTableView::applySortingIfVisible); connect(this, SIGNAL(scrollValueChanged(int)), this, SLOT(slotScrollValueChanged(int))); @@ -361,31 +365,32 @@ void WTrackTableView::loadTrackModel(QAbstractItemModel *model) { if (m_sorting) { // NOTE: Should be a UniqueConnection but that requires Qt 4.6 connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), - this, SLOT(doSortByColumn(int)), Qt::AutoConnection); + this, SLOT(slotSortingChanged(int, Qt::SortOrder)), Qt::AutoConnection); + + int sortColumn; + Qt::SortOrder sortOrder; // Stupid hack that assumes column 0 is never visible, but this is a weak // proxy for "there was a saved column sort order" if (horizontalHeader()->sortIndicatorSection() > 0) { // Sort by the saved sort section and order. - horizontalHeader()->setSortIndicator(horizontalHeader()->sortIndicatorSection(), - horizontalHeader()->sortIndicatorOrder()); - // in Qt5, we need to call it manually, which triggers finally the select() - doSortByColumn(horizontalHeader()->sortIndicatorSection()); + sortColumn = horizontalHeader()->sortIndicatorSection(); + sortOrder = horizontalHeader()->sortIndicatorOrder(); } else { // No saved order is present. Use the TrackModel's default sort order. - int sortColumn = trackModel->defaultSortColumn(); - Qt::SortOrder sortOrder = trackModel->defaultSortOrder(); + sortColumn = trackModel->defaultSortColumn(); + sortOrder = trackModel->defaultSortOrder(); // If the TrackModel has an invalid or internal column as its default // sort, find the first non-internal column and sort by that. while (sortColumn < 0 || trackModel->isColumnInternal(sortColumn)) { sortColumn++; } - // This line sorts the TrackModel - horizontalHeader()->setSortIndicator(sortColumn, sortOrder); - // in Qt5, we need to call it manually, which triggers finally the select() - doSortByColumn(sortColumn); } + + m_pSortColumn->set(trackModel->sortColumnIdFromColumnIndex(sortColumn)); + m_pSortOrder->set(sortOrder); + applySorting(); } // Set up drag and drop behavior according to whether or not the track @@ -1775,6 +1780,37 @@ void WTrackTableView::doSortByColumn(int headerSection) { horizontalScrollBar()->setValue(savedHScrollBarPos); } +void WTrackTableView::applySortingIfVisible() { + // There are multiple instances of WTrackTableView, but we only want to + // apply the sorting to the currently visible instance + if (!isVisible()) { + return; + } + + applySorting(); +} + +void WTrackTableView::applySorting() { + TrackModel* trackModel = getTrackModel(); + int sortColumnId = static_cast(m_pSortColumn->get()); + if (sortColumnId < 0 || sortColumnId >= TrackModel::SortColumnId::NUM_SORTCOLUMNIDS) { + return; + } + + int sortColumn = trackModel->columnIndexFromSortColumnId(static_cast(sortColumnId)); + if (sortColumn < 0) { + return; + } + + Qt::SortOrder sortOrder = m_pSortOrder->get() ? Qt::DescendingOrder : Qt::AscendingOrder; + + // This line sorts the TrackModel + horizontalHeader()->setSortIndicator(sortColumn, sortOrder); + + // in Qt5, we need to call it manually, which triggers finally the select() + doSortByColumn(sortColumn); +} + void WTrackTableView::slotLockBpm() { lockBpm(true); } @@ -1975,6 +2011,32 @@ void WTrackTableView::slotReloadCoverArt() { } } +void WTrackTableView::slotSortingChanged(int headerSection, Qt::SortOrder order) { + + double sortOrder = static_cast(order); + bool sortingChanged = false; + + TrackModel* trackModel = getTrackModel(); + TrackModel::SortColumnId sortColumnId = trackModel->sortColumnIdFromColumnIndex(headerSection); + + if (sortColumnId == TrackModel::SortColumnId::SORTCOLUMN_INVALID) { + return; + } + + if (sortColumnId != static_cast(m_pSortColumn->get())) { + m_pSortColumn->set(sortColumnId); + sortingChanged = true; + } + if (sortOrder != m_pSortOrder->get()) { + m_pSortOrder->set(sortOrder); + sortingChanged = true; + } + + if (sortingChanged) { + applySortingIfVisible(); + } +} + bool WTrackTableView::hasFocus() const { return QWidget::hasFocus(); } @@ -1993,4 +2055,3 @@ void WTrackTableView::keyNotationChanged() { QWidget::update(); } - diff --git a/src/widget/wtracktableview.h b/src/widget/wtracktableview.h index 302654d4b4d..80787561335 100644 --- a/src/widget/wtracktableview.h +++ b/src/widget/wtracktableview.h @@ -71,6 +71,8 @@ class WTrackTableView : public WLibraryTableView { void addSelectionToNewCrate(); void loadSelectionToGroup(QString group, bool play = false); void doSortByColumn(int headerSection); + void applySortingIfVisible(); + void applySorting(); void slotLockBpm(); void slotUnlockBpm(); void slotScaleBpm(int); @@ -93,6 +95,7 @@ class WTrackTableView : public WLibraryTableView { void slotTrackInfoClosed(); void slotTagFetcherClosed(); + void slotSortingChanged(int headerSection, Qt::SortOrder order); void keyNotationChanged(); private: @@ -217,6 +220,8 @@ class WTrackTableView : public WLibraryTableView { bool m_bCrateMenuLoaded; ControlProxy* m_pCOTGuiTick; ControlProxy* m_pKeyNotation; + ControlProxy* m_pSortColumn; + ControlProxy* m_pSortOrder; }; #endif