diff --git a/src/library/autodj/autodjfeature.cpp b/src/library/autodj/autodjfeature.cpp index be253659871..6c2823f0604 100644 --- a/src/library/autodj/autodjfeature.cpp +++ b/src/library/autodj/autodjfeature.cpp @@ -216,11 +216,12 @@ void AutoDJFeature::slotCrateChanged(CrateId crateId) { } // No child item for crate found // -> Create and append a new child item for this crate - QList rows; - rows.append(new TreeItem(crate.getName(), crate.getId().toVariant())); + // TODO() Use here std::span to get around the heap alloctaion of + // std::vector for a single element. + std::vector> rows; + rows.push_back(std::make_unique(crate.getName(), crate.getId().toVariant())); QModelIndex parentIndex = m_childModel.index(0, 0); - m_childModel.insertTreeItemRows(rows, m_crateList.length(), parentIndex); - DEBUG_ASSERT(rows.isEmpty()); // ownership passed to m_childModel + m_childModel.insertTreeItemRows(std::move(rows), m_crateList.length(), parentIndex); m_crateList.append(crate); } else { // Crate does not exist or is not a source for AutoDJ diff --git a/src/library/banshee/bansheeplaylistmodel.cpp b/src/library/banshee/bansheeplaylistmodel.cpp index a934774478a..961f51813d8 100644 --- a/src/library/banshee/bansheeplaylistmodel.cpp +++ b/src/library/banshee/bansheeplaylistmodel.cpp @@ -34,11 +34,34 @@ #define CLM_PLAYCOUNT "timesplayed" #define CLM_COMPOSER "composer" #define CLM_PREVIEW "preview" +#define CLM_CRATE "crate" namespace { QAtomicInt sTableNumber; +const QString kTrackId = QStringLiteral(CLM_TRACK_ID); +const QString kViewOrder = QStringLiteral(CLM_VIEW_ORDER); +const QString kArtist = QStringLiteral(CLM_ARTIST); +const QString kTitle = QStringLiteral(CLM_TITLE); +const QString kDuration = QStringLiteral(CLM_DURATION); +const QString kUri = QStringLiteral(CLM_URI); +const QString kAlbum = QStringLiteral(CLM_ALBUM); +const QString kAlbumArtist = QStringLiteral(CLM_ALBUM_ARTIST); +const QString kYear = QStringLiteral(CLM_YEAR); +const QString kRating = QStringLiteral(CLM_RATING); +const QString kGenre = QStringLiteral(CLM_GENRE); +const QString kGrouping = QStringLiteral(CLM_GROUPING); +const QString kTracknumber = QStringLiteral(CLM_TRACKNUMBER); +const QString kDateadded = QStringLiteral(CLM_DATEADDED); +const QString kBpm = QStringLiteral(CLM_BPM); +const QString kBitrate = QStringLiteral(CLM_BITRATE); +const QString kComment = QStringLiteral(CLM_COMMENT); +const QString kPlaycount = QStringLiteral(CLM_PLAYCOUNT); +const QString kComposer = QStringLiteral(CLM_COMPOSER); +const QString kPreview = QStringLiteral(CLM_PREVIEW); +const QString kCrate = QStringLiteral(CLM_CRATE); + } // namespace BansheePlaylistModel::BansheePlaylistModel(QObject* pParent, TrackCollectionManager* pTrackCollectionManager, BansheeDbConnection* pConnection) @@ -187,38 +210,51 @@ void BansheePlaylistModel::setTableModel(int playlistId) { } } - QStringList tableColumns; - tableColumns - << CLM_TRACK_ID // 0 - << CLM_VIEW_ORDER - << CLM_PREVIEW; // 3 - - QStringList trackSourceColumns; - trackSourceColumns - << CLM_TRACK_ID // 0 - << CLM_ARTIST - << CLM_TITLE - << CLM_DURATION - << CLM_URI - << CLM_ALBUM - << CLM_ALBUM_ARTIST - << CLM_YEAR - << CLM_RATING - << CLM_GENRE - << CLM_GROUPING - << CLM_TRACKNUMBER - << CLM_DATEADDED - << CLM_BPM - << CLM_BITRATE - << CLM_COMMENT - << CLM_PLAYCOUNT - << CLM_COMPOSER; - - QSharedPointer trackSource( - new BaseTrackCache(m_pTrackCollectionManager->internalCollection(), m_tempTableName, CLM_TRACK_ID, - trackSourceColumns, false)); - - setTable(m_tempTableName, CLM_TRACK_ID, tableColumns, trackSource); + const QString idColumn = kTrackId; + + QStringList tableColumns = { + kTrackId, + kViewOrder, + kPreview}; + + QStringList trackSourceColumns = { + kTrackId, + kArtist, + kTitle, + kDuration, + kUri, + kAlbum, + kAlbumArtist, + kYear, + kRating, + kGenre, + kGrouping, + kTracknumber, + kDateadded, + kBpm, + kBitrate, + kComment, + kPlaycount, + kComposer}; + QStringList searchColumns = { + kArtist, + kAlbum, + kAlbumArtist, + kUri, + kGrouping, + kComment, + kTitle, + kGenre}; + + auto trackSource = QSharedPointer::create( + m_pTrackCollectionManager->internalCollection(), + m_tempTableName, + idColumn, + std::move(trackSourceColumns), + std::move(searchColumns), + false); + + setTable(m_tempTableName, idColumn, std::move(tableColumns), trackSource); setSearch(""); setDefaultSort(fieldIndex(PLAYLISTTRACKSTABLE_POSITION), Qt::AscendingOrder); setSort(defaultSortColumn(), defaultSortOrder()); diff --git a/src/library/baseexternallibraryfeature.cpp b/src/library/baseexternallibraryfeature.cpp index 8f1ef33cd23..dc646a8c8b6 100644 --- a/src/library/baseexternallibraryfeature.cpp +++ b/src/library/baseexternallibraryfeature.cpp @@ -58,7 +58,8 @@ void BaseExternalLibraryFeature::onRightClick(const QPoint& globalPos) { void BaseExternalLibraryFeature::onRightClickChild( const QPoint& globalPos, const QModelIndex& index) { - //Save the model index so we can get it in the action slots... + // Save the model index so we can get it in the action slots... + // Make sure that this is reset when the related TreeItem is deleted. m_lastRightClickedIndex = index; QMenu menu(m_pSidebarWidget); menu.addAction(m_pAddToAutoDJAction); @@ -132,8 +133,8 @@ void BaseExternalLibraryFeature::appendTrackIdsFromRightClickIndex( DEBUG_ASSERT(pPlaylist); *pPlaylist = m_lastRightClickedIndex.data().toString(); - QScopedPointer pPlaylistModelToAdd( - getPlaylistModelForPlaylist(*pPlaylist)); + std::unique_ptr pPlaylistModelToAdd( + createPlaylistModelForPlaylist(*pPlaylist)); if (!pPlaylistModelToAdd || !pPlaylistModelToAdd->initialized()) { qDebug() << "BaseExternalLibraryFeature::appendTrackIdsFromRightClickIndex " diff --git a/src/library/baseexternallibraryfeature.h b/src/library/baseexternallibraryfeature.h index 97ab683c09c..9e1248a266d 100644 --- a/src/library/baseexternallibraryfeature.h +++ b/src/library/baseexternallibraryfeature.h @@ -3,9 +3,10 @@ #include #include #include +#include -#include "library/libraryfeature.h" #include "library/dao/playlistdao.h" +#include "library/libraryfeature.h" #include "util/parented_ptr.h" class BaseSqlTableModel; @@ -26,9 +27,10 @@ class BaseExternalLibraryFeature : public LibraryFeature { protected: // Must be implemented by external Libraries copied to Mixxx DB - virtual BaseSqlTableModel* getPlaylistModelForPlaylist(const QString& playlist) { + virtual std::unique_ptr createPlaylistModelForPlaylist( + const QString& playlist) { Q_UNUSED(playlist); - return nullptr; + return {}; } // Must be implemented by external Libraries not copied to Mixxx DB virtual void appendTrackIdsFromRightClickIndex(QList* trackIds, QString* pPlaylist); @@ -43,12 +45,17 @@ class BaseExternalLibraryFeature : public LibraryFeature { QModelIndex lastRightClickedIndex() const { return m_lastRightClickedIndex; } + void clearLastRightClickedIndex() { + m_lastRightClickedIndex = QModelIndex(); + }; TrackCollection* const m_pTrackCollection; private: void addToAutoDJ(PlaylistDAO::AutoDJSendLoc loc); + // Caution: Make sure this is reset whenever the library tree is updated, + // so that the internalPointer() does not become dangling QModelIndex m_lastRightClickedIndex; parented_ptr m_pAddToAutoDJAction; diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 5acecd7cabe..27e1ed7d22e 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -618,7 +618,7 @@ void BasePlaylistFeature::htmlLinkClicked(const QUrl& link) { * This method queries the database and does dynamic insertion */ QModelIndex BasePlaylistFeature::constructChildModel(int selected_id) { - QList data_list; + std::vector> data_list; int selected_row = -1; int row = 0; @@ -633,17 +633,17 @@ QModelIndex BasePlaylistFeature::constructChildModel(int selected_id) { } // Create the TreeItem whose parent is the invisible root item - TreeItem* item = new TreeItem(playlistLabel, playlistId); - item->setBold(m_playlistsSelectedTrackIsIn.contains(playlistId)); + auto pItem = std::make_unique(playlistLabel, playlistId); + pItem->setBold(m_playlistsSelectedTrackIsIn.contains(playlistId)); - decorateChild(item, playlistId); - data_list.append(item); + decorateChild(pItem.get(), playlistId); + data_list.push_back(std::move(pItem)); ++row; } // Append all the newly created TreeItems in a dynamic way to the childmodel - m_childModel.insertTreeItemRows(data_list, 0); + m_childModel.insertTreeItemRows(std::move(data_list), 0); if (selected_row == -1) { return QModelIndex(); } @@ -671,6 +671,7 @@ void BasePlaylistFeature::updateChildModel(int playlistId) { * Clears the child model dynamically, but the invisible root item remains */ void BasePlaylistFeature::clearChildModel() { + m_lastRightClickedIndex = QModelIndex(); m_childModel.removeRows(0, m_childModel.rowCount()); } diff --git a/src/library/baseplaylistfeature.h b/src/library/baseplaylistfeature.h index a1c1ab10382..4d6370ffc91 100644 --- a/src/library/baseplaylistfeature.h +++ b/src/library/baseplaylistfeature.h @@ -70,6 +70,8 @@ class BasePlaylistFeature : public BaseTrackSetFeature { virtual void clearChildModel(); virtual QList createPlaylistLabels() = 0; virtual QString fetchPlaylistLabel(int playlistId) = 0; + + /// borrows pChild which must not be null, TODO: use gsl::not_null virtual void decorateChild(TreeItem* pChild, int playlistId) = 0; virtual void addToAutoDJ(PlaylistDAO::AutoDJSendLoc loc); diff --git a/src/library/basesqltablemodel.cpp b/src/library/basesqltablemodel.cpp index 8a72b702d9f..a8bc7c9ed47 100644 --- a/src/library/basesqltablemodel.cpp +++ b/src/library/basesqltablemodel.cpp @@ -334,16 +334,16 @@ void BaseSqlTableModel::select() { << m_rowInfo.size(); } -void BaseSqlTableModel::setTable(const QString& tableName, - const QString& idColumn, - const QStringList& tableColumns, +void BaseSqlTableModel::setTable(QString tableName, + QString idColumn, + QStringList tableColumns, QSharedPointer trackSource) { if (sDebug) { qDebug() << this << "setTable" << tableName << tableColumns << idColumn; } - m_tableName = tableName; - m_idColumn = idColumn; - m_tableColumns = tableColumns; + m_tableName = std::move(tableName); + m_idColumn = std::move(idColumn); + m_tableColumns = std::move(tableColumns); if (m_trackSource) { disconnect(m_trackSource.data(), diff --git a/src/library/basesqltablemodel.h b/src/library/basesqltablemodel.h index a7c46f60897..a2076476eba 100644 --- a/src/library/basesqltablemodel.h +++ b/src/library/basesqltablemodel.h @@ -84,9 +84,10 @@ class BaseSqlTableModel : public BaseTrackTableModel { const QVariant& value, int role) final; - void setTable(const QString& tableName, const QString& trackIdColumn, - const QStringList& tableColumns, - QSharedPointer trackSource); + void setTable(QString tableName, + QString trackIdColumn, + QStringList tableColumns, + QSharedPointer trackSource); void initHeaderProperties() override; virtual void initSortColumnMapping(); diff --git a/src/library/basetrackcache.cpp b/src/library/basetrackcache.cpp index 24c325fe8ec..ae3931bf19f 100644 --- a/src/library/basetrackcache.cpp +++ b/src/library/basetrackcache.cpp @@ -17,35 +17,21 @@ constexpr bool sDebug = false; } // namespace BaseTrackCache::BaseTrackCache(TrackCollection* pTrackCollection, - const QString& tableName, - const QString& idColumn, - const QStringList& columns, - bool isCaching) - : m_tableName(tableName), - m_idColumn(idColumn), + QString tableName, + QString idColumn, + QStringList columns, + QStringList searchColumns, + bool isCaching) + : m_tableName(std::move(tableName)), + m_idColumn(std::move(idColumn)), m_columnCount(columns.size()), m_columnsJoined(columns.join(",")), - m_columnCache(columns), - m_pQueryParser(new SearchQueryParser(pTrackCollection)), + m_columnCache(std::move(columns)), + m_pQueryParser(std::make_unique( + pTrackCollection, std::move(searchColumns))), m_bIndexBuilt(false), m_bIsCaching(isCaching), m_database(pTrackCollection->database()) { - m_searchColumns << "artist" - << "album" - << "album_artist" - << "location" - << "grouping" - << "comment" - << "title" - << "genre" - << "crate"; - - // Convert all the search column names to their field indexes because we use - // them a bunch. - m_searchColumnIndices.resize(m_searchColumns.size()); - for (int i = 0; i < m_searchColumns.size(); ++i) { - m_searchColumnIndices[i] = m_columnCache.fieldIndex(m_searchColumns[i]); - } } BaseTrackCache::~BaseTrackCache() { @@ -125,10 +111,6 @@ void BaseTrackCache::ensureCached(const QSet& trackIds) { updateTracksInIndex(trackIds); } -void BaseTrackCache::setSearchColumns(const QStringList& columns) { - m_searchColumns = columns; -} - const TrackPointer& BaseTrackCache::getRecentTrack(TrackId trackId) const { DEBUG_ASSERT(m_bIsCaching); // Only refresh the recently used track if the identifiers @@ -488,7 +470,6 @@ void BaseTrackCache::filterAndSort(const QSet& trackIds, const std::unique_ptr pQuery = m_pQueryParser->parseQuery( searchQuery, - m_searchColumns, queryFragments.join(" AND ")); QString filter = pQuery->toSql(); diff --git a/src/library/basetrackcache.h b/src/library/basetrackcache.h index d4e957f2b6f..43d21a34827 100644 --- a/src/library/basetrackcache.h +++ b/src/library/basetrackcache.h @@ -43,10 +43,11 @@ class BaseTrackCache : public QObject { /// The order of the `columns` list parameter defines the initial/default /// order of columns in the library view. BaseTrackCache(TrackCollection* pTrackCollection, - const QString& tableName, - const QString& idColumn, - const QStringList& columns, - bool isCaching); + QString tableName, + QString idColumn, + QStringList columns, + QStringList searchColumns, + bool isCaching); ~BaseTrackCache() override; // Rebuild the BaseTrackCache index from the SQL table. This can be @@ -73,7 +74,6 @@ class BaseTrackCache : public QObject { virtual bool isCached(TrackId trackId) const; virtual void ensureCached(TrackId trackId); virtual void ensureCached(const QSet& trackIds); - virtual void setSearchColumns(const QStringList& columns); signals: void tracksChanged(const QSet& trackIds); @@ -126,9 +126,6 @@ class BaseTrackCache : public QObject { const StringCollator m_collator; - QStringList m_searchColumns; - QVector m_searchColumnIndices; - // Temporary storage for filterAndSort() QVector m_trackOrder; diff --git a/src/library/browse/browsefeature.cpp b/src/library/browse/browsefeature.cpp index 46f26087ce2..5c45a3f4083 100644 --- a/src/library/browse/browsefeature.cpp +++ b/src/library/browse/browsefeature.cpp @@ -151,11 +151,11 @@ void BrowseFeature::slotAddQuickLink() { QString name = extractNameFromPath(spath); QModelIndex parent = m_childModel.index(m_pQuickLinkItem->parentRow(), 0); - auto pNewChild = std::make_unique(name, vpath); - QList rows; - rows.append(pNewChild.get()); - pNewChild.release(); - m_childModel.insertTreeItemRows(rows, m_pQuickLinkItem->childRows(), parent); + std::vector> rows; + // TODO() Use here std::span to get around the heap allocation of + // std::vector for a single element. + rows.push_back(std::make_unique(name, vpath)); + m_childModel.insertTreeItemRows(std::move(rows), m_pQuickLinkItem->childRows(), parent); m_quickLinkList.append(spath); saveQuickLinks(); @@ -206,6 +206,7 @@ void BrowseFeature::slotRemoveQuickLink() { return; } + m_pLastRightClickedItem = nullptr; QModelIndex parent = m_childModel.index(m_pQuickLinkItem->parentRow(), 0); m_childModel.removeRow(index, parent); @@ -272,6 +273,8 @@ void BrowseFeature::activateChild(const QModelIndex& index) { void BrowseFeature::onRightClickChild(const QPoint& globalPos, const QModelIndex& index) { TreeItem *item = static_cast(index.internalPointer()); + + // Make sure that this is reset when the related TreeItem is deleted. m_pLastRightClickedItem = item; if (!item) { @@ -311,8 +314,8 @@ void BrowseFeature::onRightClickChild(const QPoint& globalPos, const QModelIndex namespace { // Get the list of devices (under "Removable Devices" section). -QList getRemovableDevices() { - QList ret; +std::vector> createRemovableDevices() { + std::vector> ret; #if defined(__WINDOWS__) // Repopulate drive list QFileInfoList drives = QDir::drives(); @@ -330,10 +333,9 @@ QList getRemovableDevices() { if (display_path.endsWith("/")) { display_path.chop(1); } - TreeItem* driveLetter = new TreeItem( - display_path, // Displays C: - drive.filePath()); // Displays C:/ - ret << driveLetter; + ret.push_back(std::make_unique( + display_path, // Displays C: + drive.filePath())); // Displays C:/ } #elif defined(__LINUX__) // To get devices on Linux, we look for directories under /media and @@ -351,10 +353,9 @@ QList getRemovableDevices() { // Convert devices into a QList for display. foreach(QFileInfo device, devices) { - TreeItem* folder = new TreeItem( - device.fileName(), - QVariant(device.filePath() + QStringLiteral("/"))); - ret << folder; + ret.push_back(std::make_unique( + device.fileName(), + QVariant(device.filePath() + QStringLiteral("/")))); } #endif return ret; @@ -391,15 +392,16 @@ void BrowseFeature::onLazyChildExpandation(const QModelIndex& index) { return; } + m_pLastRightClickedItem = nullptr; // Before we populate the subtree, we need to delete old subtrees m_childModel.removeRows(0, item->childRows(), index); // List of subfolders or drive letters - QList folders; + std::vector> folders; // If we are on the special device node if (path == DEVICE_NODE) { - folders += getRemovableDevices(); + folders = createRemovableDevices(); } else { // we assume that the path refers to a folder in the file system // populate children @@ -418,17 +420,16 @@ void BrowseFeature::onLazyChildExpandation(const QModelIndex& index) { // We here create new items for the sidebar models // Once the items are added to the TreeItemModel, // the models takes ownership of them and ensures their deletion - TreeItem* folder = new TreeItem( - one.fileName(), - QVariant(one.absoluteFilePath() + QStringLiteral("/"))); - folders << folder; + folders.push_back(std::make_unique( + one.fileName(), + QVariant(one.absoluteFilePath() + QStringLiteral("/")))); } } // we need to check here if subfolders are found // On Ubuntu 10.04, otherwise, this will draw an icon although the folder // has no subfolders - if (!folders.isEmpty()) { - m_childModel.insertTreeItemRows(folders, 0, index); + if (!folders.empty()) { + m_childModel.insertTreeItemRows(std::move(folders), 0, index); } } diff --git a/src/library/browse/browsefeature.h b/src/library/browse/browsefeature.h index a90fdded19a..c98e9538c77 100644 --- a/src/library/browse/browsefeature.h +++ b/src/library/browse/browsefeature.h @@ -70,6 +70,9 @@ class BrowseFeature : public LibraryFeature { QAction* m_pAddQuickLinkAction; QAction* m_pRemoveQuickLinkAction; QAction* m_pAddtoLibraryAction; + + // Caution: Make sure this is reset whenever the library tree is updated, + // so that the internalPointer() does not become dangling TreeItem* m_pLastRightClickedItem; TreeItem* m_pQuickLinkItem; QStringList m_quickLinkList; diff --git a/src/library/browse/browsetablemodel.cpp b/src/library/browse/browsetablemodel.cpp index db60c3180c1..b33d5fe6712 100644 --- a/src/library/browse/browsetablemodel.cpp +++ b/src/library/browse/browsetablemodel.cpp @@ -54,18 +54,16 @@ BrowseTableModel::BrowseTableModel(QObject* parent, listAppendOrReplaceAt(&headerLabels, COLUMN_FILE_CREATION_TIME, tr("File Created")); listAppendOrReplaceAt(&headerLabels, COLUMN_REPLAYGAIN, tr("ReplayGain")); - addSearchColumn(COLUMN_FILENAME); - addSearchColumn(COLUMN_ARTIST); - addSearchColumn(COLUMN_ALBUM); - addSearchColumn(COLUMN_TITLE); - addSearchColumn(COLUMN_GENRE); - addSearchColumn(COLUMN_COMPOSER); - addSearchColumn(COLUMN_KEY); - addSearchColumn(COLUMN_COMMENT); - addSearchColumn(COLUMN_ALBUMARTIST); - addSearchColumn(COLUMN_GROUPING); - addSearchColumn(COLUMN_FILE_MODIFIED_TIME); - addSearchColumn(COLUMN_FILE_CREATION_TIME); + m_searchColumns = { + COLUMN_FILENAME, + COLUMN_ARTIST, + COLUMN_ALBUM, + COLUMN_TITLE, + COLUMN_GENRE, + COLUMN_COMPOSER, + COLUMN_COMMENT, + COLUMN_ALBUMARTIST, + COLUMN_GROUPING}; setDefaultSort(COLUMN_FILENAME, Qt::AscendingOrder); @@ -182,10 +180,6 @@ const QList& BrowseTableModel::searchColumns() const { return m_searchColumns; } -void BrowseTableModel::addSearchColumn(int index) { - m_searchColumns.push_back(index); -} - void BrowseTableModel::setPath(const MDir& path) { m_current_directory = path; m_pBrowseThread->executePopulation(m_current_directory, this); diff --git a/src/library/browse/browsetablemodel.h b/src/library/browse/browsetablemodel.h index 629e9c05a0e..47c4a121d63 100644 --- a/src/library/browse/browsetablemodel.h +++ b/src/library/browse/browsetablemodel.h @@ -79,8 +79,6 @@ class BrowseTableModel final : public QStandardItemModel, public virtual TrackMo void trackChanged(const QString& group, TrackPointer pNewTrack, TrackPointer pOldTrack); private: - void addSearchColumn(int index); - TrackCollectionManager* const m_pTrackCollectionManager; QList m_searchColumns; diff --git a/src/library/crate/cratefeature.cpp b/src/library/crate/cratefeature.cpp index b2651e0ce73..5e09448acdf 100644 --- a/src/library/crate/cratefeature.cpp +++ b/src/library/crate/cratefeature.cpp @@ -479,13 +479,15 @@ void CrateFeature::slotAutoDjTrackSourceChanged() { QModelIndex CrateFeature::rebuildChildModel(CrateId selectedCrateId) { qDebug() << "CrateFeature::rebuildChildModel()" << selectedCrateId; + m_lastRightClickedIndex = QModelIndex(); + TreeItem* pRootItem = m_childModel.getRootItem(); VERIFY_OR_DEBUG_ASSERT(pRootItem != nullptr) { return QModelIndex(); } m_childModel.removeRows(0, pRootItem->childRows()); - QList modelRows; + std::vector> modelRows; modelRows.reserve(m_pTrackCollection->crates().countCrates()); int selectedRow = -1; @@ -493,9 +495,7 @@ QModelIndex CrateFeature::rebuildChildModel(CrateId selectedCrateId) { m_pTrackCollection->crates().selectCrateSummaries()); CrateSummary crateSummary; while (crateSummaries.populateNext(&crateSummary)) { - auto pTreeItem = newTreeItemForCrateSummary(crateSummary); - modelRows.append(pTreeItem.get()); - pTreeItem.release(); + modelRows.push_back(newTreeItemForCrateSummary(crateSummary)); if (selectedCrateId == crateSummary.getId()) { // save index for selection selectedRow = modelRows.size() - 1; @@ -503,7 +503,7 @@ QModelIndex CrateFeature::rebuildChildModel(CrateId selectedCrateId) { } // Append all the newly created TreeItems in a dynamic way to the childmodel - m_childModel.insertTreeItemRows(modelRows, 0); + m_childModel.insertTreeItemRows(std::move(modelRows), 0); // Update rendering of crates depending on the currently selected track slotTrackSelected(m_pSelectedTrack); diff --git a/src/library/dao/trackschema.h b/src/library/dao/trackschema.h index 100655df562..a5b694379a3 100644 --- a/src/library/dao/trackschema.h +++ b/src/library/dao/trackschema.h @@ -43,6 +43,7 @@ const QString LIBRARYTABLE_COVERART_SOURCE = QStringLiteral("coverart_source"); const QString LIBRARYTABLE_COVERART_TYPE = QStringLiteral("coverart_type"); const QString LIBRARYTABLE_COVERART_LOCATION = QStringLiteral("coverart_location"); const QString LIBRARYTABLE_COVERART_HASH = QStringLiteral("coverart_hash"); +const QString LIBRARYTABLE_CRATE = QStringLiteral("crate"); const QString TRACKLOCATIONSTABLE_ID = QStringLiteral("id"); const QString TRACKLOCATIONSTABLE_LOCATION = QStringLiteral("location"); diff --git a/src/library/hiddentablemodel.cpp b/src/library/hiddentablemodel.cpp index 3a2b3425ffb..adcb7008cce 100644 --- a/src/library/hiddentablemodel.cpp +++ b/src/library/hiddentablemodel.cpp @@ -40,8 +40,10 @@ void HiddenTableModel::setTableModel(int id) { QStringList tableColumns; tableColumns << LIBRARYTABLE_ID; - setTable(tableName, LIBRARYTABLE_ID, tableColumns, - m_pTrackCollectionManager->internalCollection()->getTrackSource()); + setTable(tableName, + LIBRARYTABLE_ID, + std::move(tableColumns), + m_pTrackCollectionManager->internalCollection()->getTrackSource()); setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder); setSearch(""); } diff --git a/src/library/itunes/itunesfeature.cpp b/src/library/itunes/itunesfeature.cpp index 24eab40f822..e7142c8507d 100644 --- a/src/library/itunes/itunesfeature.cpp +++ b/src/library/itunes/itunesfeature.cpp @@ -68,26 +68,39 @@ ITunesFeature::ITunesFeature(Library* pLibrary, UserSettingsPointer pConfig) m_icon(":/images/library/ic_library_itunes.svg") { QString tableName = "itunes_library"; QString idColumn = "id"; - QStringList columns; - columns << "id" - << "artist" - << "title" - << "album" - << "album_artist" - << "year" - << "genre" - << "grouping" - << "tracknumber" - << "location" - << "comment" - << "duration" - << "bitrate" - << "bpm" - << "rating"; - - m_trackSource = QSharedPointer( - new BaseTrackCache(m_pLibrary->trackCollections()->internalCollection(), tableName, idColumn, - columns, false)); + QStringList columns = { + "id", + "artist", + "title", + "album", + "album_artist", + "year", + "genre", + "grouping", + "tracknumber", + "location", + "comment", + "duration", + "bitrate", + "bpm", + "rating"}; + QStringList searchColumns = { + "artist", + "album", + "album_artist", + "location", + "grouping", + "comment", + "title", + "genre"}; + + m_trackSource = QSharedPointer::create( + m_pLibrary->trackCollections()->internalCollection(), + std::move(tableName), + std::move(idColumn), + std::move(columns), + std::move(searchColumns), + false); m_pITunesTrackModel = new BaseExternalTrackModel( this, m_pLibrary->trackCollections(), "mixxx.db.model.itunes", @@ -124,13 +137,14 @@ ITunesFeature::~ITunesFeature() { delete m_pITunesPlaylistModel; } -BaseSqlTableModel* ITunesFeature::getPlaylistModelForPlaylist(const QString& playlist) { - BaseExternalPlaylistModel* pModel = new BaseExternalPlaylistModel( - this, m_pLibrary->trackCollections(), - "mixxx.db.model.itunes_playlist", - "itunes_playlists", - "itunes_playlist_tracks", - m_trackSource); +std::unique_ptr +ITunesFeature::createPlaylistModelForPlaylist(const QString& playlist) { + auto pModel = std::make_unique(this, + m_pLibrary->trackCollections(), + "mixxx.db.model.itunes_playlist", + "itunes_playlists", + "itunes_playlist_tracks", + m_trackSource); pModel->setPlaylist(playlist); return pModel; } diff --git a/src/library/itunes/itunesfeature.h b/src/library/itunes/itunesfeature.h index a3cd26b1ffe..f72d58faf52 100644 --- a/src/library/itunes/itunesfeature.h +++ b/src/library/itunes/itunesfeature.h @@ -37,7 +37,8 @@ class ITunesFeature : public BaseExternalLibraryFeature { void onTrackCollectionLoaded(); private: - BaseSqlTableModel* getPlaylistModelForPlaylist(const QString& playlist) override; + std::unique_ptr createPlaylistModelForPlaylist( + const QString& playlist) override; static QString getiTunesMusicPath(); // returns the invisible rootItem for the sidebar model TreeItem* importLibrary(); diff --git a/src/library/librarytablemodel.cpp b/src/library/librarytablemodel.cpp index 3921a493c6a..dbb2c397272 100644 --- a/src/library/librarytablemodel.cpp +++ b/src/library/librarytablemodel.cpp @@ -50,8 +50,10 @@ void LibraryTableModel::setTableModel(int id) { tableColumns << LIBRARYTABLE_ID; tableColumns << LIBRARYTABLE_PREVIEW; tableColumns << LIBRARYTABLE_COVERART; - setTable(tableName, LIBRARYTABLE_ID, tableColumns, - m_pTrackCollectionManager->internalCollection()->getTrackSource()); + setTable(tableName, + LIBRARYTABLE_ID, + std::move(tableColumns), + m_pTrackCollectionManager->internalCollection()->getTrackSource()); setSearch(""); setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder); diff --git a/src/library/missingtablemodel.cpp b/src/library/missingtablemodel.cpp index 6e4af6cab52..fc42a67757b 100644 --- a/src/library/missingtablemodel.cpp +++ b/src/library/missingtablemodel.cpp @@ -46,8 +46,10 @@ void MissingTableModel::setTableModel(int id) { QStringList tableColumns; tableColumns << LIBRARYTABLE_ID; - setTable(tableName, LIBRARYTABLE_ID, tableColumns, - m_pTrackCollectionManager->internalCollection()->getTrackSource()); + setTable(tableName, + LIBRARYTABLE_ID, + std::move(tableColumns), + m_pTrackCollectionManager->internalCollection()->getTrackSource()); setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder); setSearch(""); diff --git a/src/library/mixxxlibraryfeature.cpp b/src/library/mixxxlibraryfeature.cpp index 33ea90143cb..ea4e0c2ee5e 100644 --- a/src/library/mixxxlibraryfeature.cpp +++ b/src/library/mixxxlibraryfeature.cpp @@ -20,44 +20,6 @@ #include "util/dnd.h" #include "widget/wlibrary.h" -namespace { - -const QStringList DEFAULT_COLUMNS = { - LIBRARYTABLE_ID, - LIBRARYTABLE_PLAYED, - LIBRARYTABLE_TIMESPLAYED, - //has to be up here otherwise Played and TimesPlayed are not shown - LIBRARYTABLE_ALBUMARTIST, - LIBRARYTABLE_ALBUM, - LIBRARYTABLE_ARTIST, - LIBRARYTABLE_TITLE, - LIBRARYTABLE_YEAR, - LIBRARYTABLE_RATING, - LIBRARYTABLE_GENRE, - LIBRARYTABLE_COMPOSER, - LIBRARYTABLE_GROUPING, - LIBRARYTABLE_TRACKNUMBER, - LIBRARYTABLE_KEY, - LIBRARYTABLE_KEY_ID, - LIBRARYTABLE_BPM, - LIBRARYTABLE_BPM_LOCK, - LIBRARYTABLE_DURATION, - LIBRARYTABLE_BITRATE, - LIBRARYTABLE_REPLAYGAIN, - LIBRARYTABLE_FILETYPE, - LIBRARYTABLE_DATETIMEADDED, - TRACKLOCATIONSTABLE_LOCATION, - TRACKLOCATIONSTABLE_FSDELETED, - LIBRARYTABLE_COMMENT, - LIBRARYTABLE_MIXXXDELETED, - LIBRARYTABLE_COLOR, - LIBRARYTABLE_COVERART_SOURCE, - LIBRARYTABLE_COVERART_TYPE, - LIBRARYTABLE_COVERART_LOCATION, - LIBRARYTABLE_COVERART_HASH}; - -} // namespace - MixxxLibraryFeature::MixxxLibraryFeature(Library* pLibrary, UserSettingsPointer pConfig) : LibraryFeature(pLibrary, pConfig), @@ -68,7 +30,51 @@ MixxxLibraryFeature::MixxxLibraryFeature(Library* pLibrary, m_pLibraryTableModel(nullptr), m_pMissingView(nullptr), m_pHiddenView(nullptr) { - QStringList columns = DEFAULT_COLUMNS; + QString idColumn = LIBRARYTABLE_ID; + QStringList columns = { + LIBRARYTABLE_ID, + LIBRARYTABLE_PLAYED, + LIBRARYTABLE_TIMESPLAYED, + // has to be up here otherwise Played and TimesPlayed are not shown + LIBRARYTABLE_ALBUMARTIST, + LIBRARYTABLE_ALBUM, + LIBRARYTABLE_ARTIST, + LIBRARYTABLE_TITLE, + LIBRARYTABLE_YEAR, + LIBRARYTABLE_RATING, + LIBRARYTABLE_GENRE, + LIBRARYTABLE_COMPOSER, + LIBRARYTABLE_GROUPING, + LIBRARYTABLE_TRACKNUMBER, + LIBRARYTABLE_KEY, + LIBRARYTABLE_KEY_ID, + LIBRARYTABLE_BPM, + LIBRARYTABLE_BPM_LOCK, + LIBRARYTABLE_DURATION, + LIBRARYTABLE_BITRATE, + LIBRARYTABLE_REPLAYGAIN, + LIBRARYTABLE_FILETYPE, + LIBRARYTABLE_DATETIMEADDED, + TRACKLOCATIONSTABLE_LOCATION, + TRACKLOCATIONSTABLE_FSDELETED, + LIBRARYTABLE_COMMENT, + LIBRARYTABLE_MIXXXDELETED, + LIBRARYTABLE_COLOR, + LIBRARYTABLE_COVERART_SOURCE, + LIBRARYTABLE_COVERART_TYPE, + LIBRARYTABLE_COVERART_LOCATION, + LIBRARYTABLE_COVERART_HASH}; + QStringList searchColumns = { + LIBRARYTABLE_ARTIST, + LIBRARYTABLE_ALBUM, + LIBRARYTABLE_ALBUMARTIST, + TRACKLOCATIONSTABLE_LOCATION, + LIBRARYTABLE_GROUPING, + LIBRARYTABLE_COMMENT, + LIBRARYTABLE_TITLE, + LIBRARYTABLE_GENRE, + LIBRARYTABLE_CRATE}; + QStringList qualifiedTableColumns; for (const auto& col : columns) { qualifiedTableColumns.append(mixxx::trackschema::tableForColumn(col) + @@ -87,8 +93,12 @@ MixxxLibraryFeature::MixxxLibraryFeature(Library* pLibrary, LOG_FAILED_QUERY(query); } - BaseTrackCache* pBaseTrackCache = new BaseTrackCache( - m_pTrackCollection, tableName, LIBRARYTABLE_ID, columns, true); + BaseTrackCache* pBaseTrackCache = new BaseTrackCache(m_pTrackCollection, + std::move(tableName), + std::move(idColumn), + std::move(columns), + std::move(searchColumns), + true); m_pBaseTrackCache = QSharedPointer(pBaseTrackCache); m_pTrackCollection->connectTrackSource(m_pBaseTrackCache); diff --git a/src/library/recording/recordingfeature.h b/src/library/recording/recordingfeature.h index 61b26ad7821..abab936428c 100644 --- a/src/library/recording/recordingfeature.h +++ b/src/library/recording/recordingfeature.h @@ -7,7 +7,6 @@ #include "library/browse/browsetablemodel.h" #include "library/browse/foldertreemodel.h" #include "library/libraryfeature.h" -#include "library/proxytrackmodel.h" class RecordingManager; diff --git a/src/library/rekordbox/rekordboxfeature.cpp b/src/library/rekordbox/rekordboxfeature.cpp index 5cddf0637e6..a8928c87e8e 100644 --- a/src/library/rekordbox/rekordboxfeature.cpp +++ b/src/library/rekordbox/rekordboxfeature.cpp @@ -162,6 +162,9 @@ bool dropTable(QSqlDatabase& database, const QString& tableName) { } // This function is executed in a separate thread other than the main thread +// The returned list owns the pointers, but we can't use a unique_ptr because +// the result is passed by a const reference inside QFuture and than copied +// to the main thread requiring a copy-able object. QList findRekordboxDevices() { QThread* thisThread = QThread::currentThread(); thisThread->setPriority(QThread::LowPriority); @@ -192,10 +195,10 @@ QList findRekordboxDevices() { QList data; data << drive.filePath(); data << IS_RECORDBOX_DEVICE; - TreeItem* foundDevice = new TreeItem( + auto* pFoundDevice = new TreeItem( std::move(displayPath), QVariant(data)); - foundDevices << foundDevice; + foundDevices << pFoundDevice; } } #elif defined(__LINUX__) @@ -223,10 +226,10 @@ QList findRekordboxDevices() { QList data; data << device.filePath(); data << IS_RECORDBOX_DEVICE; - TreeItem* foundDevice = new TreeItem( + auto* pFoundDevice = new TreeItem( device.fileName(), QVariant(data)); - foundDevices << foundDevice; + foundDevices << pFoundDevice; } } #else // __APPLE__ @@ -239,10 +242,10 @@ QList findRekordboxDevices() { QList data; data << device.filePath(); data << IS_RECORDBOX_DEVICE; - auto* foundDevice = new TreeItem( + auto* pFoundDevice = new TreeItem( device.fileName(), QVariant(data)); - foundDevices << foundDevice; + foundDevices << pFoundDevice; } } #endif @@ -1233,42 +1236,42 @@ RekordboxFeature::RekordboxFeature( m_icon(":/images/library/ic_library_rekordbox.svg") { QString tableName = kRekordboxLibraryTable; QString idColumn = LIBRARYTABLE_ID; - QStringList columns; - columns << LIBRARYTABLE_ID - << LIBRARYTABLE_ARTIST - << LIBRARYTABLE_TITLE - << LIBRARYTABLE_ALBUM - << LIBRARYTABLE_YEAR - << LIBRARYTABLE_GENRE - << LIBRARYTABLE_TRACKNUMBER - << TRACKLOCATIONSTABLE_LOCATION - << LIBRARYTABLE_COMMENT - << LIBRARYTABLE_RATING - << LIBRARYTABLE_DURATION - << LIBRARYTABLE_BITRATE - << LIBRARYTABLE_BPM - << LIBRARYTABLE_KEY - << LIBRARYTABLE_COLOR - << REKORDBOX_ANALYZE_PATH; - m_trackSource = QSharedPointer( - new BaseTrackCache(m_pTrackCollection, tableName, idColumn, columns, false)); - QStringList searchColumns; - searchColumns - << LIBRARYTABLE_ARTIST - << LIBRARYTABLE_TITLE - << LIBRARYTABLE_ALBUM - << LIBRARYTABLE_YEAR - << LIBRARYTABLE_GENRE - << LIBRARYTABLE_TRACKNUMBER - << TRACKLOCATIONSTABLE_LOCATION - << LIBRARYTABLE_COMMENT - << LIBRARYTABLE_DURATION - << LIBRARYTABLE_BITRATE - << LIBRARYTABLE_BPM - << LIBRARYTABLE_KEY; - m_trackSource->setSearchColumns(searchColumns); - - m_pRekordboxPlaylistModel = new RekordboxPlaylistModel(this, pLibrary->trackCollections(), m_trackSource); + QStringList columns = { + LIBRARYTABLE_ID, + LIBRARYTABLE_ARTIST, + LIBRARYTABLE_TITLE, + LIBRARYTABLE_ALBUM, + LIBRARYTABLE_YEAR, + LIBRARYTABLE_GENRE, + LIBRARYTABLE_TRACKNUMBER, + TRACKLOCATIONSTABLE_LOCATION, + LIBRARYTABLE_COMMENT, + LIBRARYTABLE_RATING, + LIBRARYTABLE_DURATION, + LIBRARYTABLE_BITRATE, + LIBRARYTABLE_BPM, + LIBRARYTABLE_KEY, + LIBRARYTABLE_COLOR, + REKORDBOX_ANALYZE_PATH}; + + const QStringList searchColumns = { + LIBRARYTABLE_ARTIST, + LIBRARYTABLE_TITLE, + LIBRARYTABLE_ALBUM, + LIBRARYTABLE_GENRE, + LIBRARYTABLE_TRACKNUMBER, + TRACKLOCATIONSTABLE_LOCATION, + LIBRARYTABLE_COMMENT}; + + m_trackSource = QSharedPointer::create( + m_pTrackCollection, + tableName, + std::move(idColumn), + std::move(columns), + std::move(searchColumns), + false); + m_pRekordboxPlaylistModel = make_parented( + this, pLibrary->trackCollections(), m_trackSource); m_title = tr("Rekordbox"); @@ -1308,18 +1311,16 @@ RekordboxFeature::~RekordboxFeature() { dropTable(database, kRekordboxPlaylistsTable); dropTable(database, kRekordboxLibraryTable); transaction.commit(); - - delete m_pRekordboxPlaylistModel; } -void RekordboxFeature::bindLibraryWidget(WLibrary* libraryWidget, +void RekordboxFeature::bindLibraryWidget(WLibrary* pLibraryWidget, KeyboardEventFilter* keyboard) { Q_UNUSED(keyboard); - WLibraryTextBrowser* edit = new WLibraryTextBrowser(libraryWidget); - edit->setHtml(formatRootViewHtml()); - edit->setOpenLinks(false); - connect(edit, &WLibraryTextBrowser::anchorClicked, this, &RekordboxFeature::htmlLinkClicked); - libraryWidget->registerView("REKORDBOXHOME", edit); + parented_ptr pEdit = make_parented(pLibraryWidget); + pEdit->setHtml(formatRootViewHtml()); + pEdit->setOpenLinks(false); + connect(pEdit, &WLibraryTextBrowser::anchorClicked, this, &RekordboxFeature::htmlLinkClicked); + pLibraryWidget->registerView("REKORDBOXHOME", pEdit); } void RekordboxFeature::htmlLinkClicked(const QUrl& link) { @@ -1330,10 +1331,12 @@ void RekordboxFeature::htmlLinkClicked(const QUrl& link) { } } -BaseSqlTableModel* RekordboxFeature::getPlaylistModelForPlaylist(const QString& playlist) { - RekordboxPlaylistModel* model = new RekordboxPlaylistModel(this, m_pLibrary->trackCollections(), m_trackSource); - model->setPlaylist(playlist); - return model; +std::unique_ptr +RekordboxFeature::createPlaylistModelForPlaylist(const QString& playlist) { + auto pModel = std::make_unique( + this, m_pLibrary->trackCollections(), m_trackSource); + pModel->setPlaylist(playlist); + return pModel; } QVariant RekordboxFeature::title() { @@ -1455,9 +1458,12 @@ void RekordboxFeature::activateChild(const QModelIndex& index) { } void RekordboxFeature::onRekordboxDevicesFound() { - QList foundDevices = m_devicesFuture.result(); - TreeItem* root = m_childModel.getRootItem(); + const QList result = m_devicesFuture.result(); + auto foundDevices = std::vector>(result.cbegin(), result.cend()); + + clearLastRightClickedIndex(); + TreeItem* root = m_childModel.getRootItem(); QSqlDatabase database = m_pTrackCollection->database(); if (foundDevices.size() == 0) { @@ -1484,10 +1490,8 @@ void RekordboxFeature::onRekordboxDevicesFound() { TreeItem* child = root->child(deviceIndex); bool removeChild = true; - for (int foundDeviceIndex = 0; foundDeviceIndex < foundDevices.size(); foundDeviceIndex++) { - TreeItem* deviceFound = foundDevices[foundDeviceIndex]; - - if (deviceFound->getLabel() == child->getLabel()) { + for (const auto& pDeviceFound : foundDevices) { + if (pDeviceFound->getLabel() == child->getLabel()) { removeChild = false; break; } @@ -1501,28 +1505,26 @@ void RekordboxFeature::onRekordboxDevicesFound() { } } - QList childrenToAdd; + std::vector> childrenToAdd; - for (int foundDeviceIndex = 0; foundDeviceIndex < foundDevices.size(); foundDeviceIndex++) { - TreeItem* deviceFound = foundDevices[foundDeviceIndex]; + for (auto&& pDeviceFound : foundDevices) { bool addNewChild = true; - for (int deviceIndex = 0; deviceIndex < root->childRows(); deviceIndex++) { TreeItem* child = root->child(deviceIndex); - if (deviceFound->getLabel() == child->getLabel()) { + if (pDeviceFound->getLabel() == child->getLabel()) { // This device already exists in the TreeModel, don't add or parse is again addNewChild = false; } } if (addNewChild) { - childrenToAdd << deviceFound; + childrenToAdd.push_back(std::move(pDeviceFound)); } } if (!childrenToAdd.empty()) { - m_childModel.insertTreeItemRows(childrenToAdd, 0); + m_childModel.insertTreeItemRows(std::move(childrenToAdd), 0); } } diff --git a/src/library/rekordbox/rekordboxfeature.h b/src/library/rekordbox/rekordboxfeature.h index c1388cef3f1..476bae1ec00 100644 --- a/src/library/rekordbox/rekordboxfeature.h +++ b/src/library/rekordbox/rekordboxfeature.h @@ -78,10 +78,11 @@ class RekordboxFeature : public BaseExternalLibraryFeature { private: QString formatRootViewHtml() const; - BaseSqlTableModel* getPlaylistModelForPlaylist(const QString& playlist) override; + std::unique_ptr createPlaylistModelForPlaylist( + const QString& playlist) override; TreeItemModel m_childModel; - RekordboxPlaylistModel* m_pRekordboxPlaylistModel; + parented_ptr m_pRekordboxPlaylistModel; QFutureWatcher> m_devicesFutureWatcher; QFuture> m_devicesFuture; diff --git a/src/library/rhythmbox/rhythmboxfeature.cpp b/src/library/rhythmbox/rhythmboxfeature.cpp index 948b0b0d653..159c7d5ff97 100644 --- a/src/library/rhythmbox/rhythmboxfeature.cpp +++ b/src/library/rhythmbox/rhythmboxfeature.cpp @@ -20,31 +20,35 @@ RhythmboxFeature::RhythmboxFeature(Library* pLibrary, UserSettingsPointer pConfi m_icon(":/images/library/ic_library_rhythmbox.svg") { QString tableName = "rhythmbox_library"; QString idColumn = "id"; - QStringList columns; - columns << "id" - << "artist" - << "title" - << "album" - << "year" - << "genre" - << "tracknumber" - << "location" - << "comment" - << "rating" - << "duration" - << "bitrate" - << "bpm"; - m_trackSource = QSharedPointer( - new BaseTrackCache(m_pTrackCollection, - tableName, idColumn, columns, false)); - QStringList searchColumns; - searchColumns << "artist" - << "album" - << "location" - << "comment" - << "title" - << "genre"; - m_trackSource->setSearchColumns(searchColumns); + QStringList columns = { + "id", + "artist", + "title", + "album", + "year", + "genre", + "tracknumber", + "location", + "comment", + "rating", + "duration", + "bitrate", + "bpm"}; + QStringList searchColumns = { + "artist", + "album", + "location", + "comment", + "title", + "genre"}; + + m_trackSource = QSharedPointer::create( + m_pTrackCollection, + tableName, + std::move(idColumn), + std::move(columns), + std::move(searchColumns), + false); m_pRhythmboxTrackModel = new BaseExternalTrackModel( this, pLibrary->trackCollections(), diff --git a/src/library/searchqueryparser.cpp b/src/library/searchqueryparser.cpp index f4a879aa929..577b09aae54 100644 --- a/src/library/searchqueryparser.cpp +++ b/src/library/searchqueryparser.cpp @@ -7,8 +7,11 @@ constexpr char kNegatePrefix[] = "-"; constexpr char kFuzzyPrefix[] = "~"; -SearchQueryParser::SearchQueryParser(TrackCollection* pTrackCollection) - : m_pTrackCollection(pTrackCollection) { +SearchQueryParser::SearchQueryParser(TrackCollection* pTrackCollection, QStringList searchColumns) + : m_pTrackCollection(pTrackCollection), + m_searchCrates(false) { + setSearchColumns(std::move(searchColumns)); + m_textFilters << "artist" << "album_artist" << "album" @@ -31,7 +34,6 @@ SearchQueryParser::SearchQueryParser(TrackCollection* pTrackCollection) << "dateadded" << "datetime_added" << "date_added"; - m_ignoredColumns << "crate"; m_fieldToSqlColumns["artist"] << "artist" << "album_artist"; m_fieldToSqlColumns["album_artist"] << "album_artist"; @@ -66,6 +68,19 @@ SearchQueryParser::SearchQueryParser(TrackCollection* pTrackCollection) SearchQueryParser::~SearchQueryParser() { } +void SearchQueryParser::setSearchColumns(QStringList searchColumns) { + m_queryColumns = std::move(searchColumns); + + // we need to create a filtered columns list that are handled differently + for (int i = 0; i < m_queryColumns.size(); ++i) { + if (m_queryColumns[i] == "crate") { + m_searchCrates = true; + m_queryColumns.removeAt(i); + break; + } + } +} + QString SearchQueryParser::getTextArgument(QString argument, QStringList* tokens) const { // If the argument is empty, assume the user placed a space after an @@ -116,20 +131,7 @@ QString SearchQueryParser::getTextArgument(QString argument, } void SearchQueryParser::parseTokens(QStringList tokens, - QStringList searchColumns, AndNode* pQuery) const { - // we need to create a filtered columns list that are handled differently - auto queryColumns = QStringList(); - queryColumns.reserve(searchColumns.count()); - - for (const auto& column: qAsConst(searchColumns)) { - if (m_ignoredColumns.contains(column)) { - continue; - } - queryColumns << column; - } - - while (tokens.size() > 0) { QString token = tokens.takeFirst().trimmed(); if (token.length() == 0) { @@ -227,18 +229,16 @@ void SearchQueryParser::parseTokens(QStringList tokens, // For untagged strings we search the track fields as well // as the crate names the track is in. This allows the user // to use crates like tags - if (searchColumns.contains("crate")) { - std::unique_ptr gNode = std::make_unique(); - + if (m_searchCrates) { + auto gNode = std::make_unique(); gNode->addNode(std::make_unique( &m_pTrackCollection->crates(), argument)); gNode->addNode(std::make_unique( - m_pTrackCollection->database(), queryColumns, argument)); - + m_pTrackCollection->database(), m_queryColumns, argument)); pNode = std::move(gNode); } else { pNode = std::make_unique( - m_pTrackCollection->database(), queryColumns, argument); + m_pTrackCollection->database(), m_queryColumns, argument); } } } @@ -251,9 +251,9 @@ void SearchQueryParser::parseTokens(QStringList tokens, } } -std::unique_ptr SearchQueryParser::parseQuery(const QString& query, - const QStringList& searchColumns, - const QString& extraFilter) const { +std::unique_ptr SearchQueryParser::parseQuery( + const QString& query, + const QString& extraFilter) const { auto pQuery(std::make_unique()); if (!extraFilter.isEmpty()) { @@ -262,7 +262,7 @@ std::unique_ptr SearchQueryParser::parseQuery(const QString& query, if (!query.isEmpty()) { QStringList tokens = query.split(" "); - parseTokens(tokens, searchColumns, pQuery.get()); + parseTokens(tokens, pQuery.get()); } return pQuery; diff --git a/src/library/searchqueryparser.h b/src/library/searchqueryparser.h index 9878149c0a7..848a750a802 100644 --- a/src/library/searchqueryparser.h +++ b/src/library/searchqueryparser.h @@ -10,29 +10,30 @@ class SearchQueryParser { public: - explicit SearchQueryParser(TrackCollection* pTrackCollection); + explicit SearchQueryParser(TrackCollection* pTrackCollection, QStringList searchColumns); virtual ~SearchQueryParser(); + void setSearchColumns(QStringList searchColumns); + std::unique_ptr parseQuery( const QString& query, - const QStringList& searchColumns, const QString& extraFilter) const; private: void parseTokens(QStringList tokens, - QStringList searchColumns, AndNode* pQuery) const; QString getTextArgument(QString argument, QStringList* tokens) const; TrackCollection* m_pTrackCollection; + QStringList m_queryColumns; + bool m_searchCrates; QStringList m_textFilters; QStringList m_numericFilters; QStringList m_specialFilters; - QStringList m_ignoredColumns; QStringList m_allFilters; QHash m_fieldToSqlColumns; diff --git a/src/library/serato/seratofeature.cpp b/src/library/serato/seratofeature.cpp index ec9c6d6dcd8..81768677fdf 100644 --- a/src/library/serato/seratofeature.cpp +++ b/src/library/serato/seratofeature.cpp @@ -669,6 +669,9 @@ QString parseDatabase(mixxx::DbConnectionPoolPtr dbConnectionPool, TreeItem* dat } // This function is executed in a separate thread other than the main thread +// The returned list owns the pointers, but we can't use a unique_ptr because +// the result is passed by a const reference inside QFuture and than copied +// to the main thread requiring a copy-able object. QList findSeratoDatabases() { QThread* thisThread = QThread::currentThread(); thisThread->setPriority(QThread::LowPriority); @@ -851,42 +854,40 @@ SeratoFeature::SeratoFeature( UserSettingsPointer pConfig) : BaseExternalLibraryFeature(pLibrary, pConfig), m_icon(":/images/library/ic_library_serato.svg") { - QStringList columns; - columns << LIBRARYTABLE_ID - << LIBRARYTABLE_TITLE - << LIBRARYTABLE_ARTIST - << LIBRARYTABLE_ALBUM - << LIBRARYTABLE_GENRE - << LIBRARYTABLE_COMMENT - << LIBRARYTABLE_GROUPING - << LIBRARYTABLE_YEAR - << LIBRARYTABLE_DURATION - << LIBRARYTABLE_BITRATE - << LIBRARYTABLE_SAMPLERATE - << LIBRARYTABLE_BPM - << LIBRARYTABLE_KEY - << LIBRARYTABLE_TRACKNUMBER - << TRACKLOCATIONSTABLE_LOCATION - << LIBRARYTABLE_BPM_LOCK; - - QStringList searchColumns; - searchColumns - << LIBRARYTABLE_ARTIST - << LIBRARYTABLE_TITLE - << LIBRARYTABLE_ALBUM - << LIBRARYTABLE_YEAR - << LIBRARYTABLE_GENRE - << LIBRARYTABLE_TRACKNUMBER - << TRACKLOCATIONSTABLE_LOCATION - << LIBRARYTABLE_COMMENT - << LIBRARYTABLE_DURATION - << LIBRARYTABLE_BITRATE - << LIBRARYTABLE_BPM - << LIBRARYTABLE_KEY; - - m_trackSource = QSharedPointer( - new BaseTrackCache(m_pTrackCollection, kSeratoLibraryTable, LIBRARYTABLE_ID, columns, false)); - m_trackSource->setSearchColumns(searchColumns); + QString idColumn = LIBRARYTABLE_ID; + QStringList columns = { + LIBRARYTABLE_ID, + LIBRARYTABLE_TITLE, + LIBRARYTABLE_ARTIST, + LIBRARYTABLE_ALBUM, + LIBRARYTABLE_GENRE, + LIBRARYTABLE_COMMENT, + LIBRARYTABLE_GROUPING, + LIBRARYTABLE_YEAR, + LIBRARYTABLE_DURATION, + LIBRARYTABLE_BITRATE, + LIBRARYTABLE_SAMPLERATE, + LIBRARYTABLE_BPM, + LIBRARYTABLE_KEY, + LIBRARYTABLE_TRACKNUMBER, + TRACKLOCATIONSTABLE_LOCATION, + LIBRARYTABLE_BPM_LOCK}; + QStringList searchColumns = { + LIBRARYTABLE_ARTIST, + LIBRARYTABLE_TITLE, + LIBRARYTABLE_ALBUM, + LIBRARYTABLE_GENRE, + TRACKLOCATIONSTABLE_LOCATION, + LIBRARYTABLE_COMMENT, + LIBRARYTABLE_GROUPING}; + + m_trackSource = QSharedPointer::create( + m_pTrackCollection, + kSeratoLibraryTable, + std::move(idColumn), + std::move(columns), + std::move(searchColumns), + false); m_pSeratoPlaylistModel = new SeratoPlaylistModel(this, pLibrary->trackCollections(), m_trackSource); m_title = tr("Serato"); @@ -950,10 +951,12 @@ void SeratoFeature::htmlLinkClicked(const QUrl& link) { } } -BaseSqlTableModel* SeratoFeature::getPlaylistModelForPlaylist(const QString& playlist) { - SeratoPlaylistModel* model = new SeratoPlaylistModel(this, m_pLibrary->trackCollections(), m_trackSource); - model->setPlaylist(playlist); - return model; +std::unique_ptr +SeratoFeature::createPlaylistModelForPlaylist(const QString& playlist) { + auto pModel = std::make_unique( + this, m_pLibrary->trackCollections(), m_trackSource); + pModel->setPlaylist(playlist); + return pModel; } QVariant SeratoFeature::title() { @@ -1059,9 +1062,12 @@ void SeratoFeature::activateChild(const QModelIndex& index) { } void SeratoFeature::onSeratoDatabasesFound() { - QList foundDatabases = m_databasesFuture.result(); - TreeItem* root = m_childModel.getRootItem(); + const QList result = m_databasesFuture.result(); + auto foundDatabases = std::vector>(result.cbegin(), result.cend()); + + clearLastRightClickedIndex(); + TreeItem* root = m_childModel.getRootItem(); QSqlDatabase database = m_pTrackCollection->database(); if (foundDatabases.size() == 0) { @@ -1076,44 +1082,37 @@ void SeratoFeature::onSeratoDatabasesFound() { TreeItem* child = root->child(databaseIndex); bool removeChild = true; - for (int foundDatabaseIndex = 0; foundDatabaseIndex < foundDatabases.size(); foundDatabaseIndex++) { - TreeItem* databaseFound = foundDatabases[foundDatabaseIndex]; - - if (databaseFound->getLabel() == child->getLabel()) { + for (const auto& pDatabaseFound : foundDatabases) { + if (pDatabaseFound->getLabel() == child->getLabel()) { removeChild = false; break; } } - if (removeChild) { // Device has since been unmounted, cleanup DB - m_childModel.removeRows(databaseIndex, 1); } } - QList childrenToAdd; + std::vector> childrenToAdd; - for (int foundDatabaseIndex = 0; foundDatabaseIndex < foundDatabases.size(); foundDatabaseIndex++) { - TreeItem* databaseFound = foundDatabases[foundDatabaseIndex]; + for (auto&& pDatabaseFound : foundDatabases) { bool addNewChild = true; - for (int databaseIndex = 0; databaseIndex < root->childRows(); databaseIndex++) { TreeItem* child = root->child(databaseIndex); - - if (databaseFound->getLabel() == child->getLabel()) { + if (pDatabaseFound->getLabel() == child->getLabel()) { // This database already exists in the TreeModel, don't add or parse is again addNewChild = false; + break; } } - if (addNewChild) { - childrenToAdd << databaseFound; + childrenToAdd.push_back(std::move(pDatabaseFound)); } } if (!childrenToAdd.empty()) { - m_childModel.insertTreeItemRows(childrenToAdd, 0); + m_childModel.insertTreeItemRows(std::move(childrenToAdd), 0); } } diff --git a/src/library/serato/seratofeature.h b/src/library/serato/seratofeature.h index 515add942e8..18ba2b00a3c 100644 --- a/src/library/serato/seratofeature.h +++ b/src/library/serato/seratofeature.h @@ -48,7 +48,8 @@ class SeratoFeature : public BaseExternalLibraryFeature { private: QString formatRootViewHtml() const; - BaseSqlTableModel* getPlaylistModelForPlaylist(const QString& playlist) override; + std::unique_ptr createPlaylistModelForPlaylist( + const QString& playlist) override; TreeItemModel m_childModel; SeratoPlaylistModel* m_pSeratoPlaylistModel; diff --git a/src/library/traktor/traktorfeature.cpp b/src/library/traktor/traktorfeature.cpp index 54807f7c011..22ce3c79bf5 100644 --- a/src/library/traktor/traktorfeature.cpp +++ b/src/library/traktor/traktorfeature.cpp @@ -69,32 +69,36 @@ TraktorFeature::TraktorFeature(Library* pLibrary, UserSettingsPointer pConfig) m_icon(":/images/library/ic_library_traktor.svg") { QString tableName = "traktor_library"; QString idColumn = "id"; - QStringList columns; - columns << "id" - << "artist" - << "title" - << "album" - << "year" - << "genre" - << "tracknumber" - << "location" - << "comment" - << "rating" - << "duration" - << "bitrate" - << "bpm" - << "key"; - m_trackSource = QSharedPointer( - new BaseTrackCache(pLibrary->trackCollections()->internalCollection(), tableName, idColumn, - columns, false)); - QStringList searchColumns; - searchColumns << "artist" - << "album" - << "location" - << "comment" - << "title" - << "genre"; - m_trackSource->setSearchColumns(searchColumns); + QStringList columns = { + "id", + "artist", + "title", + "album", + "year", + "genre", + "tracknumber", + "location", + "comment", + "rating", + "duration", + "bitrate", + "bpm", + "key"}; + QStringList searchColumns = { + "artist", + "album", + "location", + "comment", + "title", + "genre"}; + + m_trackSource = QSharedPointer::create( + pLibrary->trackCollections()->internalCollection(), + tableName, + std::move(idColumn), + std::move(columns), + std::move(searchColumns), + false); m_isActivated = false; m_pTraktorTableModel = new TraktorTrackModel(this, pLibrary->trackCollections(), m_trackSource); @@ -126,8 +130,10 @@ TraktorFeature::~TraktorFeature() { delete m_pTraktorPlaylistModel; } -BaseSqlTableModel* TraktorFeature::getPlaylistModelForPlaylist(const QString& playlist) { - TraktorPlaylistModel* pModel = new TraktorPlaylistModel(this, m_pLibrary->trackCollections(), m_trackSource); +std::unique_ptr +TraktorFeature::createPlaylistModelForPlaylist(const QString& playlist) { + auto pModel = std::make_unique( + this, m_pLibrary->trackCollections(), m_trackSource); pModel->setPlaylist(playlist); return pModel; } diff --git a/src/library/traktor/traktorfeature.h b/src/library/traktor/traktorfeature.h index b685eb11937..9ef67de2599 100644 --- a/src/library/traktor/traktorfeature.h +++ b/src/library/traktor/traktorfeature.h @@ -47,7 +47,8 @@ class TraktorFeature : public BaseExternalLibraryFeature { void onTrackCollectionLoaded(); private: - BaseSqlTableModel* getPlaylistModelForPlaylist(const QString& playlist) override; + std::unique_ptr createPlaylistModelForPlaylist( + const QString& playlist) override; TreeItem* importLibrary(const QString& file); // parses a track in the music collection void parseTrack(QXmlStreamReader &xml, QSqlQuery &query); diff --git a/src/library/treeitem.cpp b/src/library/treeitem.cpp index c7db2a6be4e..9861cea281e 100644 --- a/src/library/treeitem.cpp +++ b/src/library/treeitem.cpp @@ -56,16 +56,16 @@ TreeItem* TreeItem::child(int row) const { return m_children[row]; } -void TreeItem::insertChild(int row, TreeItem* pChild) { +void TreeItem::insertChild(int row, std::unique_ptr pChild) { DEBUG_ASSERT(pChild); DEBUG_ASSERT(!pChild->m_pParent); DEBUG_ASSERT(!pChild->m_pFeature || pChild->m_pFeature == m_pFeature); DEBUG_ASSERT(row >= 0); DEBUG_ASSERT(row <= m_children.size()); - m_children.insert(row, pChild); pChild->m_pParent = this; pChild->initFeatureRecursively(m_pFeature); + m_children.insert(row, pChild.release()); // transfer ownership } void TreeItem::initFeatureRecursively(LibraryFeature* pFeature) { @@ -82,34 +82,22 @@ void TreeItem::initFeatureRecursively(LibraryFeature* pFeature) { } } -TreeItem* TreeItem::appendChild( - std::unique_ptr pChild) { - insertChild(m_children.size(), pChild.get()); // transfer ownership - return pChild.release(); -} - TreeItem* TreeItem::appendChild( QString label, QVariant data) { auto pNewChild = std::make_unique( std::move(label), std::move(data)); - return appendChild(std::move(pNewChild)); -} - -void TreeItem::removeChild(int row) { - DEBUG_ASSERT(row >= 0); - DEBUG_ASSERT(row < m_children.size()); - delete m_children.takeAt(row); + TreeItem* pRet = pNewChild.get(); + insertChild(m_children.size(), std::move(pNewChild)); + return pRet; } -void TreeItem::insertChildren(int row, QList& children) { +void TreeItem::insertChildren(int row, std::vector>&& children) { DEBUG_ASSERT(row >= 0); DEBUG_ASSERT(row <= m_children.size()); - while (!children.isEmpty()) { - TreeItem* pChild = children.front(); - insertChild(row++, pChild); - children.pop_front(); + for (auto&& pChild : children) { + insertChild(row++, std::move(pChild)); } } diff --git a/src/library/treeitem.h b/src/library/treeitem.h index 92a8b958877..e7adbf44ecb 100644 --- a/src/library/treeitem.h +++ b/src/library/treeitem.h @@ -83,17 +83,13 @@ class TreeItem final { return m_children; } - // single child items - TreeItem* appendChild( - std::unique_ptr pChild); TreeItem* appendChild( QString label, QVariant data = QVariant()); - void removeChild(int row); // multiple child items // take ownership of children items - void insertChildren(int row, QList& children); + void insertChildren(int row, std::vector>&& children); void removeChildren(int row, int count); @@ -135,7 +131,7 @@ class TreeItem final { QString label = QString(), QVariant data = QVariant()); - void insertChild(int row, TreeItem* pChild); + void insertChild(int row, std::unique_ptr pChild); void initFeatureRecursively(LibraryFeature* pFeature); // The library feature is inherited from the parent. diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp index f8a869a01ae..7766a02cf9e 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -164,13 +164,13 @@ TreeItem* TreeItemModel::setRootItem(std::unique_ptr pRootItem) { /** * Before you can resize the data model dynamically by using 'insertRows' and 'removeRows' - * make sure you have initialized + * make sure you have initialized. */ void TreeItemModel::insertTreeItemRows( - QList& rows, + std::vector>&& rows, int position, const QModelIndex& parent) { - if (rows.isEmpty()) { + if (rows.empty()) { return; } @@ -178,8 +178,7 @@ void TreeItemModel::insertTreeItemRows( DEBUG_ASSERT(pParentItem != nullptr); beginInsertRows(parent, position, position + rows.size() - 1); - pParentItem->insertChildren(position, rows); - DEBUG_ASSERT(rows.isEmpty()); + pParentItem->insertChildren(position, std::move(rows)); endInsertRows(); } diff --git a/src/library/treeitemmodel.h b/src/library/treeitemmodel.h index 4c17604fa1f..212dbb8623c 100644 --- a/src/library/treeitemmodel.h +++ b/src/library/treeitemmodel.h @@ -30,7 +30,10 @@ class TreeItemModel : public QAbstractItemModel { int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; - void insertTreeItemRows(QList &rows, int position, const QModelIndex& parent = QModelIndex()); + void insertTreeItemRows( + std::vector>&&, + int position, + const QModelIndex& parent = QModelIndex()); TreeItem* setRootItem(std::unique_ptr pRootItem); TreeItem* getRootItem() const { diff --git a/src/test/searchqueryparsertest.cpp b/src/test/searchqueryparsertest.cpp index eabed3172a4..6a0335d54b8 100644 --- a/src/test/searchqueryparsertest.cpp +++ b/src/test/searchqueryparsertest.cpp @@ -21,7 +21,7 @@ TrackPointer newTestTrack(int sampleRate) { class SearchQueryParserTest : public LibraryTest { protected: SearchQueryParserTest() - : m_parser(internalCollection()) { + : m_parser(internalCollection(), QStringList()) { } virtual ~SearchQueryParserTest() { @@ -43,7 +43,7 @@ class SearchQueryParserTest : public LibraryTest { TEST_F(SearchQueryParserTest, EmptySearch) { auto pQuery( - m_parser.parseQuery("", QStringList(), "")); + m_parser.parseQuery("", QString())); // An empty query matches all tracks. TrackPointer pTrack(Track::newTemporary()); @@ -54,11 +54,9 @@ TEST_F(SearchQueryParserTest, EmptySearch) { } TEST_F(SearchQueryParserTest, OneTermOneColumn) { - QStringList searchColumns; - searchColumns << "artist"; - + m_parser.setSearchColumns({"artist"}); auto pQuery( - m_parser.parseQuery("asdf", searchColumns, "")); + m_parser.parseQuery("asdf", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setTitle("testASDFtest"); @@ -72,12 +70,9 @@ TEST_F(SearchQueryParserTest, OneTermOneColumn) { } TEST_F(SearchQueryParserTest, OneTermMultipleColumns) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("asdf", searchColumns, "")); + m_parser.parseQuery("asdf", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setTitle("testASDFtest"); @@ -91,12 +86,9 @@ TEST_F(SearchQueryParserTest, OneTermMultipleColumns) { } TEST_F(SearchQueryParserTest, OneTermMultipleColumnsNegation) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("-asdf", searchColumns, "")); + m_parser.parseQuery("-asdf", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setTitle("testASDFtest"); @@ -110,11 +102,9 @@ TEST_F(SearchQueryParserTest, OneTermMultipleColumnsNegation) { } TEST_F(SearchQueryParserTest, MultipleTermsOneColumn) { - QStringList searchColumns; - searchColumns << "artist"; - + m_parser.setSearchColumns({"artist"}); auto pQuery( - m_parser.parseQuery("asdf zxcv", searchColumns, "")); + m_parser.parseQuery("asdf zxcv", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setTitle("test zXcV test"); @@ -128,12 +118,9 @@ TEST_F(SearchQueryParserTest, MultipleTermsOneColumn) { } TEST_F(SearchQueryParserTest, MultipleTermsMultipleColumns) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("asdf zxcv", searchColumns, "")); + m_parser.parseQuery("asdf zxcv", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setTitle("asdf zxcv"); @@ -153,12 +140,9 @@ TEST_F(SearchQueryParserTest, MultipleTermsMultipleColumns) { } TEST_F(SearchQueryParserTest, MultipleTermsMultipleColumnsNegation) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("asdf -zxcv", searchColumns, "")); + m_parser.parseQuery("asdf -zxcv", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setTitle("asdf zxcv"); @@ -179,12 +163,9 @@ TEST_F(SearchQueryParserTest, MultipleTermsMultipleColumnsNegation) { } TEST_F(SearchQueryParserTest, TextFilter) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("comment:asdf", searchColumns, "")); + m_parser.parseQuery("comment:asdf", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf"); @@ -198,13 +179,10 @@ TEST_F(SearchQueryParserTest, TextFilter) { } TEST_F(SearchQueryParserTest, TextFilterEmpty) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); // An empty argument should pass everything. auto pQuery( - m_parser.parseQuery("comment:", searchColumns, "")); + m_parser.parseQuery("comment:", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setComment("test ASDF test"); @@ -216,12 +194,9 @@ TEST_F(SearchQueryParserTest, TextFilterEmpty) { } TEST_F(SearchQueryParserTest, TextFilterQuote) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("comment:\"asdf zxcv\"", searchColumns, "")); + m_parser.parseQuery("comment:\"asdf zxcv\"", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf zxcv"); @@ -235,12 +210,9 @@ TEST_F(SearchQueryParserTest, TextFilterQuote) { } TEST_F(SearchQueryParserTest, TextFilterQuote_NoEndQuoteTakesWholeQuery) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("comment:\"asdf zxcv qwer", searchColumns, "")); + m_parser.parseQuery("comment:\"asdf zxcv qwer", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf zxcv qwer"); @@ -254,12 +226,9 @@ TEST_F(SearchQueryParserTest, TextFilterQuote_NoEndQuoteTakesWholeQuery) { } TEST_F(SearchQueryParserTest, TextFilterAllowsSpace) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("comment: asdf", searchColumns, "")); + m_parser.parseQuery("comment: asdf", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf"); @@ -273,12 +242,9 @@ TEST_F(SearchQueryParserTest, TextFilterAllowsSpace) { } TEST_F(SearchQueryParserTest, TextFilterQuotes) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("comment:\"asdf ewe\"", searchColumns, "")); + m_parser.parseQuery("comment:\"asdf ewe\"", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf"); @@ -292,12 +258,10 @@ TEST_F(SearchQueryParserTest, TextFilterQuotes) { } TEST_F(SearchQueryParserTest, TextFilterDecoration) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - - auto pQuery( - m_parser.parseQuery(QString::fromUtf8("comment:\"asdf\xC2\xB0 ewe\""), searchColumns, "")); // with ˚ + m_parser.setSearchColumns({"artist", "album"}); + auto pQuery(m_parser.parseQuery( + QString::fromUtf8("comment:\"asdf\xC2\xB0 ewe\""), + QString())); // with ˚ TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf"); @@ -316,12 +280,9 @@ TEST_F(SearchQueryParserTest, TextFilterDecoration) { } TEST_F(SearchQueryParserTest, TextFilterTrailingSpace) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("comment:\"asdf \"", searchColumns, "")); + m_parser.parseQuery("comment:\"asdf \"", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf"); @@ -335,7 +296,7 @@ TEST_F(SearchQueryParserTest, TextFilterTrailingSpace) { // We allow to search for two consequitve spaces auto pQuery2( - m_parser.parseQuery("comment:\" \"", searchColumns, "")); + m_parser.parseQuery("comment:\" \"", QString())); EXPECT_FALSE(pQuery2->match(pTrack)); @@ -345,12 +306,9 @@ TEST_F(SearchQueryParserTest, TextFilterTrailingSpace) { } TEST_F(SearchQueryParserTest, TextFilterNegation) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("-comment: asdf", searchColumns, "")); + m_parser.parseQuery("-comment: asdf", QString())); TrackPointer pTrack(Track::newTemporary()); pTrack->setArtist("asdf"); @@ -364,12 +322,9 @@ TEST_F(SearchQueryParserTest, TextFilterNegation) { } TEST_F(SearchQueryParserTest, NumericFilter) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("bpm:127.12", searchColumns, "")); + m_parser.parseQuery("bpm:127.12", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->trySetBpm(127); @@ -405,12 +360,9 @@ TEST_F(SearchQueryParserTest, NumericFilterYear) { } TEST_F(SearchQueryParserTest, NumericFilterEmpty) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("bpm:", searchColumns, "")); + m_parser.parseQuery("bpm:", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->trySetBpm(127); @@ -422,12 +374,9 @@ TEST_F(SearchQueryParserTest, NumericFilterEmpty) { } TEST_F(SearchQueryParserTest, NumericFilterNegation) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("-bpm:127.12", searchColumns, "")); + m_parser.parseQuery("-bpm:127.12", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->trySetBpm(127); @@ -441,12 +390,9 @@ TEST_F(SearchQueryParserTest, NumericFilterNegation) { } TEST_F(SearchQueryParserTest, NumericFilterAllowsSpace) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("bpm: 127.12", searchColumns, "")); + m_parser.parseQuery("bpm: 127.12", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->trySetBpm(127); @@ -460,12 +406,9 @@ TEST_F(SearchQueryParserTest, NumericFilterAllowsSpace) { } TEST_F(SearchQueryParserTest, NumericFilterOperators) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("bpm:>127.12", searchColumns, "")); + m_parser.parseQuery("bpm:>127.12", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->trySetBpm(127.12); @@ -476,8 +419,7 @@ TEST_F(SearchQueryParserTest, NumericFilterOperators) { qPrintable(QString("bpm > 127.12")), qPrintable(pQuery->toSql())); - - pQuery = m_parser.parseQuery("bpm:>=127.12", searchColumns, ""); + pQuery = m_parser.parseQuery("bpm:>=127.12", QString()); pTrack->trySetBpm(127.11); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->trySetBpm(127.12); @@ -486,7 +428,7 @@ TEST_F(SearchQueryParserTest, NumericFilterOperators) { qPrintable(QString("bpm >= 127.12")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("bpm:<127.12", searchColumns, ""); + pQuery = m_parser.parseQuery("bpm:<127.12", QString()); pTrack->trySetBpm(127.12); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->trySetBpm(127.11); @@ -495,7 +437,7 @@ TEST_F(SearchQueryParserTest, NumericFilterOperators) { qPrintable(QString("bpm < 127.12")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("bpm:<=127.12", searchColumns, ""); + pQuery = m_parser.parseQuery("bpm:<=127.12", QString()); pTrack->trySetBpm(127.13); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->trySetBpm(127.12); @@ -506,12 +448,9 @@ TEST_F(SearchQueryParserTest, NumericFilterOperators) { } TEST_F(SearchQueryParserTest, NumericRangeFilter) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("bpm:127.12-129", searchColumns, "")); + m_parser.parseQuery("bpm:127.12-129", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->trySetBpm(125); @@ -527,13 +466,9 @@ TEST_F(SearchQueryParserTest, NumericRangeFilter) { } TEST_F(SearchQueryParserTest, MultipleFilters) { - QStringList searchColumns; - searchColumns << "artist" - << "title"; - + m_parser.setSearchColumns({"artist", "title"}); auto pQuery( - m_parser.parseQuery("bpm:127.12-129 artist:\"com truise\" Colorvision", - searchColumns, "")); + m_parser.parseQuery("bpm:127.12-129 artist:\"com truise\" Colorvision", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->trySetBpm(128); @@ -552,11 +487,9 @@ TEST_F(SearchQueryParserTest, MultipleFilters) { } TEST_F(SearchQueryParserTest, ExtraFilterAppended) { - QStringList searchColumns; - searchColumns << "artist"; - + m_parser.setSearchColumns({"artist"}); auto pQuery( - m_parser.parseQuery("asdf", searchColumns, "1 > 2")); + m_parser.parseQuery("asdf", "1 > 2")); TrackPointer pTrack = newTestTrack(44100); pTrack->setArtist("zxcv"); @@ -570,12 +503,9 @@ TEST_F(SearchQueryParserTest, ExtraFilterAppended) { } TEST_F(SearchQueryParserTest, HumanReadableDurationSearch) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("duration:1:30", searchColumns, "")); + m_parser.parseQuery("duration:1:30", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->setDuration(91); @@ -587,7 +517,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearch) { qPrintable(QString("duration = 90")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:1m30s", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:1m30s", QString()); pTrack->setDuration(91); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(90); @@ -597,7 +527,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearch) { qPrintable(QString("duration = 90")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:90", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:90", QString()); pTrack->setDuration(91); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(90); @@ -609,12 +539,9 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearch) { } TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("duration:>1:30", searchColumns, "")); + m_parser.parseQuery("duration:>1:30", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->setDuration(89); @@ -625,7 +552,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration > 90")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:>=90", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:>=90", QString()); pTrack->setDuration(89); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(90); @@ -634,7 +561,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration >= 90")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:>=1:30", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:>=1:30", QString()); pTrack->setDuration(89); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(90); @@ -643,7 +570,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration >= 90")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:<2:30", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:<2:30", QString()); pTrack->setDuration(151); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(89); @@ -652,7 +579,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration < 150")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:<=2:30", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:<=2:30", QString()); pTrack->setDuration(191); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(150); @@ -661,7 +588,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration <= 150")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:<=150", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:<=150", QString()); pTrack->setDuration(191); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(150); @@ -670,7 +597,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration <= 150")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:<=2m30s", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:<=2m30s", QString()); pTrack->setDuration(191); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(150); @@ -679,7 +606,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration <= 150")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:<=2m", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:<=2m", QString()); pTrack->setDuration(191); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(110); @@ -688,7 +615,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration <= 120")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:<=2:", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:<=2:", QString()); pTrack->setDuration(191); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(110); @@ -697,7 +624,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { qPrintable(QString("duration <= 120")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:>=1:3", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:>=1:3", QString()); pTrack->setDuration(60); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(150); @@ -708,12 +635,9 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { } TEST_F(SearchQueryParserTest, HumanReadableDurationSearchwithRangeFilter) { - QStringList searchColumns; - searchColumns << "artist" - << "album"; - + m_parser.setSearchColumns({"artist", "album"}); auto pQuery( - m_parser.parseQuery("duration:2:30-3:20", searchColumns, "")); + m_parser.parseQuery("duration:2:30-3:20", QString())); TrackPointer pTrack = newTestTrack(44100); pTrack->setDuration(80); @@ -727,7 +651,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchwithRangeFilter) { qPrintable(QString("duration BETWEEN 150 AND 200")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:2:30-200", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:2:30-200", QString()); pTrack->setDuration(80); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(150); @@ -739,7 +663,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchwithRangeFilter) { qPrintable(QString("duration BETWEEN 150 AND 200")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:150-200", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:150-200", QString()); pTrack->setDuration(80); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(150); @@ -751,7 +675,7 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchwithRangeFilter) { qPrintable(QString("duration BETWEEN 150 AND 200")), qPrintable(pQuery->toSql())); - pQuery = m_parser.parseQuery("duration:2m30s-3m20s", searchColumns, ""); + pQuery = m_parser.parseQuery("duration:2m30s-3m20s", QString()); pTrack->setDuration(80); EXPECT_FALSE(pQuery->match(pTrack)); pTrack->setDuration(150); @@ -769,8 +693,7 @@ TEST_F(SearchQueryParserTest, CrateFilter) { QString searchTerm = "test"; // Parse the user query - auto pQuery(m_parser.parseQuery(QString("crate: %1").arg(searchTerm), - QStringList(), "")); + auto pQuery(m_parser.parseQuery(QString("crate: %1").arg(searchTerm), QString())); // locations for test tracks const QString kTrackALocationTest(QDir::currentPath() % @@ -807,14 +730,9 @@ TEST_F(SearchQueryParserTest, ShortCrateFilter) { // User's search term QString crateName = "somecrate"; QString searchTerm = "ecrat"; - QStringList searchColumns; - searchColumns << "crate" - << "artist" - << "comment"; - + m_parser.setSearchColumns({"crate", "artist", "comment"}); // Parse the user query - auto pQuery(m_parser.parseQuery(QString("%1").arg(searchTerm), - searchColumns, "")); + auto pQuery(m_parser.parseQuery(QString("%1").arg(searchTerm), QString())); // locations for test tracks const QString kTrackALocationTest(QDir::currentPath() % @@ -852,7 +770,7 @@ TEST_F(SearchQueryParserTest, ShortCrateFilter) { TEST_F(SearchQueryParserTest, CrateFilterEmpty) { // Empty should match everything - auto pQuery(m_parser.parseQuery(QString("crate: "), QStringList(), "")); + auto pQuery(m_parser.parseQuery(QString("crate: "), QString())); TrackPointer pTrackA(Track::newTemporary()); @@ -869,8 +787,7 @@ TEST_F(SearchQueryParserTest, CrateFilterQuote){ QString searchTerm = "test with whitespace"; // Parse the user query - auto pQuery(m_parser.parseQuery(QString("crate: \"%1\"").arg(searchTerm), - QStringList(), "")); + auto pQuery(m_parser.parseQuery(QString("crate: \"%1\"").arg(searchTerm), QString())); // locations for test tracks const QString kTrackALocationTest(QDir::currentPath() % @@ -913,8 +830,7 @@ TEST_F(SearchQueryParserTest, CrateFilterWithOther){ QString searchTerm = "test"; // Parse the user query - auto pQuery(m_parser.parseQuery(QString("crate: %1 artist: asdf").arg(searchTerm), - QStringList(), "")); + auto pQuery(m_parser.parseQuery(QString("crate: %1 artist: asdf").arg(searchTerm), QString())); // locations for test tracks const QString kTrackALocationTest(QDir::currentPath() % @@ -958,8 +874,9 @@ TEST_F(SearchQueryParserTest, CrateFilterWithCrateFilterAndNegation){ QString searchTermB = "testB"; // Parse the user query - auto pQueryA(m_parser.parseQuery(QString("crate: %1 crate: %2").arg(searchTermA, searchTermB), - QStringList(), "")); + auto pQueryA(m_parser.parseQuery( + QString("crate: %1 crate: %2").arg(searchTermA, searchTermB), + QString())); // locations for test tracks const QString kTrackALocationTest(QDir::currentPath() % @@ -1002,8 +919,9 @@ TEST_F(SearchQueryParserTest, CrateFilterWithCrateFilterAndNegation){ qPrintable(pQueryA->toSql())); // parse again to test negation - auto pQueryB(m_parser.parseQuery(QString("crate: %1 -crate: %2").arg(searchTermA, searchTermB), - QStringList(), "")); + auto pQueryB(m_parser.parseQuery( + QString("crate: %1 -crate: %2").arg(searchTermA, searchTermB), + QString())); EXPECT_FALSE(pQueryB->match(pTrackA)); EXPECT_TRUE(pQueryB->match(pTrackB));