diff --git a/src/library/librarymodel.cpp b/src/library/librarymodel.cpp index 258a4ce11..3b1b01cc5 100644 --- a/src/library/librarymodel.cpp +++ b/src/library/librarymodel.cpp @@ -671,10 +671,11 @@ void LibraryModel::ResetAsyncQueryFinished() { init_task_id_ = -1; } - reset(); + endResetModel(); } void LibraryModel::BeginReset() { + beginResetModel(); delete root_; song_nodes_.clear(); container_nodes_[0].clear(); @@ -706,7 +707,7 @@ void LibraryModel::Reset() { // Populate top level LazyPopulate(root_, false); - reset(); + endResetModel(); } void LibraryModel::InitQuery(GroupBy type, LibraryQuery* q) { diff --git a/src/library/libraryview.cpp b/src/library/libraryview.cpp index 8a12e2287..ab1758529 100644 --- a/src/library/libraryview.cpp +++ b/src/library/libraryview.cpp @@ -185,6 +185,111 @@ LibraryView::LibraryView(QWidget* parent) LibraryView::~LibraryView() { } +void LibraryView::SaveFocus() { + QModelIndex current = currentIndex(); + QVariant type = model()->data(current, LibraryModel::Role_Type); + if (!type.isValid() || !(type.toInt() == LibraryItem::Type_Song || + type.toInt() == LibraryItem::Type_Container || + type.toInt() == LibraryItem::Type_Divider)) { + return; + } + + last_selected_path_.clear(); + last_selected_song_ = Song(); + last_selected_container_ = QString(); + + switch (type.toInt()) { + case LibraryItem::Type_Song: { + QModelIndex index = qobject_cast(model()) + ->mapToSource(current); + SongList songs = app_->library_model()->GetChildSongs(index); + if (!songs.isEmpty()) { + last_selected_song_ = songs.last(); + } + break; + } + + case LibraryItem::Type_Container: + case LibraryItem::Type_Divider: { + QString text = model()->data(current, LibraryModel::Role_SortText).toString(); + last_selected_container_ = text; + break; + } + + default: + return; + } + + SaveContainerPath(current); +} + +void LibraryView::SaveContainerPath(const QModelIndex& child) { + QModelIndex current = model()->parent(child); + QVariant type = model()->data(current, LibraryModel::Role_Type); + if (!type.isValid() || !(type.toInt() == LibraryItem::Type_Container || + type.toInt() == LibraryItem::Type_Divider)) { + return; + } + + QString text = model()->data(current, LibraryModel::Role_SortText).toString(); + last_selected_path_ << text; + SaveContainerPath(current); +} + +void LibraryView::RestoreFocus() { + if (last_selected_container_.isEmpty() && last_selected_song_.url().isEmpty()) { + return; + } + RestoreLevelFocus(); +} + +bool LibraryView::RestoreLevelFocus(const QModelIndex& parent) { + if (model()->canFetchMore(parent)) { + model()->fetchMore(parent); + } + int rows = model()->rowCount(parent); + for (int i = 0; i < rows; i++) { + QModelIndex current = model()->index(i, 0, parent); + QVariant type = model()->data(current, LibraryModel::Role_Type); + switch (type.toInt()) { + case LibraryItem::Type_Song: + if (!last_selected_song_.url().isEmpty()) { + QModelIndex index = qobject_cast(model()) + ->mapToSource(current); + SongList songs = app_->library_model()->GetChildSongs(index); + foreach (const Song& song, songs) { + if (song == last_selected_song_) { + setCurrentIndex(current); + return true; + } + } + } + break; + + case LibraryItem::Type_Container: + case LibraryItem::Type_Divider: { + QString text = model()->data(current, LibraryModel::Role_SortText).toString(); + if (!last_selected_container_.isEmpty() && last_selected_container_ == text) { + emit expand(current); + setCurrentIndex(current); + return true; + } else if (last_selected_path_.contains(text)) { + emit expand(current); + // If a selected container or song were not found, we've got into a wrong subtree + // (happens with "unknown" all the time) + if (!RestoreLevelFocus(current)) { + emit collapse(current); + } else { + return true; + } + } + break; + } + } + } + return false; +} + void LibraryView::ReloadSettings() { QSettings s; s.beginGroup(kSettingsGroup); diff --git a/src/library/libraryview.h b/src/library/libraryview.h index 0003b8bb2..85afe7e8a 100644 --- a/src/library/libraryview.h +++ b/src/library/libraryview.h @@ -73,6 +73,9 @@ class LibraryView : public AutoExpandingTreeView { void FilterReturnPressed(); + void SaveFocus(); + void RestoreFocus(); + signals: void ShowConfigDialog(); @@ -107,6 +110,8 @@ class LibraryView : public AutoExpandingTreeView { private: void RecheckIsEmpty(); void ShowInVarious(bool on); + bool RestoreLevelFocus(const QModelIndex& parent = QModelIndex()); + void SaveContainerPath(const QModelIndex& child); private: Application* app_; @@ -139,6 +144,11 @@ class LibraryView : public AutoExpandingTreeView { boost::scoped_ptr edit_tag_dialog_; bool is_in_keyboard_search_; + + // Save focus + Song last_selected_song_; + QString last_selected_container_; + QSet last_selected_path_; }; #endif // LIBRARYVIEW_H diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 559b78775..893b03804 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -433,6 +433,8 @@ MainWindow::MainWindow(Application* app, connect(library_view_->view(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*))); connect(library_view_->view(), SIGNAL(ShowConfigDialog()), SLOT(ShowLibraryConfig())); connect(app_->library_model(), SIGNAL(TotalSongCountUpdated(int)), library_view_->view(), SLOT(TotalSongCountUpdated(int))); + connect(app_->library_model(), SIGNAL(modelAboutToBeReset()), library_view_->view(), SLOT(SaveFocus())); + connect(app_->library_model(), SIGNAL(modelReset()), library_view_->view(), SLOT(RestoreFocus())); connect(app_->task_manager(), SIGNAL(PauseLibraryWatchers()), app_->library(), SLOT(PauseWatcher())); connect(app_->task_manager(), SIGNAL(ResumeLibraryWatchers()), app_->library(), SLOT(ResumeWatcher()));