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:
con
2010-04-22 17:36:09 +02:00
parent 2958b0bae2
commit 3d1a97e6df
7 changed files with 55 additions and 15 deletions

View File

@@ -36,6 +36,7 @@
#include "uniqueidmanager.h"
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtGui/QAction>
#include <QtGui/QMenuBar>
@@ -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<ActionContainerPrivate*>(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;

View File

@@ -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() {}
};

View File

@@ -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<Command *> commands() const { return m_commands; }
QList<ActionContainer *> 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<int, int> m_posmap;
QList<ActionContainer *> m_subContainers;
QList<Command *> 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;
};

View File

@@ -274,10 +274,6 @@ void ActionManagerPrivate::setContext(const QList<int> &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<int> context) const

View File

@@ -337,11 +337,17 @@ bool Shortcut::setCurrentContext(const QList<int> &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<int> &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();
}
}

View File

@@ -81,6 +81,7 @@ public:
signals:
void keySequenceChanged();
void activeStateChanged();
};
} // namespace Core

View File

@@ -137,6 +137,8 @@ private slots:
void actionChanged();
private:
void setActive(bool state);
QAction *m_action;
QList<CommandLocation> m_locations;
QString m_toolTip;