Qt Utilities  6.4.1
Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models
recentmenumanager.cpp
Go to the documentation of this file.
1 #include "./recentmenumanager.h"
2 
3 #include <QAction>
4 #include <QCoreApplication>
5 #include <QFile>
6 #include <QMenu>
7 #include <QMessageBox>
8 #include <QPushButton>
9 #include <QStringList>
10 
11 namespace QtUtilities {
12 
30 RecentMenuManager::RecentMenuManager(QMenu *menu, QObject *parent)
31  : QObject(parent)
32  , m_menu(menu)
33 {
34  m_menu->clear();
35  m_menu->setTitle(tr("&Recent"));
36  m_menu->setIcon(QIcon::fromTheme(QStringLiteral("document-open-recent")));
37  m_sep = m_menu->addSeparator();
38  m_clearAction = m_menu->addAction(QIcon::fromTheme(QStringLiteral("edit-clear")), tr("&Clear list"), this, &RecentMenuManager::clearEntries);
39 }
40 
44 void RecentMenuManager::restore(const QStringList &savedEntries)
45 {
46  QAction *action = nullptr;
47  for (const QString &path : savedEntries) {
48  if (!path.isEmpty()) {
49  action = new QAction(path, m_menu);
50  action->setProperty("file_path", path);
51  m_menu->insertAction(m_sep, action);
52  connect(action, &QAction::triggered, this, &RecentMenuManager::handleActionTriggered);
53  }
54  }
55  if (action) {
56  m_menu->actions().front()->setShortcut(QKeySequence(Qt::Key_F6));
57  m_menu->setEnabled(true);
58  }
59 }
60 
65 {
66  QStringList existingEntires;
67  QList<QAction *> entryActions = m_menu->actions();
68  existingEntires.reserve(entryActions.size());
69  for (const QAction *action : entryActions) {
70  QVariant path = action->property("file_path");
71  if (!path.isNull()) {
72  existingEntires << path.toString();
73  }
74  }
75  return existingEntires;
76 }
77 
82 void RecentMenuManager::addEntry(const QString &path)
83 {
84  QList<QAction *> existingEntries = m_menu->actions();
85  QAction *entry = nullptr;
86  // remove shortcut from existing entries
87  for (QAction *existingEntry : existingEntries) {
88  existingEntry->setShortcut(QKeySequence());
89  // check whether existing entry matches entry to add
90  if (existingEntry->property("file_path").toString() == path) {
91  entry = existingEntry;
92  break;
93  }
94  }
95  if (!entry) {
96  // remove old entries to have never more than 10 entries
97  for (int i = existingEntries.size() - 1; i > 8; --i) {
98  delete existingEntries[i];
99  }
100  existingEntries = m_menu->actions();
101  // create new action
102  entry = new QAction(path, this);
103  entry->setProperty("file_path", path);
104  connect(entry, &QAction::triggered, this, &RecentMenuManager::handleActionTriggered);
105  } else {
106  // remove existing action (will be inserted again as first action)
107  m_menu->removeAction(entry);
108  }
109  // add shortcut for new entry
110  entry->setShortcut(QKeySequence(Qt::Key_F6));
111  // ensure menu is enabled
112  m_menu->setEnabled(true);
113  // add action as first action in the recent menu
114  m_menu->insertAction(m_menu->isEmpty() ? nullptr : m_menu->actions().front(), entry);
115 }
116 
121 {
122  QList<QAction *> entries = m_menu->actions();
123  for (auto i = entries.begin(), end = entries.end() - 2; i != end; ++i) {
124  if (*i != m_clearAction) {
125  delete *i;
126  }
127  }
128  m_menu->setEnabled(false);
129 }
130 
135 void RecentMenuManager::handleActionTriggered()
136 {
137  if (QAction *action = qobject_cast<QAction *>(sender())) {
138  const QString path = action->property("file_path").toString();
139  if (!path.isEmpty()) {
140  if (QFile::exists(path)) {
141  emit fileSelected(path);
142  } else {
143  QMessageBox msg;
144  msg.setWindowTitle(tr("Recently opened files - ") + QCoreApplication::applicationName());
145  msg.setText(tr("The selected file can't be found anymore. Do you want "
146  "to delete the obsolete entry from the list?"));
147  msg.setIcon(QMessageBox::Warning);
148  QPushButton *keepEntryButton = msg.addButton(tr("keep entry"), QMessageBox::NoRole);
149  QPushButton *deleteEntryButton = msg.addButton(tr("delete entry"), QMessageBox::YesRole);
150  msg.setEscapeButton(keepEntryButton);
151  msg.exec();
152  if (msg.clickedButton() == deleteEntryButton) {
153  delete action;
154  QList<QAction *> remainingActions = m_menu->actions();
155  if (!remainingActions.isEmpty() && remainingActions.front() != m_sep && remainingActions.front() != m_clearAction) {
156  remainingActions.front()->setShortcut(QKeySequence(Qt::Key_F6));
157  m_menu->setEnabled(true);
158  } else {
159  m_menu->setEnabled(false);
160  }
161  }
162  }
163  }
164  }
165 }
166 
173 } // namespace QtUtilities
void addEntry(const QString &path)
Ensures an entry for the specified path is present and the first entry in the list.
void fileSelected(const QString &path)
Emitted after the user selected a file.
QStringList save()
Saves the current entries.
void restore(const QStringList &savedEntries)
Restores the specified entries.
RecentMenuManager(QMenu *menu, QObject *parent=nullptr)
Constructs a new recent menu manager.
void clearEntries()
Clears all entries.