Fix memory leak and use ItemToIndex / IndexToItem (#6262)

This commit is contained in:
Jonas Kvinge 2019-01-21 22:38:46 +01:00 committed by John Maguire
parent 7e25a7c7e4
commit ed3d462674
8 changed files with 195 additions and 166 deletions

View File

@ -91,7 +91,11 @@ void ConnectedDevice::InitBackendDirectory(const QString& mount_point,
void ConnectedDevice::ConnectAsync() { emit ConnectFinished(unique_id_, true); } void ConnectedDevice::ConnectAsync() { emit ConnectFinished(unique_id_, true); }
void ConnectedDevice::Eject() { 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) { void ConnectedDevice::FinishCopy(bool) {
@ -103,18 +107,24 @@ void ConnectedDevice::FinishDelete(bool) {
} }
MusicStorage::TranscodeMode ConnectedDevice::GetTranscodeMode() const { MusicStorage::TranscodeMode ConnectedDevice::GetTranscodeMode() const {
int index = manager_->FindDeviceById(unique_id_); 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( return MusicStorage::TranscodeMode(
manager_->index(index, 0, QModelIndex()) idx.data(DeviceManager::Role_TranscodeMode).toInt());
.data(DeviceManager::Role_TranscodeMode)
.toInt());
} }
Song::FileType ConnectedDevice::GetTranscodeFormat() const { Song::FileType ConnectedDevice::GetTranscodeFormat() const {
int index = manager_->FindDeviceById(unique_id_); DeviceInfo* info = manager_->FindDeviceById(unique_id_);
return Song::FileType(manager_->index(index, 0, QModelIndex()) if (!info) return Song::Type_Unknown;
.data(DeviceManager::Role_TranscodeFormat)
.toInt()); QModelIndex idx = manager_->ItemToIndex(info);
if (!idx.isValid()) return Song::Type_Unknown;
return Song::FileType(idx.data(DeviceManager::Role_TranscodeFormat).toInt());
} }
void ConnectedDevice::BackendTotalSongCountUpdated(int count) { void ConnectedDevice::BackendTotalSongCountUpdated(int count) {

View File

@ -138,19 +138,19 @@ void DeviceManager::LoadAllDevices() {
Q_ASSERT(QThread::currentThread() != qApp->thread()); Q_ASSERT(QThread::currentThread() != qApp->thread());
DeviceDatabaseBackend::DeviceList devices = backend_->GetAllDevices(); DeviceDatabaseBackend::DeviceList devices = backend_->GetAllDevices();
for (const DeviceDatabaseBackend::Device& device : devices) { for (const DeviceDatabaseBackend::Device& device : devices) {
DeviceInfo* info = new DeviceInfo(DeviceInfo::Type_Root, root_); DeviceInfo* info = new DeviceInfo(DeviceInfo::Type_Device, root_);
info->InitFromDb(device); info->InitFromDb(device);
beginInsertRows(QModelIndex(), devices_.count(), devices_.count()); beginInsertRows(ItemToIndex(root_), devices_.count(), devices_.count());
devices_ << info; devices_ << info;
endInsertRows(); 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(); if (!info) return QVariant();
switch (role) { switch (role) {
@ -218,13 +218,14 @@ QVariant DeviceManager::data(const QModelIndex& index, int role) const {
case MusicStorage::Role_Storage: case MusicStorage::Role_Storage:
if (!info->device_ && info->database_id_ != -1) if (!info->device_ && info->database_id_ != -1)
const_cast<DeviceManager*>(this)->Connect(index.row()); const_cast<DeviceManager*>(this)->Connect(info);
if (!info->device_) return QVariant(); if (!info->device_) return QVariant();
return QVariant::fromValue<std::shared_ptr<MusicStorage>>(info->device_); return QVariant::fromValue<std::shared_ptr<MusicStorage>>(info->device_);
case MusicStorage::Role_StorageForceConnect: case MusicStorage::Role_StorageForceConnect:
if (!info->BestBackend()) return QVariant();
if (!info->device_) { if (!info->device_) {
if (info->database_id_ == -1 && info->BestBackend() && if (info->database_id_ == -1 &&
!info->BestBackend()->lister_->DeviceNeedsMount( !info->BestBackend()->lister_->DeviceNeedsMount(
info->BestBackend()->unique_id_)) { info->BestBackend()->unique_id_)) {
if (info->BestBackend()->lister_->AskForScan( if (info->BestBackend()->lister_->AskForScan(
@ -243,7 +244,7 @@ QVariant DeviceManager::data(const QModelIndex& index, int role) const {
} }
} }
const_cast<DeviceManager*>(this)->Connect(index.row()); const_cast<DeviceManager*>(this)->Connect(info);
} }
if (!info->device_) return QVariant(); if (!info->device_) return QVariant();
return QVariant::fromValue<std::shared_ptr<MusicStorage>>(info->device_); return QVariant::fromValue<std::shared_ptr<MusicStorage>>(info->device_);
@ -285,17 +286,17 @@ void DeviceManager::AddLister(DeviceLister* lister) {
lister->Start(); lister->Start();
} }
int DeviceManager::FindDeviceById(const QString& id) const { DeviceInfo* DeviceManager::FindDeviceById(const QString& id) const {
for (int i = 0; i < devices_.count(); ++i) { for (int i = 0; i < devices_.count(); ++i) {
for (const DeviceInfo::Backend& backend : devices_[i]->backends_) { 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<QUrl>& urls) const { DeviceInfo* DeviceManager::FindDeviceByUrl(const QList<QUrl>& urls) const {
if (urls.isEmpty()) return -1; if (urls.isEmpty()) return nullptr;
for (int i = 0; i < devices_.count(); ++i) { for (int i = 0; i < devices_.count(); ++i) {
for (const DeviceInfo::Backend& backend : devices_[i]->backends_) { for (const DeviceInfo::Backend& backend : devices_[i]->backends_) {
@ -304,11 +305,11 @@ int DeviceManager::FindDeviceByUrl(const QList<QUrl>& urls) const {
QList<QUrl> device_urls = QList<QUrl> device_urls =
backend.lister_->MakeDeviceUrls(backend.unique_id_); backend.lister_->MakeDeviceUrls(backend.unique_id_);
for (const QUrl& url : device_urls) { for (const QUrl& url : device_urls) {
if (urls.contains(url)) return i; if (urls.contains(url)) return devices_[i];
} }
} }
} }
return -1; return nullptr;
} }
void DeviceManager::PhysicalDeviceAdded(const QString& id) { void DeviceManager::PhysicalDeviceAdded(const QString& id) {
@ -317,9 +318,8 @@ void DeviceManager::PhysicalDeviceAdded(const QString& id) {
qLog(Info) << "Device added:" << id; qLog(Info) << "Device added:" << id;
// Do we have this device already? // Do we have this device already?
int i = FindDeviceById(id); DeviceInfo* info = FindDeviceById(id);
if (i != -1) { if (info) {
DeviceInfo* info = devices_[i];
for (int backend_index = 0; backend_index < info->backends_.count(); for (int backend_index = 0; backend_index < info->backends_.count();
++backend_index) { ++backend_index) {
if (info->backends_[backend_index].unique_id_ == id) { if (info->backends_[backend_index].unique_id_ == id) {
@ -327,14 +327,13 @@ void DeviceManager::PhysicalDeviceAdded(const QString& id) {
break; break;
} }
} }
QModelIndex idx = ItemToIndex(info);
emit dataChanged(index(i, 0), index(i, 0)); if (idx.isValid()) emit dataChanged(idx, idx);
} else { } else {
// Check if we have another device with the same URL // Check if we have another device with the same URL
i = FindDeviceByUrl(lister->MakeDeviceUrls(id)); info = FindDeviceByUrl(lister->MakeDeviceUrls(id));
if (i != -1) { if (info) {
// Add this device's lister to the existing device // Add this device's lister to the existing device
DeviceInfo* info = devices_[i];
info->backends_ << DeviceInfo::Backend(lister, id); info->backends_ << DeviceInfo::Backend(lister, id);
// If the user hasn't saved the device in the DB yet then overwrite the // If the user hasn't saved the device in the DB yet then overwrite the
@ -345,16 +344,17 @@ void DeviceManager::PhysicalDeviceAdded(const QString& id) {
info->LoadIcon(lister->DeviceIcons(id), info->friendly_name_); 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 { } else {
// It's a completely new device // It's a completely new device
DeviceInfo* info = new DeviceInfo(DeviceInfo::Type_Root, root_); DeviceInfo* info = new DeviceInfo(DeviceInfo::Type_Device, root_);
info->backends_ << DeviceInfo::Backend(lister, id); info->backends_ << DeviceInfo::Backend(lister, id);
info->friendly_name_ = lister->MakeFriendlyName(id); info->friendly_name_ = lister->MakeFriendlyName(id);
info->size_ = lister->DeviceCapacity(id); info->size_ = lister->DeviceCapacity(id);
info->LoadIcon(lister->DeviceIcons(id), info->friendly_name_); info->LoadIcon(lister->DeviceIcons(id), info->friendly_name_);
beginInsertRows(QModelIndex(), devices_.count(), devices_.count()); beginInsertRows(ItemToIndex(root_), devices_.count(), devices_.count());
devices_ << info; devices_ << info;
endInsertRows(); endInsertRows();
} }
@ -366,13 +366,14 @@ void DeviceManager::PhysicalDeviceRemoved(const QString& id) {
qLog(Info) << "Device removed:" << id; qLog(Info) << "Device removed:" << id;
int i = FindDeviceById(id); DeviceInfo* info = FindDeviceById(id);
if (i == -1) { if (!info) {
// Shouldn't happen // Shouldn't happen
return; return;
} }
DeviceInfo* info = devices_[i]; QModelIndex idx = ItemToIndex(info);
if (!idx.isValid()) return;
if (info->database_id_ != -1) { if (info->database_id_ != -1) {
// Keep the structure around, but just "disconnect" it // Keep the structure around, but just "disconnect" it
@ -387,9 +388,9 @@ void DeviceManager::PhysicalDeviceRemoved(const QString& id) {
if (info->device_ && info->device_->lister() == lister) if (info->device_ && info->device_->lister() == lister)
info->device_.reset(); 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 { } else {
// If this was the last lister for the device then remove it from the model // If this was the last lister for the device then remove it from the model
for (int backend_index = 0; backend_index < info->backends_.count(); for (int backend_index = 0; backend_index < info->backends_.count();
@ -401,16 +402,9 @@ void DeviceManager::PhysicalDeviceRemoved(const QString& id) {
} }
if (info->backends_.isEmpty()) { if (info->backends_.isEmpty()) {
beginRemoveRows(QModelIndex(), i, i); beginRemoveRows(ItemToIndex(root_), idx.row(), idx.row());
devices_.removeAt(i); devices_.removeAll(info);
root_->Delete(info->row);
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()));
}
endRemoveRows(); endRemoveRows();
} }
} }
@ -420,8 +414,8 @@ void DeviceManager::PhysicalDeviceChanged(const QString& id) {
DeviceLister* lister = qobject_cast<DeviceLister*>(sender()); DeviceLister* lister = qobject_cast<DeviceLister*>(sender());
Q_UNUSED(lister); Q_UNUSED(lister);
int i = FindDeviceById(id); DeviceInfo* info = FindDeviceById(id);
if (i == -1) { if (!info) {
// Shouldn't happen // Shouldn't happen
return; return;
} }
@ -429,14 +423,22 @@ void DeviceManager::PhysicalDeviceChanged(const QString& id) {
// TODO // TODO
} }
std::shared_ptr<ConnectedDevice> DeviceManager::Connect(int row) { std::shared_ptr<ConnectedDevice> DeviceManager::Connect(QModelIndex idx) {
DeviceInfo* info = devices_[row]; DeviceInfo* info = IndexToItem(idx);
if (!info) return std::shared_ptr<ConnectedDevice>();
return Connect(info);
}
std::shared_ptr<ConnectedDevice> DeviceManager::Connect(DeviceInfo* info) {
std::shared_ptr<ConnectedDevice> ret;
if (!info) return ret;
if (info->device_) // Already connected if (info->device_) // Already connected
return info->device_; return info->device_;
std::shared_ptr<ConnectedDevice> ret; if (!info->BestBackend() ||
!info->BestBackend()->lister_) // Not physically connected
if (!info->BestBackend()->lister_) // Not physically connected
return ret; return ret;
if (info->BestBackend()->lister_->DeviceNeedsMount( if (info->BestBackend()->lister_->DeviceNeedsMount(
@ -521,9 +523,9 @@ std::shared_ptr<ConnectedDevice> DeviceManager::Connect(int row) {
ret->Init(); ret->Init();
info->device_ = ret; info->device_ = ret;
QModelIndex index = ItemToIndex(info); QModelIndex idx = ItemToIndex(info);
if (!index.isValid()) return ret; if (!idx.isValid()) return ret;
emit dataChanged(index, index); emit dataChanged(idx, idx);
connect(info->device_.get(), SIGNAL(TaskStarted(int)), connect(info->device_.get(), SIGNAL(TaskStarted(int)),
SLOT(DeviceTaskStarted(int))); SLOT(DeviceTaskStarted(int)));
connect(info->device_.get(), SIGNAL(SongCountUpdated(int)), connect(info->device_.get(), SIGNAL(SongCountUpdated(int)),
@ -537,62 +539,75 @@ std::shared_ptr<ConnectedDevice> DeviceManager::Connect(int row) {
} }
void DeviceManager::DeviceConnectFinished(const QString& id, bool success) { void DeviceManager::DeviceConnectFinished(const QString& id, bool success) {
int row = FindDeviceById(id); DeviceInfo* info = FindDeviceById(id);
if (row != -1) { if (!info) return;
if (success) {
emit DeviceConnected(row); QModelIndex idx = ItemToIndex(info);
} else { if (!idx.isValid()) return;
devices_[row]->device_.reset();
} if (success) {
emit DeviceConnected(idx);
} else {
info->device_.reset();
} }
} }
std::shared_ptr<ConnectedDevice> DeviceManager::GetConnectedDevice( std::shared_ptr<ConnectedDevice> DeviceManager::GetConnectedDevice(
int row) const { QModelIndex idx) const {
return devices_[row]->device_; DeviceInfo* info = IndexToItem(idx);
if (!info) return std::shared_ptr<ConnectedDevice>();
return info->device_;
} }
int DeviceManager::GetDatabaseId(int row) const { std::shared_ptr<ConnectedDevice> DeviceManager::GetConnectedDevice(
return devices_[row]->database_id_; DeviceInfo* info) const {
if (!info) return std::shared_ptr<ConnectedDevice>();
return info->device_;
} }
DeviceLister* DeviceManager::GetLister(int row) const { int DeviceManager::GetDatabaseId(const QModelIndex& idx) const {
return devices_[row]->BestBackend()->lister_; if (!idx.isValid()) return -1;
DeviceInfo* info = IndexToItem(idx);
if (!info) return -1;
return info->database_id_;
} }
void DeviceManager::Disconnect(int row) { DeviceLister* DeviceManager::GetLister(QModelIndex idx) const {
DeviceInfo* info = devices_[row]; if (!idx.isValid()) return nullptr;
if (!info->device_) // Already disconnected
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_) // Already disconnected
return; return;
info->device_.reset(); info->device_.reset();
emit DeviceDisconnected(row); emit DeviceDisconnected(idx);
QModelIndex index = ItemToIndex(info); emit dataChanged(idx, idx);
if (!index.isValid()) return;
emit dataChanged(index, index);
} }
void DeviceManager::Forget(int row) { void DeviceManager::Forget(QModelIndex idx) {
DeviceInfo* info = devices_[row]; if (!idx.isValid()) return;
DeviceInfo* info = IndexToItem(idx);
if (!info) return;
if (info->database_id_ == -1) return; if (info->database_id_ == -1) return;
if (info->device_) Disconnect(row); if (info->device_) Disconnect(idx);
backend_->RemoveDevice(info->database_id_); backend_->RemoveDevice(info->database_id_);
info->database_id_ = -1; info->database_id_ = -1;
if (!info->BestBackend()->lister_) { if (!info->BestBackend() ||
(info->BestBackend() && !info->BestBackend()->lister_)) {
// It's not attached any more so remove it from the list // It's not attached any more so remove it from the list
beginRemoveRows(QModelIndex(), row, row); beginRemoveRows(ItemToIndex(root_), idx.row(), idx.row());
devices_.removeAt(row); devices_.removeAll(info);
root_->Delete(info->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()));
}
endRemoveRows(); endRemoveRows();
} else { } else {
// It's still attached, set the name and icon back to what they were // It's still attached, set the name and icon back to what they were
@ -603,21 +618,24 @@ void DeviceManager::Forget(int row) {
info->LoadIcon(info->BestBackend()->lister_->DeviceIcons(id), info->LoadIcon(info->BestBackend()->lister_->DeviceIcons(id),
info->friendly_name_); info->friendly_name_);
dataChanged(index(row, 0), index(row, 0)); dataChanged(idx, idx);
} }
} }
void DeviceManager::SetDeviceOptions(int row, const QString& friendly_name, void DeviceManager::SetDeviceOptions(QModelIndex idx,
const QString& friendly_name,
const QString& icon_name, const QString& icon_name,
MusicStorage::TranscodeMode mode, MusicStorage::TranscodeMode mode,
Song::FileType format) { Song::FileType format) {
DeviceInfo* info = devices_[row]; if (!idx.isValid()) return;
DeviceInfo* info = IndexToItem(idx);
if (!info) return;
info->friendly_name_ = friendly_name; info->friendly_name_ = friendly_name;
info->LoadIcon(QVariantList() << icon_name, friendly_name); info->LoadIcon(QVariantList() << icon_name, friendly_name);
info->transcode_mode_ = mode; info->transcode_mode_ = mode;
info->transcode_format_ = format; info->transcode_format_ = format;
emit dataChanged(index(row, 0), index(row, 0)); emit dataChanged(idx, idx);
if (info->database_id_ != -1) if (info->database_id_ != -1)
backend_->SetDeviceOptions(info->database_id_, friendly_name, icon_name, backend_->SetDeviceOptions(info->database_id_, friendly_name, icon_name,
@ -648,38 +666,41 @@ void DeviceManager::TasksChanged() {
for (const TaskManager::Task& task : tasks) { for (const TaskManager::Task& task : tasks) {
if (!active_tasks_.contains(task.id)) continue; if (!active_tasks_.contains(task.id)) continue;
QPersistentModelIndex index = active_tasks_[task.id]; QPersistentModelIndex idx = active_tasks_[task.id];
if (!index.isValid()) continue; if (!idx.isValid()) continue;
DeviceInfo* info = IndexToItem(index); DeviceInfo* info = IndexToItem(idx);
if (task.progress_max) if (task.progress_max)
info->task_percentage_ = float(task.progress) / task.progress_max * 100; info->task_percentage_ = float(task.progress) / task.progress_max * 100;
else else
info->task_percentage_ = 0; info->task_percentage_ = 0;
emit dataChanged(index, index); emit dataChanged(idx, idx);
finished_tasks.removeAll(index); finished_tasks.removeAll(idx);
} }
for (const QPersistentModelIndex& index : finished_tasks) { for (const QPersistentModelIndex& idx : finished_tasks) {
if (!index.isValid()) continue; if (!idx.isValid()) continue;
DeviceInfo* info = devices_[index.row()]; DeviceInfo* info = IndexToItem(idx);
if (!info) continue;
info->task_percentage_ = -1; 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) { void DeviceManager::UnmountAsync(QModelIndex idx) {
Q_ASSERT(QMetaObject::invokeMethod(this, "Unmount", Q_ARG(int, row))); Q_ASSERT(QMetaObject::invokeMethod(this, "Unmount", Q_ARG(QModelIndex, idx)));
} }
void DeviceManager::Unmount(int row) { void DeviceManager::Unmount(QModelIndex idx) {
DeviceInfo* info = devices_[row]; if (!idx.isValid()) return;
DeviceInfo* info = IndexToItem(idx);
if (!info) return;
if (info->database_id_ != -1 && !info->device_) return; if (info->database_id_ != -1 && !info->device_) return;
if (info->device_) Disconnect(row); if (info->device_) Disconnect(idx);
if (info->BestBackend()->lister_) if (info->BestBackend()->lister_)
info->BestBackend()->lister_->UnmountDevice( info->BestBackend()->lister_->UnmountDevice(
@ -690,13 +711,13 @@ void DeviceManager::DeviceSongCountUpdated(int count) {
ConnectedDevice* device = qobject_cast<ConnectedDevice*>(sender()); ConnectedDevice* device = qobject_cast<ConnectedDevice*>(sender());
if (!device) return; if (!device) return;
int row = FindDeviceById(device->unique_id()); DeviceInfo* info = FindDeviceById(device->unique_id());
if (row == -1) return; if (!info) return;
QModelIndex index = ItemToIndex(devices_[row]); QModelIndex idx = ItemToIndex(info);
if (!index.isValid()) return; if (!idx.isValid()) return;
emit dataChanged(index, index); emit dataChanged(idx, idx);
} }
void DeviceManager::LazyPopulate(DeviceInfo* parent, bool signal) { void DeviceManager::LazyPopulate(DeviceInfo* parent, bool signal) {

View File

@ -72,33 +72,35 @@ class DeviceManager : public SimpleTreeModel<DeviceInfo> {
} }
// Get info about devices // Get info about devices
int GetDatabaseId(int row) const; int GetDatabaseId(const QModelIndex& idx) const;
DeviceLister* GetLister(int row) const; DeviceLister* GetLister(QModelIndex idx) const;
std::shared_ptr<ConnectedDevice> GetConnectedDevice(int row) const; std::shared_ptr<ConnectedDevice> GetConnectedDevice(QModelIndex idx) const;
std::shared_ptr<ConnectedDevice> GetConnectedDevice(DeviceInfo* info) const;
int FindDeviceById(const QString& id) const; DeviceInfo* FindDeviceById(const QString& id) const;
int FindDeviceByUrl(const QList<QUrl>& url) const; DeviceInfo* FindDeviceByUrl(const QList<QUrl>& url) const;
// Actions on devices // Actions on devices
std::shared_ptr<ConnectedDevice> Connect(int row); std::shared_ptr<ConnectedDevice> Connect(DeviceInfo* info);
void Disconnect(int row); std::shared_ptr<ConnectedDevice> Connect(QModelIndex idx);
void Forget(int row); void Disconnect(QModelIndex idx);
void UnmountAsync(int row); void Forget(QModelIndex idx);
void UnmountAsync(QModelIndex idx);
void SetDeviceOptions(int row, const QString& friendly_name, void SetDeviceOptions(QModelIndex idx, const QString& friendly_name,
const QString& icon_name, const QString& icon_name,
MusicStorage::TranscodeMode mode, MusicStorage::TranscodeMode mode,
Song::FileType format); Song::FileType format);
// QAbstractItemModel // QAbstractItemModel
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex& idx, int role = Qt::DisplayRole) const;
public slots: public slots:
void Unmount(int row); void Unmount(QModelIndex idx);
signals: signals:
void DeviceConnected(int row); void DeviceConnected(QModelIndex idx);
void DeviceDisconnected(int row); void DeviceDisconnected(QModelIndex idx);
private slots: private slots:
void PhysicalDeviceAdded(const QString& id); void PhysicalDeviceAdded(const QString& id);

View File

@ -59,7 +59,7 @@ void DeviceProperties::SetDeviceManager(DeviceManager* manager) {
SLOT(ModelChanged())); SLOT(ModelChanged()));
} }
void DeviceProperties::ShowDevice(int row) { void DeviceProperties::ShowDevice(QModelIndex idx) {
if (ui_->icon->count() == 0) { if (ui_->icon->count() == 0) {
// Only load the icons the first time the dialog is shown // Only load the icons the first time the dialog is shown
QStringList icon_names = QStringList() QStringList icon_names = QStringList()
@ -97,7 +97,7 @@ void DeviceProperties::ShowDevice(int row) {
ui_->transcode_format->model()->sort(0); ui_->transcode_format->model()->sort(0);
} }
index_ = manager_->index(row, 0, QModelIndex()); index_ = idx;
// Basic information // Basic information
ui_->name->setText(index_.data(DeviceManager::Role_FriendlyName).toString()); ui_->name->setText(index_.data(DeviceManager::Role_FriendlyName).toString());
@ -137,7 +137,7 @@ void DeviceProperties::ModelChanged() {
void DeviceProperties::UpdateHardwareInfo() { void DeviceProperties::UpdateHardwareInfo() {
// Hardware information // Hardware information
QString id = index_.data(DeviceManager::Role_UniqueId).toString(); 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); QVariantMap info = lister->DeviceHardwareInfo(id);
// Remove empty items // Remove empty items
@ -180,9 +180,9 @@ void DeviceProperties::UpdateHardwareInfo() {
void DeviceProperties::UpdateFormats() { void DeviceProperties::UpdateFormats() {
QString id = index_.data(DeviceManager::Role_UniqueId).toString(); QString id = index_.data(DeviceManager::Role_UniqueId).toString();
DeviceLister* lister = manager_->GetLister(index_.row()); DeviceLister* lister = manager_->GetLister(index_);
std::shared_ptr<ConnectedDevice> device = std::shared_ptr<ConnectedDevice> device =
manager_->GetConnectedDevice(index_.row()); manager_->GetConnectedDevice(index_);
// Transcode mode // Transcode mode
MusicStorage::TranscodeMode mode = MusicStorage::TranscodeMode( MusicStorage::TranscodeMode mode = MusicStorage::TranscodeMode(
@ -255,11 +255,11 @@ void DeviceProperties::accept() {
icon_name = ui_->icon->currentItem()->data(Qt::UserRole).toString(); icon_name = ui_->icon->currentItem()->data(Qt::UserRole).toString();
} }
manager_->SetDeviceOptions(index_.row(), ui_->name->text(), icon_name, mode, manager_->SetDeviceOptions(index_, ui_->name->text(), icon_name, mode,
format); format);
} }
void DeviceProperties::OpenDevice() { manager_->Connect(index_.row()); } void DeviceProperties::OpenDevice() { manager_->Connect(index_); }
void DeviceProperties::UpdateFormatsFinished(QFuture<bool> future) { void DeviceProperties::UpdateFormatsFinished(QFuture<bool> future) {
updating_formats_ = false; updating_formats_ = false;

View File

@ -35,7 +35,7 @@ class DeviceProperties : public QDialog {
~DeviceProperties(); ~DeviceProperties();
void SetDeviceManager(DeviceManager* manager); void SetDeviceManager(DeviceManager* manager);
void ShowDevice(int row); void ShowDevice(QModelIndex idx);
public slots: public slots:
void accept(); void accept();

View File

@ -167,10 +167,10 @@ void DeviceView::SetApplication(Application* app) {
Q_ASSERT(app_ == nullptr); Q_ASSERT(app_ == nullptr);
app_ = app; app_ = app;
connect(app_->device_manager(), SIGNAL(DeviceConnected(int)), connect(app_->device_manager(), SIGNAL(DeviceConnected(QModelIndex)),
SLOT(DeviceConnected(int))); SLOT(DeviceConnected(QModelIndex)));
connect(app_->device_manager(), SIGNAL(DeviceDisconnected(int)), connect(app_->device_manager(), SIGNAL(DeviceDisconnected(QModelIndex)),
SLOT(DeviceDisconnected(int))); SLOT(DeviceDisconnected(QModelIndex)));
sort_model_ = new QSortFilterProxyModel(this); sort_model_ = new QSortFilterProxyModel(this);
sort_model_->setSourceModel(app_->device_manager()); sort_model_->setSourceModel(app_->device_manager());
@ -239,10 +239,9 @@ void DeviceView::contextMenuEvent(QContextMenuEvent* e) {
const QModelIndex library_index = MapToLibrary(menu_index_); const QModelIndex library_index = MapToLibrary(menu_index_);
if (device_index.isValid()) { if (device_index.isValid()) {
const bool is_plugged_in = const bool is_plugged_in = app_->device_manager()->GetLister(device_index);
app_->device_manager()->GetLister(device_index.row());
const bool is_remembered = const bool is_remembered =
app_->device_manager()->GetDatabaseId(device_index.row()) != -1; app_->device_manager()->GetDatabaseId(device_index) != -1;
forget_action_->setEnabled(is_remembered); forget_action_->setEnabled(is_remembered);
eject_action_->setEnabled(is_plugged_in); eject_action_->setEnabled(is_plugged_in);
@ -254,7 +253,7 @@ void DeviceView::contextMenuEvent(QContextMenuEvent* e) {
bool is_filesystem_device = false; bool is_filesystem_device = false;
if (parent_device_index.isValid()) { if (parent_device_index.isValid()) {
std::shared_ptr<ConnectedDevice> device = std::shared_ptr<ConnectedDevice> device =
app_->device_manager()->GetConnectedDevice(parent_device_index.row()); app_->device_manager()->GetConnectedDevice(parent_device_index);
if (device && !device->LocalPath().isEmpty()) is_filesystem_device = true; if (device && !device->LocalPath().isEmpty()) is_filesystem_device = true;
} }
@ -298,13 +297,12 @@ void DeviceView::Connect() {
MusicStorage::Role_StorageForceConnect); MusicStorage::Role_StorageForceConnect);
} }
void DeviceView::DeviceConnected(int row) { void DeviceView::DeviceConnected(QModelIndex idx) {
std::shared_ptr<ConnectedDevice> device = std::shared_ptr<ConnectedDevice> device =
app_->device_manager()->GetConnectedDevice(row); app_->device_manager()->GetConnectedDevice(idx);
if (!device) return; if (!device) return;
QModelIndex sort_idx = QModelIndex sort_idx = sort_model_->mapFromSource(idx);
sort_model_->mapFromSource(app_->device_manager()->index(row, 0));
QSortFilterProxyModel* sort_model = QSortFilterProxyModel* sort_model =
new QSortFilterProxyModel(device->model()); new QSortFilterProxyModel(device->model());
@ -317,9 +315,8 @@ void DeviceView::DeviceConnected(int row) {
expand(menu_index_); expand(menu_index_);
} }
void DeviceView::DeviceDisconnected(int row) { void DeviceView::DeviceDisconnected(QModelIndex idx) {
merged_model_->RemoveSubModel( merged_model_->RemoveSubModel(sort_model_->mapFromSource(idx));
sort_model_->mapFromSource(app_->device_manager()->index(row, 0)));
} }
void DeviceView::Forget() { void DeviceView::Forget() {
@ -327,9 +324,8 @@ void DeviceView::Forget() {
QString unique_id = app_->device_manager() QString unique_id = app_->device_manager()
->data(device_idx, DeviceManager::Role_UniqueId) ->data(device_idx, DeviceManager::Role_UniqueId)
.toString(); .toString();
if (app_->device_manager()->GetLister(device_idx.row()) && if (app_->device_manager()->GetLister(device_idx) &&
app_->device_manager()->GetLister(device_idx.row())->AskForScan( app_->device_manager()->GetLister(device_idx)->AskForScan(unique_id)) {
unique_id)) {
std::unique_ptr<QMessageBox> dialog(new QMessageBox( std::unique_ptr<QMessageBox> dialog(new QMessageBox(
QMessageBox::Question, tr("Forget device"), QMessageBox::Question, tr("Forget device"),
tr("Forgetting a device will remove it from this list and Clementine " tr("Forgetting a device will remove it from this list and Clementine "
@ -342,11 +338,11 @@ void DeviceView::Forget() {
if (dialog->clickedButton() != forget) return; if (dialog->clickedButton() != forget) return;
} }
app_->device_manager()->Forget(device_idx.row()); app_->device_manager()->Forget(device_idx);
} }
void DeviceView::Properties() { void DeviceView::Properties() {
properties_dialog_->ShowDevice(MapToDevice(menu_index_).row()); properties_dialog_->ShowDevice(MapToDevice(menu_index_));
} }
void DeviceView::mouseDoubleClickEvent(QMouseEvent* event) { void DeviceView::mouseDoubleClickEvent(QMouseEvent* event) {
@ -355,7 +351,7 @@ void DeviceView::mouseDoubleClickEvent(QMouseEvent* event) {
QModelIndex merged_index = indexAt(event->pos()); QModelIndex merged_index = indexAt(event->pos());
QModelIndex device_index = MapToDevice(merged_index); QModelIndex device_index = MapToDevice(merged_index);
if (device_index.isValid()) { if (device_index.isValid()) {
if (!app_->device_manager()->GetConnectedDevice(device_index.row())) { if (!app_->device_manager()->GetConnectedDevice(device_index)) {
menu_index_ = merged_index; menu_index_ = merged_index;
Connect(); Connect();
} }
@ -436,7 +432,7 @@ void DeviceView::Organise() {
void DeviceView::Unmount() { void DeviceView::Unmount() {
QModelIndex device_idx = MapToDevice(menu_index_); 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) { void DeviceView::DeleteFinished(const SongList& songs_with_errors) {

View File

@ -71,8 +71,8 @@ class DeviceView : public AutoExpandingTreeView {
void Organise(); void Organise();
void Delete(); void Delete();
void DeviceConnected(int row); void DeviceConnected(QModelIndex idx);
void DeviceDisconnected(int row); void DeviceDisconnected(QModelIndex idx);
void DeleteFinished(const SongList& songs_with_errors); void DeleteFinished(const SongList& songs_with_errors);

View File

@ -40,7 +40,7 @@ FilesystemDevice::FilesystemDevice(const QUrl& url, DeviceLister* lister,
watcher_->set_device_name( watcher_->set_device_name(
manager manager
->data(manager->index(manager->FindDeviceById(unique_id), 0), ->data(manager->ItemToIndex(manager->FindDeviceById(unique_id)),
DeviceManager::Role_FriendlyName) DeviceManager::Role_FriendlyName)
.toString()); .toString());
watcher_->set_backend(backend_); watcher_->set_backend(backend_);