From 90ecb036a26fe334394adc0581424be0992aa4f5 Mon Sep 17 00:00:00 2001 From: con <qtc-committer@nokia.com> Date: Mon, 6 Dec 2010 17:21:03 +0100 Subject: [PATCH] Make it possible to specify shortcuts for Locator filters. Task-number: QTCREATORBUG-1147 --- .../actionmanager/actionmanager.cpp | 37 ++++++++++++++++++- .../coreplugin/actionmanager/actionmanager.h | 7 +++- .../actionmanager/actionmanager_p.h | 1 + .../coreplugin/actionmanager/command.cpp | 19 ++++++++++ .../coreplugin/actionmanager/command_p.h | 2 + .../actionmanager/commandmappings.cpp | 9 +++++ .../actionmanager/commandmappings.h | 1 + .../coreplugin/dialogs/shortcutsettings.cpp | 20 +++++++++- .../coreplugin/dialogs/shortcutsettings.h | 4 +- src/plugins/locator/locatorplugin.cpp | 12 +++--- src/plugins/locator/locatorwidget.cpp | 34 ++++++++++++++++- src/plugins/locator/locatorwidget.h | 1 + 12 files changed, 136 insertions(+), 11 deletions(-) diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp index c44c6591695..8f96443600a 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp +++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp @@ -35,6 +35,7 @@ #include <coreplugin/coreconstants.h> #include <coreplugin/icore.h> +#include <utils/qtcassert.h> #include <QtCore/QDebug> #include <QtCore/QSettings> @@ -198,6 +199,17 @@ namespace { \sa ActionManager::createMenu() \sa ActionManager::createMenuBar() */ + +/*! + \fn Command *ActionManager::unregisterAction(QAction *action, const QString &id) + \brief Removes the knowledge about an \a action under the specified string \a id. + + 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. +*/ + /*! \fn ActionManager::ActionManager(QObject *parent) \internal @@ -332,6 +344,7 @@ Command *ActionManagerPrivate::registerAction(QAction *action, const Id &id, con a = static_cast<Action *>(c); if (a) a->addOverrideAction(action, context); + emit commandListChanged(); return a; } @@ -375,10 +388,31 @@ Command *ActionManagerPrivate::registerOverridableAction(QAction *action, const } else if (checkUnique) { qWarning() << "registerOverridableAction: id" << id << "is already registered."; } - return a; } +void ActionManagerPrivate::unregisterAction(QAction *action, const Id &id) +{ + Action *a = 0; + const int uid = UniqueIDManager::instance()->uniqueIdentifier(id); + CommandPrivate *c = m_idCmdMap.value(uid, 0); + QTC_ASSERT(c, return); + a = qobject_cast<Action *>(c); + if (!a) { + qWarning() << "registerAction: id" << id << "is registered with a different command type."; + return; + } + a->removeOverrideAction(action); + if (a->isEmpty()) { + // clean up + m_mainWnd->removeAction(a->action()); + delete a->action(); + m_idCmdMap.remove(uid); + delete a; + } + emit commandListChanged(); +} + Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &id, const Context &context) { Shortcut *sc = 0; @@ -410,6 +444,7 @@ Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &i else sc->setContext(context); + emit commandListChanged(); return sc; } diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.h b/src/plugins/coreplugin/actionmanager/actionmanager.h index eca4b877894..4dcc7d029b3 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.h +++ b/src/plugins/coreplugin/actionmanager/actionmanager.h @@ -32,6 +32,7 @@ #include "coreplugin/core_global.h" #include "coreplugin/uniqueidmanager.h" +#include "coreplugin/icontext.h" #include <QtCore/QObject> #include <QtCore/QList> @@ -46,7 +47,6 @@ namespace Core { class ActionContainer; class Command; -class Context; class CORE_EXPORT ActionManager : public QObject { @@ -65,6 +65,11 @@ public: virtual ActionContainer *actionContainer(const Id &id) const = 0; virtual QList<Command *> commands() const = 0; + + virtual void unregisterAction(QAction *action, const Id &id) = 0; + +signals: + void commandListChanged(); }; } // namespace Core diff --git a/src/plugins/coreplugin/actionmanager/actionmanager_p.h b/src/plugins/coreplugin/actionmanager/actionmanager_p.h index 39cb3f65665..67a4746b9b0 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager_p.h +++ b/src/plugins/coreplugin/actionmanager/actionmanager_p.h @@ -91,6 +91,7 @@ public: Core::Command *command(const Id &id) const; Core::ActionContainer *actionContainer(const Id &id) const; + void unregisterAction(QAction *action, const Id &id); private: bool hasContext(const Context &context) const; diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp index ccf4ccd56ee..d82a377fd5e 100644 --- a/src/plugins/coreplugin/actionmanager/command.cpp +++ b/src/plugins/coreplugin/actionmanager/command.cpp @@ -495,6 +495,20 @@ void Action::addOverrideAction(QAction *action, const Core::Context &context) } } +void Action::removeOverrideAction(QAction *action) +{ + QMutableMapIterator<int, QPointer<QAction> > it(m_contextActionMap); + while (it.hasNext()) { + it.next(); + if (it.value() == 0) { + it.remove(); + } else if (it.value() == action) { + it.remove(); + } + } + setCurrentContext(m_context); +} + void Action::actionChanged() { if (hasAttribute(CA_UpdateIcon)) { @@ -535,3 +549,8 @@ void Action::setActive(bool state) } } +bool Action::isEmpty() const +{ + return m_contextActionMap.isEmpty(); +} + diff --git a/src/plugins/coreplugin/actionmanager/command_p.h b/src/plugins/coreplugin/actionmanager/command_p.h index a7bac35da14..37e534ebff3 100644 --- a/src/plugins/coreplugin/actionmanager/command_p.h +++ b/src/plugins/coreplugin/actionmanager/command_p.h @@ -130,6 +130,8 @@ public: bool setCurrentContext(const Context &context); bool isActive() const; void addOverrideAction(QAction *action, const Context &context); + void removeOverrideAction(QAction *action); + bool isEmpty() const; protected: void updateToolTipWithKeySequence(); diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.cpp b/src/plugins/coreplugin/actionmanager/commandmappings.cpp index f49f621bc99..541ac4768c7 100644 --- a/src/plugins/coreplugin/actionmanager/commandmappings.cpp +++ b/src/plugins/coreplugin/actionmanager/commandmappings.cpp @@ -158,6 +158,8 @@ void CommandMappings::commandChanged(QTreeWidgetItem *current) void CommandMappings::filterChanged(const QString &f) { + if (!m_page) + return; for (int i=0; i<m_page->commandList->topLevelItemCount(); ++i) { QTreeWidgetItem *item = m_page->commandList->topLevelItem(i); item->setHidden(filter(f, item)); @@ -203,3 +205,10 @@ void CommandMappings::setModified(QTreeWidgetItem *item , bool modified) f.setBold(modified); item->setFont(2, f); } + +QString CommandMappings::filterText() const +{ + if (!m_page) + return QString(); + return m_page->filterEdit->text(); +} diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.h b/src/plugins/coreplugin/actionmanager/commandmappings.h index 66631e99a49..e809b80e7ea 100644 --- a/src/plugins/coreplugin/actionmanager/commandmappings.h +++ b/src/plugins/coreplugin/actionmanager/commandmappings.h @@ -80,6 +80,7 @@ protected: void setImportExportEnabled(bool enabled); QTreeWidget *commandList() const; QLineEdit *targetEdit() const; + QString filterText() const; void setPageTitle(const QString &s); void setTargetLabelText(const QString &s); void setTargetEditTitle(const QString &s); diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp index 74abe1321e1..abc491adce7 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp @@ -56,8 +56,10 @@ using namespace Core; using namespace Core::Internal; ShortcutSettings::ShortcutSettings(QObject *parent) - : CommandMappings(parent) + : CommandMappings(parent), m_initialized(false) { + Core::Internal::ActionManagerPrivate *am = ActionManagerPrivate::instance(); + connect(am, SIGNAL(commandListChanged()), this, SLOT(initialize())); } ShortcutSettings::~ShortcutSettings() @@ -94,6 +96,7 @@ QIcon ShortcutSettings::categoryIcon() const QWidget *ShortcutSettings::createPage(QWidget *parent) { + m_initialized = true; m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0; QWidget *w = CommandMappings::createPage(parent); @@ -128,6 +131,7 @@ void ShortcutSettings::finish() m_scitems.clear(); CommandMappings::finish(); + m_initialized = false; } bool ShortcutSettings::matches(const QString &s) const @@ -271,8 +275,21 @@ void ShortcutSettings::exportAction() } } +void ShortcutSettings::clear() +{ + QTreeWidget *tree = commandList(); + for (int i = tree->topLevelItemCount()-1; i >= 0 ; --i) { + delete tree->takeTopLevelItem(i); + } + qDeleteAll(m_scitems); + m_scitems.clear(); +} + void ShortcutSettings::initialize() { + if (!m_initialized) + return; + clear(); Core::Internal::ActionManagerPrivate *am = ActionManagerPrivate::instance(); UniqueIDManager *uidm = UniqueIDManager::instance(); @@ -325,6 +342,7 @@ void ShortcutSettings::initialize() markPossibleCollisions(s); } + filterChanged(filterText()); } void ShortcutSettings::handleKeyEvent(QKeyEvent *e) diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.h b/src/plugins/coreplugin/dialogs/shortcutsettings.h index 161ed2d4a8f..19f0b14fbb6 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.h +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.h @@ -86,10 +86,11 @@ private slots: void importAction(); void exportAction(); void defaultAction(); + void initialize(); private: void setKeySequence(const QKeySequence &key); - void initialize(); + void clear(); void handleKeyEvent(QKeyEvent *e); int translateModifiers(Qt::KeyboardModifiers state, const QString &text); @@ -101,6 +102,7 @@ private: int m_key[4], m_keyNum; QString m_searchKeywords; + bool m_initialized; }; } // namespace Internal diff --git a/src/plugins/locator/locatorplugin.cpp b/src/plugins/locator/locatorplugin.cpp index d88f44b6ef5..6b18c994180 100644 --- a/src/plugins/locator/locatorplugin.cpp +++ b/src/plugins/locator/locatorplugin.cpp @@ -36,11 +36,6 @@ #include "filesystemfilter.h" #include "settingspage.h" -#include <QtCore/QSettings> -#include <QtCore/QtPlugin> -#include <QtCore/QFuture> -#include <QtCore/QFutureWatcher> - #include <coreplugin/statusbarwidget.h> #include <coreplugin/coreconstants.h> #include <coreplugin/settingsdatabase.h> @@ -54,6 +49,12 @@ #include <extensionsystem/pluginmanager.h> #include <qtconcurrent/QtConcurrentTools> +#include <QtCore/QSettings> +#include <QtCore/QtPlugin> +#include <QtCore/QFuture> +#include <QtCore/QFutureWatcher> +#include <QtGui/QAction> + /*! \namespace Locator The Locator namespace provides the hooks for Locator content. @@ -142,6 +143,7 @@ void LocatorPlugin::extensionsInitialized() { m_filters = ExtensionSystem::PluginManager::instance()->getObjects<ILocatorFilter>(); qSort(m_filters.begin(), m_filters.end(), filterLessThan); + setFilters(m_filters); } void LocatorPlugin::startSettingsLoad() diff --git a/src/plugins/locator/locatorwidget.cpp b/src/plugins/locator/locatorwidget.cpp index 044213d091c..5d650d65464 100644 --- a/src/plugins/locator/locatorwidget.cpp +++ b/src/plugins/locator/locatorwidget.cpp @@ -37,6 +37,8 @@ #include <extensionsystem/pluginmanager.h> #include <coreplugin/icore.h> #include <coreplugin/modemanager.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/command.h> #include <coreplugin/coreconstants.h> #include <coreplugin/fileiconprovider.h> #include <utils/filterlineedit.h> @@ -321,12 +323,40 @@ LocatorWidget::LocatorWidget(LocatorPlugin *qop) : void LocatorWidget::updateFilterList() { m_filterMenu->clear(); + + // update actions and menu + Core::ActionManager *am = Core::ICore::instance()->actionManager(); + QMap<QString, QAction *> actionCopy = m_filterActionMap; + m_filterActionMap.clear(); + // register new actions, update existent foreach (ILocatorFilter *filter, m_locatorPlugin->filters()) { - if (!filter->shortcutString().isEmpty() && !filter->isHidden()) { - QAction *action = m_filterMenu->addAction(filter->displayName(), this, SLOT(filterSelected())); + if (filter->shortcutString().isEmpty() || filter->isHidden()) + continue; + QAction *action = 0; + Core::Command *cmd = 0; + if (!actionCopy.contains(filter->id())) { + // register new action + action = new QAction(filter->displayName(), this); + cmd = am->registerAction(action, QLatin1String("Locator.") + filter->id(), + Core::Context(Core::Constants::C_GLOBAL)); + cmd->setAttribute(Core::Command::CA_UpdateText); + connect(action, SIGNAL(triggered()), this, SLOT(filterSelected())); action->setData(qVariantFromValue(filter)); + } else { + action = actionCopy.take(filter->id()); + action->setText(filter->displayName()); + cmd = am->command(QLatin1String("Locator.") + filter->id()); } + m_filterActionMap.insert(filter->id(), action); + m_filterMenu->addAction(cmd->action()); + } + + // unregister actions that are deleted now + foreach (const QString &id, actionCopy.keys()) { + am->unregisterAction(actionCopy.value(id), QLatin1String("Locator.") + id); } + qDeleteAll(actionCopy); + m_filterMenu->addSeparator(); m_filterMenu->addAction(m_refreshAction); m_filterMenu->addAction(m_configureAction); diff --git a/src/plugins/locator/locatorwidget.h b/src/plugins/locator/locatorwidget.h index a3a0cd33b63..a3452067246 100644 --- a/src/plugins/locator/locatorwidget.h +++ b/src/plugins/locator/locatorwidget.h @@ -91,6 +91,7 @@ private: Utils::FilterLineEdit *m_fileLineEdit; QTimer *m_showPopupTimer; QFutureWatcher<FilterEntry> *m_entriesWatcher; + QMap<QString, QAction *> m_filterActionMap; }; } // namespace Internal -- GitLab