diff --git a/src/plugins/coreplugin/actionmanager/actioncontainer.cpp b/src/plugins/coreplugin/actionmanager/actioncontainer.cpp index fb50edfd95b..aa8ff2c7ed7 100644 --- a/src/plugins/coreplugin/actionmanager/actioncontainer.cpp +++ b/src/plugins/coreplugin/actionmanager/actioncontainer.cpp @@ -36,6 +36,7 @@ #include "uniqueidmanager.h" #include +#include #include #include @@ -152,7 +153,7 @@ using namespace Core::Internal; */ ActionContainerPrivate::ActionContainerPrivate(int id) - : m_data(0), m_id(id) + : m_data(0), m_id(id), m_updateRequested(false) { } @@ -253,6 +254,7 @@ void ActionContainerPrivate::addAction(Command *action, int pos, bool setpos) m_commands.append(action); m_posmap.insert(pos, action->id()); + connect(action, SIGNAL(activeStateChanged()), this, SLOT(scheduleUpdate())); insertAction(ba, a->action()); } @@ -320,6 +322,20 @@ int ActionContainerPrivate::calcPosition(int pos, int prevKey) const return grp + (prevKey & 0xFFFF) + 10; } +void ActionContainerPrivate::scheduleUpdate() +{ + if (m_updateRequested) + return; + m_updateRequested = true; + QTimer::singleShot(0, this, SLOT(update())); +} + +void ActionContainerPrivate::update() +{ + updateInternal(); + m_updateRequested = false; +} + // ---------- MenuActionContainer ------------ /*! @@ -368,7 +384,7 @@ CommandLocation MenuActionContainer::location() const return m_location; } -bool MenuActionContainer::update() +bool MenuActionContainer::updateInternal() { if (hasEmptyAction(EA_None)) return true; @@ -380,7 +396,7 @@ bool MenuActionContainer::update() qWarning() << Q_FUNC_INFO << "container" << (this->menu() ? this->menu()->title() : "") << "contains itself as subcontainer"; continue; } - if (container->update()) { + if (qobject_cast(container)->updateInternal()) { hasitems = true; break; } @@ -441,7 +457,7 @@ void MenuBarActionContainer::insertMenu(QAction *before, QMenu *menu) m_menuBar->insertMenu(before, menu); } -bool MenuBarActionContainer::update() +bool MenuBarActionContainer::updateInternal() { if (hasEmptyAction(EA_None)) return true; diff --git a/src/plugins/coreplugin/actionmanager/actioncontainer.h b/src/plugins/coreplugin/actionmanager/actioncontainer.h index 2fa268ba3f6..042921df65b 100644 --- a/src/plugins/coreplugin/actionmanager/actioncontainer.h +++ b/src/plugins/coreplugin/actionmanager/actioncontainer.h @@ -66,7 +66,6 @@ public: virtual void addAction(Core::Command *action, const QString &group = QString()) = 0; virtual void addMenu(Core::ActionContainer *menu, const QString &group = QString()) = 0; - virtual bool update() = 0; virtual ~ActionContainer() {} }; diff --git a/src/plugins/coreplugin/actionmanager/actioncontainer_p.h b/src/plugins/coreplugin/actionmanager/actioncontainer_p.h index ba9f7ed6c0c..226fcc35acf 100644 --- a/src/plugins/coreplugin/actionmanager/actioncontainer_p.h +++ b/src/plugins/coreplugin/actionmanager/actioncontainer_p.h @@ -40,6 +40,8 @@ namespace Internal { class ActionContainerPrivate : public Core::ActionContainer { + Q_OBJECT + public: ActionContainerPrivate(int id); virtual ~ActionContainerPrivate() {} @@ -62,6 +64,9 @@ public: QList commands() const { return m_commands; } QList subContainers() const { return m_subContainers; } + + virtual bool updateInternal() = 0; + protected: bool canAddAction(Command *action) const; bool canAddMenu(ActionContainer *menu) const; @@ -70,6 +75,10 @@ protected: void addAction(Command *action, int pos, bool setpos); void addMenu(ActionContainer *menu, int pos, bool setpos); +private slots: + void scheduleUpdate(); + void update(); + private: QAction *beforeAction(int pos, int *prevKey) const; int calcPosition(int pos, int prevKey) const; @@ -80,6 +89,7 @@ private: QMap m_posmap; QList m_subContainers; QList m_commands; + bool m_updateRequested; }; class MenuActionContainer : public ActionContainerPrivate @@ -95,10 +105,11 @@ public: void insertAction(QAction *before, QAction *action); void insertMenu(QAction *before, QMenu *menu); - bool update(); protected: bool canBeAddedToMenu() const; + bool updateInternal(); + private: QMenu *m_menu; CommandLocation m_location; @@ -114,10 +125,11 @@ public: void insertAction(QAction *before, QAction *action); void insertMenu(QAction *before, QMenu *menu); - bool update(); protected: bool canBeAddedToMenu() const; + bool updateInternal(); + private: QMenuBar *m_menuBar; }; diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp index 91289fb1c9a..ff219e117f9 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp +++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp @@ -274,10 +274,6 @@ void ActionManagerPrivate::setContext(const QList &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); - - const IdContainerMap::const_iterator acend = m_idContainerMap.constEnd(); - for (IdContainerMap::const_iterator it = m_idContainerMap.constBegin(); it != acend; ++it) - it.value()->update(); } bool ActionManagerPrivate::hasContext(QList context) const diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp index 5cb8ad0f398..015f4f344c9 100644 --- a/src/plugins/coreplugin/actionmanager/command.cpp +++ b/src/plugins/coreplugin/actionmanager/command.cpp @@ -337,11 +337,17 @@ bool Shortcut::setCurrentContext(const QList &context) { foreach (int ctxt, m_context) { if (context.contains(ctxt)) { - m_shortcut->setEnabled(true); + if (!m_shortcut->isEnabled()) { + m_shortcut->setEnabled(true); + emit activeStateChanged(); + } return true; } } - m_shortcut->setEnabled(false); + if (m_shortcut->isEnabled()) { + m_shortcut->setEnabled(false); + emit activeStateChanged(); + } return false; } @@ -454,14 +460,13 @@ bool Action::setCurrentContext(const QList &context) // we need to update the checked state, so we connect to setChecked slot, which also fires a toggled signal connect(m_action, SIGNAL(toggled(bool)), m_currentAction, SLOT(setChecked(bool))); actionChanged(); - m_active = true; return true; } // no active/delegate action, "visible" action is not enabled/visible if (hasAttribute(CA_Hide)) m_action->setVisible(false); m_action->setEnabled(false); - m_active = false; + setActive(false); return false; } @@ -517,9 +522,18 @@ void Action::actionChanged() m_action->setEnabled(m_currentAction->isEnabled()); m_action->setVisible(m_currentAction->isVisible()); + setActive(m_action->isEnabled() && m_action->isVisible() && !m_action->isSeparator()); } bool Action::isActive() const { return m_active; } + +void Action::setActive(bool state) +{ + if (state != m_active) { + m_active = state; + emit activeStateChanged(); + } +} diff --git a/src/plugins/coreplugin/actionmanager/command.h b/src/plugins/coreplugin/actionmanager/command.h index 88651f6cd66..2d842b13f83 100644 --- a/src/plugins/coreplugin/actionmanager/command.h +++ b/src/plugins/coreplugin/actionmanager/command.h @@ -81,6 +81,7 @@ public: signals: void keySequenceChanged(); + void activeStateChanged(); }; } // namespace Core diff --git a/src/plugins/coreplugin/actionmanager/command_p.h b/src/plugins/coreplugin/actionmanager/command_p.h index aaf6da028b3..6c99cab2e94 100644 --- a/src/plugins/coreplugin/actionmanager/command_p.h +++ b/src/plugins/coreplugin/actionmanager/command_p.h @@ -137,6 +137,8 @@ private slots: void actionChanged(); private: + void setActive(bool state); + QAction *m_action; QList m_locations; QString m_toolTip;