mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-23 16:28:19 +01:00
Clear cached indexes in InternetModel when rows are removed
When opening a context menu on an internet item, the selected items are stored in the InternetModel instance. In cases when the items are removed, certain menu options can cause a crash. A specific case is downloading a podcast when the user has chosen to limit the number of visible episodes. The subtree for the podcast is rebuilt after the download completes, so if a context menu was opened during the download time, selecting the append to playlist option will attempt to operate on bad indexes. This fix uses the rowsAboutToBeRemoved signal to remove these stored indexes. There are likely another rare cases where the indexes can become invalid. For example, sibling items within a subtree may be removed, causing the stored indexes to become incorrect or out of range.
This commit is contained in:
parent
fe88d8f8b0
commit
ccba649f62
@ -81,6 +81,8 @@ InternetModel::InternetModel(Application* app, QObject* parent)
|
|||||||
Q_ASSERT(sServices->isEmpty());
|
Q_ASSERT(sServices->isEmpty());
|
||||||
|
|
||||||
merged_model_->setSourceModel(this);
|
merged_model_->setSourceModel(this);
|
||||||
|
connect(merged_model_, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
|
||||||
|
SLOT(RowsAboutToBeRemoved(QModelIndex, int, int)));
|
||||||
|
|
||||||
AddService(new ClassicalRadioService(app, this));
|
AddService(new ClassicalRadioService(app, this));
|
||||||
AddService(new DigitallyImportedService(app, this));
|
AddService(new DigitallyImportedService(app, this));
|
||||||
@ -234,6 +236,48 @@ int InternetModel::rowCount(const QModelIndex& parent) const {
|
|||||||
return QStandardItemModel::rowCount(parent);
|
return QStandardItemModel::rowCount(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InternetModel::RowsAboutToBeRemoved(const QModelIndex& parent, int first,
|
||||||
|
int last) {
|
||||||
|
for (int i = first; i <= last; i++) {
|
||||||
|
// Assuming we're always looking at column 0
|
||||||
|
QModelIndex removing =
|
||||||
|
merged_model_->mapToSource(merged_model_->index(first, 0, parent));
|
||||||
|
IndexAboutToBeRemoved(removing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternetModel::IndexAboutToBeRemoved(const QModelIndex& index) {
|
||||||
|
if (IsInLineage(current_index_, index)) {
|
||||||
|
qLog(Debug) << "Removing current index";
|
||||||
|
// Invalidate index
|
||||||
|
current_index_ = QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndexList::iterator iter = selected_indexes_.begin();
|
||||||
|
while (iter != selected_indexes_.end()) {
|
||||||
|
if (IsInLineage(*iter, index)) {
|
||||||
|
qLog(Debug) << "Removing selected item";
|
||||||
|
iter = selected_indexes_.erase(iter);
|
||||||
|
} else {
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InternetModel::IsInLineage(QModelIndex d, const QModelIndex& a) {
|
||||||
|
if (!a.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (d.isValid()) {
|
||||||
|
if (d == a) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
d = d.parent();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool InternetModel::IsPlayable(const QModelIndex& index) const {
|
bool InternetModel::IsPlayable(const QModelIndex& index) const {
|
||||||
QVariant behaviour = index.data(Role_PlayBehaviour);
|
QVariant behaviour = index.data(Role_PlayBehaviour);
|
||||||
if (!behaviour.isValid()) return false;
|
if (!behaviour.isValid()) return false;
|
||||||
|
@ -186,8 +186,14 @@ class InternetModel : public QStandardItemModel {
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ServiceDeleted();
|
void ServiceDeleted();
|
||||||
|
void RowsAboutToBeRemoved(const QModelIndex& parent, int first, int last);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Index is about to be removed from the merged model
|
||||||
|
void IndexAboutToBeRemoved(const QModelIndex& index);
|
||||||
|
// Determine if d or one of its ancestors is equal to a.
|
||||||
|
bool IsInLineage(QModelIndex d, const QModelIndex& a);
|
||||||
|
|
||||||
QMap<InternetService*, ServiceItem> shown_services_;
|
QMap<InternetService*, ServiceItem> shown_services_;
|
||||||
|
|
||||||
static QMap<QString, InternetService*>* sServices;
|
static QMap<QString, InternetService*>* sServices;
|
||||||
|
Loading…
Reference in New Issue
Block a user