2 ******************************************************************************
4 * @file modemanager.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
7 * @addtogroup GCSPlugins GCS Plugins
9 * @addtogroup CorePlugin Core Plugin
11 * @brief The Core GCS plugin
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "modemanager.h"
31 #include "utils/mytabwidget.h"
33 #include "mainwindow.h"
35 #include <aggregation/aggregate.h>
37 #include <coreplugin/actionmanager/actionmanager.h>
38 #include <coreplugin/actionmanager/command.h>
39 #include <coreplugin/coreconstants.h>
40 #include <coreplugin/imode.h>
41 #include <coreplugin/uniqueidmanager.h>
43 #include <extensionsystem/pluginmanager.h>
45 #include <utils/qtcassert.h>
47 #include <QtCore/QObject>
48 #include <QtCore/QDebug>
49 #include <QtCore/QSignalMapper>
54 #include <QVBoxLayout>
57 using namespace Core::Internal
;
59 ModeManager
*ModeManager::m_instance
= 0;
61 ModeManager::ModeManager(Internal::MainWindow
*mainWindow
, MyTabWidget
*modeStack
) :
62 m_mainWindow(mainWindow
),
63 m_modeStack(modeStack
),
64 m_signalMapper(new QSignalMapper(this)),
65 m_isReprioritizing(false)
69 // connect((m_modeStack), SIGNAL(currentAboutToShow(int)), SLOT(currentTabAboutToChange(int)));
70 connect(m_modeStack
, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
71 connect(m_modeStack
, SIGNAL(tabMoved(int, int)), this, SLOT(tabMoved(int, int)));
72 connect(m_signalMapper
, SIGNAL(mapped(QString
)), this, SLOT(activateMode(QString
)));
75 void ModeManager::init()
77 QObject::connect(ExtensionSystem::PluginManager::instance(), SIGNAL(objectAdded(QObject
*)),
78 this, SLOT(objectAdded(QObject
*)));
79 QObject::connect(ExtensionSystem::PluginManager::instance(), SIGNAL(aboutToRemoveObject(QObject
*)),
80 this, SLOT(aboutToRemoveObject(QObject
*)));
83 void ModeManager::addWidget(QWidget
*widget
)
87 // We want the actionbar to stay on the bottom
88 // so m_modeStack->cornerWidgetCount() -1 inserts it at the position immediately above
90 // m_modeStack->insertCornerWidget(m_modeStack->cornerWidgetCount() -1, widget);
93 IMode
*ModeManager::currentMode() const
95 if (m_modes
.count() > m_modeStack
->currentIndex()) {
96 return m_modes
.at(m_modeStack
->currentIndex());
98 m_modeStack
->setCurrentIndex(0); // Fix illegal Index.
103 int ModeManager::indexOf(const QString
&id
) const
105 for (int i
= 0; i
< m_modes
.count(); ++i
) {
106 if (m_modes
.at(i
)->uniqueModeName() == id
) {
110 // qDebug() << "Warning, no such mode:" << id;
114 IMode
*ModeManager::mode(const QString
&id
) const
116 const int index
= indexOf(id
);
119 return m_modes
.at(index
);
124 void ModeManager::activateMode(const QString
&id
)
126 const int index
= indexOf(id
);
129 m_modeStack
->setCurrentIndex(index
);
133 void ModeManager::activateModeByWorkspaceName(const QString
&id
)
135 for (int i
= 0; i
< m_modes
.count(); ++i
) {
136 if (m_modes
.at(i
)->name() == id
) {
137 m_modeStack
->setCurrentIndex(i
);
143 void ModeManager::objectAdded(QObject
*obj
)
145 IMode
*mode
= Aggregation::query
<IMode
>(obj
);
151 m_mainWindow
->addContextObject(mode
);
153 // Count the number of modes with a higher priority
155 foreach(const IMode
* m
, m_modes
)
156 if (m
->priority() > mode
->priority()) {
160 m_modes
.insert(index
, mode
);
161 m_modeStack
->insertTab(index
, mode
->widget(), mode
->icon(), mode
->name());
163 // Register mode shortcut
164 ActionManager
*am
= m_mainWindow
->actionManager();
165 const QString shortcutId
= QLatin1String("GCS.Mode.") + mode
->uniqueModeName();
166 QShortcut
*shortcut
= new QShortcut(m_mainWindow
);
167 shortcut
->setWhatsThis(tr("Switch to %1 mode").arg(mode
->name()));
168 Command
*cmd
= am
->registerShortcut(shortcut
, shortcutId
, QList
<int>() << Constants::C_GLOBAL_ID
);
170 m_modeShortcuts
.insert(index
, cmd
);
171 connect(cmd
, SIGNAL(keySequenceChanged()), this, SLOT(updateModeToolTip()));
173 setDefaultKeyshortcuts();
175 m_signalMapper
->setMapping(shortcut
, mode
->uniqueModeName());
176 connect(shortcut
, SIGNAL(activated()), m_signalMapper
, SLOT(map()));
179 void ModeManager::setDefaultKeyshortcuts()
181 for (int i
= 0; i
< m_modeShortcuts
.size(); ++i
) {
182 Command
*currentCmd
= m_modeShortcuts
.at(i
);
183 bool currentlyHasDefaultSequence
= (currentCmd
->keySequence()
184 == currentCmd
->defaultKeySequence());
186 currentCmd
->setDefaultKeySequence(QKeySequence(QString("Meta+%1").arg(i
+ 1)));
188 currentCmd
->setDefaultKeySequence(QKeySequence(QString("Ctrl+%1").arg(i
+ 1)));
190 if (currentlyHasDefaultSequence
) {
191 currentCmd
->setKeySequence(currentCmd
->defaultKeySequence());
196 void ModeManager::updateModeToolTip()
198 Command
*cmd
= qobject_cast
<Command
*>(sender());
201 int index
= m_modeShortcuts
.indexOf(cmd
);
203 m_modeStack
->setTabToolTip(index
, cmd
->stringWithAppendedShortcut(cmd
->shortcut()->whatsThis()));
208 void ModeManager::updateModeNameIcon(IMode
*mode
, const QIcon
&icon
, const QString
&label
)
210 int index
= indexOf(mode
->uniqueModeName());
215 m_modeStack
->setTabIcon(index
, icon
);
216 m_modeStack
->setTabText(index
, label
);
219 void ModeManager::aboutToRemoveObject(QObject
*obj
)
221 IMode
*mode
= Aggregation::query
<IMode
>(obj
);
227 const int index
= m_modes
.indexOf(mode
);
228 m_modes
.remove(index
);
229 m_modeShortcuts
.remove(index
);
230 disconnect(m_modeStack
, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
231 m_modeStack
->removeTab(index
);
232 connect(m_modeStack
, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
234 m_mainWindow
->removeContextObject(mode
);
237 void ModeManager::addAction(Command
*command
, int priority
, QMenu
*menu
)
241 m_actions
.insert(command
, priority
);
243 // Count the number of commands with a higher priority
245 foreach(int p
, m_actions
.values())
250 // m_actionBar->insertAction(index, command->action(), menu);
253 void ModeManager::currentTabAboutToChange(int index
)
256 IMode
*mode
= m_modes
.at(index
);
258 emit
currentModeAboutToChange(mode
);
263 void ModeManager::currentTabChanged(int index
)
265 // qDebug() << "Current tab changed " << index;
266 // Tab index changes to -1 when there is no tab left.
268 IMode
*mode
= m_modes
.at(index
);
270 // FIXME: This hardcoded context update is required for the Debug and Edit modes, since
271 // they use the editor widget, which is already a context widget so the main window won't
272 // go further up the parent tree to find the mode context.
273 ICore
*core
= ICore::instance();
274 foreach(const int context
, m_addedContexts
)
275 core
->removeAdditionalContext(context
);
277 m_addedContexts
= mode
->context();
278 foreach(const int context
, m_addedContexts
)
279 core
->addAdditionalContext(context
);
280 emit
currentModeChanged(mode
);
281 core
->updateContext();
285 void ModeManager::tabMoved(int from
, int to
)
287 IMode
*mode
= m_modes
.at(from
);
289 m_modes
.remove(from
);
290 m_modes
.insert(to
, mode
);
291 Command
*cmd
= m_modeShortcuts
.at(from
);
292 m_modeShortcuts
.remove(from
);
293 m_modeShortcuts
.insert(to
, cmd
);
294 setDefaultKeyshortcuts();
295 // Reprioritize, high priority means show to the left
296 if (!m_isReprioritizing
) {
297 for (int i
= 0; i
< m_modes
.count(); ++i
) {
298 m_modes
.at(i
)->setPriority(100 - i
);
300 emit
newModeOrder(m_modes
);
304 void ModeManager::reorderModes(QMap
<QString
, int> priorities
)
306 foreach(IMode
* mode
, m_modes
)
307 mode
->setPriority(priorities
.value(QString(QLatin1String(mode
->uniqueModeName())), mode
->priority()));
309 m_isReprioritizing
= true;
310 IMode
*current
= currentMode();
312 bool swapped
= false;
315 for (int i
= 0; i
< m_modes
.count() - 1; ++i
) {
316 IMode
*mode1
= m_modes
.at(i
);
317 IMode
*mode2
= m_modes
.at(i
+ 1);
318 // qDebug() << "Comparing " << i << " to " << i+1 << " p1 " << mode1->priority() << " p2 " << mode2->priority();
319 if (mode2
->priority() > mode1
->priority()) {
320 m_modeStack
->moveTab(i
, i
+ 1);
321 // qDebug() << "Tab moved from " << i << " to " << i+1;
326 m_isReprioritizing
= false;
327 m_modeStack
->setCurrentIndex(0);
328 activateMode(current
->uniqueModeName());
329 emit
newModeOrder(m_modes
);
333 void ModeManager::setFocusToCurrentMode()
335 IMode
*mode
= currentMode();
337 QTC_ASSERT(mode
, return );
338 QWidget
*widget
= mode
->widget();
340 QWidget
*focusWidget
= widget
->focusWidget();
343 focusWidget
->setFocus();
350 void ModeManager::triggerAction(const QString
&actionId
)
352 foreach(Command
* command
, m_actions
.keys()) {
353 if (command
->action()->objectName() == actionId
) {
354 command
->action()->trigger();