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 "modemanager.h"
using namespace Core;
IMode::IMode(QObject *parent) : IContext(parent)
{
ModeManager::instance()->addMode(this);
}
IMode::~IMode()
{
ModeManager::instance()->removeMode(this);
delete m_menu;
}

View File

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

View File

@@ -59,6 +59,8 @@ namespace Core {
struct ModeManagerPrivate
{
void showMenu(int index, QMouseEvent *event);
void addModeHelper(IMode *mode);
void enabledStateChanged(IMode *mode);
Internal::MainWindow *m_mainWindow;
Internal::FancyTabWidget *m_modeStack;
@@ -111,14 +113,6 @@ ModeManager::ModeManager(Internal::MainWindow *mainWindow,
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()
{
delete d;
@@ -150,34 +144,41 @@ void ModeManager::activateMode(Id id)
d->m_modeStack->setCurrentIndex(newIndex);
}
void ModeManager::objectAdded(QObject *obj)
void ModeManager::addMode(IMode *mode)
{
IMode *mode = qobject_cast<IMode *>(obj);
if (!mode)
return;
// Delay needed to get access to subclass's IMode::widget().
QTimer::singleShot(0, [mode] { d->addModeHelper(mode); });
}
d->m_mainWindow->addContextObject(mode);
void ModeManagerPrivate::addModeHelper(IMode *mode)
{
m_mainWindow->addContextObject(mode);
// Count the number of modes with a higher priority
int index = 0;
foreach (const IMode *m, d->m_modes)
foreach (const IMode *m, m_modes)
if (m->priority() > mode->priority())
++index;
d->m_modes.insert(index, mode);
d->m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(),
m_modes.insert(index, mode);
m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(),
mode->menu() != nullptr);
d->m_modeStack->setTabEnabled(index, mode->isEnabled());
m_modeStack->setTabEnabled(index, mode->isEnabled());
// Register mode shortcut
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);
d->m_modeCommands.insert(index, cmd);
connect(cmd, &Command::keySequenceChanged, m_instance, &ModeManager::updateModeToolTip);
for (int i = 0; i < d->m_modeCommands.size(); ++i) {
Command *currentCmd = d->m_modeCommands.at(i);
m_modeCommands.insert(index, cmd);
QObject::connect(cmd, &Command::keySequenceChanged, m_instance, [cmd, this] {
int index = m_modeCommands.indexOf(cmd);
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
// because we call setDefaultShortcut multiple times on the same cmd
// and still expect the current shortcut to change with it
@@ -190,52 +191,35 @@ void ModeManager::objectAdded(QObject *obj)
}
Id id = mode->id();
connect(action, &QAction::triggered, [id] {
m_instance->activateMode(id);
ICore::raiseWindow(d->m_modeStack);
QObject::connect(action, &QAction::triggered, [this, id] {
ModeManager::activateMode(id);
ICore::raiseWindow(m_modeStack);
});
connect(mode, &IMode::enabledStateChanged,
m_instance, &ModeManager::enabledStateChanged);
QObject::connect(mode, &IMode::enabledStateChanged, [this, mode] { enabledStateChanged(mode); });
}
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);
QTC_ASSERT(index >= 0, return);
d->m_modeStack->setTabEnabled(index, mode->isEnabled());
// 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.
for (int i = 0; i < d->m_modes.count(); ++i) {
if (d->m_modes.at(i) != mode &&
d->m_modes.at(i)->isEnabled()) {
activateMode(d->m_modes.at(i)->id());
ModeManager::activateMode(d->m_modes.at(i)->id());
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);
d->m_modes.remove(index);
d->m_modeCommands.remove(index);

View File

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