Add a management class for creating Directory objects.

Create a DirectorManager class that is owned by the Library or Device objects
and provided to methods that need to create Directory objects. This will allow
information to be provided through the Directory object. For example:
- If the directory is on a removable device.
- A mount point that may change on future uses.
- Whether paths should be relative or absolute.
This commit is contained in:
Jim Broadus 2020-01-25 13:13:57 -08:00
parent fdb3f7ac37
commit 03dae637f0
10 changed files with 54 additions and 28 deletions

View File

@ -72,6 +72,7 @@ void RegisterMetaTypes() {
qRegisterMetaType<GstElement*>("GstElement*"); qRegisterMetaType<GstElement*>("GstElement*");
qRegisterMetaType<GstEngine::OutputDetails>("GstEngine::OutputDetails"); qRegisterMetaType<GstEngine::OutputDetails>("GstEngine::OutputDetails");
qRegisterMetaType<GstEnginePipeline*>("GstEnginePipeline*"); qRegisterMetaType<GstEnginePipeline*>("GstEnginePipeline*");
qRegisterMetaType<DirectoryManager*>("DirectoryManager*");
qRegisterMetaType<PlaylistItemList>("PlaylistItemList"); qRegisterMetaType<PlaylistItemList>("PlaylistItemList");
qRegisterMetaType<PlaylistItemPtr>("PlaylistItemPtr"); qRegisterMetaType<PlaylistItemPtr>("PlaylistItemPtr");
qRegisterMetaType<PodcastEpisodeList>("PodcastEpisodeList"); qRegisterMetaType<PodcastEpisodeList>("PodcastEpisodeList");

View File

@ -40,6 +40,7 @@ ConnectedDevice::ConnectedDevice(const QUrl& url, DeviceLister* lister,
unique_id_(unique_id), unique_id_(unique_id),
database_id_(database_id), database_id_(database_id),
manager_(manager), manager_(manager),
directory_manager_(new DirectoryManager),
model_(nullptr), model_(nullptr),
song_count_(0) { song_count_(0) {
qLog(Info) << "connected" << url << unique_id << first_time; qLog(Info) << "connected" << url << unique_id << first_time;
@ -61,12 +62,12 @@ ConnectedDevice::ConnectedDevice(const QUrl& url, DeviceLister* lister,
model_ = new LibraryModel(backend_, app_, this); model_ = new LibraryModel(backend_, app_, this);
} }
ConnectedDevice::~ConnectedDevice() {} ConnectedDevice::~ConnectedDevice() { delete directory_manager_; }
void ConnectedDevice::InitBackendDirectory(const QString& mount_point, void ConnectedDevice::InitBackendDirectory(const QString& mount_point,
bool first_time, bool rewrite_path) { bool first_time, bool rewrite_path) {
if (first_time || backend_->GetAllDirectories().isEmpty()) { if (first_time || backend_->GetAllDirectories(directory_manager_).isEmpty()) {
backend_->AddDirectory(mount_point); backend_->AddDirectory(directory_manager_, mount_point);
} else { } else {
if (rewrite_path) { if (rewrite_path) {
// This is a bit of a hack. The device might not be mounted at the same // This is a bit of a hack. The device might not be mounted at the same
@ -76,7 +77,7 @@ void ConnectedDevice::InitBackendDirectory(const QString& mount_point,
// Get the directory it was mounted at last time. Devices only have one // Get the directory it was mounted at last time. Devices only have one
// directory (the root). // directory (the root).
Directory dir = backend_->GetAllDirectories()[0]; Directory dir = backend_->GetAllDirectories(directory_manager_)[0];
if (dir.path != mount_point) { if (dir.path != mount_point) {
// The directory is different, commence the munging. // The directory is different, commence the munging.
qLog(Info) << "Changing path from" << dir.path << "to" << mount_point; qLog(Info) << "Changing path from" << dir.path << "to" << mount_point;
@ -85,7 +86,7 @@ void ConnectedDevice::InitBackendDirectory(const QString& mount_point,
} }
// Load the directory properly now // Load the directory properly now
backend_->LoadDirectoriesAsync(); backend_->LoadDirectoriesAsync(directory_manager_);
} }
} }

View File

@ -30,6 +30,7 @@ class Application;
class Database; class Database;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
class DirectoryManager;
class LibraryBackend; class LibraryBackend;
class LibraryModel; class LibraryModel;
@ -42,7 +43,7 @@ class ConnectedDevice : public QObject,
ConnectedDevice(const QUrl& url, DeviceLister* lister, ConnectedDevice(const QUrl& url, DeviceLister* lister,
const QString& unique_id, DeviceManager* manager, const QString& unique_id, DeviceManager* manager,
Application* app, int database_id, bool first_time); Application* app, int database_id, bool first_time);
~ConnectedDevice(); virtual ~ConnectedDevice();
virtual void Init() = 0; virtual void Init() = 0;
virtual void ConnectAsync(); virtual void ConnectAsync();
@ -84,6 +85,7 @@ class ConnectedDevice : public QObject,
DeviceManager* manager_; DeviceManager* manager_;
std::shared_ptr<LibraryBackend> backend_; std::shared_ptr<LibraryBackend> backend_;
DirectoryManager* directory_manager_;
LibraryModel* model_; LibraryModel* model_;
int song_count_; int song_count_;

View File

@ -39,6 +39,17 @@ Q_DECLARE_METATYPE(Directory)
typedef QList<Directory> DirectoryList; typedef QList<Directory> DirectoryList;
Q_DECLARE_METATYPE(DirectoryList) Q_DECLARE_METATYPE(DirectoryList)
struct DirectoryManager {
DirectoryManager() {}
virtual ~DirectoryManager() {}
virtual Directory GetDirectory(const QString& path) const {
Directory dir;
dir.path = path;
return dir;
}
};
Q_DECLARE_METATYPE(DirectoryManager)
struct Subdirectory { struct Subdirectory {
Subdirectory() : directory_id(-1), mtime(0) {} Subdirectory() : directory_id(-1), mtime(0) {}

View File

@ -39,6 +39,7 @@ Library::Library(Application* app, QObject* parent)
: QObject(parent), : QObject(parent),
app_(app), app_(app),
backend_(nullptr), backend_(nullptr),
directory_manager_(new DirectoryManager),
model_(nullptr), model_(nullptr),
watcher_(nullptr), watcher_(nullptr),
watcher_thread_(nullptr), watcher_thread_(nullptr),
@ -57,7 +58,7 @@ Library::Library(Application* app, QObject* parent)
using smart_playlists::SearchTerm; using smart_playlists::SearchTerm;
model_ = new LibraryModel(backend_, app_, this); model_ = new LibraryModel(backend_, app_, this);
dir_model_ = new LibraryDirectoryModel(backend_, this); dir_model_ = new LibraryDirectoryModel(backend_, directory_manager_, this);
model_->set_show_smart_playlists(true); model_->set_show_smart_playlists(true);
model_->set_default_smart_playlists( model_->set_default_smart_playlists(
LibraryModel::DefaultGenerators() LibraryModel::DefaultGenerators()
@ -172,7 +173,7 @@ void Library::Init() {
connect(app_->player(), SIGNAL(Stopped()), SLOT(Stopped())); connect(app_->player(), SIGNAL(Stopped()), SLOT(Stopped()));
// This will start the watcher checking for updates // This will start the watcher checking for updates
backend_->LoadDirectoriesAsync(); backend_->LoadDirectoriesAsync(directory_manager_.get());
} }
void Library::IncrementalScan() { watcher_->IncrementalScanAsync(); } void Library::IncrementalScan() { watcher_->IncrementalScanAsync(); }

View File

@ -27,6 +27,7 @@
class Application; class Application;
class Database; class Database;
class DirectoryManager;
class LibraryBackend; class LibraryBackend;
class LibraryModel; class LibraryModel;
class LibraryDirectoryModel; class LibraryDirectoryModel;
@ -80,6 +81,7 @@ class Library : public QObject {
private: private:
Application* app_; Application* app_;
std::shared_ptr<LibraryBackend> backend_; std::shared_ptr<LibraryBackend> backend_;
std::shared_ptr<DirectoryManager> directory_manager_;
LibraryModel* model_; LibraryModel* model_;
LibraryDirectoryModel* dir_model_; LibraryDirectoryModel* dir_model_;

View File

@ -63,8 +63,9 @@ void LibraryBackend::Init(Database* db, const QString& songs_table,
subdirs_table_ = subdirs_table; subdirs_table_ = subdirs_table;
} }
void LibraryBackend::LoadDirectoriesAsync() { void LibraryBackend::LoadDirectoriesAsync(DirectoryManager* directory_manager) {
metaObject()->invokeMethod(this, "LoadDirectories", Qt::QueuedConnection); metaObject()->invokeMethod(this, "LoadDirectories", Qt::QueuedConnection,
Q_ARG(DirectoryManager*, directory_manager));
} }
void LibraryBackend::UpdateTotalSongCountAsync() { void LibraryBackend::UpdateTotalSongCountAsync() {
@ -99,8 +100,8 @@ void LibraryBackend::UpdateSongsRatingAsync(const QList<int>& ids,
Q_ARG(float, rating)); Q_ARG(float, rating));
} }
void LibraryBackend::LoadDirectories() { void LibraryBackend::LoadDirectories(DirectoryManager* info) {
DirectoryList dirs = GetAllDirectories(); DirectoryList dirs = GetAllDirectories(info);
QMutexLocker l(db_->Mutex()); QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect()); QSqlDatabase db(db_->Connect());
@ -155,7 +156,9 @@ void LibraryBackend::ChangeDirPath(int id, const QString& old_path,
t.Commit(); t.Commit();
} }
DirectoryList LibraryBackend::GetAllDirectories() { DirectoryList LibraryBackend::GetAllDirectories(
DirectoryManager* directory_manager) {
Q_ASSERT(directory_manager);
QMutexLocker l(db_->Mutex()); QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect()); QSqlDatabase db(db_->Connect());
@ -167,9 +170,8 @@ DirectoryList LibraryBackend::GetAllDirectories() {
if (db_->CheckErrors(q)) return ret; if (db_->CheckErrors(q)) return ret;
while (q.next()) { while (q.next()) {
Directory dir; Directory dir = directory_manager->GetDirectory(q.value(1).toString());
dir.id = q.value(0).toInt(); dir.id = q.value(0).toInt();
dir.path = q.value(1).toString();
ret << dir; ret << dir;
} }
@ -217,7 +219,9 @@ void LibraryBackend::UpdateTotalSongCount() {
emit TotalSongCountUpdated(q.value(0).toInt()); emit TotalSongCountUpdated(q.value(0).toInt());
} }
void LibraryBackend::AddDirectory(const QString& path) { void LibraryBackend::AddDirectory(DirectoryManager* directory_manager,
const QString& path) {
Q_ASSERT(directory_manager);
QString canonical_path = QFileInfo(path).canonicalFilePath(); QString canonical_path = QFileInfo(path).canonicalFilePath();
QString db_path = canonical_path; QString db_path = canonical_path;
@ -238,8 +242,7 @@ void LibraryBackend::AddDirectory(const QString& path) {
q.exec(); q.exec();
if (db_->CheckErrors(q)) return; if (db_->CheckErrors(q)) return;
Directory dir; Directory dir = directory_manager->GetDirectory(canonical_path);
dir.path = canonical_path;
dir.id = q.lastInsertId().toInt(); dir.id = q.lastInsertId().toInt();
emit DirectoryDiscovered(dir, SubdirectoryList()); emit DirectoryDiscovered(dir, SubdirectoryList());

View File

@ -69,14 +69,14 @@ class LibraryBackendInterface : public QObject {
virtual QString songs_table() const = 0; virtual QString songs_table() const = 0;
// Get a list of directories in the library. Emits DirectoriesDiscovered. // Get a list of directories in the library. Emits DirectoriesDiscovered.
virtual void LoadDirectoriesAsync() = 0; virtual void LoadDirectoriesAsync(DirectoryManager* directory_manager) = 0;
// Counts the songs in the library. Emits TotalSongCountUpdated // Counts the songs in the library. Emits TotalSongCountUpdated
virtual void UpdateTotalSongCountAsync() = 0; virtual void UpdateTotalSongCountAsync() = 0;
virtual SongList FindSongsInDirectory(int id) = 0; virtual SongList FindSongsInDirectory(int id) = 0;
virtual SubdirectoryList SubdirsInDirectory(int id) = 0; virtual SubdirectoryList SubdirsInDirectory(int id) = 0;
virtual DirectoryList GetAllDirectories() = 0; virtual DirectoryList GetAllDirectories(DirectoryManager* info) = 0;
virtual void ChangeDirPath(int id, const QString& old_path, virtual void ChangeDirPath(int id, const QString& old_path,
const QString& new_path) = 0; const QString& new_path) = 0;
@ -118,7 +118,8 @@ class LibraryBackendInterface : public QObject {
// songs. // songs.
virtual Song GetSongByUrl(const QUrl& url, qint64 beginning = 0) = 0; virtual Song GetSongByUrl(const QUrl& url, qint64 beginning = 0) = 0;
virtual void AddDirectory(const QString& path) = 0; virtual void AddDirectory(DirectoryManager* directory_manager,
const QString& path) = 0;
virtual void RemoveDirectory(int dir_id) = 0; virtual void RemoveDirectory(int dir_id) = 0;
virtual bool ExecQuery(LibraryQuery* q) = 0; virtual bool ExecQuery(LibraryQuery* q) = 0;
@ -142,14 +143,14 @@ class LibraryBackend : public LibraryBackendInterface {
QString subdirs_table() const { return subdirs_table_; } QString subdirs_table() const { return subdirs_table_; }
// Get a list of directories in the library. Emits DirectoriesDiscovered. // Get a list of directories in the library. Emits DirectoriesDiscovered.
void LoadDirectoriesAsync(); void LoadDirectoriesAsync(DirectoryManager* directory_manager);
// Counts the songs in the library. Emits TotalSongCountUpdated // Counts the songs in the library. Emits TotalSongCountUpdated
void UpdateTotalSongCountAsync(); void UpdateTotalSongCountAsync();
SongList FindSongsInDirectory(int id); SongList FindSongsInDirectory(int id);
SubdirectoryList SubdirsInDirectory(int id); SubdirectoryList SubdirsInDirectory(int id);
DirectoryList GetAllDirectories(); DirectoryList GetAllDirectories(DirectoryManager* directory_manager);
void ChangeDirPath(int id, const QString& old_path, const QString& new_path); void ChangeDirPath(int id, const QString& old_path, const QString& new_path);
QStringList GetAll(const QString& column, QStringList GetAll(const QString& column,
@ -186,7 +187,7 @@ class LibraryBackend : public LibraryBackendInterface {
SongList GetSongsByUrl(const QUrl& url); SongList GetSongsByUrl(const QUrl& url);
Song GetSongByUrl(const QUrl& url, qint64 beginning = 0); Song GetSongByUrl(const QUrl& url, qint64 beginning = 0);
void AddDirectory(const QString& path); void AddDirectory(DirectoryManager* directory_manager, const QString& path);
void RemoveDirectory(int dir_id); void RemoveDirectory(int dir_id);
bool ExecQuery(LibraryQuery* q); bool ExecQuery(LibraryQuery* q);
@ -203,7 +204,7 @@ class LibraryBackend : public LibraryBackendInterface {
void DeleteAll(); void DeleteAll();
public slots: public slots:
void LoadDirectories(); void LoadDirectories(DirectoryManager* directory_manager);
void UpdateTotalSongCount(); void UpdateTotalSongCount();
void AddOrUpdateSongs(const SongList& songs); void AddOrUpdateSongs(const SongList& songs);
void UpdateMTimesOnly(const SongList& songs); void UpdateMTimesOnly(const SongList& songs);

View File

@ -25,10 +25,12 @@
#include "ui/iconloader.h" #include "ui/iconloader.h"
LibraryDirectoryModel::LibraryDirectoryModel( LibraryDirectoryModel::LibraryDirectoryModel(
std::shared_ptr<LibraryBackend> backend, QObject* parent) std::shared_ptr<LibraryBackend> backend,
std::shared_ptr<DirectoryManager> directory_manager, QObject* parent)
: QStandardItemModel(parent), : QStandardItemModel(parent),
dir_icon_(IconLoader::Load("document-open-folder", IconLoader::Base)), dir_icon_(IconLoader::Load("document-open-folder", IconLoader::Base)),
backend_(backend) { backend_(backend),
directory_manager_(directory_manager) {
connect(backend_.get(), connect(backend_.get(),
SIGNAL(DirectoryDiscovered(Directory, SubdirectoryList)), SIGNAL(DirectoryDiscovered(Directory, SubdirectoryList)),
SLOT(DirectoryDiscovered(Directory))); SLOT(DirectoryDiscovered(Directory)));
@ -67,7 +69,7 @@ void LibraryDirectoryModel::DirectoryDeleted(int dir_id) {
void LibraryDirectoryModel::AddDirectory(const QString& path) { void LibraryDirectoryModel::AddDirectory(const QString& path) {
if (!backend_) return; if (!backend_) return;
backend_->AddDirectory(path); backend_->AddDirectory(directory_manager_.get(), path);
} }
void LibraryDirectoryModel::RemoveDirectory(const QModelIndex& index) { void LibraryDirectoryModel::RemoveDirectory(const QModelIndex& index) {

View File

@ -32,6 +32,7 @@ class LibraryDirectoryModel : public QStandardItemModel {
public: public:
LibraryDirectoryModel(std::shared_ptr<LibraryBackend> backend, LibraryDirectoryModel(std::shared_ptr<LibraryBackend> backend,
std::shared_ptr<DirectoryManager> directory_manager,
QObject* parent = nullptr); QObject* parent = nullptr);
~LibraryDirectoryModel(); ~LibraryDirectoryModel();
@ -51,6 +52,7 @@ class LibraryDirectoryModel : public QStandardItemModel {
QIcon dir_icon_; QIcon dir_icon_;
std::shared_ptr<LibraryBackend> backend_; std::shared_ptr<LibraryBackend> backend_;
std::shared_ptr<DirectoryManager> directory_manager_;
QList<std::shared_ptr<MusicStorage>> storage_; QList<std::shared_ptr<MusicStorage>> storage_;
}; };