├── LICENSE ├── QRecentFilesMenu.cpp ├── QRecentFilesMenu.h ├── README.md ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── recentfiles.pro └── screen-capture.png /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011 Morgan Leborgne 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QRecentFilesMenu.cpp: -------------------------------------------------------------------------------- 1 | #include "QRecentFilesMenu.h" 2 | 3 | #include 4 | 5 | static const qint32 RecentFilesMenuMagic = 0xff; 6 | 7 | QRecentFilesMenu::QRecentFilesMenu(QWidget * parent) 8 | : QMenu(parent) 9 | , m_maxCount(5) 10 | , m_format(QLatin1String("%d %s")) 11 | { 12 | connect(this, SIGNAL(triggered(QAction*)), this, SLOT(menuTriggered(QAction*))); 13 | 14 | setMaxCount(m_maxCount); 15 | } 16 | 17 | QRecentFilesMenu::QRecentFilesMenu(const QString & title, QWidget * parent) 18 | : QMenu(title, parent) 19 | , m_maxCount(5) 20 | , m_format(QLatin1String("%d %s")) 21 | { 22 | connect(this, SIGNAL(triggered(QAction*)), this, SLOT(menuTriggered(QAction*))); 23 | 24 | setMaxCount(m_maxCount); 25 | } 26 | 27 | void QRecentFilesMenu::addRecentFile(const QString &fileName) 28 | { 29 | m_files.removeAll(fileName); 30 | m_files.prepend(fileName); 31 | 32 | while (m_files.size() > maxCount()) 33 | m_files.removeLast(); 34 | 35 | updateRecentFileActions(); 36 | } 37 | 38 | void QRecentFilesMenu::clearMenu() 39 | { 40 | m_files.clear(); 41 | 42 | updateRecentFileActions(); 43 | } 44 | 45 | int QRecentFilesMenu::maxCount() const 46 | { 47 | return m_maxCount; 48 | } 49 | 50 | void QRecentFilesMenu::setFormat(const QString &format) 51 | { 52 | if (m_format == format) 53 | return; 54 | m_format = format; 55 | 56 | updateRecentFileActions(); 57 | } 58 | 59 | const QString & QRecentFilesMenu::format() const 60 | { 61 | return m_format; 62 | } 63 | 64 | QByteArray QRecentFilesMenu::saveState() const 65 | { 66 | int version = 0; 67 | QByteArray data; 68 | QDataStream stream(&data, QIODevice::WriteOnly); 69 | 70 | stream << qint32(RecentFilesMenuMagic); 71 | stream << qint32(version); 72 | stream << m_files; 73 | 74 | return data; 75 | } 76 | 77 | bool QRecentFilesMenu::restoreState(const QByteArray &state) 78 | { 79 | int version = 0; 80 | QByteArray sd = state; 81 | QDataStream stream(&sd, QIODevice::ReadOnly); 82 | qint32 marker; 83 | qint32 v; 84 | 85 | stream >> marker; 86 | stream >> v; 87 | if (marker != RecentFilesMenuMagic || v != version) 88 | return false; 89 | 90 | stream >> m_files; 91 | 92 | updateRecentFileActions(); 93 | 94 | return true; 95 | } 96 | 97 | void QRecentFilesMenu::setMaxCount(int count) 98 | { 99 | m_maxCount = count; 100 | 101 | updateRecentFileActions(); 102 | } 103 | 104 | void QRecentFilesMenu::menuTriggered(QAction* action) 105 | { 106 | if (action->data().isValid()) 107 | emit recentFileTriggered(action->data().toString()); 108 | } 109 | 110 | void QRecentFilesMenu::updateRecentFileActions() 111 | { 112 | int numRecentFiles = qMin(m_files.size(), maxCount()); 113 | 114 | clear(); 115 | 116 | for (int i = 0; i < numRecentFiles; ++i) { 117 | QString strippedName = QFileInfo(m_files[i]).fileName(); 118 | 119 | QString text = m_format; 120 | text.replace(QLatin1String("%d"), QString::number(i + 1)); 121 | text.replace(QLatin1String("%s"), strippedName); 122 | 123 | QAction* recentFileAct = addAction(text); 124 | recentFileAct->setData(m_files[i]); 125 | } 126 | addSeparator(); 127 | addAction(tr("Clear Menu"), this, SLOT(clearMenu())); 128 | 129 | setEnabled(numRecentFiles > 0); 130 | } 131 | 132 | -------------------------------------------------------------------------------- /QRecentFilesMenu.h: -------------------------------------------------------------------------------- 1 | #ifndef QRECENTFILESMENU_H 2 | #define QRECENTFILESMENU_H 3 | 4 | #include 5 | #include 6 | 7 | class QRecentFilesMenu : public QMenu 8 | { 9 | Q_OBJECT 10 | Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) 11 | Q_PROPERTY(QString format READ format WRITE setFormat) 12 | public: 13 | //! Constructs a menu with parent parent. 14 | QRecentFilesMenu(QWidget * parent = 0 ); 15 | 16 | //! Constructs a menu with a title and a parent. 17 | QRecentFilesMenu(const QString & title, QWidget * parent = 0 ); 18 | 19 | //! Returns the maximum number of entries in the menu. 20 | int maxCount() const; 21 | 22 | /** This property holds the string used to generate the item text. 23 | * %d is replaced by the item number 24 | * %s is replaced by the item text 25 | * The default value is "%d %s". 26 | */ 27 | void setFormat(const QString &format); 28 | 29 | //! Returns the current format. /sa setFormat 30 | const QString & format() const; 31 | 32 | /** Saves the state of the recent entries. 33 | * Typically this is used in conjunction with QSettings to remember entries 34 | * for a future session. A version number is stored as part of the data. 35 | * Here is an example: 36 | * QSettings settings; 37 | * settings.setValue("recentFiles", recentFilesMenu->saveState()); 38 | */ 39 | QByteArray saveState() const; 40 | 41 | /** Restores the recent entries to the state specified. 42 | * Typically this is used in conjunction with QSettings to restore entries from a past session. 43 | * Returns false if there are errors. 44 | * Here is an example: 45 | * QSettings settings; 46 | * recentFilesMenu->restoreState(settings.value("recentFiles").toByteArray()); 47 | */ 48 | bool restoreState(const QByteArray &state); 49 | 50 | public slots: 51 | //! 52 | void addRecentFile(const QString &fileName); 53 | 54 | //! Removes all the menu's actions. 55 | void clearMenu(); 56 | 57 | //! Sets the maximum number of entries int he menu. 58 | void setMaxCount(int); 59 | signals: 60 | //! This signal is emitted when a recent file in this menu is triggered. 61 | void recentFileTriggered(const QString & filename); 62 | 63 | private slots: 64 | void menuTriggered(QAction*); 65 | void updateRecentFileActions(); 66 | private: 67 | int m_maxCount; 68 | QString m_format; 69 | QStringList m_files; 70 | }; 71 | 72 | #endif // QRECENTFILEMENU_H 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | The QRecentFilesMenu class provides a recent files menu widget for use in menu bars, context menus, and other popup menus. 4 | 5 | * Use QRecentFilesMenu::addRecentFile() to insert a recent file into the menu. 6 | * QRecentFilesMenu provides the signal recentFileTriggered to notifed whenever a recent file has been triggered(). 7 | * You can save and restore the recent files entries from a QByteArray using saveState() and restoreState() respectively. 8 | 9 | 10 | 11 | 12 | ## Dependency 13 | Qt 4.x. 14 | 15 | ## License 16 | 17 | MIT 18 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mainwindow.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | QApplication app(argc, argv); 8 | QApplication::setOrganizationName("QtApp"); 9 | QApplication::setApplicationName("Recent Files Example"); 10 | 11 | MainWindow *mainWin = new MainWindow; 12 | mainWin->show(); 13 | return app.exec(); 14 | } 15 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mainwindow.h" 4 | 5 | MainWindow::MainWindow() 6 | { 7 | setAttribute(Qt::WA_DeleteOnClose); 8 | 9 | textEdit = new QTextEdit; 10 | setCentralWidget(textEdit); 11 | 12 | createActions(); 13 | createMenus(); 14 | 15 | setWindowFilePath(QString()); 16 | resize(400, 300); 17 | } 18 | 19 | MainWindow::~MainWindow() 20 | { 21 | QSettings settings; 22 | settings.setValue("recentFiles", recentFilesMenu->saveState()); 23 | } 24 | 25 | void MainWindow::open() 26 | { 27 | QString fileName = QFileDialog::getOpenFileName(this); 28 | if (!fileName.isEmpty()) 29 | loadFile(fileName); 30 | } 31 | 32 | void MainWindow::createActions() 33 | { 34 | openAct = new QAction(tr("&Open..."), this); 35 | openAct->setShortcuts(QKeySequence::Open); 36 | openAct->setStatusTip(tr("Open an existing file")); 37 | connect(openAct, SIGNAL(triggered()), this, SLOT(open())); 38 | 39 | exitAct = new QAction(tr("E&xit"), this); 40 | exitAct->setShortcut(tr("Ctrl+Q")); 41 | exitAct->setStatusTip(tr("Exit the application")); 42 | connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); 43 | } 44 | 45 | void MainWindow::createMenus() 46 | { 47 | fileMenu = menuBar()->addMenu(tr("&File")); 48 | fileMenu->addAction(openAct); 49 | 50 | recentFilesMenu = new QRecentFilesMenu(tr("Recent Files"), fileMenu); 51 | 52 | QSettings settings; 53 | recentFilesMenu->restoreState(settings.value("recentFiles").toByteArray()); 54 | 55 | connect(recentFilesMenu, SIGNAL(recentFileTriggered(const QString &)), this, SLOT(loadFile(const QString &))); 56 | 57 | fileMenu->addMenu(recentFilesMenu); 58 | 59 | fileMenu->addSeparator(); 60 | fileMenu->addAction(exitAct); 61 | } 62 | 63 | void MainWindow::loadFile(const QString &fileName) 64 | { 65 | QFile file(fileName); 66 | if (!file.open(QFile::ReadOnly | QFile::Text)) { 67 | QMessageBox::warning(this, tr("Recent Files"), 68 | tr("Cannot read file %1:\n%2.") 69 | .arg(fileName) 70 | .arg(file.errorString())); 71 | return; 72 | } 73 | 74 | QTextStream in(&file); 75 | QApplication::setOverrideCursor(Qt::WaitCursor); 76 | textEdit->setPlainText(in.readAll()); 77 | QApplication::restoreOverrideCursor(); 78 | 79 | setWindowFilePath(fileName); 80 | 81 | recentFilesMenu->addRecentFile(fileName); 82 | } 83 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "QRecentFilesMenu.h" 6 | 7 | class QAction; 8 | class QMenu; 9 | class QTextEdit; 10 | 11 | class MainWindow : public QMainWindow 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | MainWindow(); 17 | ~MainWindow(); 18 | private slots: 19 | void open(); 20 | void loadFile(const QString &fileName); 21 | 22 | private: 23 | void createActions(); 24 | void createMenus(); 25 | 26 | QTextEdit *textEdit; 27 | QMenu *fileMenu; 28 | QRecentFilesMenu *recentFilesMenu; 29 | QAction *openAct; 30 | QAction *exitAct; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /recentfiles.pro: -------------------------------------------------------------------------------- 1 | HEADERS = mainwindow.h \ 2 | QRecentFilesMenu.h 3 | SOURCES = main.cpp \ 4 | mainwindow.cpp \ 5 | QRecentFilesMenu.cpp 6 | 7 | -------------------------------------------------------------------------------- /screen-capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mojocorp/QRecentFilesMenu/af1dc1a3cb7aa99ebdec0e8bdbbd88b23ad0f2c8/screen-capture.png --------------------------------------------------------------------------------