2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2014-01-07 13:27:11 +01:00
|
|
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
2012-10-02 09:12:39 +02:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 14:09:21 +01:00
|
|
|
|
2012-05-24 13:49:06 +02:00
|
|
|
#include "actionmanager.h"
|
2009-01-13 13:07:29 +01:00
|
|
|
#include "actionmanager_p.h"
|
2009-01-14 12:25:54 +01:00
|
|
|
#include "actioncontainer_p.h"
|
2009-01-14 12:58:06 +01:00
|
|
|
#include "command_p.h"
|
2013-08-29 16:36:42 +02:00
|
|
|
#include <coreplugin/id.h>
|
|
|
|
|
#include <coreplugin/mainwindow.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-06 17:21:03 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDebug>
|
|
|
|
|
#include <QSettings>
|
|
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QMenu>
|
|
|
|
|
#include <QAction>
|
|
|
|
|
#include <QShortcut>
|
|
|
|
|
#include <QMenuBar>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
enum { warnAboutFindFailures = 0 };
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-24 15:20:50 +01:00
|
|
|
static const char kKeyboardSettingsKey[] = "KeyboardShortcuts";
|
|
|
|
|
|
2012-05-24 13:49:06 +02:00
|
|
|
using namespace Core;
|
|
|
|
|
using namespace Core::Internal;
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2009-01-13 13:39:31 +01:00
|
|
|
\class Core::ActionManager
|
2008-12-02 12:01:29 +01:00
|
|
|
\mainclass
|
2013-12-11 15:37:48 +01:00
|
|
|
\inmodule Qt Creator
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The ActionManager class is responsible for registration of menus and
|
2009-01-13 19:02:54 +01:00
|
|
|
menu items and keyboard shortcuts.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-13 13:39:31 +01:00
|
|
|
The ActionManager is the central bookkeeper of actions and their shortcuts and layout.
|
2013-10-07 13:34:40 +02:00
|
|
|
It is a singleton containing mostly static functions. If you need access to the instance,
|
|
|
|
|
e.g. for connecting to signals, is its ActionManager::instance() function.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
The main reasons for the need of this class is to provide a central place where the user
|
|
|
|
|
can specify all his keyboard shortcuts, and to provide a solution for actions that should
|
|
|
|
|
behave differently in different contexts (like the copy/replace/undo/redo actions).
|
|
|
|
|
|
2009-05-04 15:09:31 +02:00
|
|
|
\section1 Contexts
|
|
|
|
|
|
2012-05-24 13:49:06 +02:00
|
|
|
All actions that are registered with the same Id (but different context lists)
|
2009-01-13 19:02:54 +01:00
|
|
|
are considered to be overloads of the same command, represented by an instance
|
2009-01-14 13:17:53 +01:00
|
|
|
of the Command class.
|
2009-05-04 15:09:31 +02:00
|
|
|
Exactly only one of the registered actions with the same ID is active at any time.
|
|
|
|
|
Which action this is, is defined by the context list that the actions were registered
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
If the current focus widget was registered via \l{ICore::addContextObject()},
|
|
|
|
|
all the contexts returned by its IContext object are active. In addition all
|
|
|
|
|
contexts set via \l{ICore::addAdditionalContext()} are active as well. If one
|
|
|
|
|
of the actions was registered for one of these active contexts, it is the one
|
|
|
|
|
active action, and receives \c triggered and \c toggled signals. Also the
|
|
|
|
|
appearance of the visible action for this ID might be adapted to this
|
|
|
|
|
active action (depending on the settings of the corresponding \l{Command} object).
|
|
|
|
|
|
2009-01-14 13:17:53 +01:00
|
|
|
The action that is visible to the user is the one returned by Command::action().
|
2009-01-13 19:02:54 +01:00
|
|
|
If you provide yourself a user visible representation of your action you need
|
2009-01-14 13:17:53 +01:00
|
|
|
to use Command::action() for this.
|
2009-01-13 19:02:54 +01:00
|
|
|
When this action is invoked by the user,
|
|
|
|
|
the signal is forwarded to the registered action that is valid for the current context.
|
|
|
|
|
|
2009-05-04 15:09:31 +02:00
|
|
|
\section1 Registering Actions
|
|
|
|
|
|
|
|
|
|
To register a globally active action "My Action"
|
2013-10-07 13:34:40 +02:00
|
|
|
put the following in your plugin's IPlugin::initialize function:
|
2009-01-13 19:02:54 +01:00
|
|
|
\code
|
|
|
|
|
QAction *myAction = new QAction(tr("My Action"), this);
|
2012-05-24 13:49:06 +02:00
|
|
|
Core::Command *cmd = Core::ActionManager::registerAction(myAction,
|
2009-01-13 19:02:54 +01:00
|
|
|
"myplugin.myaction",
|
2010-06-28 14:30:03 +02:00
|
|
|
Core::Context(C_GLOBAL));
|
2009-01-13 19:02:54 +01:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+u")));
|
|
|
|
|
connect(myAction, SIGNAL(triggered()), this, SLOT(performMyAction()));
|
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
|
|
So the \c connect is done to your own QAction instance. If you create e.g.
|
|
|
|
|
a tool button that should represent the action you add the action
|
2009-01-14 13:17:53 +01:00
|
|
|
from Command::action() to it:
|
2009-01-13 19:02:54 +01:00
|
|
|
\code
|
|
|
|
|
QToolButton *myButton = new QToolButton(someParentWidget);
|
|
|
|
|
myButton->setDefaultAction(cmd->action());
|
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
|
|
Also use the ActionManager to add items to registered
|
|
|
|
|
action containers like the applications menu bar or menus in that menu bar.
|
|
|
|
|
To do this, you register your action via the
|
2013-10-07 13:34:40 +02:00
|
|
|
registerAction functions, get the action container for a specific ID (like specified in
|
2009-01-13 19:02:54 +01:00
|
|
|
the Core::Constants namespace) with a call of
|
2012-04-01 21:24:03 +03:00
|
|
|
actionContainer(const Id&) and add your command to this container.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-13 19:02:54 +01:00
|
|
|
Following the example adding "My Action" to the "Tools" menu would be done by
|
|
|
|
|
\code
|
2012-05-24 13:49:06 +02:00
|
|
|
Core::ActionManager::actionContainer(Core::M_TOOLS)->addAction(cmd);
|
2009-01-13 19:02:54 +01:00
|
|
|
\endcode
|
|
|
|
|
|
2009-05-04 15:09:31 +02:00
|
|
|
\section1 Important Guidelines:
|
2008-12-02 12:01:29 +01:00
|
|
|
\list
|
2013-02-06 08:50:23 +01:00
|
|
|
\li Always register your actions and shortcuts!
|
|
|
|
|
\li Register your actions and shortcuts during your plugin's \l{ExtensionSystem::IPlugin::initialize()}
|
2013-10-07 13:34:40 +02:00
|
|
|
or \l{ExtensionSystem::IPlugin::extensionsInitialized()} functions, otherwise the shortcuts won't appear
|
2009-01-13 19:02:54 +01:00
|
|
|
in the keyboard settings dialog from the beginning.
|
2013-02-06 08:50:23 +01:00
|
|
|
\li When registering an action with \c{cmd=registerAction(action, id, contexts)} be sure to connect
|
2009-05-04 15:09:31 +02:00
|
|
|
your own action \c{connect(action, SIGNAL...)} but make \c{cmd->action()} visible to the user, i.e.
|
|
|
|
|
\c{widget->addAction(cmd->action())}.
|
2013-02-06 08:50:23 +01:00
|
|
|
\li Use this class to add actions to the applications menus
|
2008-12-02 12:01:29 +01:00
|
|
|
\endlist
|
|
|
|
|
|
2009-01-13 19:02:54 +01:00
|
|
|
\sa Core::ICore
|
2009-01-14 13:17:53 +01:00
|
|
|
\sa Core::Command
|
2009-01-14 12:39:59 +01:00
|
|
|
\sa Core::ActionContainer
|
2009-01-13 19:02:54 +01:00
|
|
|
\sa Core::IContext
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
|
2013-12-11 15:37:48 +01:00
|
|
|
/*!
|
|
|
|
|
\fn void ActionManager::commandListChanged()
|
|
|
|
|
|
|
|
|
|
Emitted when the command list has changed.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\fn void ActionManager::commandAdded(const QString &id)
|
|
|
|
|
|
|
|
|
|
Emitted when a command (with the \a id) is added.
|
|
|
|
|
*/
|
|
|
|
|
|
2012-05-24 13:49:06 +02:00
|
|
|
static ActionManager *m_instance = 0;
|
2013-06-25 13:37:21 +02:00
|
|
|
static ActionManagerPrivate *d;
|
2012-05-24 13:49:06 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2012-05-24 13:49:06 +02:00
|
|
|
\internal
|
|
|
|
|
*/
|
|
|
|
|
ActionManager::ActionManager(QObject *parent)
|
2013-06-25 13:37:21 +02:00
|
|
|
: QObject(parent)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
|
|
|
|
m_instance = this;
|
2013-06-25 13:37:21 +02:00
|
|
|
d = new ActionManagerPrivate;
|
2012-05-24 13:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\internal
|
|
|
|
|
*/
|
|
|
|
|
ActionManager::~ActionManager()
|
|
|
|
|
{
|
|
|
|
|
delete d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
2013-12-11 15:37:48 +01:00
|
|
|
Returns the pointer to the instance, which is only used for connecting to signals.
|
|
|
|
|
*/
|
2012-05-24 13:49:06 +02:00
|
|
|
ActionManager *ActionManager::instance()
|
|
|
|
|
{
|
|
|
|
|
return m_instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Creates a new menu with the given \a id.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-14 12:39:59 +01:00
|
|
|
Returns a new ActionContainer that you can use to get the QMenu instance
|
2009-01-13 19:02:54 +01:00
|
|
|
or to add menu items to the menu. The ActionManager owns
|
2009-01-14 12:39:59 +01:00
|
|
|
the returned ActionContainer.
|
2009-01-13 19:02:54 +01:00
|
|
|
Add your menu to some other menu or a menu bar via the
|
2013-10-07 13:34:40 +02:00
|
|
|
ActionManager::actionContainer and ActionContainer::addMenu functions.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
ActionContainer *ActionManager::createMenu(Id id)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
2013-06-25 13:37:21 +02:00
|
|
|
const ActionManagerPrivate::IdContainerMap::const_iterator it = d->m_idContainerMap.constFind(id);
|
|
|
|
|
if (it != d->m_idContainerMap.constEnd())
|
2012-05-24 13:49:06 +02:00
|
|
|
return it.value();
|
|
|
|
|
|
|
|
|
|
QMenu *m = new QMenu(ICore::mainWindow());
|
|
|
|
|
m->setObjectName(QLatin1String(id.name()));
|
|
|
|
|
|
|
|
|
|
MenuActionContainer *mc = new MenuActionContainer(id);
|
|
|
|
|
mc->setMenu(m);
|
|
|
|
|
|
2013-06-25 13:37:21 +02:00
|
|
|
d->m_idContainerMap.insert(id, mc);
|
|
|
|
|
connect(mc, SIGNAL(destroyed()), d, SLOT(containerDestroyed()));
|
2012-05-24 13:49:06 +02:00
|
|
|
|
|
|
|
|
return mc;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Creates a new menu bar with the given \a id.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-14 12:39:59 +01:00
|
|
|
Returns a new ActionContainer that you can use to get the QMenuBar instance
|
2009-01-13 19:02:54 +01:00
|
|
|
or to add menus to the menu bar. The ActionManager owns
|
2009-01-14 12:39:59 +01:00
|
|
|
the returned ActionContainer.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
ActionContainer *ActionManager::createMenuBar(Id id)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
2013-06-25 13:37:21 +02:00
|
|
|
const ActionManagerPrivate::IdContainerMap::const_iterator it = d->m_idContainerMap.constFind(id);
|
|
|
|
|
if (it != d->m_idContainerMap.constEnd())
|
2012-05-24 13:49:06 +02:00
|
|
|
return it.value();
|
|
|
|
|
|
|
|
|
|
QMenuBar *mb = new QMenuBar; // No parent (System menu bar on Mac OS X)
|
|
|
|
|
mb->setObjectName(id.toString());
|
|
|
|
|
|
|
|
|
|
MenuBarActionContainer *mbc = new MenuBarActionContainer(id);
|
|
|
|
|
mbc->setMenuBar(mb);
|
|
|
|
|
|
2013-06-25 13:37:21 +02:00
|
|
|
d->m_idContainerMap.insert(id, mbc);
|
|
|
|
|
connect(mbc, SIGNAL(destroyed()), d, SLOT(containerDestroyed()));
|
2012-05-24 13:49:06 +02:00
|
|
|
|
|
|
|
|
return mbc;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Makes an \a action known to the system under the specified \a id.
|
2009-01-13 19:02:54 +01:00
|
|
|
|
|
|
|
|
Returns a command object that represents the action in the application and is
|
2012-04-01 21:24:03 +03:00
|
|
|
owned by the ActionManager. You can register several actions with the
|
2009-01-13 19:02:54 +01:00
|
|
|
same \a id as long as the \a context is different. In this case
|
|
|
|
|
a trigger of the actual action is forwarded to the registered QAction
|
|
|
|
|
for the currently active context.
|
2010-12-20 10:35:30 +01:00
|
|
|
A scriptable action can be called from a script without the need for the user
|
|
|
|
|
to interact with it.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
Command *ActionManager::registerAction(QAction *action, Id id, const Context &context, bool scriptable)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
2013-06-25 13:37:21 +02:00
|
|
|
Action *a = d->overridableAction(id);
|
2012-05-24 13:49:06 +02:00
|
|
|
if (a) {
|
|
|
|
|
a->addOverrideAction(action, context, scriptable);
|
|
|
|
|
emit m_instance->commandListChanged();
|
|
|
|
|
emit m_instance->commandAdded(id.toString());
|
|
|
|
|
}
|
|
|
|
|
return a;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Makes a \a shortcut known to the system under the specified \a id.
|
2009-01-13 19:02:54 +01:00
|
|
|
|
|
|
|
|
Returns a command object that represents the shortcut in the application and is
|
|
|
|
|
owned by the ActionManager. You can registered several shortcuts with the
|
|
|
|
|
same \a id as long as the \a context is different. In this case
|
|
|
|
|
a trigger of the actual shortcut is forwarded to the registered QShortcut
|
|
|
|
|
for the currently active context.
|
2010-12-20 10:35:30 +01:00
|
|
|
A scriptable shortcut can be called from a script without the need for the user
|
|
|
|
|
to interact with it.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
Command *ActionManager::registerShortcut(QShortcut *shortcut, Id id, const Context &context, bool scriptable)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
2013-01-28 11:59:54 +01:00
|
|
|
QTC_CHECK(!context.isEmpty());
|
2012-05-24 13:49:06 +02:00
|
|
|
Shortcut *sc = 0;
|
2013-06-25 13:37:21 +02:00
|
|
|
if (CommandPrivate *c = d->m_idCmdMap.value(id, 0)) {
|
2012-05-24 13:49:06 +02:00
|
|
|
sc = qobject_cast<Shortcut *>(c);
|
|
|
|
|
if (!sc) {
|
|
|
|
|
qWarning() << "registerShortcut: id" << id.name()
|
|
|
|
|
<< "is registered with a different command type.";
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
sc = new Shortcut(id);
|
2013-06-25 13:37:21 +02:00
|
|
|
d->m_idCmdMap.insert(id, sc);
|
2012-05-24 13:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sc->shortcut()) {
|
|
|
|
|
qWarning() << "registerShortcut: action already registered, id" << id.name() << ".";
|
|
|
|
|
return sc;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-25 13:37:21 +02:00
|
|
|
if (!d->hasContext(context))
|
2012-05-24 13:49:06 +02:00
|
|
|
shortcut->setEnabled(false);
|
|
|
|
|
shortcut->setObjectName(id.toString());
|
|
|
|
|
shortcut->setParent(ICore::mainWindow());
|
2013-05-07 11:39:45 +02:00
|
|
|
shortcut->setContext(Qt::ApplicationShortcut);
|
2012-05-24 13:49:06 +02:00
|
|
|
sc->setShortcut(shortcut);
|
|
|
|
|
sc->setScriptable(scriptable);
|
2013-01-28 11:59:54 +01:00
|
|
|
sc->setContext(context);
|
2014-02-27 17:10:24 +01:00
|
|
|
d->readUserSettings(id, sc);
|
2012-05-24 13:49:06 +02:00
|
|
|
|
|
|
|
|
emit m_instance->commandListChanged();
|
|
|
|
|
emit m_instance->commandAdded(id.toString());
|
|
|
|
|
|
|
|
|
|
if (isPresentationModeEnabled())
|
2013-06-25 13:37:21 +02:00
|
|
|
connect(sc->shortcut(), SIGNAL(activated()), d, SLOT(shortcutTriggered()));
|
2012-05-24 13:49:06 +02:00
|
|
|
return sc;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Returns the Command object that is known to the system
|
2012-05-24 13:49:06 +02:00
|
|
|
under the given \a id.
|
2009-01-13 19:02:54 +01:00
|
|
|
|
|
|
|
|
\sa ActionManager::registerAction()
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
Command *ActionManager::command(Id id)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
2013-06-25 13:37:21 +02:00
|
|
|
const ActionManagerPrivate::IdCmdMap::const_iterator it = d->m_idCmdMap.constFind(id);
|
|
|
|
|
if (it == d->m_idCmdMap.constEnd()) {
|
2012-05-24 13:49:06 +02:00
|
|
|
if (warnAboutFindFailures)
|
|
|
|
|
qWarning() << "ActionManagerPrivate::command(): failed to find :"
|
|
|
|
|
<< id.name();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return it.value();
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Returns the IActionContainter object that is know to the system
|
2012-05-24 13:49:06 +02:00
|
|
|
under the given \a id.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-13 19:02:54 +01:00
|
|
|
\sa ActionManager::createMenu()
|
|
|
|
|
\sa ActionManager::createMenuBar()
|
|
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
ActionContainer *ActionManager::actionContainer(Id id)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
2013-06-25 13:37:21 +02:00
|
|
|
const ActionManagerPrivate::IdContainerMap::const_iterator it = d->m_idContainerMap.constFind(id);
|
|
|
|
|
if (it == d->m_idContainerMap.constEnd()) {
|
2012-05-24 13:49:06 +02:00
|
|
|
if (warnAboutFindFailures)
|
|
|
|
|
qWarning() << "ActionManagerPrivate::actionContainer(): failed to find :"
|
|
|
|
|
<< id.name();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return it.value();
|
|
|
|
|
}
|
2010-12-06 17:21:03 +01:00
|
|
|
|
|
|
|
|
/*!
|
2013-12-11 15:37:48 +01:00
|
|
|
Returns all commands that have been registered.
|
|
|
|
|
*/
|
2012-05-24 13:49:06 +02:00
|
|
|
QList<Command *> ActionManager::commands()
|
|
|
|
|
{
|
|
|
|
|
// transform list of CommandPrivate into list of Command
|
|
|
|
|
QList<Command *> result;
|
2013-12-16 15:54:02 +01:00
|
|
|
foreach (Command *cmd, d->m_idCmdMap)
|
2012-05-24 13:49:06 +02:00
|
|
|
result << cmd;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Removes the knowledge about an \a action under the specified \a id.
|
2010-12-06 17:21:03 +01:00
|
|
|
|
|
|
|
|
Usually you do not need to unregister actions. The only valid use case for unregistering
|
|
|
|
|
actions, is for actions that represent user definable actions, like for the custom Locator
|
|
|
|
|
filters. If the user removes such an action, it also has to be unregistered from the action manager,
|
|
|
|
|
to make it disappear from shortcut settings etc.
|
|
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
void ActionManager::unregisterAction(QAction *action, Id id)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
|
|
|
|
Action *a = 0;
|
2013-06-25 13:37:21 +02:00
|
|
|
CommandPrivate *c = d->m_idCmdMap.value(id, 0);
|
2012-05-24 13:49:06 +02:00
|
|
|
QTC_ASSERT(c, return);
|
|
|
|
|
a = qobject_cast<Action *>(c);
|
|
|
|
|
if (!a) {
|
|
|
|
|
qWarning() << "unregisterAction: id" << id.name()
|
|
|
|
|
<< "is registered with a different command type.";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
a->removeOverrideAction(action);
|
|
|
|
|
if (a->isEmpty()) {
|
|
|
|
|
// clean up
|
|
|
|
|
// ActionContainers listen to the commands' destroyed signals
|
|
|
|
|
ICore::mainWindow()->removeAction(a->action());
|
|
|
|
|
delete a->action();
|
2013-06-25 13:37:21 +02:00
|
|
|
d->m_idCmdMap.remove(id);
|
2012-05-24 13:49:06 +02:00
|
|
|
delete a;
|
|
|
|
|
}
|
|
|
|
|
emit m_instance->commandListChanged();
|
|
|
|
|
}
|
2010-12-06 17:21:03 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Removes the knowledge about a shortcut under the specified \a id.
|
2012-05-24 13:49:06 +02:00
|
|
|
|
|
|
|
|
Usually you do not need to unregister shortcuts. The only valid use case for unregistering
|
|
|
|
|
shortcuts, is for shortcuts that represent user definable actions. If the user removes such an action,
|
|
|
|
|
a corresponding shortcut also has to be unregistered from the action manager,
|
|
|
|
|
to make it disappear from shortcut settings etc.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2013-05-26 00:29:33 +02:00
|
|
|
void ActionManager::unregisterShortcut(Id id)
|
2012-05-24 13:49:06 +02:00
|
|
|
{
|
|
|
|
|
Shortcut *sc = 0;
|
2013-06-25 13:37:21 +02:00
|
|
|
CommandPrivate *c = d->m_idCmdMap.value(id, 0);
|
2012-05-24 13:49:06 +02:00
|
|
|
QTC_ASSERT(c, return);
|
|
|
|
|
sc = qobject_cast<Shortcut *>(c);
|
|
|
|
|
if (!sc) {
|
|
|
|
|
qWarning() << "unregisterShortcut: id" << id.name()
|
|
|
|
|
<< "is registered with a different command type.";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
delete sc->shortcut();
|
2013-06-25 13:37:21 +02:00
|
|
|
d->m_idCmdMap.remove(id);
|
2012-05-24 13:49:06 +02:00
|
|
|
delete sc;
|
|
|
|
|
emit m_instance->commandListChanged();
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-12-11 15:37:48 +01:00
|
|
|
/*!
|
|
|
|
|
Handles the display of the used shortcuts in the presentation mode. The presentation mode is
|
|
|
|
|
enabled when starting \QC with the command line argument \c{-presentationMode}. In the
|
|
|
|
|
presentation mode, \QC displays any pressed shortcut in a grey box.
|
|
|
|
|
*/
|
2012-05-24 13:49:06 +02:00
|
|
|
void ActionManager::setPresentationModeEnabled(bool enabled)
|
|
|
|
|
{
|
|
|
|
|
if (enabled == isPresentationModeEnabled())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Signal/slots to commands:
|
|
|
|
|
foreach (Command *c, commands()) {
|
|
|
|
|
if (c->action()) {
|
|
|
|
|
if (enabled)
|
2013-06-25 13:37:21 +02:00
|
|
|
connect(c->action(), SIGNAL(triggered()), d, SLOT(actionTriggered()));
|
2012-05-24 13:49:06 +02:00
|
|
|
else
|
2013-06-25 13:37:21 +02:00
|
|
|
disconnect(c->action(), SIGNAL(triggered()), d, SLOT(actionTriggered()));
|
2012-05-24 13:49:06 +02:00
|
|
|
}
|
|
|
|
|
if (c->shortcut()) {
|
|
|
|
|
if (enabled)
|
2013-06-25 13:37:21 +02:00
|
|
|
connect(c->shortcut(), SIGNAL(activated()), d, SLOT(shortcutTriggered()));
|
2012-05-24 13:49:06 +02:00
|
|
|
else
|
2013-06-25 13:37:21 +02:00
|
|
|
disconnect(c->shortcut(), SIGNAL(activated()), d, SLOT(shortcutTriggered()));
|
2012-05-24 13:49:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The label for the shortcuts:
|
2013-06-25 13:37:21 +02:00
|
|
|
if (!d->m_presentationLabel) {
|
|
|
|
|
d->m_presentationLabel = new QLabel(0, Qt::ToolTip | Qt::WindowStaysOnTopHint);
|
|
|
|
|
QFont font = d->m_presentationLabel->font();
|
2012-05-24 13:49:06 +02:00
|
|
|
font.setPixelSize(45);
|
2013-06-25 13:37:21 +02:00
|
|
|
d->m_presentationLabel->setFont(font);
|
|
|
|
|
d->m_presentationLabel->setAlignment(Qt::AlignCenter);
|
|
|
|
|
d->m_presentationLabel->setMargin(5);
|
2012-05-24 13:49:06 +02:00
|
|
|
|
2013-06-25 13:37:21 +02:00
|
|
|
connect(&d->m_presentationLabelTimer, SIGNAL(timeout()), d->m_presentationLabel, SLOT(hide()));
|
2012-05-24 13:49:06 +02:00
|
|
|
} else {
|
2013-06-25 13:37:21 +02:00
|
|
|
d->m_presentationLabelTimer.stop();
|
|
|
|
|
delete d->m_presentationLabel;
|
|
|
|
|
d->m_presentationLabel = 0;
|
2012-05-24 13:49:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ActionManager::isPresentationModeEnabled()
|
|
|
|
|
{
|
2013-06-25 13:37:21 +02:00
|
|
|
return d->m_presentationLabel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ActionManager::initialize()
|
|
|
|
|
{
|
|
|
|
|
d->initialize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ActionManager::saveSettings(QSettings *settings)
|
|
|
|
|
{
|
|
|
|
|
d->saveSettings(settings);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ActionManager::setContext(const Context &context)
|
|
|
|
|
{
|
|
|
|
|
d->setContext(context);
|
2012-05-24 13:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2009-01-13 19:02:54 +01:00
|
|
|
\class ActionManagerPrivate
|
|
|
|
|
\inheaderfile actionmanager_p.h
|
|
|
|
|
\internal
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
|
2012-05-24 13:49:06 +02:00
|
|
|
ActionManagerPrivate::ActionManagerPrivate()
|
|
|
|
|
: m_presentationLabel(0)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2011-10-14 13:01:07 +00:00
|
|
|
m_presentationLabelTimer.setInterval(1000);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2009-01-13 13:07:29 +01:00
|
|
|
ActionManagerPrivate::~ActionManagerPrivate()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2011-01-20 15:28:34 +01:00
|
|
|
// first delete containers to avoid them reacting to command deletion
|
2011-01-21 10:58:06 +01:00
|
|
|
foreach (ActionContainerPrivate *container, m_idContainerMap)
|
|
|
|
|
disconnect(container, SIGNAL(destroyed()), this, SLOT(containerDestroyed()));
|
2013-03-14 14:19:23 +01:00
|
|
|
qDeleteAll(m_idContainerMap);
|
|
|
|
|
qDeleteAll(m_idCmdMap);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-01-11 13:34:31 +01:00
|
|
|
QDebug operator<<(QDebug d, const Context &context)
|
2010-06-28 10:30:45 +02:00
|
|
|
{
|
2013-01-11 13:34:31 +01:00
|
|
|
d << "CONTEXT: ";
|
|
|
|
|
foreach (Id id, context)
|
|
|
|
|
d << " " << id.uniqueIdentifier() << " " << id.toString();
|
|
|
|
|
return d;
|
2010-06-28 10:30:45 +02:00
|
|
|
}
|
|
|
|
|
|
2010-06-25 12:56:16 +02:00
|
|
|
void ActionManagerPrivate::setContext(const Context &context)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
// here are possibilities for speed optimization if necessary:
|
|
|
|
|
// let commands (de-)register themselves for contexts
|
|
|
|
|
// and only update commands that are either in old or new contexts
|
|
|
|
|
m_context = context;
|
|
|
|
|
const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
|
|
|
|
|
for (IdCmdMap::const_iterator it = m_idCmdMap.constBegin(); it != cmdcend; ++it)
|
|
|
|
|
it.value()->setCurrentContext(m_context);
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-25 12:56:16 +02:00
|
|
|
bool ActionManagerPrivate::hasContext(const Context &context) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-06-25 18:05:09 +02:00
|
|
|
for (int i = 0; i < m_context.size(); ++i) {
|
|
|
|
|
if (context.contains(m_context.at(i)))
|
2008-12-02 12:01:29 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-21 10:58:06 +01:00
|
|
|
void ActionManagerPrivate::containerDestroyed()
|
|
|
|
|
{
|
|
|
|
|
ActionContainerPrivate *container = static_cast<ActionContainerPrivate *>(sender());
|
|
|
|
|
m_idContainerMap.remove(m_idContainerMap.key(container));
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-14 13:01:07 +00:00
|
|
|
void ActionManagerPrivate::actionTriggered()
|
|
|
|
|
{
|
|
|
|
|
QAction *action = qobject_cast<QAction *>(QObject::sender());
|
|
|
|
|
if (action)
|
|
|
|
|
showShortcutPopup(action->shortcut().toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ActionManagerPrivate::shortcutTriggered()
|
|
|
|
|
{
|
|
|
|
|
QShortcut *sc = qobject_cast<QShortcut *>(QObject::sender());
|
|
|
|
|
if (sc)
|
|
|
|
|
showShortcutPopup(sc->key().toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ActionManagerPrivate::showShortcutPopup(const QString &shortcut)
|
|
|
|
|
{
|
2012-05-24 13:49:06 +02:00
|
|
|
if (shortcut.isEmpty() || !ActionManager::isPresentationModeEnabled())
|
2011-10-14 13:01:07 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_presentationLabel->setText(shortcut);
|
|
|
|
|
m_presentationLabel->adjustSize();
|
|
|
|
|
|
2012-05-24 13:49:06 +02:00
|
|
|
QPoint p = ICore::mainWindow()->mapToGlobal(ICore::mainWindow()->rect().center() - m_presentationLabel->rect().center());
|
2011-10-14 13:01:07 +00:00
|
|
|
m_presentationLabel->move(p);
|
|
|
|
|
|
|
|
|
|
m_presentationLabel->show();
|
|
|
|
|
m_presentationLabel->raise();
|
|
|
|
|
m_presentationLabelTimer.start();
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-26 00:29:33 +02:00
|
|
|
Action *ActionManagerPrivate::overridableAction(Id id)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-01-14 15:33:58 +01:00
|
|
|
Action *a = 0;
|
2011-11-11 12:16:20 +01:00
|
|
|
if (CommandPrivate *c = m_idCmdMap.value(id, 0)) {
|
2010-01-14 15:33:58 +01:00
|
|
|
a = qobject_cast<Action *>(c);
|
2009-05-06 16:06:43 +02:00
|
|
|
if (!a) {
|
2011-09-02 12:45:36 +02:00
|
|
|
qWarning() << "registerAction: id" << id.name()
|
|
|
|
|
<< "is registered with a different command type.";
|
2011-01-12 09:45:19 +01:00
|
|
|
return 0;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2009-05-06 16:06:43 +02:00
|
|
|
} else {
|
2011-11-11 12:16:20 +01:00
|
|
|
a = new Action(id);
|
|
|
|
|
m_idCmdMap.insert(id, a);
|
2014-02-24 15:20:50 +01:00
|
|
|
readUserSettings(id, a);
|
2012-05-24 13:49:06 +02:00
|
|
|
ICore::mainWindow()->addAction(a->action());
|
2011-09-02 12:45:36 +02:00
|
|
|
a->action()->setObjectName(id.toString());
|
2011-01-12 09:45:19 +01:00
|
|
|
a->action()->setShortcutContext(Qt::ApplicationShortcut);
|
2011-01-18 17:03:14 +01:00
|
|
|
a->setCurrentContext(m_context);
|
2011-10-14 13:01:07 +00:00
|
|
|
|
2012-05-24 13:49:06 +02:00
|
|
|
if (ActionManager::isPresentationModeEnabled())
|
2011-10-14 13:01:07 +00:00
|
|
|
connect(a->action(), SIGNAL(triggered()), this, SLOT(actionTriggered()));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-24 15:20:50 +01:00
|
|
|
void ActionManagerPrivate::readUserSettings(Id id, CommandPrivate *cmd)
|
|
|
|
|
{
|
|
|
|
|
QSettings *settings = Core::ICore::settings();
|
|
|
|
|
settings->beginGroup(QLatin1String(kKeyboardSettingsKey));
|
|
|
|
|
if (settings->contains(id.toString()))
|
|
|
|
|
cmd->setKeySequence(QKeySequence(settings->value(id.toString()).toString()));
|
|
|
|
|
settings->endGroup();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char oldSettingsGroup[] = "KeyBindings";
|
|
|
|
|
static const char oldIdKey[] = "ID";
|
|
|
|
|
static const char oldSequenceKey[] = "Keysequence";
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-13 13:07:29 +01:00
|
|
|
void ActionManagerPrivate::initialize()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-02-24 15:20:50 +01:00
|
|
|
// TODO remove me after some period after 3.1
|
|
|
|
|
// check if settings in old style (pre 3.1) exist
|
2012-01-24 15:36:40 +01:00
|
|
|
QSettings *settings = Core::ICore::settings();
|
2014-02-24 15:20:50 +01:00
|
|
|
if (settings->contains(QLatin1String(kKeyboardSettingsKey)))
|
|
|
|
|
return;
|
|
|
|
|
// move old settings style to new settings style
|
|
|
|
|
QMap<Id, QKeySequence> shortcutMap;
|
|
|
|
|
const int shortcuts = settings->beginReadArray(QLatin1String(oldSettingsGroup));
|
2011-09-02 12:45:36 +02:00
|
|
|
for (int i = 0; i < shortcuts; ++i) {
|
2008-12-02 12:01:29 +01:00
|
|
|
settings->setArrayIndex(i);
|
2014-02-24 15:20:50 +01:00
|
|
|
const QKeySequence key(settings->value(QLatin1String(oldSequenceKey)).toString());
|
|
|
|
|
const Id id = Id::fromSetting(settings->value(QLatin1String(oldIdKey)));
|
|
|
|
|
shortcutMap.insert(id, key);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
settings->endArray();
|
2014-02-24 15:20:50 +01:00
|
|
|
// write settings in new style
|
|
|
|
|
settings->beginGroup(QLatin1String(kKeyboardSettingsKey));
|
|
|
|
|
QMapIterator<Id, QKeySequence> it(shortcutMap);
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
it.next();
|
|
|
|
|
settings->setValue(it.key().toString(), it.value().toString());
|
|
|
|
|
}
|
|
|
|
|
settings->endGroup();
|
|
|
|
|
// remove old settings
|
|
|
|
|
settings->remove(QLatin1String(oldSettingsGroup));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2009-01-13 13:07:29 +01:00
|
|
|
void ActionManagerPrivate::saveSettings(QSettings *settings)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-02-24 15:20:50 +01:00
|
|
|
settings->beginGroup(QLatin1String(kKeyboardSettingsKey));
|
2008-12-02 12:01:29 +01:00
|
|
|
const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
|
|
|
|
|
for (IdCmdMap::const_iterator j = m_idCmdMap.constBegin(); j != cmdcend; ++j) {
|
2011-11-11 12:16:20 +01:00
|
|
|
const Id id = j.key();
|
2009-01-14 12:58:06 +01:00
|
|
|
CommandPrivate *cmd = j.value();
|
2008-12-02 12:01:29 +01:00
|
|
|
QKeySequence key = cmd->keySequence();
|
2014-02-24 15:20:50 +01:00
|
|
|
if (key != cmd->defaultKeySequence())
|
|
|
|
|
settings->setValue(id.toString(), key.toString());
|
|
|
|
|
else
|
|
|
|
|
settings->remove(id.toString());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2014-02-24 15:20:50 +01:00
|
|
|
settings->endGroup();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|