diff --git a/src/devices/connecteddevice.cpp b/src/devices/connecteddevice.cpp index 94dbea37e..9f94b5406 100644 --- a/src/devices/connecteddevice.cpp +++ b/src/devices/connecteddevice.cpp @@ -46,7 +46,6 @@ ConnectedDevice::ConnectedDevice(DeviceLister* lister, const QString& unique_id, // Create the model model_ = new LibraryModel(backend_, this); - model_->Init(); } ConnectedDevice::~ConnectedDevice() { diff --git a/src/devices/filesystemdevice.cpp b/src/devices/filesystemdevice.cpp index eb3cef527..b138c2285 100644 --- a/src/devices/filesystemdevice.cpp +++ b/src/devices/filesystemdevice.cpp @@ -58,8 +58,26 @@ FilesystemDevice::FilesystemDevice( if (first_time) backend_->AddDirectory(mount_point); - else + else { + // This is a bit of a hack. The device might not be mounted at the same + // path each time, so if it's different we have to munge all the paths in + // the database to fix it. This can be done entirely in sqlite so it's + // relatively fast... + + // Get the directory it was mounted at last time. Devices only have one + // directory (the root). + Directory dir = backend_->GetAllDirectories()[0]; + if (dir.path != mount_point) { + // The directory is different, commence the munging. + qDebug() << "Changing path from" << dir.path << "to" << mount_point; + backend_->ChangeDirPath(dir.id, mount_point); + } + + // Load the directory properly now, this signals the watcher as well. backend_->LoadDirectoriesAsync(); + } + + model_->Init(); } FilesystemDevice::~FilesystemDevice() { diff --git a/src/library/librarybackend.cpp b/src/library/librarybackend.cpp index 6536d6509..5ba04511c 100644 --- a/src/library/librarybackend.cpp +++ b/src/library/librarybackend.cpp @@ -49,20 +49,67 @@ void LibraryBackend::UpdateTotalSongCountAsync() { } void LibraryBackend::LoadDirectories() { + DirectoryList dirs = GetAllDirectories(); + QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q(QString("SELECT ROWID, path FROM %1").arg(dirs_table_), db); + foreach (const Directory& dir, dirs) { + emit DirectoryDiscovered(dir, SubdirsInDirectory(dir.id, db)); + } +} + +void LibraryBackend::ChangeDirPath(int id, const QString &new_path) { + QMutexLocker l(db_->Mutex()); + QSqlDatabase db(db_->Connect()); + ScopedTransaction t(&db); + + // Do the dirs table + QSqlQuery q(QString("UPDATE %1 SET path=:path WHERE ROWID=:id").arg(dirs_table_), db); + q.bindValue(":path", new_path); + q.bindValue(":id", id); q.exec(); if (db_->CheckErrors(q.lastError())) return; + const int path_len = new_path.length(); + + // Do the subdirs table + q = QSqlQuery(QString("UPDATE %1 SET path=:path || substr(path, %2)" + " WHERE directory=:id").arg(subdirs_table_).arg(path_len), db); + q.bindValue(":path", new_path); + q.bindValue(":id", id); + q.exec(); + if (db_->CheckErrors(q.lastError())) return; + + // Do the songs table + q = QSqlQuery(QString("UPDATE %1 SET filename=:path || substr(filename, %2)" + " WHERE directory=:id").arg(songs_table_).arg(path_len), db); + q.bindValue(":path", new_path); + q.bindValue(":id", id); + q.exec(); + if (db_->CheckErrors(q.lastError())) return; + + t.Commit(); +} + +DirectoryList LibraryBackend::GetAllDirectories() { + QMutexLocker l(db_->Mutex()); + QSqlDatabase db(db_->Connect()); + + DirectoryList ret; + + QSqlQuery q(QString("SELECT ROWID, path FROM %1").arg(dirs_table_), db); + q.exec(); + if (db_->CheckErrors(q.lastError())) return ret; + while (q.next()) { Directory dir; dir.id = q.value(0).toInt(); dir.path = q.value(1).toString(); - emit DirectoryDiscovered(dir, SubdirsInDirectory(dir.id, db)); + ret << dir; } + return ret; } SubdirectoryList LibraryBackend::SubdirsInDirectory(int id) { diff --git a/src/library/librarybackend.h b/src/library/librarybackend.h index ad63561c7..d8c5c00e6 100644 --- a/src/library/librarybackend.h +++ b/src/library/librarybackend.h @@ -66,6 +66,8 @@ class LibraryBackend : public QObject { SongList FindSongsInDirectory(int id); SubdirectoryList SubdirsInDirectory(int id); + DirectoryList GetAllDirectories(); + void ChangeDirPath(int id, const QString& new_path); QStringList GetAllArtists(const QueryOptions& opt = QueryOptions()); QStringList GetAllArtistsWithAlbums(const QueryOptions& opt = QueryOptions());