From ad4d25589fcd5efd4faa3074c19928d195f615bb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 21 Jul 2015 08:43:39 +0200 Subject: Add recent file handling to SDI/MDI and remove the recentfiles example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing recentfiles example was basically a clone of the SDI example with a "Recent" menu added. Assuming it is better to have it all in one place, the functionality is merged into the existing SDI/MDI examples. - Implement recently opened files handling using a submenu and a QSettings array in the SDI/MDI examples. - Remove recentfiles example. Change-Id: Id5a1ab9fa1c2e6b9ec81309cfe74cf86f450392a Reviewed-by: Topi Reiniƶ --- examples/widgets/mainwindows/mdi/main.cpp | 2 + examples/widgets/mainwindows/mdi/mainwindow.cpp | 121 ++++++++++++++++++++++-- examples/widgets/mainwindows/mdi/mainwindow.h | 11 +++ 3 files changed, 124 insertions(+), 10 deletions(-) (limited to 'examples/widgets/mainwindows/mdi') diff --git a/examples/widgets/mainwindows/mdi/main.cpp b/examples/widgets/mainwindows/mdi/main.cpp index 5976c85c1c..f02285d1cf 100644 --- a/examples/widgets/mainwindows/mdi/main.cpp +++ b/examples/widgets/mainwindows/mdi/main.cpp @@ -49,6 +49,8 @@ int main(int argc, char *argv[]) Q_INIT_RESOURCE(mdi); QApplication app(argc, argv); + QCoreApplication::setApplicationName("MDI Example"); + QCoreApplication::setOrganizationName("QtProject"); QCoreApplication::setApplicationVersion(QT_VERSION_STR); QCommandLineParser parser; parser.setApplicationDescription("Qt MDI Example"); diff --git a/examples/widgets/mainwindows/mdi/mainwindow.cpp b/examples/widgets/mainwindows/mdi/mainwindow.cpp index 4dada5ce70..35136c81c4 100644 --- a/examples/widgets/mainwindows/mdi/mainwindow.cpp +++ b/examples/widgets/mainwindows/mdi/mainwindow.cpp @@ -82,19 +82,24 @@ void MainWindow::newFile() void MainWindow::open() { - QString fileName = QFileDialog::getOpenFileName(this); - if (!fileName.isEmpty()) { - if (QMdiSubWindow *existing = findMdiChild(fileName)) { - mdiArea->setActiveSubWindow(existing); - return; - } + const QString fileName = QFileDialog::getOpenFileName(this); + if (!fileName.isEmpty()) + openFile(fileName); +} - if (openFile(fileName)) - statusBar()->showMessage(tr("File loaded"), 2000); +bool MainWindow::openFile(const QString &fileName) +{ + if (QMdiSubWindow *existing = findMdiChild(fileName)) { + mdiArea->setActiveSubWindow(existing); + return true; } + const bool succeeded = loadFile(fileName); + if (succeeded) + statusBar()->showMessage(tr("File loaded"), 2000); + return succeeded; } -bool MainWindow::openFile(const QString &fileName) +bool MainWindow::loadFile(const QString &fileName) { MdiChild *child = createMdiChild(); const bool succeeded = child->loadFile(fileName); @@ -102,9 +107,87 @@ bool MainWindow::openFile(const QString &fileName) child->show(); else child->close(); + MainWindow::prependToRecentFiles(fileName); return succeeded; } +static inline QString recentFilesKey() { return QStringLiteral("recentFileList"); } +static inline QString fileKey() { return QStringLiteral("file"); } + +static QStringList readRecentFiles(QSettings &settings) +{ + QStringList result; + const int count = settings.beginReadArray(recentFilesKey()); + for (int i = 0; i < count; ++i) { + settings.setArrayIndex(i); + result.append(settings.value(fileKey()).toString()); + } + settings.endArray(); + return result; +} + +static void writeRecentFiles(const QStringList &files, QSettings &settings) +{ + const int count = files.size(); + settings.beginWriteArray(recentFilesKey()); + for (int i = 0; i < count; ++i) { + settings.setArrayIndex(i); + settings.setValue(fileKey(), files.at(i)); + } + settings.endArray(); +} + +bool MainWindow::hasRecentFiles() +{ + QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + const int count = settings.beginReadArray(recentFilesKey()); + settings.endArray(); + return count > 0; +} + +void MainWindow::prependToRecentFiles(const QString &fileName) +{ + QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + + const QStringList oldRecentFiles = readRecentFiles(settings); + QStringList recentFiles = oldRecentFiles; + recentFiles.removeAll(fileName); + recentFiles.prepend(fileName); + if (oldRecentFiles != recentFiles) + writeRecentFiles(recentFiles, settings); + + setRecentFilesVisible(!recentFiles.isEmpty()); +} + +void MainWindow::setRecentFilesVisible(bool visible) +{ + recentFileSubMenuAct->setVisible(visible); + recentFileSeparator->setVisible(visible); +} + +void MainWindow::updateRecentFileActions() +{ + QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + + const QStringList recentFiles = readRecentFiles(settings); + const int count = qMin(int(MaxRecentFiles), recentFiles.size()); + int i = 0; + for ( ; i < count; ++i) { + const QString fileName = QFileInfo(recentFiles.at(i)).fileName(); + recentFileActs[i]->setText(tr("&%1 %2").arg(i + 1).arg(fileName)); + recentFileActs[i]->setData(recentFiles.at(i)); + recentFileActs[i]->setVisible(true); + } + for ( ; i < MaxRecentFiles; ++i) + recentFileActs[i]->setVisible(false); +} + +void MainWindow::openRecentFile() +{ + if (const QAction *action = qobject_cast(sender())) + openFile(action->data().toString()); +} + void MainWindow::save() { if (activeMdiChild() && activeMdiChild()->save()) @@ -113,8 +196,11 @@ void MainWindow::save() void MainWindow::saveAs() { - if (activeMdiChild() && activeMdiChild()->saveAs()) + MdiChild *child = activeMdiChild(); + if (child && child->saveAs()) { statusBar()->showMessage(tr("File saved"), 2000); + MainWindow::prependToRecentFiles(child->currentFile()); + } } #ifndef QT_NO_CLIPBOARD @@ -262,8 +348,23 @@ void MainWindow::createActions() fileMenu->addSeparator(); + QMenu *recentMenu = fileMenu->addMenu(tr("Recent...")); + connect(recentMenu, &QMenu::aboutToShow, this, &MainWindow::updateRecentFileActions); + recentFileSubMenuAct = recentMenu->menuAction(); + + for (int i = 0; i < MaxRecentFiles; ++i) { + recentFileActs[i] = recentMenu->addAction(QString(), this, &MainWindow::openRecentFile); + recentFileActs[i]->setVisible(false); + } + + recentFileSeparator = fileMenu->addSeparator(); + + setRecentFilesVisible(MainWindow::hasRecentFiles()); + fileMenu->addAction(tr("Switch layout direction"), this, &MainWindow::switchLayoutDirection); + fileMenu->addSeparator(); + //! [0] const QIcon exitIcon = QIcon::fromTheme("application-exit"); QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), qApp, &QApplication::closeAllWindows); diff --git a/examples/widgets/mainwindows/mdi/mainwindow.h b/examples/widgets/mainwindows/mdi/mainwindow.h index bdc2a6a09d..3ac60282fd 100644 --- a/examples/widgets/mainwindows/mdi/mainwindow.h +++ b/examples/widgets/mainwindows/mdi/mainwindow.h @@ -68,6 +68,8 @@ private slots: void open(); void save(); void saveAs(); + void updateRecentFileActions(); + void openRecentFile(); #ifndef QT_NO_CLIPBOARD void cut(); void copy(); @@ -80,10 +82,16 @@ private slots: void switchLayoutDirection(); private: + enum { MaxRecentFiles = 5 }; + void createActions(); void createStatusBar(); void readSettings(); void writeSettings(); + bool loadFile(const QString &fileName); + static bool hasRecentFiles(); + void prependToRecentFiles(const QString &fileName); + void setRecentFilesVisible(bool visible); MdiChild *activeMdiChild() const; QMdiSubWindow *findMdiChild(const QString &fileName) const; @@ -93,6 +101,9 @@ private: QAction *newAct; QAction *saveAct; QAction *saveAsAct; + QAction *recentFileActs[MaxRecentFiles]; + QAction *recentFileSeparator; + QAction *recentFileSubMenuAct; #ifndef QT_NO_CLIPBOARD QAction *cutAct; QAction *copyAct; -- cgit v1.2.3