Core: Keep track of modes in the ModeManager directly

... instead of having the indirection of the global object pool.

ModeManagerPrivate has been maintaining the list of instantiated
modes by tracking (all...) pool object additions / removals. This
can be achieved more directly by calling functions from the
IMode base constructor/destructor.

The pattern used deviates a bit from the otherwise used 'static
QList<Foo *> allFoos();' acessor pattern as there is some sorting
logic etc. associated each time a mode is appended.
Sticking to the preexisting structure seemed less effort for now.

Change-Id: Ic1b4e641e155f949248890acc48cafbe74025115
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
hjk
2018-01-19 15:51:23 +01:00
parent 437590a999
commit cf7f898db3
4 changed files with 41 additions and 55 deletions

View File

@@ -25,13 +25,17 @@
#include "imode.h" #include "imode.h"
#include "modemanager.h"
using namespace Core; using namespace Core;
IMode::IMode(QObject *parent) : IContext(parent) IMode::IMode(QObject *parent) : IContext(parent)
{ {
ModeManager::instance()->addMode(this);
} }
IMode::~IMode() IMode::~IMode()
{ {
ModeManager::instance()->removeMode(this);
delete m_menu; delete m_menu;
} }

View File

@@ -311,7 +311,6 @@ bool MainWindow::init(QString *errorMessage)
PluginManager::addObject(m_coreImpl); PluginManager::addObject(m_coreImpl);
m_statusBarManager->init(); m_statusBarManager->init();
m_modeManager->init();
m_progressManager->init(); // needs the status bar manager m_progressManager->init(); // needs the status bar manager
PluginManager::addObject(m_generalSettings); PluginManager::addObject(m_generalSettings);

View File

