Skip to content

Commit

Permalink
Library: allow views to save/restore the current state
Browse files Browse the repository at this point in the history
library views store states in a QCache in WTrackTableView incl.
 * track selection
 * current index (focused track)
 * scroll positions, horizontal + vertical
with a unique key composed of
 * feature (playlist/crate/browse ...)
 * child item (playlistId/crateId/directory ...)
 * current search term

Credits for this and the required commits go to
https://github.com/poelzi <[email protected]>
I just boiled down some picks from stalled #3063
  • Loading branch information
ronso0 committed Aug 9, 2021
1 parent 7297b1d commit 4966ec3
Show file tree
Hide file tree
Showing 15 changed files with 188 additions and 134 deletions.
8 changes: 7 additions & 1 deletion src/library/autodj/dlgautodj.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
#include "library/trackcollection.h"
#include "preferences/usersettings.h"
#include "track/track_decl.h"
#include "widget/wtracktableview.h"

class PlaylistTableModel;
class WLibrary;
class WTrackTableView;

class DlgAutoDJ : public QWidget, public Ui::DlgAutoDJ, public LibraryView {
Q_OBJECT
Expand All @@ -33,6 +33,12 @@ class DlgAutoDJ : public QWidget, public Ui::DlgAutoDJ, public LibraryView {
void loadSelectedTrack() override;
void loadSelectedTrackToGroup(const QString& group, bool play) override;
void moveSelection(int delta) override;
void saveCurrentViewState() override {
m_pTrackTableView->saveCurrentViewState();
};
void restoreCurrentViewState() override {
m_pTrackTableView->restoreCurrentViewState();
};

public slots:
void shufflePlaylistButton(bool buttonChecked);
Expand Down
12 changes: 9 additions & 3 deletions src/library/dlganalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
#include <QButtonGroup>
#include <QItemSelection>

#include "preferences/usersettings.h"
#include "analyzer/analyzerprogress.h"
#include "library/analysislibrarytablemodel.h"
#include "library/libraryview.h"
#include "library/ui_dlganalysis.h"
#include "analyzer/analyzerprogress.h"
#include "preferences/usersettings.h"
#include "widget/wanalysislibrarytableview.h"

class AnalysisLibraryTableModel;
class WAnalysisLibraryTableView;
class Library;
class WLibrary;

Expand All @@ -34,6 +34,12 @@ class DlgAnalysis : public QWidget, public Ui::DlgAnalysis, public virtual Libra
inline const QString currentSearch() {
return m_pAnalysisLibraryTableModel->currentSearch();
}
void saveCurrentViewState() override {
m_pAnalysisLibraryTableView->saveCurrentViewState();
};
void restoreCurrentViewState() override {
m_pAnalysisLibraryTableView->restoreCurrentViewState();
};

public slots:
void tableSelectionChanged(const QItemSelection& selected,
Expand Down
14 changes: 10 additions & 4 deletions src/library/dlghidden.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

#include <QItemSelection>

#include "library/ui_dlghidden.h"
#include "preferences/usersettings.h"
#include "controllers/keyboard/keyboardeventfilter.h"
#include "library/library.h"
#include "library/libraryview.h"
#include "controllers/keyboard/keyboardeventfilter.h"
#include "library/ui_dlghidden.h"
#include "preferences/usersettings.h"
#include "widget/wtracktableview.h"

class WLibrary;
class WTrackTableView;
class HiddenTableModel;

class DlgHidden : public QWidget, public Ui::DlgHidden, public LibraryView {
Expand All @@ -25,6 +25,12 @@ class DlgHidden : public QWidget, public Ui::DlgHidden, public LibraryView {
bool hasFocus() const override;
void onSearch(const QString& text) override;
QString currentSearch();
void saveCurrentViewState() override {
m_pTrackTableView->saveCurrentViewState();
};
void restoreCurrentViewState() override {
m_pTrackTableView->restoreCurrentViewState();
};

public slots:
void clicked();
Expand Down
14 changes: 10 additions & 4 deletions src/library/dlgmissing.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

#include <QItemSelection>

#include "library/ui_dlgmissing.h"
#include "preferences/usersettings.h"
#include "controllers/keyboard/keyboardeventfilter.h"
#include "library/library.h"
#include "library/libraryview.h"
#include "controllers/keyboard/keyboardeventfilter.h"
#include "library/ui_dlgmissing.h"
#include "preferences/usersettings.h"
#include "widget/wtracktableview.h"

class WLibrary;
class WTrackTableView;
class MissingTableModel;

class DlgMissing : public QWidget, public Ui::DlgMissing, public LibraryView {
Expand All @@ -25,6 +25,12 @@ class DlgMissing : public QWidget, public Ui::DlgMissing, public LibraryView {
bool hasFocus() const override;
void onSearch(const QString& text) override;
QString currentSearch();
void saveCurrentViewState() override {
m_pTrackTableView->saveCurrentViewState();
};
void restoreCurrentViewState() override {
m_pTrackTableView->restoreCurrentViewState();
};

public slots:
void clicked();
Expand Down
9 changes: 8 additions & 1 deletion src/library/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,14 @@ void Library::bindLibraryWidget(
&Library::switchToView,
pLibraryWidget,
&WLibrary::switchToView);

connect(this,
&Library::saveModelState,
pTrackTableView,
&WTrackTableView::slotSaveCurrentViewState);
connect(this,
&Library::restoreModelState,
pTrackTableView,
&WTrackTableView::slotRestoreCurrentViewState);
connect(pTrackTableView,
&WTrackTableView::trackSelected,
this,
Expand Down
2 changes: 1 addition & 1 deletion src/library/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class Library: public QObject {
void onSkinLoadFinished();

signals:
void showTrackModel(QAbstractItemModel* model);
void showTrackModel(QAbstractItemModel* model, bool restoreState = true);
void switchToView(const QString& view);
void loadTrack(TrackPointer pTrack);
void loadTrackToPlayer(TrackPointer pTrack, const QString& group, bool play = false);
Expand Down
2 changes: 1 addition & 1 deletion src/library/libraryfeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class LibraryFeature : public QObject {
Q_UNUSED(index);
}
signals:
void showTrackModel(QAbstractItemModel* model);
void showTrackModel(QAbstractItemModel* model, bool restoreState = true);
void switchToView(const QString& view);
void loadTrack(TrackPointer pTrack);
void loadTrackToPlayer(TrackPointer pTrack, const QString& group, bool play = false);
Expand Down
2 changes: 2 additions & 0 deletions src/library/libraryview.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class LibraryView {
virtual void slotAddToAutoDJBottom() {};
virtual void slotAddToAutoDJTop() {};
virtual void slotAddToAutoDJReplace() {};
virtual void saveCurrentViewState(){};
virtual void restoreCurrentViewState(){};

/// If applicable, requests that the LibraryView load the selected track to
/// the specified group. Does nothing otherwise.
Expand Down
4 changes: 4 additions & 0 deletions src/library/recording/dlgrecording.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ DlgRecording::DlgRecording(
&RecordingManager::durationRecorded,
this,
&DlgRecording::slotDurationRecorded);
connect(&m_browseModel,
&BrowseTableModel::restoreModelState,
m_pTrackTableView,
&WTrackTableView::restoreCurrentViewState);

QBoxLayout* box = qobject_cast<QBoxLayout*>(layout());
VERIFY_OR_DEBUG_ASSERT(box) { //Assumes the form layout is a QVBox/QHBoxLayout!
Expand Down
8 changes: 7 additions & 1 deletion src/library/recording/dlgrecording.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#include "preferences/usersettings.h"
#include "recording/recordingmanager.h"
#include "track/track_decl.h"
#include "widget/wtracktableview.h"

class PlaylistTableModel;
class WLibrary;
class WTrackTableView;

class DlgRecording : public QWidget, public Ui::DlgRecording, public virtual LibraryView {
Q_OBJECT
Expand All @@ -33,6 +33,12 @@ class DlgRecording : public QWidget, public Ui::DlgRecording, public virtual Lib
void loadSelectedTrackToGroup(const QString& group, bool play) override;
void moveSelection(int delta) override;
inline const QString currentSearch() { return m_proxyModel.currentSearch(); }
void saveCurrentViewState() override {
m_pTrackTableView->saveCurrentViewState();
};
void restoreCurrentViewState() override {
m_pTrackTableView->restoreCurrentViewState();
};

public slots:
void slotRecordingStateChanged(bool);
Expand Down
19 changes: 5 additions & 14 deletions src/widget/wlibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,9 @@ void WLibrary::switchToView(const QString& name) {
QMutexLocker lock(&m_mutex);
//qDebug() << "WLibrary::switchToView" << name;

WTrackTableView* ttView = qobject_cast<WTrackTableView*>(
LibraryView* oldLibraryView = dynamic_cast<LibraryView*>(
currentWidget());

if (ttView != nullptr){
//qDebug("trying to save position");
ttView->saveCurrentVScrollBarPos();
}

QWidget* widget = m_viewMap.value(name, nullptr);
if (widget != nullptr) {
LibraryView * lview = dynamic_cast<LibraryView*>(widget);
Expand All @@ -72,17 +67,13 @@ void WLibrary::switchToView(const QString& name) {
return;
}
if (currentWidget() != widget) {
if (oldLibraryView) {
oldLibraryView->saveCurrentViewState();
}
//qDebug() << "WLibrary::setCurrentWidget" << name;
setCurrentWidget(widget);
lview->onShow();
}

WTrackTableView* ttWidgetView = qobject_cast<WTrackTableView*>(
widget);

if (ttWidgetView != nullptr){
qDebug("trying to restore position");
ttWidgetView->restoreCurrentVScrollBarPos();
lview->restoreCurrentViewState();
}
}
}
Expand Down
122 changes: 79 additions & 43 deletions src/widget/wlibrarytableview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
#include "widget/wskincolor.h"
#include "widget/wwidget.h"

namespace {
// number of entries in the model cache
constexpr int kModelCacheSize = 1000;
} // namespace

WLibraryTableView::WLibraryTableView(QWidget* parent,
UserSettingsPointer pConfig,
const ConfigKey& vScrollBarPosKey)
UserSettingsPointer pConfig)
: QTableView(parent),
m_pConfig(pConfig),
m_vScrollBarPosKey(vScrollBarPosKey) {
loadVScrollBarPosState();

m_modelStateCache(kModelCacheSize) {
// Setup properties for table

// Editing starts when clicking on an already selected item.
Expand Down Expand Up @@ -53,37 +55,9 @@ WLibraryTableView::WLibraryTableView(QWidget* parent,
}

WLibraryTableView::~WLibraryTableView() {
m_modelStateCache.clear();
}

void WLibraryTableView::loadVScrollBarPosState() {
// TODO(rryan) I'm not sure I understand the value in saving the v-scrollbar
// position across restarts of Mixxx. Now that we have different views for
// each mode, the views should just maintain their scrollbar position when
// you switch views. We should discuss this.
m_noSearchVScrollBarPos = m_pConfig->getValueString(m_vScrollBarPosKey).toInt();
}

void WLibraryTableView::restoreNoSearchVScrollBarPos() {
// Restore the scrollbar's position (scroll to that spot)
// when the search has been cleared
//qDebug() << "restoreNoSearchVScrollBarPos()" << m_noSearchVScrollBarPos;
updateGeometries();
verticalScrollBar()->setValue(m_noSearchVScrollBarPos);
}

void WLibraryTableView::saveNoSearchVScrollBarPos() {
// Save the scrollbar's position so we can return here after
// a search is cleared.
//qDebug() << "saveNoSearchVScrollBarPos()" << m_noSearchVScrollBarPos;
m_noSearchVScrollBarPos = verticalScrollBar()->value();
}


void WLibraryTableView::saveVScrollBarPosState() {
//Save the vertical scrollbar position.
int scrollbarPosition = verticalScrollBar()->value();
m_pConfig->set(m_vScrollBarPosKey, ConfigValue(scrollbarPosition));
}

void WLibraryTableView::moveSelection(int delta) {
QAbstractItemModel* pModel = model();
Expand Down Expand Up @@ -131,19 +105,63 @@ void WLibraryTableView::moveSelection(int delta) {
}
}

void WLibraryTableView::saveVScrollBarPos(TrackModel* key){
m_vScrollBarPosValues[key] = verticalScrollBar()->value();
void WLibraryTableView::saveTrackModelState(
const QAbstractItemModel* model, const QString& key) {
//qDebug() << "saveTrackModelState:" << model << key;
VERIFY_OR_DEBUG_ASSERT(model) {
return;
}
VERIFY_OR_DEBUG_ASSERT(!key.isEmpty()) {
return;
}
ModelState* state = m_modelStateCache.take(key);
if (!state) {
state = new ModelState();
}
state->verticalScrollPosition = verticalScrollBar()->value();
state->horizontalScrollPosition = horizontalScrollBar()->value();
if (!selectionModel()->selectedIndexes().isEmpty()) {
state->selectionIndex = selectionModel()->selectedIndexes();
} else {
state->selectionIndex = QModelIndexList();
}
const QModelIndex currIndex = selectionModel()->currentIndex();
if (currIndex.isValid()) {
state->currentIndex = currIndex;
} else {
state->currentIndex = QModelIndex();
}
m_modelStateCache.insert(key, state, 1);
}

void WLibraryTableView::restoreVScrollBarPos(TrackModel* key){
updateGeometries();
void WLibraryTableView::restoreTrackModelState(
const QAbstractItemModel* model, const QString& key) {
//qDebug() << "restoreTrackModelState:" << model << key;
//<< m_vModelState.keys();
if (model == nullptr) {
return;
}

if (m_vScrollBarPosValues.contains(key)){
verticalScrollBar()->setValue(m_vScrollBarPosValues[key]);
}else{
m_vScrollBarPosValues[key] = 0;
verticalScrollBar()->setValue(0);
ModelState* state = m_modelStateCache.take(key);
if (!state) {
return;
}

verticalScrollBar()->setValue(state->verticalScrollPosition);
horizontalScrollBar()->setValue(state->horizontalScrollPosition);

auto selection = selectionModel();
selection->clearSelection();
if (!state->selectionIndex.isEmpty()) {
for (auto index : qAsConst(state->selectionIndex)) {
selection->select(index, QItemSelectionModel::Select);
}
}
if (state->currentIndex.isValid()) {
selection->setCurrentIndex(state->currentIndex, QItemSelectionModel::NoUpdate);
}
// reinsert the state into the cache
m_modelStateCache.insert(key, state, 1);
}

void WLibraryTableView::setTrackTableFont(const QFont& font) {
Expand Down Expand Up @@ -176,6 +194,24 @@ void WLibraryTableView::setSelectedClick(bool enable) {
}
}

void WLibraryTableView::saveCurrentViewState() {
const QAbstractItemModel* currentModel = model();
QString key = getStateKey();
if (!currentModel || key.isEmpty()) {
return;
}
saveTrackModelState(currentModel, key);
}

void WLibraryTableView::restoreCurrentViewState() {
const QAbstractItemModel* currentModel = model();
QString key = getStateKey();
if (!currentModel || key.isEmpty()) {
return;
}
restoreTrackModelState(currentModel, key);
}

void WLibraryTableView::focusInEvent(QFocusEvent* event) {
QTableView::focusInEvent(event);

Expand Down
Loading

0 comments on commit 4966ec3

Please sign in to comment.