forked from qt-creator/qt-creator
Fix updating the state of menus.
The menus were only updated during context changes (not if action states where updated directly), and didn't take into account that the active action for a context might still be disabled. Also, enabled separators should not automatically lead to enabled menus.
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
#include "uniqueidmanager.h"
|
#include "uniqueidmanager.h"
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QTimer>
|
||||||
#include <QtGui/QAction>
|
#include <QtGui/QAction>
|
||||||
#include <QtGui/QMenuBar>
|
#include <QtGui/QMenuBar>
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ using namespace Core::Internal;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ActionContainerPrivate::ActionContainerPrivate(int id)
|
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_commands.append(action);
|
||||||
m_posmap.insert(pos, action->id());
|
m_posmap.insert(pos, action->id());
|
||||||
|
connect(action, SIGNAL(activeStateChanged()), this, SLOT(scheduleUpdate()));
|
||||||
insertAction(ba, a->action());
|
insertAction(ba, a->action());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +322,20 @@ int ActionContainerPrivate::calcPosition(int pos, int prevKey) const
|
|||||||
return grp + (prevKey & 0xFFFF) + 10;
|
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 ------------
|
// ---------- MenuActionContainer ------------
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -368,7 +384,7 @@ CommandLocation MenuActionContainer::location() const
|
|||||||
return m_location;
|
return m_location;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuActionContainer::update()
|
bool MenuActionContainer::updateInternal()
|
||||||
{
|
{
|
||||||
if (hasEmptyAction(EA_None))
|
if (hasEmptyAction(EA_None))
|
||||||
return true;
|
return true;
|
||||||
@@ -380,7 +396,7 @@ bool MenuActionContainer::update()
|
|||||||
qWarning() << Q_FUNC_INFO << "container" << (this->menu() ? this->menu()->title() : "") << "contains itself as subcontainer";
|
qWarning() << Q_FUNC_INFO << "container" << (this->menu() ? this->menu()->title() : "") << "contains itself as subcontainer";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (container->update()) {
|
if (qobject_cast<ActionContainerPrivate*>(container)->updateInternal()) {
|
||||||
hasitems = true;
|
hasitems = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -441,7 +457,7 @@ void MenuBarActionContainer::insertMenu(QAction *before, QMenu *menu)
|
|||||||
m_menuBar->insertMenu(before, menu);
|
m_menuBar->insertMenu(before, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuBarActionContainer::update()
|
bool MenuBarActionContainer::updateInternal()
|
||||||
{
|
{
|
||||||
if (hasEmptyAction(EA_None))
|
if (hasEmptyAction(EA_None))
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ public:
|
|||||||
virtual void addAction(Core::Command *action, const QString &group = QString()) = 0;
|
virtual void addAction(Core::Command *action, const QString &group = QString()) = 0;
|
||||||
virtual void addMenu(Core::ActionContainer *menu, const QString &group = QString()) = 0;
|
virtual void addMenu(Core::ActionContainer *menu, const QString &group = QString()) = 0;
|
||||||
|
|
||||||
virtual bool update() = 0;
|
|
||||||
virtual ~ActionContainer() {}
|
virtual ~ActionContainer() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ namespace Internal {
|
|||||||
|
|
||||||
class ActionContainerPrivate : public Core::ActionContainer
|
class ActionContainerPrivate : public Core::ActionContainer
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ActionContainerPrivate(int id);
|
ActionContainerPrivate(int id);
|
||||||
virtual ~ActionContainerPrivate() {}
|
virtual ~ActionContainerPrivate() {}
|
||||||
@@ -62,6 +64,9 @@ public:
|
|||||||
|
|
||||||
QList<Command *> commands() const { return m_commands; }
|
QList<Command *> commands() const { return m_commands; }
|
||||||
QList<ActionContainer *> subContainers() const { return m_subContainers; }
|
QList<ActionContainer *> subContainers() const { return m_subContainers; }
|
||||||
|
|
||||||
|
virtual bool updateInternal() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool canAddAction(Command *action) const;
|
bool canAddAction(Command *action) const;
|
||||||
bool canAddMenu(ActionContainer *menu) const;
|
bool canAddMenu(ActionContainer *menu) const;
|
||||||
@@ -70,6 +75,10 @@ protected:
|
|||||||
void addAction(Command *action, int pos, bool setpos);
|
void addAction(Command *action, int pos, bool setpos);
|
||||||
void addMenu(ActionContainer *menu, int pos, bool setpos);
|
void addMenu(ActionContainer *menu, int pos, bool setpos);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void scheduleUpdate();
|
||||||
|
void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QAction *beforeAction(int pos, int *prevKey) const;
|
QAction *beforeAction(int pos, int *prevKey) const;
|
||||||
int calcPosition(int pos, int prevKey) const;
|
int calcPosition(int pos, int prevKey) const;
|
||||||
@@ -80,6 +89,7 @@ private:
|
|||||||
QMap<int, int> m_posmap;
|
QMap<int, int> m_posmap;
|
||||||
QList<ActionContainer *> m_subContainers;
|
QList<ActionContainer *> m_subContainers;
|
||||||
QList<Command *> m_commands;
|
QList<Command *> m_commands;
|
||||||
|
bool m_updateRequested;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MenuActionContainer : public ActionContainerPrivate
|
class MenuActionContainer : public ActionContainerPrivate
|
||||||
@@ -95,10 +105,11 @@ public:
|
|||||||
|
|
||||||
void insertAction(QAction *before, QAction *action);
|
void insertAction(QAction *before, QAction *action);
|
||||||
void insertMenu(QAction *before, QMenu *menu);
|
void insertMenu(QAction *before, QMenu *menu);
|
||||||
bool update();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool canBeAddedToMenu() const;
|
bool canBeAddedToMenu() const;
|
||||||
|
bool updateInternal();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMenu *m_menu;
|
QMenu *m_menu;
|
||||||
CommandLocation m_location;
|
CommandLocation m_location;
|
||||||
@@ -114,10 +125,11 @@ public:
|
|||||||
|
|
||||||
void insertAction(QAction *before, QAction *action);
|
void insertAction(QAction *before, QAction *action);
|
||||||
void insertMenu(QAction *before, QMenu *menu);
|
void insertMenu(QAction *before, QMenu *menu);
|
||||||
bool update();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool canBeAddedToMenu() const;
|
bool canBeAddedToMenu() const;
|
||||||
|
bool updateInternal();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMenuBar *m_menuBar;
|
QMenuBar *m_menuBar;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -274,10 +274,6 @@ void ActionManagerPrivate::setContext(const QList<int> &context)
|
|||||||
const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
|
const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
|
||||||
for (IdCmdMap::const_iterator it = m_idCmdMap.constBegin(); it != cmdcend; ++it)
|
for (IdCmdMap::const_iterator it = m_idCmdMap.constBegin(); it != cmdcend; ++it)
|
||||||
it.value()->setCurrentContext(m_context);
|
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<int> context) const
|
bool ActionManagerPrivate::hasContext(QList<int> context) const
|
||||||
|
|||||||
@@ -337,11 +337,17 @@ bool Shortcut::setCurrentContext(const QList<int> &context)
|
|||||||
{
|
{
|
||||||
foreach (int ctxt, m_context) {
|
foreach (int ctxt, m_context) {
|
||||||
if (context.contains(ctxt)) {
|
if (context.contains(ctxt)) {
|
||||||
m_shortcut->setEnabled(true);
|
if (!m_shortcut->isEnabled()) {
|
||||||
|
m_shortcut->setEnabled(true);
|
||||||
|
emit activeStateChanged();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_shortcut->setEnabled(false);
|
if (m_shortcut->isEnabled()) {
|
||||||
|
m_shortcut->setEnabled(false);
|
||||||
|
emit activeStateChanged();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,14 +460,13 @@ bool Action::setCurrentContext(const QList<int> &context)
|
|||||||
// we need to update the checked state, so we connect to setChecked slot, which also fires a toggled signal
|
// 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)));
|
connect(m_action, SIGNAL(toggled(bool)), m_currentAction, SLOT(setChecked(bool)));
|
||||||
actionChanged();
|
actionChanged();
|
||||||
m_active = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// no active/delegate action, "visible" action is not enabled/visible
|
// no active/delegate action, "visible" action is not enabled/visible
|
||||||
if (hasAttribute(CA_Hide))
|
if (hasAttribute(CA_Hide))
|
||||||
m_action->setVisible(false);
|
m_action->setVisible(false);
|
||||||
m_action->setEnabled(false);
|
m_action->setEnabled(false);
|
||||||
m_active = false;
|
setActive(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,9 +522,18 @@ void Action::actionChanged()
|
|||||||
|
|
||||||
m_action->setEnabled(m_currentAction->isEnabled());
|
m_action->setEnabled(m_currentAction->isEnabled());
|
||||||
m_action->setVisible(m_currentAction->isVisible());
|
m_action->setVisible(m_currentAction->isVisible());
|
||||||
|
setActive(m_action->isEnabled() && m_action->isVisible() && !m_action->isSeparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Action::isActive() const
|
bool Action::isActive() const
|
||||||
{
|
{
|
||||||
return m_active;
|
return m_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Action::setActive(bool state)
|
||||||
|
{
|
||||||
|
if (state != m_active) {
|
||||||
|
m_active = state;
|
||||||
|
emit activeStateChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void keySequenceChanged();
|
void keySequenceChanged();
|
||||||
|
void activeStateChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ private slots:
|
|||||||
void actionChanged();
|
void actionChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setActive(bool state);
|
||||||
|
|
||||||
QAction *m_action;
|
QAction *m_action;
|
||||||
QList<CommandLocation> m_locations;
|
QList<CommandLocation> m_locations;
|
||||||
QString m_toolTip;
|
QString m_toolTip;
|
||||||
|
|||||||
Reference in New Issue
Block a user