From ad5e366aad4b481969f35566e16b907d56c388ef Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Mon, 21 Jan 2019 17:44:37 +0100 Subject: [PATCH] Use ItemToIndex and fix memory leaks in devices --- src/device/connecteddevice.cpp | 32 +++- src/device/deviceinfo.cpp | 15 +- src/device/deviceinfo.h | 8 +- src/device/devicemanager.cpp | 305 +++++++++++++++++--------------- src/device/devicemanager.h | 30 ++-- src/device/deviceproperties.cpp | 14 +- src/device/deviceproperties.h | 2 +- src/device/deviceview.cpp | 41 ++--- src/device/deviceview.h | 6 +- src/device/filesystemdevice.cpp | 1 - 10 files changed, 248 insertions(+), 206 deletions(-) diff --git a/src/device/connecteddevice.cpp b/src/device/connecteddevice.cpp index 696ec1d4d..e4963feab 100644 --- a/src/device/connecteddevice.cpp +++ b/src/device/connecteddevice.cpp @@ -100,7 +100,15 @@ void ConnectedDevice::InitBackendDirectory(const QString &mount_point, bool firs } void ConnectedDevice::Eject() { - manager_->UnmountAsync(manager_->FindDeviceById(unique_id_)); + + DeviceInfo *info = manager_->FindDeviceById(unique_id_); + if (!info) return; + + QModelIndex idx = manager_->ItemToIndex(info); + if (!idx.isValid()) return; + + manager_->UnmountAsync(idx); + } void ConnectedDevice::FinishCopy(bool) { @@ -112,13 +120,27 @@ void ConnectedDevice::FinishDelete(bool) { } MusicStorage::TranscodeMode ConnectedDevice::GetTranscodeMode() const { - int index = manager_->FindDeviceById(unique_id_); - return MusicStorage::TranscodeMode(manager_->index(index, 0, QModelIndex()).data(DeviceManager::Role_TranscodeMode).toInt()); + + DeviceInfo *info = manager_->FindDeviceById(unique_id_); + if (!info) return MusicStorage::TranscodeMode(); + + QModelIndex idx = manager_->ItemToIndex(info); + if (!idx.isValid()) return MusicStorage::TranscodeMode(); + + return MusicStorage::TranscodeMode(idx.data(DeviceManager::Role_TranscodeMode).toInt()); + } Song::FileType ConnectedDevice::GetTranscodeFormat() const { - int index = manager_->FindDeviceById(unique_id_); - return Song::FileType(manager_->index(index, 0, QModelIndex()).data(DeviceManager::Role_TranscodeFormat).toInt()); + + DeviceInfo *info = manager_->FindDeviceById(unique_id_); + if (!info) return Song::FileType_Unknown; + + QModelIndex idx = manager_->ItemToIndex(info); + if (!idx.isValid()) return Song::FileType_Unknown; + + return Song::FileType(idx.data(DeviceManager::Role_TranscodeFormat).toInt()); + } void ConnectedDevice::BackendTotalSongCountUpdated(int count) { diff --git a/src/device/deviceinfo.cpp b/src/device/deviceinfo.cpp index f19181629..5e3b2b2c7 100644 --- a/src/device/deviceinfo.cpp +++ b/src/device/deviceinfo.cpp @@ -123,16 +123,11 @@ void DeviceInfo::LoadIcon(const QVariantList &icons, const QString &name_hint) { QString hint = QString(icons.first().toString() + name_hint).toLower(); - if (hint.contains("phone")) - icon_name_ = "device-phone"; - else if (hint.contains("ipod") || hint.contains("apple")) - icon_name_ = "device-ipod"; - else if ((hint.contains("usb")) && (hint.contains("reader"))) - icon_name_ = "device-usb-flash"; - else if (hint.contains("usb")) - icon_name_ = "device-usb-drive"; - else - icon_name_ = "device"; + if (hint.contains("phone")) icon_name_ = "device-phone"; + else if (hint.contains("ipod") || hint.contains("apple")) icon_name_ = "device-ipod"; + else if ((hint.contains("usb")) && (hint.contains("reader"))) icon_name_ = "device-usb-flash"; + else if (hint.contains("usb")) icon_name_ = "device-usb-drive"; + else icon_name_ = "device"; icon_ = IconLoader::Load(icon_name_); diff --git a/src/device/deviceinfo.h b/src/device/deviceinfo.h index 068c15dbf..ce851b378 100644 --- a/src/device/deviceinfo.h +++ b/src/device/deviceinfo.h @@ -42,10 +42,7 @@ #include "devicedatabasebackend.h" #include "devicelister.h" -class Application; class ConnectedDevice; -class DeviceLister; -class DeviceStateFilterModel; // Devices can be in three different states: // 1) Remembered in the database but not physically connected at the moment. @@ -85,7 +82,10 @@ class DeviceInfo : public SimpleTreeItem { // Sometimes the same device is discovered more than once. In this case the device will have multiple "backends". struct Backend { Backend(DeviceLister *lister = nullptr, const QString &id = QString()) - : lister_(lister), unique_id_(id) {} + : + lister_(lister), + unique_id_(id) + {} DeviceLister *lister_; // nullptr if not physically connected QString unique_id_; diff --git a/src/device/devicemanager.cpp b/src/device/devicemanager.cpp index 5ffc29136..1d4bf9e57 100644 --- a/src/device/devicemanager.cpp +++ b/src/device/devicemanager.cpp @@ -157,6 +157,8 @@ DeviceManager::~DeviceManager() { backend_->deleteLater(); + delete root_; + } void DeviceManager::LoadAllDevices() { @@ -165,20 +167,20 @@ void DeviceManager::LoadAllDevices() { DeviceDatabaseBackend::DeviceList devices = backend_->GetAllDevices(); for (const DeviceDatabaseBackend::Device &device : devices) { - DeviceInfo *info = new DeviceInfo(DeviceInfo::Type_Root, root_); + beginInsertRows(ItemToIndex(root_), devices_.count(), devices_.count()); + DeviceInfo *info = new DeviceInfo(DeviceInfo::Type_Device, root_); info->InitFromDb(device); - beginInsertRows(QModelIndex(), devices_.count(), devices_.count()); devices_ << info; endInsertRows(); } } -QVariant DeviceManager::data(const QModelIndex &index, int role) const { +QVariant DeviceManager::data(const QModelIndex &idx, int role) const { - if (!index.isValid() || index.column() != 0) return QVariant(); + if (!idx.isValid() || idx.column() != 0) return QVariant(); - const DeviceInfo *info = IndexToItem(index); + DeviceInfo *info = IndexToItem(idx); if (!info) return QVariant(); switch (role) { @@ -239,24 +241,22 @@ QVariant DeviceManager::data(const QModelIndex &index, int role) const { case MusicStorage::Role_Storage: if (!info->device_ && info->database_id_ != -1) - const_cast(this)->Connect(index.row()); + const_cast(this)->Connect(info); if (!info->device_) return QVariant(); return QVariant::fromValue>(info->device_); case MusicStorage::Role_StorageForceConnect: + if (!info->BestBackend()) return QVariant(); if (!info->device_) { - if (info->database_id_ == -1 && info->BestBackend() && !info->BestBackend()->lister_->DeviceNeedsMount(info->BestBackend()->unique_id_)) { - - if (info->BestBackend() && info->BestBackend()->lister_->AskForScan(info->BestBackend()->unique_id_)) { + if (info->database_id_ == -1 && !info->BestBackend()->lister_->DeviceNeedsMount(info->BestBackend()->unique_id_)) { + if (info->BestBackend()->lister_->AskForScan(info->BestBackend()->unique_id_)) { std::unique_ptr dialog(new QMessageBox(QMessageBox::Information, tr("Connect device"), tr("This is the first time you have connected this device. Strawberry will now scan the device to find music files - this may take some time."), QMessageBox::Cancel)); QPushButton *connect = dialog->addButton(tr("Connect device"), QMessageBox::AcceptRole); dialog->exec(); - if (dialog->clickedButton() != connect) return QVariant(); } } - - const_cast(this)->Connect(index.row()); + const_cast(this)->Connect(info); } if (!info->device_) return QVariant(); return QVariant::fromValue>(info->device_); @@ -298,21 +298,21 @@ void DeviceManager::AddLister(DeviceLister *lister) { } -int DeviceManager::FindDeviceById(const QString &id) const { +DeviceInfo *DeviceManager::FindDeviceById(const QString &id) const { for (int i = 0; i < devices_.count(); ++i) { for (const DeviceInfo::Backend &backend : devices_[i]->backends_) { - if (backend.unique_id_ == id) return i; + if (backend.unique_id_ == id) return devices_[i]; } } - return -1; + return nullptr; } -int DeviceManager::FindDeviceByUrl(const QList &urls) const { +DeviceInfo *DeviceManager::FindDeviceByUrl(const QList &urls) const { - if (urls.isEmpty()) return -1; + if (urls.isEmpty()) return nullptr; for (int i = 0; i < devices_.count(); ++i) { for (const DeviceInfo::Backend &backend : devices_[i]->backends_) { @@ -320,12 +320,12 @@ int DeviceManager::FindDeviceByUrl(const QList &urls) const { QList device_urls = backend.lister_->MakeDeviceUrls(backend.unique_id_); for (const QUrl &url : device_urls) { - if (urls.contains(url)) return i; + if (urls.contains(url)) return devices_[i]; } } } - return -1; + return nullptr; } @@ -337,24 +337,22 @@ void DeviceManager::PhysicalDeviceAdded(const QString &id) { qLog(Info) << "Device added:" << id << lister->DeviceUniqueIDs(); // Do we have this device already? - int i = FindDeviceById(id); - if (i != -1) { - DeviceInfo *info = devices_[i]; + DeviceInfo *info = FindDeviceById(id); + if (info) { for (int backend_index = 0 ; backend_index < info->backends_.count() ; ++backend_index) { if (info->backends_[backend_index].unique_id_ == id) { info->backends_[backend_index].lister_ = lister; break; } } - - emit dataChanged(index(i, 0), index(i, 0)); + QModelIndex idx = ItemToIndex(info); + if (idx.isValid()) emit dataChanged(idx, idx); } else { // Check if we have another device with the same URL - i = FindDeviceByUrl(lister->MakeDeviceUrls(id)); - if (i != -1) { + info = FindDeviceByUrl(lister->MakeDeviceUrls(id)); + if (info) { // Add this device's lister to the existing device - DeviceInfo *info = devices_[i]; info->backends_ << DeviceInfo::Backend(lister, id); // If the user hasn't saved the device in the DB yet then overwrite the device's name and icon etc. @@ -363,18 +361,17 @@ void DeviceManager::PhysicalDeviceAdded(const QString &id) { info->size_ = lister->DeviceCapacity(id); info->LoadIcon(lister->DeviceIcons(id), info->friendly_name_); } - - emit dataChanged(index(i, 0), index(i, 0)); + QModelIndex idx = ItemToIndex(info); + if (idx.isValid()) emit dataChanged(idx, idx); } else { // It's a completely new device - DeviceInfo *info = new DeviceInfo(DeviceInfo::Type_Root, root_); + beginInsertRows(ItemToIndex(root_), devices_.count(), devices_.count()); + DeviceInfo *info = new DeviceInfo(DeviceInfo::Type_Device, root_); info->backends_ << DeviceInfo::Backend(lister, id); info->friendly_name_ = lister->MakeFriendlyName(id); info->size_ = lister->DeviceCapacity(id); info->LoadIcon(lister->DeviceIcons(id), info->friendly_name_); - - beginInsertRows(QModelIndex(), devices_.count(), devices_.count()); devices_ << info; endInsertRows(); } @@ -388,13 +385,11 @@ void DeviceManager::PhysicalDeviceRemoved(const QString &id) { qLog(Info) << "Device removed:" << id; - int i = FindDeviceById(id); - if (i == -1) { - // Shouldn't happen - return; - } + DeviceInfo *info = FindDeviceById(id); + if (!info) return; - DeviceInfo *info = devices_[i]; + QModelIndex idx = ItemToIndex(info); + if (!idx.isValid()) return; if (info->database_id_ != -1) { // Keep the structure around, but just "disconnect" it @@ -407,9 +402,9 @@ void DeviceManager::PhysicalDeviceRemoved(const QString &id) { if (info->device_ && info->device_->lister() == lister) info->device_.reset(); - if (!info->device_) emit DeviceDisconnected(i); + if (!info->device_) emit DeviceDisconnected(idx); - emit dataChanged(index(i, 0), index(i, 0)); + emit dataChanged(idx, idx); } else { // If this was the last lister for the device then remove it from the model @@ -421,16 +416,9 @@ void DeviceManager::PhysicalDeviceRemoved(const QString &id) { } if (info->backends_.isEmpty()) { - beginRemoveRows(QModelIndex(), i, i); - devices_.removeAt(i); - - for (const QModelIndex &idx : persistentIndexList()) { - if (idx.row() == i) - changePersistentIndex(idx, QModelIndex()); - else if (idx.row() > i) - changePersistentIndex(idx, index(idx.row() - 1, idx.column())); - } - + beginRemoveRows(ItemToIndex(root_), idx.row(), idx.row()); + devices_.removeAll(info); + root_->Delete(info->row); endRemoveRows(); } } @@ -442,29 +430,38 @@ void DeviceManager::PhysicalDeviceChanged(const QString &id) { DeviceLister *lister = qobject_cast(sender()); Q_UNUSED(lister); - int i = FindDeviceById(id); - if (i == -1) { - // Shouldn't happen - return; - } + DeviceInfo *info = FindDeviceById(id); + if (!info) return; // TODO } -std::shared_ptr DeviceManager::Connect(int row) { - - DeviceInfo *info = devices_[row]; - if (info->device_) // Already connected - return info->device_; +std::shared_ptr DeviceManager::Connect(QModelIndex idx) { std::shared_ptr ret; - if (!info->BestBackend()->lister_) // Not physically connected - return ret; + DeviceInfo *info = IndexToItem(idx); + if (!info) return ret; - if (info->BestBackend()->lister_->DeviceNeedsMount(info->BestBackend()->unique_id_)) { - // Mount the device + return Connect(info); + +} + +std::shared_ptr DeviceManager::Connect(DeviceInfo *info) { + + std::shared_ptr ret; + + if (!info) return ret; + if (info->device_) { // Already connected + return info->device_; + } + + if (!info->BestBackend() || !info->BestBackend()->lister_) { // Not physically connected + return ret; + } + + if (info->BestBackend()->lister_->DeviceNeedsMount(info->BestBackend()->unique_id_)) { // Mount the device info->BestBackend()->lister_->MountDevice(info->BestBackend()->unique_id_); return ret; } @@ -525,8 +522,10 @@ std::shared_ptr DeviceManager::Connect(int row) { Q_ARG(QUrl, device_url), Q_ARG(DeviceLister*, info->BestBackend()->lister_), Q_ARG(QString, info->BestBackend()->unique_id_), - Q_ARG(DeviceManager*, this), Q_ARG(Application*, app_), - Q_ARG(int, info->database_id_), Q_ARG(bool, first_time)); + Q_ARG(DeviceManager*, this), + Q_ARG(Application*, app_), + Q_ARG(int, info->database_id_), + Q_ARG(bool, first_time)); ret.reset(static_cast(instance)); @@ -541,91 +540,121 @@ std::shared_ptr DeviceManager::Connect(int row) { return ret; } info->device_ = ret; - QModelIndex index = ItemToIndex(info); - if (!index.isValid()) return ret; - emit dataChanged(index, index); + QModelIndex idx = ItemToIndex(info); + if (!idx.isValid()) return ret; + + emit dataChanged(idx, idx); + connect(info->device_.get(), SIGNAL(TaskStarted(int)), SLOT(DeviceTaskStarted(int))); connect(info->device_.get(), SIGNAL(SongCountUpdated(int)), SLOT(DeviceSongCountUpdated(int))); - emit DeviceConnected(row); + emit DeviceConnected(idx); return ret; } -std::shared_ptr DeviceManager::GetConnectedDevice(int row) const { - return devices_[row]->device_; +DeviceInfo *DeviceManager::GetDevice(QModelIndex idx) const { + + DeviceInfo *info = IndexToItem(idx); + return info; + } -int DeviceManager::GetDatabaseId(int row) const { - return devices_[row]->database_id_; +std::shared_ptr DeviceManager::GetConnectedDevice(QModelIndex idx) const { + + std::shared_ptr ret; + DeviceInfo *info = IndexToItem(idx); + if (!info) return ret; + return info->device_; + } -DeviceLister *DeviceManager::GetLister(int row) const { - return devices_[row]->BestBackend()->lister_; +std::shared_ptr DeviceManager::GetConnectedDevice(DeviceInfo *info) const { + + std::shared_ptr ret; + if (!info) return ret; + return info->device_; + } -void DeviceManager::Disconnect(int row) { +int DeviceManager::GetDatabaseId(QModelIndex idx) const { - DeviceInfo *info = devices_[row]; - if (!info || !info->device_) - return; + if (!idx.isValid()) return -1; + + DeviceInfo *info = IndexToItem(idx); + if (!info) return -1; + return info->database_id_; + +} + +DeviceLister *DeviceManager::GetLister(QModelIndex idx) const { + + if (!idx.isValid()) return nullptr; + + DeviceInfo *info = IndexToItem(idx); + if (!info || !info->BestBackend()) return nullptr; + return info->BestBackend()->lister_; + +} + +void DeviceManager::Disconnect(QModelIndex idx) { + + if (!idx.isValid()) return; + + DeviceInfo *info = IndexToItem(idx); + if (!info || !info->device_) return; info->device_.reset(); - emit DeviceDisconnected(row); - QModelIndex index = ItemToIndex(info); - if (!index.isValid()) return; - - emit dataChanged(index, index); + emit DeviceDisconnected(idx); + emit dataChanged(idx, idx); } -void DeviceManager::Forget(int row) { +void DeviceManager::Forget(QModelIndex idx) { + + if (!idx.isValid()) return; + + DeviceInfo *info = IndexToItem(idx); + if (!info) return; - DeviceInfo *info = devices_[row]; if (info->database_id_ == -1) return; - - if (info->device_) Disconnect(row); + if (info->device_) Disconnect(idx); backend_->RemoveDevice(info->database_id_); info->database_id_ = -1; - if (!info->BestBackend()->lister_) { - // It's not attached any more so remove it from the list - beginRemoveRows(QModelIndex(), row, row); - devices_.removeAt(row); - - for (const QModelIndex &idx : persistentIndexList()) { - if (idx.row() == row) - changePersistentIndex(idx, QModelIndex()); - else if (idx.row() > row) - changePersistentIndex(idx, index(idx.row() - 1, idx.column())); - } - + if (!info->BestBackend() || (info->BestBackend() && !info->BestBackend()->lister_)) { // It's not attached any more so remove it from the list + beginRemoveRows(ItemToIndex(root_), idx.row(), idx.row()); + devices_.removeAll(info); + root_->Delete(info->row); endRemoveRows(); } - else { - // It's still attached, set the name and icon back to what they were originally + else { // It's still attached, set the name and icon back to what they were originally const QString id = info->BestBackend()->unique_id_; info->friendly_name_ = info->BestBackend()->lister_->MakeFriendlyName(id); info->LoadIcon(info->BestBackend()->lister_->DeviceIcons(id), info->friendly_name_); - dataChanged(index(row, 0), index(row, 0)); + dataChanged(idx, idx); } } -void DeviceManager::SetDeviceOptions(int row, const QString &friendly_name, const QString &icon_name, MusicStorage::TranscodeMode mode, Song::FileType format) { +void DeviceManager::SetDeviceOptions(QModelIndex idx, const QString &friendly_name, const QString &icon_name, MusicStorage::TranscodeMode mode, Song::FileType format) { + + if (!idx.isValid()) return; + + DeviceInfo *info = IndexToItem(idx); + if (!info) return; - DeviceInfo *info = devices_[row]; info->friendly_name_ = friendly_name; info->LoadIcon(QVariantList() << icon_name, friendly_name); info->transcode_mode_ = mode; info->transcode_format_ = format; - emit dataChanged(index(row, 0), index(row, 0)); + emit dataChanged(idx, idx); if (info->database_id_ != -1) backend_->SetDeviceOptions(info->database_id_, friendly_name, icon_name, mode, format); @@ -659,42 +688,49 @@ void DeviceManager::TasksChanged() { for (const TaskManager::Task &task : tasks) { if (!active_tasks_.contains(task.id)) continue; - QPersistentModelIndex index = active_tasks_[task.id]; - if (!index.isValid()) continue; + QPersistentModelIndex idx = active_tasks_[task.id]; + if (!idx.isValid()) continue; - DeviceInfo *info = IndexToItem(index); + DeviceInfo *info = IndexToItem(idx); if (task.progress_max) info->task_percentage_ = float(task.progress) / task.progress_max * 100; else info->task_percentage_ = 0; - emit dataChanged(index, index); - finished_tasks.removeAll(index); + emit dataChanged(idx, idx); + finished_tasks.removeAll(idx); } - for (const QPersistentModelIndex &index : finished_tasks) { - if (!index.isValid()) continue; + for (const QPersistentModelIndex &idx : finished_tasks) { + + if (!idx.isValid()) continue; + + DeviceInfo *info = IndexToItem(idx); + if (!info) continue; - DeviceInfo *info = devices_[index.row()]; info->task_percentage_ = -1; - emit dataChanged(index, index); + emit dataChanged(idx, idx); - active_tasks_.remove(active_tasks_.key(index)); + active_tasks_.remove(active_tasks_.key(idx)); } } -void DeviceManager::UnmountAsync(int row) { - Q_ASSERT(QMetaObject::invokeMethod(this, "Unmount", Q_ARG(int, row))); +void DeviceManager::UnmountAsync(QModelIndex idx) { + Q_ASSERT(QMetaObject::invokeMethod(this, "Unmount", Q_ARG(QModelIndex, idx))); } -void DeviceManager::Unmount(int row) { +void DeviceManager::Unmount(QModelIndex idx) { + + if (!idx.isValid()) return; + + DeviceInfo *info = IndexToItem(idx); + if (!info) return; - DeviceInfo *info = devices_[row]; if (info->database_id_ != -1 && !info->device_) return; - if (info->device_) Disconnect(row); + if (info->device_) Disconnect(idx); if (info->BestBackend()->lister_) info->BestBackend()->lister_->UnmountDevice(info->BestBackend()->unique_id_); @@ -706,13 +742,13 @@ void DeviceManager::DeviceSongCountUpdated(int count) { ConnectedDevice *device = qobject_cast(sender()); if (!device) return; - int row = FindDeviceById(device->unique_id()); - if (row == -1) return; + DeviceInfo *info = FindDeviceById(device->unique_id()); + if (!info) return; - QModelIndex index = ItemToIndex(devices_[row]); - if (!index.isValid()) return; + QModelIndex idx = ItemToIndex(info); + if (!idx.isValid()) return; - emit dataChanged(index, index); + emit dataChanged(idx, idx); } @@ -721,21 +757,14 @@ void DeviceManager::LazyPopulate(DeviceInfo *parent, bool signal) { parent->lazy_loaded = true; } -DeviceInfo *DeviceManager::ItemFromRow(int row) { - return devices_[row]; -} - QString DeviceManager::DeviceNameByID(QString unique_id) { - int row = FindDeviceById(unique_id); - if (row == -1) return QString(); - - DeviceInfo *info = devices_[row]; + DeviceInfo *info = FindDeviceById(unique_id); if (!info) return QString(); - QModelIndex index = ItemToIndex(info); - if (!index.isValid()) return QString(); + QModelIndex idx = ItemToIndex(info); + if (!idx.isValid()) return QString(); - return data(index, DeviceManager::Role_FriendlyName).toString(); + return data(idx, DeviceManager::Role_FriendlyName).toString(); } diff --git a/src/device/devicemanager.h b/src/device/devicemanager.h index 572db7e9c..8063bf7fe 100644 --- a/src/device/devicemanager.h +++ b/src/device/devicemanager.h @@ -88,32 +88,34 @@ class DeviceManager : public SimpleTreeModel { DeviceStateFilterModel *connected_devices_model() const { return connected_devices_model_; } // Get info about devices - int GetDatabaseId(int row) const; - DeviceLister *GetLister(int row) const; - std::shared_ptr GetConnectedDevice(int row) const; + int GetDatabaseId(QModelIndex idx) const; + DeviceLister *GetLister(QModelIndex idx) const; + DeviceInfo *GetDevice(QModelIndex idx) const; + std::shared_ptr GetConnectedDevice(QModelIndex idx) const; + std::shared_ptr GetConnectedDevice(DeviceInfo *info) const; - DeviceInfo *ItemFromRow(int row); - int FindDeviceById(const QString &id) const; - int FindDeviceByUrl(const QList &url) const; + DeviceInfo *FindDeviceById(const QString &id) const; + DeviceInfo *FindDeviceByUrl(const QList &url) const; QString DeviceNameByID(QString unique_id); // Actions on devices - std::shared_ptr Connect(int row); - void Disconnect(int row); - void Forget(int row); - void UnmountAsync(int row); + std::shared_ptr Connect(DeviceInfo *info); + std::shared_ptr Connect(QModelIndex idx); + void Disconnect(QModelIndex idx); + void Forget(QModelIndex idx); + void UnmountAsync(QModelIndex idx); - void SetDeviceOptions(int row, const QString &friendly_name, const QString &icon_name, MusicStorage::TranscodeMode mode, Song::FileType format); + void SetDeviceOptions(QModelIndex idx, const QString &friendly_name, const QString &icon_name, MusicStorage::TranscodeMode mode, Song::FileType format); // QAbstractItemModel QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; public slots: - void Unmount(int row); + void Unmount(QModelIndex idx); signals: - void DeviceConnected(int row); - void DeviceDisconnected(int row); + void DeviceConnected(QModelIndex idx); + void DeviceDisconnected(QModelIndex idx); private slots: void PhysicalDeviceAdded(const QString &id); diff --git a/src/device/deviceproperties.cpp b/src/device/deviceproperties.cpp index c473b1695..e27be6a70 100644 --- a/src/device/deviceproperties.cpp +++ b/src/device/deviceproperties.cpp @@ -89,7 +89,7 @@ void DeviceProperties::SetDeviceManager(DeviceManager *manager) { } -void DeviceProperties::ShowDevice(int row) { +void DeviceProperties::ShowDevice(QModelIndex idx) { if (ui_->icon->count() == 0) { // Only load the icons the first time the dialog is shown @@ -117,7 +117,7 @@ void DeviceProperties::ShowDevice(int row) { #endif } - index_ = manager_->index(row, 0, QModelIndex()); + index_ = idx; // Basic information ui_->name->setText(index_.data(DeviceManager::Role_FriendlyName).toString()); @@ -160,7 +160,7 @@ void DeviceProperties::UpdateHardwareInfo() { // Hardware information QString id = index_.data(DeviceManager::Role_UniqueId).toString(); - if (DeviceLister *lister = manager_->GetLister(index_.row())) { + if (DeviceLister *lister = manager_->GetLister(index_)) { QVariantMap info = lister->DeviceHardwareInfo(id); // Remove empty items @@ -206,8 +206,8 @@ void DeviceProperties::UpdateHardwareInfo() { void DeviceProperties::UpdateFormats() { QString id = index_.data(DeviceManager::Role_UniqueId).toString(); - DeviceLister *lister = manager_->GetLister(index_.row()); - std::shared_ptr device = manager_->GetConnectedDevice(index_.row()); + DeviceLister *lister = manager_->GetLister(index_); + std::shared_ptr device = manager_->GetConnectedDevice(index_); // Transcode mode MusicStorage::TranscodeMode mode = MusicStorage::TranscodeMode(index_.data(DeviceManager::Role_TranscodeMode).toInt()); @@ -277,11 +277,11 @@ void DeviceProperties::accept() { icon_name = ui_->icon->currentItem()->data(Qt::UserRole).toString(); } - manager_->SetDeviceOptions(index_.row(), ui_->name->text(), icon_name, mode, format); + manager_->SetDeviceOptions(index_, ui_->name->text(), icon_name, mode, format); } -void DeviceProperties::OpenDevice() { manager_->Connect(index_.row()); } +void DeviceProperties::OpenDevice() { manager_->Connect(index_); } void DeviceProperties::UpdateFormatsFinished(QFuture future) { diff --git a/src/device/deviceproperties.h b/src/device/deviceproperties.h index a61fe07f6..78d1f201d 100644 --- a/src/device/deviceproperties.h +++ b/src/device/deviceproperties.h @@ -48,7 +48,7 @@ class DeviceProperties : public QDialog { ~DeviceProperties(); void SetDeviceManager(DeviceManager *manager); - void ShowDevice(int row); + void ShowDevice(QModelIndex idx); public slots: void accept(); diff --git a/src/device/deviceview.cpp b/src/device/deviceview.cpp index 9cc8b7bd8..51a35b3c8 100644 --- a/src/device/deviceview.cpp +++ b/src/device/deviceview.cpp @@ -190,8 +190,8 @@ void DeviceView::SetApplication(Application *app) { Q_ASSERT(app_ == nullptr); app_ = app; - connect(app_->device_manager(), SIGNAL(DeviceConnected(int)), SLOT(DeviceConnected(int))); - connect(app_->device_manager(), SIGNAL(DeviceDisconnected(int)), SLOT(DeviceDisconnected(int))); + connect(app_->device_manager(), SIGNAL(DeviceConnected(QModelIndex)), SLOT(DeviceConnected(QModelIndex))); + connect(app_->device_manager(), SIGNAL(DeviceDisconnected(QModelIndex)), SLOT(DeviceDisconnected(QModelIndex))); sort_model_ = new QSortFilterProxyModel(this); sort_model_->setSourceModel(app_->device_manager()); @@ -240,8 +240,8 @@ void DeviceView::contextMenuEvent(QContextMenuEvent *e) { const QModelIndex collection_index = MapToCollection(menu_index_); if (device_index.isValid()) { - const bool is_plugged_in = app_->device_manager()->GetLister(device_index.row()); - const bool is_remembered = app_->device_manager()->GetDatabaseId(device_index.row()) != -1; + const bool is_plugged_in = app_->device_manager()->GetLister(device_index); + const bool is_remembered = app_->device_manager()->GetDatabaseId(device_index) != -1; forget_action_->setEnabled(is_remembered); eject_action_->setEnabled(is_plugged_in); @@ -253,7 +253,7 @@ void DeviceView::contextMenuEvent(QContextMenuEvent *e) { bool is_filesystem_device = false; if (parent_device_index.isValid()) { - std::shared_ptr device = app_->device_manager()->GetConnectedDevice(parent_device_index.row()); + std::shared_ptr device = app_->device_manager()->GetConnectedDevice(parent_device_index); if (device && !device->LocalPath().isEmpty()) is_filesystem_device = true; } @@ -295,16 +295,14 @@ void DeviceView::Connect() { app_->device_manager()->data(device_idx, MusicStorage::Role_StorageForceConnect); } -void DeviceView::DeviceConnected(int row) { +void DeviceView::DeviceConnected(QModelIndex idx) { - std::shared_ptr device = app_->device_manager()->GetConnectedDevice(row); + if (!idx.isValid()) return; + + std::shared_ptr device = app_->device_manager()->GetConnectedDevice(idx); if (!device) return; - DeviceInfo *info = app_->device_manager()->ItemFromRow(row); - if (!info) return; - QModelIndex index = app_->device_manager()->ItemToIndex(info); - if (!index.isValid()) return; - QModelIndex sort_idx = sort_model_->mapFromSource(index); + QModelIndex sort_idx = sort_model_->mapFromSource(idx); if (!sort_idx.isValid()) return; QSortFilterProxyModel *sort_model = new QSortFilterProxyModel(device->model()); @@ -318,19 +316,16 @@ void DeviceView::DeviceConnected(int row) { } -void DeviceView::DeviceDisconnected(int row) { - DeviceInfo *info = app_->device_manager()->ItemFromRow(row); - if (!info) return; - QModelIndex index = app_->device_manager()->ItemToIndex(info); - if (!index.isValid()) return; - merged_model_->RemoveSubModel(sort_model_->mapFromSource(index)); +void DeviceView::DeviceDisconnected(QModelIndex idx) { + if (!idx.isValid()) return; + merged_model_->RemoveSubModel(sort_model_->mapFromSource(idx)); } void DeviceView::Forget() { QModelIndex device_idx = MapToDevice(menu_index_); QString unique_id = app_->device_manager()->data(device_idx, DeviceManager::Role_UniqueId).toString(); - if (app_->device_manager()->GetLister(device_idx.row()) && app_->device_manager()->GetLister(device_idx.row())->AskForScan(unique_id)) { + if (app_->device_manager()->GetLister(device_idx) && app_->device_manager()->GetLister(device_idx)->AskForScan(unique_id)) { std::unique_ptr dialog(new QMessageBox( QMessageBox::Question, tr("Forget device"), tr("Forgetting a device will remove it from this list and Strawberry will have to rescan all the songs again next time you connect it."), @@ -341,12 +336,12 @@ void DeviceView::Forget() { if (dialog->clickedButton() != forget) return; } - app_->device_manager()->Forget(device_idx.row()); + app_->device_manager()->Forget(device_idx); } void DeviceView::Properties() { - properties_dialog_->ShowDevice(MapToDevice(menu_index_).row()); + properties_dialog_->ShowDevice(MapToDevice(menu_index_)); } void DeviceView::mouseDoubleClickEvent(QMouseEvent *event) { @@ -356,7 +351,7 @@ void DeviceView::mouseDoubleClickEvent(QMouseEvent *event) { QModelIndex merged_index = indexAt(event->pos()); QModelIndex device_index = MapToDevice(merged_index); if (device_index.isValid()) { - if (!app_->device_manager()->GetConnectedDevice(device_index.row())) { + if (!app_->device_manager()->GetConnectedDevice(device_index)) { menu_index_ = merged_index; Connect(); } @@ -439,7 +434,7 @@ void DeviceView::Organise() { void DeviceView::Unmount() { QModelIndex device_idx = MapToDevice(menu_index_); - app_->device_manager()->Unmount(device_idx.row()); + app_->device_manager()->Unmount(device_idx); } void DeviceView::DeleteFinished(const SongList &songs_with_errors) { diff --git a/src/device/deviceview.h b/src/device/deviceview.h index 35750f58d..5d17a936f 100644 --- a/src/device/deviceview.h +++ b/src/device/deviceview.h @@ -88,13 +88,13 @@ class DeviceView : public AutoExpandingTreeView { void Organise(); void Delete(); - void DeviceConnected(int row); - void DeviceDisconnected(int row); + void DeviceConnected(QModelIndex idx); + void DeviceDisconnected(QModelIndex idx); void DeleteFinished(const SongList &songs_with_errors); // AutoExpandingTreeView - bool CanRecursivelyExpand(const QModelIndex &index) const; + bool CanRecursivelyExpand(const QModelIndex &idx) const; private: QModelIndex MapToDevice(const QModelIndex &merged_model_index) const; diff --git a/src/device/filesystemdevice.cpp b/src/device/filesystemdevice.cpp index 437a9ce2e..0dc19cb52 100644 --- a/src/device/filesystemdevice.cpp +++ b/src/device/filesystemdevice.cpp @@ -44,7 +44,6 @@ FilesystemDevice::FilesystemDevice(const QUrl &url, DeviceLister *lister, const watcher_->moveToThread(watcher_thread_); watcher_thread_->start(QThread::IdlePriority); - qLog(Debug) << __PRETTY_FUNCTION__ << unique_id; watcher_->set_device_name(manager->DeviceNameByID(unique_id)); watcher_->set_backend(backend_); watcher_->set_task_manager(app_->task_manager());