dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
actionmanager.cpp
Go to the documentation of this file.
1 
13 /*
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  */
27 
28 #include "actionmanager_p.h"
29 #include "mainwindow.h"
30 #include "actioncontainer_p.h"
31 #include "command_p.h"
32 #include "uniqueidmanager.h"
33 
35 
36 #include <QtCore/QDebug>
37 #include <QtCore/QSettings>
38 #include <QMenu>
39 #include <QAction>
40 #include <QShortcut>
41 #include <QMenuBar>
42 
43 namespace {
44 enum { warnAboutFindFailures = 0 };
45 }
46 
207 using namespace Core;
208 using namespace Core::Internal;
209 
210 ActionManagerPrivate *ActionManagerPrivate::m_instance = nullptr;
211 
219  : ActionManager(mainWnd)
220  , m_mainWnd(mainWnd)
221 {
223  m_defaultGroups << uidmgr->uniqueIdentifier(Constants::G_DEFAULT_ONE);
224  m_defaultGroups << uidmgr->uniqueIdentifier(Constants::G_DEFAULT_TWO);
225  m_defaultGroups << uidmgr->uniqueIdentifier(Constants::G_DEFAULT_THREE);
226  m_instance = this;
227 }
228 
230 {
231  qDeleteAll(m_idCmdMap.values());
232  qDeleteAll(m_idContainerMap.values());
233 }
234 
236 {
237  return m_instance;
238 }
239 
241 {
242  return m_defaultGroups;
243 }
244 
246 {
247  return m_idCmdMap.values();
248 }
249 
251 {
252  return m_idContainerMap.values();
253 }
254 
255 bool ActionManagerPrivate::hasContext(int context) const
256 {
257  return m_context.contains(context);
258 }
259 
261 {
262  // here are possibilities for speed optimization if necessary:
263  // let commands (de-)register themselves for contexts
264  // and only update commands that are either in old or new contexts
265  m_context = context;
266  const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
267  for (IdCmdMap::const_iterator it = m_idCmdMap.constBegin(); it != cmdcend; ++it)
268  it.value()->setCurrentContext(m_context);
269 
270  const IdContainerMap::const_iterator acend = m_idContainerMap.constEnd();
271  for (IdContainerMap::const_iterator it = m_idContainerMap.constBegin(); it != acend; ++it)
272  it.value()->update();
273 }
274 
276 {
277  for (int i = 0; i < m_context.count(); ++i) {
278  if (context.contains(m_context.at(i)))
279  return true;
280  }
281  return false;
282 }
283 
285 {
286  const int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
287  const IdContainerMap::const_iterator it = m_idContainerMap.constFind(uid);
288  if (it != m_idContainerMap.constEnd())
289  return it.value();
290 
291  QMenu *m = new QMenu(m_mainWnd);
292  m->setObjectName(id);
293 
295  mc->setMenu(m);
296 
297  m_idContainerMap.insert(uid, mc);
298 
299  return mc;
300 }
301 
303 {
304  const int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
305  const IdContainerMap::const_iterator it = m_idContainerMap.constFind(uid);
306  if (it != m_idContainerMap.constEnd())
307  return it.value();
308 
309  QMenuBar *mb = new QMenuBar; // No parent (System menu bar on Mac OS X)
310  mb->setObjectName(id);
311 
313  mbc->setMenuBar(mb);
314 
315  m_idContainerMap.insert(uid, mbc);
316 
317  return mbc;
318 }
319 
320 Command *ActionManagerPrivate::registerAction(QAction *action, const QString &id,
321  const QList<int> &context)
322 {
323  OverrideableAction *a = nullptr;
324  Command *c = registerOverridableAction(action, id, false);
325  a = static_cast<OverrideableAction *>(c);
326  if (a)
327  a->addOverrideAction(action, context);
328  return a;
329 }
330 
331 Command *ActionManagerPrivate::registerOverridableAction(QAction *action, const QString &id,
332  bool checkUnique)
333 {
334  OverrideableAction *a = nullptr;
335  const int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
336  if (CommandPrivate *c = m_idCmdMap.value(uid, 0)) {
337  a = qobject_cast<OverrideableAction *>(c);
338  if (!a) {
339  qWarning() << "registerAction: id" << id
340  << "is registered with a different command type.";
341  return c;
342  }
343  } else {
344  a = new OverrideableAction(uid);
345  m_idCmdMap.insert(uid, a);
346  }
347 
348  if (!a->action()) {
349  QAction *baseAction = new QAction(m_mainWnd);
350  baseAction->setObjectName(id);
351  baseAction->setCheckable(action->isCheckable());
352  baseAction->setIcon(action->icon());
353  baseAction->setIconText(action->iconText());
354  baseAction->setText(action->text());
355  baseAction->setToolTip(action->toolTip());
356  baseAction->setStatusTip(action->statusTip());
357  baseAction->setWhatsThis(action->whatsThis());
358  baseAction->setChecked(action->isChecked());
359  baseAction->setSeparator(action->isSeparator());
360  baseAction->setShortcutContext(Qt::ApplicationShortcut);
361  baseAction->setEnabled(false);
362  baseAction->setParent(m_mainWnd);
363 #ifdef Q_OS_MAC
364  baseAction->setIconVisibleInMenu(false);
365 #endif
366  a->setAction(baseAction);
367  m_mainWnd->addAction(baseAction);
368  a->setKeySequence(a->keySequence());
369  a->setDefaultKeySequence(QKeySequence());
370  } else if (checkUnique) {
371  qWarning() << "registerOverridableAction: id" << id << "is already registered.";
372  }
373 
374  return a;
375 }
376 
377 Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const QString &id,
378  const QList<int> &context)
379 {
380  Shortcut *sc = nullptr;
382  if (CommandPrivate *c = m_idCmdMap.value(uid, 0)) {
383  sc = qobject_cast<Shortcut *>(c);
384  if (!sc) {
385  qWarning() << "registerShortcut: id" << id
386  << "is registered with a different command type.";
387  return c;
388  }
389  } else {
390  sc = new Shortcut(uid);
391  m_idCmdMap.insert(uid, sc);
392  }
393 
394  if (sc->shortcut()) {
395  qWarning() << "registerShortcut: action already registered (id" << id << ".";
396  return sc;
397  }
398 
399  if (!hasContext(context))
400  shortcut->setEnabled(false);
401  shortcut->setObjectName(id);
402  shortcut->setParent(m_mainWnd);
403  sc->setShortcut(shortcut);
404 
405  if (context.isEmpty())
406  sc->setContext(QList<int>() << 0);
407  else
408  sc->setContext(context);
409 
410  sc->setKeySequence(shortcut->key());
411  sc->setDefaultKeySequence(QKeySequence());
412 
413  return sc;
414 }
415 
416 Command *ActionManagerPrivate::command(const QString &id) const
417 {
418  const int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
419  const IdCmdMap::const_iterator it = m_idCmdMap.constFind(uid);
420  if (it == m_idCmdMap.constEnd()) {
421  if (warnAboutFindFailures)
422  qWarning() << "ActionManagerPrivate::command(): failed to find :" << id << '/' << uid;
423  return nullptr;
424  }
425  return it.value();
426 }
427 
429 {
430  const int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
431  const IdContainerMap::const_iterator it = m_idContainerMap.constFind(uid);
432  if (it == m_idContainerMap.constEnd()) {
433  if (warnAboutFindFailures)
434  qWarning() << "ActionManagerPrivate::actionContainer(): failed to find :" << id << '/'
435  << uid;
436  return nullptr;
437  }
438  return it.value();
439 }
440 
442 {
443  const IdCmdMap::const_iterator it = m_idCmdMap.constFind(uid);
444  if (it == m_idCmdMap.constEnd()) {
445  if (warnAboutFindFailures)
446  qWarning() << "ActionManagerPrivate::command(): failed to find :"
447  << UniqueIDManager::instance()->stringForUniqueIdentifier(uid) << '/' << uid;
448  return nullptr;
449  }
450  return it.value();
451 }
452 
454 {
455  const IdContainerMap::const_iterator it = m_idContainerMap.constFind(uid);
456  if (it == m_idContainerMap.constEnd()) {
457  if (warnAboutFindFailures)
458  qWarning() << "ActionManagerPrivate::actionContainer(): failed to find :"
460  return nullptr;
461  }
462  return it.value();
463 }
464 
465 static const char *settingsGroup = "KeyBindings";
466 static const char *idKey = "ID";
467 static const char *sequenceKey = "Keysequence";
468 
469 void ActionManagerPrivate::readSettings(QSettings *settings)
470 {
471  const int shortcuts = settings->beginReadArray(QLatin1String(settingsGroup));
472  for (int i = 0; i < shortcuts; ++i) {
473  settings->setArrayIndex(i);
474  const QString sid = settings->value(QLatin1String(idKey)).toString();
475  const QKeySequence key(settings->value(QLatin1String(sequenceKey)).toString());
476  const int id = UniqueIDManager::instance()->uniqueIdentifier(sid);
477 
478  Command *cmd = command(id);
479  if (cmd)
480  cmd->setKeySequence(key);
481  }
482  settings->endArray();
483 }
484 
485 void ActionManagerPrivate::saveSettings(QSettings *settings)
486 {
487  settings->beginWriteArray(QLatin1String(settingsGroup));
488  int count = 0;
489 
490  const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
491  for (IdCmdMap::const_iterator j = m_idCmdMap.constBegin(); j != cmdcend; ++j) {
492  const int id = j.key();
493  CommandPrivate *cmd = j.value();
494  QKeySequence key = cmd->keySequence();
495  if (key != cmd->defaultKeySequence()) {
496  const QString sid = UniqueIDManager::instance()->stringForUniqueIdentifier(id);
497  settings->setArrayIndex(count);
498  settings->setValue(QLatin1String(idKey), sid);
499  settings->setValue(QLatin1String(sequenceKey), key.toString());
500  count++;
501  }
502  }
503 
504  settings->endArray();
505 }
static UniqueIDManager * instance()
int uniqueIdentifier(const QString &id)
void addOverrideAction(QAction *action, const QList< int > &context)
Definition: command.cpp:473
void setKeySequence(const QKeySequence &key)
Definition: command.cpp:304
Command * registerShortcut(QShortcut *shortcut, const QString &id, const QList< int > &context)
Makes a shortcut known to the system under the specified string id.
ActionContainer * createMenuBar(const QString &id)
Creates a new menu bar with the given string id.
bool hasContext(int context) const
QKeySequence keySequence() const
Definition: command.cpp:408
Command * command(int uid) const
for i
Definition: OPPlots.m:140
virtual QKeySequence keySequence() const =0
void setAction(QAction *action)
Definition: command.cpp:428
void setKeySequence(const QKeySequence &key)
Definition: command.cpp:393
void setContext(const QList< int > &context)
Definition: command.cpp:287
void setDefaultKeySequence(const QKeySequence &key)
Definition: command.cpp:386
void readSettings(QSettings *settings)
static ActionManagerPrivate * instance()
end a
Definition: OPPlots.m:98
QList< ActionContainerPrivate * > containers() const
QShortcut * shortcut() const
Definition: command.cpp:282
void saveSettings(QSettings *settings)
Command * registerAction(QAction *action, const QString &id, const QList< int > &context)
Makes an action known to the system under the specified string id.
void setDefaultKeySequence(const QKeySequence &key)
Definition: command.cpp:297
void setContext(const QList< int > &context)
virtual void setKeySequence(const QKeySequence &key)=0
QString stringForUniqueIdentifier(int uid)
ActionContainer * createMenu(const QString &id)
Creates a new menu with the given string id.
QKeySequence defaultKeySequence() const
Definition: command.cpp:204
The action manager is responsible for registration of menus and menu items and keyboard shortcuts...
Definition: actionmanager.h:47
const char *const G_DEFAULT_ONE
ActionContainer * actionContainer(int uid) const
ActionManagerPrivate(MainWindow *mainWnd)
const char *const G_DEFAULT_TWO
QAction * action() const
Definition: command.cpp:371
QList< CommandPrivate * > commands() const
The class Command represents an action like a menu item, tool button, or shortcut. You don't create Command objects directly, instead use {ActionManager::registerAction()} to register an action and retrieve a Command. The Command object represents the user visible action and its properties. If multiple actions are registered with the same ID (but different contexts) the returned Command is the shared one between these actions.
Definition: command.h:43
void setShortcut(QShortcut *shortcut)
Definition: command.cpp:277
const char *const G_DEFAULT_THREE