From 84ce5022ce9e65d753354bc472b7f28fbc014ebf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 9 Nov 2018 11:26:00 +0100 Subject: QFileDialog (widgets-based): Remember selection in history Extend the history by a persistent model index list reflecting the selection. [ChangeLog][QtWidgets][QFileDialog] The widgets-based dialog now remembers the selected files when navigating the history Fixes: QTBUG-71415 Change-Id: I86774439be070c1b922acd0e9a27d029f02f68d3 Reviewed-by: Shawn Rutledge --- src/widgets/dialogs/qfiledialog.cpp | 62 +++++++++++++++++++++++++++++++------ src/widgets/dialogs/qfiledialog_p.h | 12 ++++++- 2 files changed, 63 insertions(+), 11 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index f772eb1241..fcac12068d 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -77,6 +77,8 @@ #include #endif +#include + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QUrl, lastVisitedDir) @@ -3372,6 +3374,18 @@ void QFileDialogPrivate::_q_goHome() q->setDirectory(QDir::homePath()); } + +void QFileDialogPrivate::saveHistorySelection() +{ + if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size()) + return; + auto &item = currentHistory[currentHistoryLocation]; + item.selection.clear(); + const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows(); + for (const auto &index : selectedIndexes) + item.selection.append(QPersistentModelIndex(index)); +} + /*! \internal @@ -3385,17 +3399,49 @@ void QFileDialogPrivate::_q_pathChanged(const QString &newPath) qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath)); q->setHistory(qFileDialogUi->lookInCombo->history()); - if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation) != QDir::toNativeSeparators(newPath)) { + const QString newNativePath = QDir::toNativeSeparators(newPath); + + // equal paths indicate this was invoked by _q_navigateBack/Forward() + if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) { + if (currentHistoryLocation >= 0) + saveHistorySelection(); while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.count()) { currentHistory.removeLast(); } - currentHistory.append(QDir::toNativeSeparators(newPath)); + currentHistory.append({newNativePath, PersistentModelIndexList()}); ++currentHistoryLocation; } qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1); qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0); } +void QFileDialogPrivate::navigate(HistoryItem &historyItem) +{ + Q_Q(QFileDialog); + q->setDirectory(historyItem.path); + // Restore selection unless something has changed in the file system + if (qFileDialogUi.isNull() || historyItem.selection.isEmpty()) + return; + if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(), + [](const QPersistentModelIndex &i) { return !i.isValid(); })) { + historyItem.selection.clear(); + return; + } + + QAbstractItemView *view = q->viewMode() == QFileDialog::List + ? static_cast(qFileDialogUi->listView) + : static_cast(qFileDialogUi->treeView); + auto selectionModel = view->selectionModel(); + const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select + | QItemSelectionModel::Rows; + selectionModel->select(historyItem.selection.constFirst(), + flags | QItemSelectionModel::Clear | QItemSelectionModel::Current); + for (int i = 1, size = historyItem.selection.size(); i < size; ++i) + selectionModel->select(historyItem.selection.at(i), flags); + + view->scrollTo(historyItem.selection.constFirst()); +} + /*! \internal @@ -3403,11 +3449,9 @@ void QFileDialogPrivate::_q_pathChanged(const QString &newPath) */ void QFileDialogPrivate::_q_navigateBackward() { - Q_Q(QFileDialog); if (!currentHistory.isEmpty() && currentHistoryLocation > 0) { - --currentHistoryLocation; - QString previousHistory = currentHistory.at(currentHistoryLocation); - q->setDirectory(previousHistory); + saveHistorySelection(); + navigate(currentHistory[--currentHistoryLocation]); } } @@ -3418,11 +3462,9 @@ void QFileDialogPrivate::_q_navigateBackward() */ void QFileDialogPrivate::_q_navigateForward() { - Q_Q(QFileDialog); if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) { - ++currentHistoryLocation; - QString nextHistory = currentHistory.at(currentHistoryLocation); - q->setDirectory(nextHistory); + saveHistorySelection(); + navigate(currentHistory[++currentHistoryLocation]); } } diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index 7e53b61031..dcf147348f 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -116,6 +116,14 @@ class Q_WIDGETS_EXPORT QFileDialogPrivate : public QDialogPrivate Q_DECLARE_PUBLIC(QFileDialog) public: + using PersistentModelIndexList = QVector; + + struct HistoryItem + { + QString path; + PersistentModelIndexList selection; + }; + QFileDialogPrivate(); QPlatformFileDialogHelper *platformFileDialogHelper() const @@ -193,9 +201,11 @@ public: void retranslateWindowTitle(); void retranslateStrings(); void emitFilesSelected(const QStringList &files); + void saveHistorySelection(); void _q_goHome(); void _q_pathChanged(const QString &); + void navigate(HistoryItem &); void _q_navigateBackward(); void _q_navigateForward(); void _q_navigateToParent(); @@ -237,7 +247,7 @@ public: QString setWindowTitle; - QStringList currentHistory; + QList currentHistory; int currentHistoryLocation; QAction *renameAction; -- cgit v1.2.3