@@ -59,6 +59,8 @@ namespace Core {
struct ModeManagerPrivate struct ModeManagerPrivate
{ {
void showMenu(int index, QMouseEvent *event); void showMenu(int index, QMouseEvent *event);
void addModeHelper(IMode *mode);
void enabledStateChanged(IMode *mode);
Internal::MainWindow *m_mainWindow; Internal::MainWindow *m_mainWindow;
Internal::FancyTabWidget *m_modeStack; Internal::FancyTabWidget *m_modeStack;
@@ -111,14 +113,6 @@ ModeManager::ModeManager(Internal::MainWindow *mainWindow,
this, [](int index, QMouseEvent *e) { d->showMenu(index, e); }); this, [](int index, QMouseEvent *e) { d->showMenu(index, e); });
} }
void ModeManager::init()
{
QObject::connect(ExtensionSystem::PluginManager::instance(), &ExtensionSystem::PluginManager::objectAdded,
m_instance, &ModeManager::objectAdded);
QObject::connect(ExtensionSystem::PluginManager::instance(), &ExtensionSystem::PluginManager::aboutToRemoveObject,
m_instance, &ModeManager::aboutToRemoveObject);
}
ModeManager::~ModeManager() ModeManager::~ModeManager()
{ {
delete d; delete d;
@@ -150,34 +144,41 @@ void ModeManager::activateMode(Id id)
d->m_modeStack->setCurrentIndex(newIndex); d->m_modeStack->setCurrentIndex(newIndex);
} }
void ModeManager::objectAdded(QObject *obj) void ModeManager::addMode(IMode *mode)
{ {
IMode *mode = qobject_cast<IMode *>(obj); // Delay needed to get access to subclass's IMode::widget().
if (!mode) QTimer::singleShot(0, [mode] { d->addModeHelper(mode); });
return; }
d->m_mainWindow->addContextObject(mode); void ModeManagerPrivate::addModeHelper(IMode *mode)
{
m_mainWindow->addContextObject(mode);
// Count the number of modes with a higher priority // Count the number of modes with a higher priority
int index = 0; int index = 0;
foreach (const IMode *m, d->m_modes) foreach (const IMode *m, m_modes)
if (m->priority() > mode->priority()) if (m->priority() > mode->priority())
++index; ++index;
d->m_modes.insert(index, mode); m_modes.insert(index, mode);
d->m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(), m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(),
mode->menu() != nullptr); mode->menu() != nullptr);
d->m_modeStack->setTabEnabled(index, mode->isEnabled()); m_modeStack->setTabEnabled(index, mode->isEnabled());
// Register mode shortcut // Register mode shortcut
const Id actionId = mode->id().withPrefix("QtCreator.Mode."); const Id actionId = mode->id().withPrefix("QtCreator.Mode.");
QAction *action = new QAction(tr("Switch to <b>%1</b> mode").arg(mode->displayName()), this); QAction *action = new QAction(ModeManager::tr("Switch to <b>%1</b> mode").arg(mode->displayName()), m_instance);
Command *cmd = ActionManager::registerAction(action, actionId); Command *cmd = ActionManager::registerAction(action, actionId);
d->m_modeCommands.insert(index, cmd); m_modeCommands.insert(index, cmd);
connect(cmd, &Command::keySequenceChanged, m_instance, &ModeManager::updateModeToolTip); QObject::connect(cmd, &Command::keySequenceChanged, m_instance, [cmd, this] {
for (int i = 0; i < d->m_modeCommands.size(); ++i) { int index = m_modeCommands.indexOf(cmd);
Command *currentCmd = d->m_modeCommands.at(i); if (index != -1)
m_modeStack->setTabToolTip(index, cmd->action()->toolTip());
});
for (int i = 0; i < m_modeCommands.size(); ++i) {
Command *currentCmd = m_modeCommands.at(i);
// we need this hack with currentlyHasDefaultSequence // we need this hack with currentlyHasDefaultSequence
// because we call setDefaultShortcut multiple times on the same cmd // because we call setDefaultShortcut multiple times on the same cmd
// and still expect the current shortcut to change with it // and still expect the current shortcut to change with it
@@ -190,52 +191,35 @@ void ModeManager::objectAdded(QObject *obj)
} }
Id id = mode->id(); Id id = mode->id();
connect(action, &QAction::triggered, [id] { QObject::connect(action, &QAction::triggered, [this, id] {
m_instance->activateMode(id); ModeManager::activateMode(id);
ICore::raiseWindow(d->m_modeStack); ICore::raiseWindow(m_modeStack);
}); });
connect(mode, &IMode::enabledStateChanged, QObject::connect(mode, &IMode::enabledStateChanged, [this, mode] { enabledStateChanged(mode); });
m_instance, &ModeManager::enabledStateChanged);
} }
void ModeManager::updateModeToolTip() void ModeManagerPrivate::enabledStateChanged(IMode *mode)
{ {
Command *cmd = qobject_cast<Command *>(sender());
if (cmd) {
int index = d->m_modeCommands.indexOf(cmd);
if (index != -1)
d->m_modeStack->setTabToolTip(index, cmd->action()->toolTip());
}
}
void ModeManager::enabledStateChanged()
{
IMode *mode = qobject_cast<IMode *>(sender());
QTC_ASSERT(mode, return);
int index = d->m_modes.indexOf(mode); int index = d->m_modes.indexOf(mode);
QTC_ASSERT(index >= 0, return); QTC_ASSERT(index >= 0, return);
d->m_modeStack->setTabEnabled(index, mode->isEnabled()); d->m_modeStack->setTabEnabled(index, mode->isEnabled());
// Make sure we leave any disabled mode to prevent possible crashes: // Make sure we leave any disabled mode to prevent possible crashes:
if (mode->id() == currentMode() && !mode->isEnabled()) { if (mode->id() == ModeManager::currentMode() && !mode->isEnabled()) {
// This assumes that there is always at least one enabled mode. // This assumes that there is always at least one enabled mode.
for (int i = 0; i < d->m_modes.count(); ++i) { for (int i = 0; i < d->m_modes.count(); ++i) {
if (d->m_modes.at(i) != mode && if (d->m_modes.at(i) != mode &&
d->m_modes.at(i)->isEnabled()) { d->m_modes.at(i)->isEnabled()) {
activateMode(d->m_modes.at(i)->id()); ModeManager::activateMode(d->m_modes.at(i)->id());
break; break;
} }
} }
} }
} }
void ModeManager::aboutToRemoveObject(QObject *obj) void ModeManager::removeMode(IMode *mode)
{ {
IMode *mode = qobject_cast<IMode *>(obj);
if (!mode)
return;
const int index = d->m_modes.indexOf(mode); const int index = d->m_modes.indexOf(mode);
d->m_modes.remove(index); d->m_modes.remove(index);
d->m_modeCommands.remove(index); d->m_modeCommands.remove(index);

View File

@@ -34,6 +34,8 @@ QT_END_NAMESPACE
namespace Core { namespace Core {
class IMode;
namespace Internal { namespace Internal {
class MainWindow; class MainWindow;
class FancyTabWidget; class FancyTabWidget;
@@ -68,15 +70,12 @@ private:
explicit ModeManager(Internal::MainWindow *mainWindow, Internal::FancyTabWidget *modeStack); explicit ModeManager(Internal::MainWindow *mainWindow, Internal::FancyTabWidget *modeStack);
~ModeManager(); ~ModeManager();
static void init(); static void addMode(IMode *mode);
static void removeMode(IMode *mode);
void objectAdded(QObject *obj);
void aboutToRemoveObject(QObject *obj);
void currentTabAboutToChange(int index); void currentTabAboutToChange(int index);
void currentTabChanged(int index); void currentTabChanged(int index);
void updateModeToolTip();
void enabledStateChanged();
friend class IMode;
friend class Core::Internal::MainWindow; friend class Core::Internal::MainWindow;
}; };