From da22a46777d35566ce7863453ae4fe3c400eb04b Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Sat, 7 Sep 2019 14:08:17 +0200 Subject: Add extension points for synchronization of external libraries --- src/library/library.cpp | 138 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 128 insertions(+), 10 deletions(-) (limited to 'src/library/library.cpp') diff --git a/src/library/library.cpp b/src/library/library.cpp index d95416941d..307a9fa072 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -40,6 +40,7 @@ #include "controllers/keyboard/keyboardeventfilter.h" +#include "library/externaltrackcollection.h" namespace { @@ -91,17 +92,20 @@ Library::Library( kLogger.info() << "Connecting database"; m_pTrackCollection->connectDatabase(dbConnection); +#if defined(__AOIDE__) + m_externalTrackCollections += new mixxx::aoide::TrackCollection(pConfig, m_pTrackCollection, this); +#endif + qRegisterMetaType("Library::RemovalType"); m_pKeyNotation.reset(new ControlObject(ConfigKey(kConfigGroup, "key_notation"))); - connect(&m_scanner, SIGNAL(scanStarted()), - this, SIGNAL(scanStarted())); - connect(&m_scanner, SIGNAL(scanFinished()), - this, SIGNAL(scanFinished())); - // Refresh the library models when the library (re)scan is finished. - connect(&m_scanner, SIGNAL(scanFinished()), - this, SLOT(slotRefreshLibraryModels())); + connect(&m_scanner, &LibraryScanner::scanStarted, this, &Library::scanStarted); + connect(&m_scanner, &LibraryScanner::scanFinished, this, &Library::scanFinished); + connect(&m_scanner, &LibraryScanner::scanFinished, this, &Library::slotRefreshLibraryModels); + connect(&m_scanner, &LibraryScanner::trackAdded, this, &Library::slotScanTrackAdded); + connect(&m_scanner, &LibraryScanner::tracksChanged, this, &Library::slotScanTracksUpdated); + connect(&m_scanner, &LibraryScanner::tracksReplaced, this, &Library::slotScanTracksReplaced); // TODO(rryan) -- turn this construction / adding of features into a static // method or something -- CreateDefaultLibrary @@ -161,6 +165,10 @@ Library::Library( addFeature(new TraktorFeature(this, m_pTrackCollection)); } + for (const auto& externalTrackCollection : m_externalTrackCollections) { + addFeature(externalTrackCollection->newLibraryFeature(this)); + } + // On startup we need to check if all of the user's library folders are // accessible to us. If the user is using a database from <1.12.0 with // sandboxing then we will need them to give us permission. @@ -200,6 +208,10 @@ Library::~Library() { delete m_pLibraryControl; + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->shutdown(); + } + kLogger.info() << "Disconnecting database"; m_pTrackCollection->disconnectDatabase(); @@ -245,7 +257,12 @@ void Library::bindSidebarWidget(WLibrarySidebar* pSidebarWidget) { void Library::bindWidget(WLibrary* pLibraryWidget, KeyboardEventFilter* pKeyboard) { WTrackTableView* pTrackTableView = - new WTrackTableView(pLibraryWidget, m_pConfig, m_pTrackCollection); + new WTrackTableView( + pLibraryWidget, + m_pConfig, + m_pTrackCollection, + true, + m_externalTrackCollections); pTrackTableView->installEventFilter(pKeyboard); connect(this, SIGNAL(showTrackModel(QAbstractItemModel*)), pTrackTableView, SLOT(loadTrackModel(QAbstractItemModel*))); @@ -410,7 +427,7 @@ void Library::slotRequestRemoveDir(QString dir, RemovalType removalType) { break; case Library::PurgeTracks: // The user requested that we purge all metadata. - m_pTrackCollection->purgeTracks(dir); + purgeAllTracks(dir); break; case Library::LeaveTracksUnchanged: default: @@ -438,7 +455,7 @@ void Library::slotRequestRemoveDir(QString dir, RemovalType removalType) { } void Library::slotRequestRelocateDir(QString oldDir, QString newDir) { - m_pTrackCollection->relocateDirectory(oldDir, newDir); + relocateDirectory(oldDir, newDir); // also update the config file if necessary so that downgrading is still // possible @@ -482,8 +499,109 @@ void Library::saveCachedTrack(Track* pTrack) noexcept { // concurrently. m_pTrackCollection->exportTrackMetadata(pTrack); + if (!m_externalTrackCollections.isEmpty()) { + if (pTrack->getId().isValid()) { + if (pTrack->isDirty()) { + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->saveTrack(*pTrack, ExternalTrackCollection::ChangeHint::Modified); + } + } + } else { + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->purgeTracks(QStringList{pTrack->getLocation()}); + } + } + } + + // Updating the track in the local database might reset the + // dirty flag and other properties of the track still exists. + // Therefore this must be done AFTER external libraries got + // their chance to update the track! + // The track must be saved while the cache is locked to // prevent that a new track is created from the outdated // metadata that is is the database before saving is finished. m_pTrackCollection->saveTrack(pTrack); } + +void Library::relocateDirectory(QString oldDir, QString newDir) { + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->relocateDirectory(oldDir, newDir); + } + m_pTrackCollection->relocateDirectory(oldDir, newDir); +} + +void Library::purgeTracks(const QList& trackIds) { + if (trackIds.isEmpty()) { + return; + } + if (!m_externalTrackCollections.isEmpty()) { + const auto trackLocations = + m_pTrackCollection->getTrackDAO().getTrackLocations(trackIds); + DEBUG_ASSERT(trackLocations.size() <= trackIds.size()); + VERIFY_OR_DEBUG_ASSERT(trackLocations.size() == trackIds.size()) { + kLogger.warning() + << "Purging only" + << trackLocations.size() + << "of" + << trackIds.size() + << "tracks from external libraries"; + } + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->purgeTracks(trackLocations); + } + } + m_pTrackCollection->purgeTracks(trackIds); +} + +void Library::purgeAllTracks(const QDir& rootDir) { + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->purgeAllTracks(rootDir); + } + m_pTrackCollection->purgeAllTracks(rootDir); +} + +void Library::slotScanTrackAdded(TrackPointer pTrack) { + DEBUG_ASSERT(pTrack); + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->saveTrack(*pTrack, ExternalTrackCollection::ChangeHint::Added); + } + // Already added to m_pTrackCollection +} + +void Library::slotScanTracksUpdated(QSet updatedTrackIds) { + if (updatedTrackIds.isEmpty()) { + return; + } + if (!m_externalTrackCollections.isEmpty()) { + QList trackRefs; + trackRefs.reserve(updatedTrackIds.size()); + for (const auto& trackId : updatedTrackIds) { + auto trackLocation = m_pTrackCollection->getTrackDAO().getTrackLocation(trackId); + if (!trackLocation.isEmpty()) { + trackRefs += TrackRef::fromFileInfo(trackLocation, trackId); + } + } + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->updateTracks(trackRefs); + } + } + // Already updated in m_pTrackCollection +} + +void Library::slotScanTracksReplaced(QList> replacedTracks) { + if (!m_externalTrackCollections.isEmpty()) { + QList duplicateTracks; + duplicateTracks.reserve(replacedTracks.size()); + for (const auto& replacedTrack : replacedTracks) { + ExternalTrackCollection::DuplicateTrack duplicateTrack; + duplicateTrack.removed = replacedTrack.first; + duplicateTrack.replacedBy = replacedTrack.second; + duplicateTracks += duplicateTrack; + } + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->deduplicateTracks(duplicateTracks); + } + } + // Already replaced in m_pTrackCollection +} -- cgit v1.2.3 From 2831c4ef7e60a423b57d7655227747044843fd5f Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Thu, 19 Sep 2019 13:35:32 +0200 Subject: Move transaction boundaries from DirectoryDAO into TrackCollection --- src/library/library.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/library/library.cpp') diff --git a/src/library/library.cpp b/src/library/library.cpp index 307a9fa072..d64a1f7bd8 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -405,7 +405,7 @@ void Library::slotRequestAddDir(QString dir) { QDir directory(dir); Sandbox::createSecurityToken(directory); - if (!m_pTrackCollection->getDirectoryDAO().addDirectory(dir)) { + if (!m_pTrackCollection->addDirectory(dir)) { QMessageBox::information(0, tr("Add Directory to Library"), tr("Could not add the directory to your library. Either this " "directory is already in your library or you are currently " -- cgit v1.2.3 From fed23f188357f1858d1c591526d9a747531904d7 Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Sat, 21 Sep 2019 00:19:32 +0200 Subject: Replace += with append() and insert() --- src/library/library.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/library/library.cpp') diff --git a/src/library/library.cpp b/src/library/library.cpp index d64a1f7bd8..d5309bf37b 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -579,7 +579,7 @@ void Library::slotScanTracksUpdated(QSet updatedTrackIds) { for (const auto& trackId : updatedTrackIds) { auto trackLocation = m_pTrackCollection->getTrackDAO().getTrackLocation(trackId); if (!trackLocation.isEmpty()) { - trackRefs += TrackRef::fromFileInfo(trackLocation, trackId); + trackRefs.append(TrackRef::fromFileInfo(trackLocation, trackId)); } } for (const auto& externalTrackCollection : m_externalTrackCollections) { @@ -597,7 +597,7 @@ void Library::slotScanTracksReplaced(QList> replacedTr ExternalTrackCollection::DuplicateTrack duplicateTrack; duplicateTrack.removed = replacedTrack.first; duplicateTrack.replacedBy = replacedTrack.second; - duplicateTracks += duplicateTrack; + duplicateTracks.append(duplicateTrack); } for (const auto& externalTrackCollection : m_externalTrackCollections) { externalTrackCollection->deduplicateTracks(duplicateTracks); -- cgit v1.2.3 From 40564ba5ca70795114436d92701821dcce731ce3 Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Sat, 21 Sep 2019 00:55:32 +0200 Subject: Clarify execution order of operations --- src/library/library.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'src/library/library.cpp') diff --git a/src/library/library.cpp b/src/library/library.cpp index d5309bf37b..9c11f00d2f 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -499,28 +499,36 @@ void Library::saveCachedTrack(Track* pTrack) noexcept { // concurrently. m_pTrackCollection->exportTrackMetadata(pTrack); + // The track must be saved in external track collections before + // updating the internal database. Updating the track in the + // internal track collection will reset its state and modify some + // properties, e.g. clear the dirty flag. The dirty flag is used + // to decide if the track actually needs to be sent to external + // collections. if (!m_externalTrackCollections.isEmpty()) { if (pTrack->getId().isValid()) { + // Track still exists in the internal collection/database if (pTrack->isDirty()) { for (const auto& externalTrackCollection : m_externalTrackCollections) { - externalTrackCollection->saveTrack(*pTrack, ExternalTrackCollection::ChangeHint::Modified); + externalTrackCollection->saveTrack( + *pTrack, + ExternalTrackCollection::ChangeHint::Modified); } } } else { + // Track has been deleted from the local internal collection/database + // while it was cached in-memory for (const auto& externalTrackCollection : m_externalTrackCollections) { - externalTrackCollection->purgeTracks(QStringList{pTrack->getLocation()}); + externalTrackCollection->purgeTracks( + QStringList{pTrack->getLocation()}); } } } - // Updating the track in the local database might reset the - // dirty flag and other properties of the track still exists. - // Therefore this must be done AFTER external libraries got - // their chance to update the track! - - // The track must be saved while the cache is locked to - // prevent that a new track is created from the outdated - // metadata that is is the database before saving is finished. + // Finally update the track in the local database and reset its + // state. This operation must be executed synchronously while + // the cache is locked to prevent that a new track is created from + // outdated metadata in the database before saving finished. m_pTrackCollection->saveTrack(pTrack); } -- cgit v1.2.3 From 11ecb27ee69fa91f09d11d9ea8f1697c6c150876 Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Sat, 21 Sep 2019 00:55:51 +0200 Subject: Use early exit if possible --- src/library/library.cpp | 54 +++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'src/library/library.cpp') diff --git a/src/library/library.cpp b/src/library/library.cpp index 9c11f00d2f..bc27606f8f 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -571,45 +571,47 @@ void Library::purgeAllTracks(const QDir& rootDir) { void Library::slotScanTrackAdded(TrackPointer pTrack) { DEBUG_ASSERT(pTrack); + // Already added to m_pTrackCollection for (const auto& externalTrackCollection : m_externalTrackCollections) { externalTrackCollection->saveTrack(*pTrack, ExternalTrackCollection::ChangeHint::Added); } - // Already added to m_pTrackCollection } void Library::slotScanTracksUpdated(QSet updatedTrackIds) { + // Already updated in m_pTrackCollection if (updatedTrackIds.isEmpty()) { return; } - if (!m_externalTrackCollections.isEmpty()) { - QList trackRefs; - trackRefs.reserve(updatedTrackIds.size()); - for (const auto& trackId : updatedTrackIds) { - auto trackLocation = m_pTrackCollection->getTrackDAO().getTrackLocation(trackId); - if (!trackLocation.isEmpty()) { - trackRefs.append(TrackRef::fromFileInfo(trackLocation, trackId)); - } - } - for (const auto& externalTrackCollection : m_externalTrackCollections) { - externalTrackCollection->updateTracks(trackRefs); + if (m_externalTrackCollections.isEmpty()) { + return; + } + QList trackRefs; + trackRefs.reserve(updatedTrackIds.size()); + for (const auto& trackId : updatedTrackIds) { + auto trackLocation = m_pTrackCollection->getTrackDAO().getTrackLocation(trackId); + if (!trackLocation.isEmpty()) { + trackRefs.append(TrackRef::fromFileInfo(trackLocation, trackId)); } } - // Already updated in m_pTrackCollection + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->updateTracks(trackRefs); + } } void Library::slotScanTracksReplaced(QList> replacedTracks) { - if (!m_externalTrackCollections.isEmpty()) { - QList duplicateTracks; - duplicateTracks.reserve(replacedTracks.size()); - for (const auto& replacedTrack : replacedTracks) { - ExternalTrackCollection::DuplicateTrack duplicateTrack; - duplicateTrack.removed = replacedTrack.first; - duplicateTrack.replacedBy = replacedTrack.second; - duplicateTracks.append(duplicateTrack); - } - for (const auto& externalTrackCollection : m_externalTrackCollections) { - externalTrackCollection->deduplicateTracks(duplicateTracks); - } - } // Already replaced in m_pTrackCollection + if (m_externalTrackCollections.isEmpty()) { + return; + } + QList duplicateTracks; + duplicateTracks.reserve(replacedTracks.size()); + for (const auto& replacedTrack : replacedTracks) { + ExternalTrackCollection::DuplicateTrack duplicateTrack; + duplicateTrack.removed = replacedTrack.first; + duplicateTrack.replacedBy = replacedTrack.second; + duplicateTracks.append(duplicateTrack); + } + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->deduplicateTracks(duplicateTracks); + } } -- cgit v1.2.3 From 9f3b4424b81f29bdaf8371796d3dd11bb42f84bc Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Sat, 21 Sep 2019 12:42:47 +0200 Subject: Update external track collections after internal database --- src/library/library.cpp | 202 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 158 insertions(+), 44 deletions(-) (limited to 'src/library/library.cpp') diff --git a/src/library/library.cpp b/src/library/library.cpp index bc27606f8f..2c04fc0fb9 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -166,7 +166,18 @@ Library::Library( } for (const auto& externalTrackCollection : m_externalTrackCollections) { - addFeature(externalTrackCollection->newLibraryFeature(this)); + auto feature = externalTrackCollection->newLibraryFeature(this); + if (feature) { + kLogger.info() + << "Adding library feature for" + << externalTrackCollection->name(); + addFeature(feature); + } else { + kLogger.info() + << "Library feature for" + << externalTrackCollection->name() + << "is not available"; + } } // On startup we need to check if all of the user's library folders are @@ -499,79 +510,158 @@ void Library::saveCachedTrack(Track* pTrack) noexcept { // concurrently. m_pTrackCollection->exportTrackMetadata(pTrack); - // The track must be saved in external track collections before - // updating the internal database. Updating the track in the - // internal track collection will reset its state and modify some - // properties, e.g. clear the dirty flag. The dirty flag is used - // to decide if the track actually needs to be sent to external - // collections. - if (!m_externalTrackCollections.isEmpty()) { - if (pTrack->getId().isValid()) { - // Track still exists in the internal collection/database - if (pTrack->isDirty()) { - for (const auto& externalTrackCollection : m_externalTrackCollections) { - externalTrackCollection->saveTrack( - *pTrack, - ExternalTrackCollection::ChangeHint::Modified); - } - } - } else { - // Track has been deleted from the local internal collection/database - // while it was cached in-memory + // Th dirty flag is reset while saving the track in the internal + // collection! + const bool trackDirty = pTrack->isDirty(); + + // This operation must be executed synchronously while the cache is + // locked to prevent that a new track is created from outdated + // metadata in the database before saving finished. + kLogger.debug() + << "Saving cached track" + << pTrack->getLocation() + << "in internal collection"; + m_pTrackCollection->saveTrack(pTrack); + + if (m_externalTrackCollections.isEmpty()) { + return; + } + if (pTrack->getId().isValid()) { + // Track still exists in the internal collection/database + if (trackDirty) { + kLogger.debug() + << "Saving modified track" + << pTrack->getLocation() + << "in" + << m_externalTrackCollections.size() + << "external collection(s)"; for (const auto& externalTrackCollection : m_externalTrackCollections) { - externalTrackCollection->purgeTracks( - QStringList{pTrack->getLocation()}); + externalTrackCollection->saveTrack( + *pTrack, + ExternalTrackCollection::ChangeHint::Modified); } } + } else { + // Track has been deleted from the local internal collection/database + // while it was cached in-memory + kLogger.debug() + << "Purging deleted track" + << pTrack->getLocation() + << "from" + << m_externalTrackCollections.size() + << "external collection(s)"; + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->purgeTracks( + QStringList{pTrack->getLocation()}); + } } - - // Finally update the track in the local database and reset its - // state. This operation must be executed synchronously while - // the cache is locked to prevent that a new track is created from - // outdated metadata in the database before saving finished. - m_pTrackCollection->saveTrack(pTrack); } void Library::relocateDirectory(QString oldDir, QString newDir) { + kLogger.debug() + << "Relocating directory in internal track collection:" + << oldDir + << "->" + << newDir; + // TODO(XXX): Add error handling in TrackCollection::relocateDirectory() + m_pTrackCollection->relocateDirectory(oldDir, newDir); + if (m_externalTrackCollections.isEmpty()) { + return; + } + kLogger.debug() + << "Relocating directory in" + << m_externalTrackCollections.size() + << "external track collection(s):" + << oldDir + << "->" + << newDir; for (const auto& externalTrackCollection : m_externalTrackCollections) { externalTrackCollection->relocateDirectory(oldDir, newDir); } - m_pTrackCollection->relocateDirectory(oldDir, newDir); } void Library::purgeTracks(const QList& trackIds) { if (trackIds.isEmpty()) { return; } + // Collect the corresponding track locations BEFORE purging the + // tracks from the internal collection! + QList trackLocations; if (!m_externalTrackCollections.isEmpty()) { - const auto trackLocations = + trackLocations = m_pTrackCollection->getTrackDAO().getTrackLocations(trackIds); - DEBUG_ASSERT(trackLocations.size() <= trackIds.size()); - VERIFY_OR_DEBUG_ASSERT(trackLocations.size() == trackIds.size()) { - kLogger.warning() - << "Purging only" - << trackLocations.size() - << "of" - << trackIds.size() - << "tracks from external libraries"; - } - for (const auto& externalTrackCollection : m_externalTrackCollections) { - externalTrackCollection->purgeTracks(trackLocations); - } } - m_pTrackCollection->purgeTracks(trackIds); + DEBUG_ASSERT(trackLocations.size() <= trackIds.size()); + kLogger.debug() + << "Purging" + << trackIds.size() + << "tracks from internal collection"; + if (!m_pTrackCollection->purgeTracks(trackIds)) { + kLogger.warning() + << "Failed to purge tracks from internal collection"; + return; + } + if (m_externalTrackCollections.isEmpty()) { + return; + } + VERIFY_OR_DEBUG_ASSERT(trackLocations.size() == trackIds.size()) { + kLogger.warning() + << "Purging only" + << trackLocations.size() + << "of" + << trackIds.size() + << "tracks from" + << m_externalTrackCollections.size() + << "external collection(s)"; + } else { + kLogger.debug() + << "Purging" + << trackLocations.size() + << "tracks from" + << m_externalTrackCollections.size() + << "external collection(s)"; + } + for (const auto& externalTrackCollection : m_externalTrackCollections) { + externalTrackCollection->purgeTracks(trackLocations); + } } void Library::purgeAllTracks(const QDir& rootDir) { + kLogger.debug() + << "Purging directory" + << rootDir + << "from internal track collection"; + if (!m_pTrackCollection->purgeAllTracks(rootDir)) { + kLogger.warning() + << "Failed to purge directory from internal collection"; + return; + } + if (m_externalTrackCollections.isEmpty()) { + return; + } + kLogger.debug() + << "Purging directory" + << rootDir + << "from" + << m_externalTrackCollections.size() + << "external track collection(s)"; for (const auto& externalTrackCollection : m_externalTrackCollections) { externalTrackCollection->purgeAllTracks(rootDir); } - m_pTrackCollection->purgeAllTracks(rootDir); } void Library::slotScanTrackAdded(TrackPointer pTrack) { DEBUG_ASSERT(pTrack); // Already added to m_pTrackCollection + if (m_externalTrackCollections.isEmpty()) { + return; + } + kLogger.debug() + << "Adding new track" + << pTrack->getLocation() + << "to" + << m_externalTrackCollections.size() + << "external track collection(s)"; for (const auto& externalTrackCollection : m_externalTrackCollections) { externalTrackCollection->saveTrack(*pTrack, ExternalTrackCollection::ChangeHint::Added); } @@ -593,6 +683,24 @@ void Library::slotScanTracksUpdated(QSet updatedTrackIds) { trackRefs.append(TrackRef::fromFileInfo(trackLocation, trackId)); } } + DEBUG_ASSERT(trackRefs.size() <= updatedTrackIds.size()); + VERIFY_OR_DEBUG_ASSERT(trackRefs.size() == updatedTrackIds.size()) { + kLogger.warning() + << "Updating only" + << trackRefs.size() + << "of" + << updatedTrackIds.size() + << "track(s) in" + << m_externalTrackCollections.size() + << "external collection(s)"; + } else { + kLogger.debug() + << "Updating" + << trackRefs.size() + << "track(s) in" + << m_externalTrackCollections.size() + << "external collection(s)"; + } for (const auto& externalTrackCollection : m_externalTrackCollections) { externalTrackCollection->updateTracks(trackRefs); } @@ -611,6 +719,12 @@ void Library::slotScanTracksReplaced(QList> replacedTr duplicateTrack.replacedBy = replacedTrack.second; duplicateTracks.append(duplicateTrack); } + kLogger.debug() + << "Deduplicating" + << duplicateTracks.size() + << "replaced track(s) in" + << m_externalTrackCollections.size() + << "external collection(s)"; for (const auto& externalTrackCollection : m_externalTrackCollections) { externalTrackCollection->deduplicateTracks(duplicateTracks); } -- cgit v1.2.3