1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "mainwindow.h"
34 #include "actioncontainer.h"
36 #include "actionmanager_p.h"
38 #include "coreconstants.h"
39 #include "editormanager.h"
40 #include "externaltool.h"
41 #include "toolsettings.h"
42 #include "mimetypesettings.h"
43 #include "fancytabwidget.h"
44 #include "filemanager.h"
45 #include "generalsettings.h"
46 #include "helpmanager.h"
48 #include "ifilefactory.h"
49 #include "messagemanager.h"
50 #include "modemanager.h"
51 #include "mimedatabase.h"
52 #include "newdialog.h"
53 #include "outputpanemanager.h"
54 #include "outputpane.h"
55 #include "plugindialog.h"
56 #include "progressmanager_p.h"
57 #include "progressview.h"
58 #include "shortcutsettings.h"
59 #include "vcsmanager.h"
60 #include "variablechooser.h"
62 #include "scriptmanager_p.h"
63 #include "settingsdialog.h"
64 #include "variablemanager.h"
65 #include "versiondialog.h"
66 #include "statusbarmanager.h"
67 #include "uniqueidmanager.h"
68 #include "manhattanstyle.h"
69 #include "navigationwidget.h"
70 #include "rightpane.h"
71 #include "editormanager/ieditorfactory.h"
72 #include "statusbarwidget.h"
73 #include "basefilewizard.h"
74 #include "ioutputpane.h"
75 #include "editormanager/systemeditor.h"
77 #include <coreplugin/findplaceholder.h>
78 #include <coreplugin/icorelistener.h>
79 #include <coreplugin/inavigationwidgetfactory.h>
80 #include <coreplugin/settingsdatabase.h>
81 #include <utils/pathchooser.h>
82 #include <utils/stylehelper.h>
83 #include <utils/stringutils.h>
84 #include <extensionsystem/pluginmanager.h>
86 #include <QtCore/QDebug>
87 #include <QtCore/QFileInfo>
88 #include <QtCore/QSettings>
89 #include <QtCore/QTimer>
90 #include <QtCore/QtPlugin>
91 #include <QtCore/QUrl>
92 #include <QtCore/QDir>
93 #include <QtCore/QFile>
95 #include <QtGui/QApplication>
96 #include <QtGui/QCloseEvent>
97 #include <QtGui/QMenu>
98 #include <QtGui/QPixmap>
99 #include <QtGui/QPrinter>
100 #include <QtGui/QShortcut>
101 #include <QtGui/QStatusBar>
102 #include <QtGui/QWizard>
103 #include <QtGui/QToolButton>
104 #include <QtGui/QMessageBox>
105 #include <QtGui/QMenuBar>
110 extern "C" void handleSigInt(int sig)
113 Core::ICore::instance()->exit();
114 qDebug() << "SIGINT caught. Shutting down.";
119 using namespace Core;
120 using namespace Core::Internal;
122 enum { debugMainWindow = 0 };
124 MainWindow::MainWindow() :
125 EventFilteringMainWindow(),
126 m_coreImpl(new CoreImpl(this)),
127 m_uniqueIDManager(new UniqueIDManager()),
128 m_additionalContexts(Constants::C_GLOBAL),
129 m_settings(ExtensionSystem::PluginManager::instance()->settings()),
130 m_globalSettings(new QSettings(QSettings::IniFormat, QSettings::SystemScope,
131 QLatin1String("Nokia"), QLatin1String("QtCreator"), this)),
132 m_settingsDatabase(new SettingsDatabase(QFileInfo(m_settings->fileName()).path(),
133 QLatin1String("QtCreator"),
136 m_actionManager(new ActionManagerPrivate(this)),
138 m_externalToolManager(0),
139 m_fileManager(new FileManager(this)),
140 m_progressManager(new ProgressManagerPrivate()),
141 m_scriptManager(new ScriptManagerPrivate(this)),
142 m_variableManager(new VariableManager),
143 m_vcsManager(new VcsManager),
144 m_statusBarManager(0),
146 m_mimeDatabase(new MimeDatabase),
147 m_helpManager(new HelpManager),
148 m_navigationWidget(0),
149 m_rightPaneWidget(0),
152 m_generalSettings(new GeneralSettings),
153 m_shortcutSettings(new ShortcutSettings),
154 m_toolSettings(new ToolSettings),
155 m_mimeTypeSettings(new MimeTypeSettings),
156 m_systemEditor(new SystemEditor),
164 m_toggleSideBarAction(0),
165 m_toggleFullScreenAction(0),
170 m_toggleSideBarButton(new QToolButton)
172 OutputPaneManager::create();
174 setWindowTitle(tr("Qt Creator"));
176 QApplication::setWindowIcon(QIcon(QLatin1String(Constants::ICON_QTLOGO_128)));
178 QCoreApplication::setApplicationName(QLatin1String("QtCreator"));
179 QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));
180 QCoreApplication::setOrganizationName(QLatin1String("Nokia"));
181 QSettings::setDefaultFormat(QSettings::IniFormat);
182 QString baseName = QApplication::style()->objectName();
184 if (baseName == QLatin1String("windows")) {
185 // Sometimes we get the standard windows 95 style as a fallback
186 // e.g. if we are running on a KDE4 desktop
187 QByteArray desktopEnvironment = qgetenv("DESKTOP_SESSION");
188 if (desktopEnvironment == "kde")
189 baseName = QLatin1String("plastique");
191 baseName = QLatin1String("cleanlooks");
194 qApp->setStyle(new ManhattanStyle(baseName));
196 setDockNestingEnabled(true);
198 setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
199 setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
201 registerDefaultContainers();
202 registerDefaultActions();
204 m_navigationWidget = new NavigationWidget(m_toggleSideBarAction);
205 m_rightPaneWidget = new RightPaneWidget();
207 m_modeStack = new FancyTabWidget(this);
208 m_modeManager = new ModeManager(this, m_modeStack);
209 m_modeManager->addWidget(m_progressManager->progressView());
210 m_statusBarManager = new StatusBarManager(this);
211 m_messageManager = new MessageManager;
212 m_editorManager = new EditorManager(m_coreImpl, this);
213 m_editorManager->hide();
214 m_externalToolManager = new ExternalToolManager(m_coreImpl);
215 setCentralWidget(m_modeStack);
217 connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
218 this, SLOT(updateFocusWidget(QWidget*,QWidget*)));
219 // Add a small Toolbutton for toggling the navigation widget
220 statusBar()->insertPermanentWidget(0, m_toggleSideBarButton);
222 // setUnifiedTitleAndToolBarOnMac(true);
224 //signal(SIGINT, handleSigInt);
227 statusBar()->setProperty("p_styled", true);
228 setAcceptDrops(true);
231 void MainWindow::setSidebarVisible(bool visible)
233 if (NavigationWidgetPlaceHolder::current()) {
234 if (m_navigationWidget->isSuppressed() && visible) {
235 m_navigationWidget->setShown(true);
236 m_navigationWidget->setSuppressed(false);
238 m_navigationWidget->setShown(visible);
243 void MainWindow::setSuppressNavigationWidget(bool suppress)
245 if (NavigationWidgetPlaceHolder::current())
246 m_navigationWidget->setSuppressed(suppress);
249 void MainWindow::setOverrideColor(const QColor &color)
251 m_overrideColor = color;
254 MainWindow::~MainWindow()
256 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
257 pm->removeObject(m_shortcutSettings);
258 pm->removeObject(m_generalSettings);
259 pm->removeObject(m_toolSettings);
260 pm->removeObject(m_mimeTypeSettings);
261 pm->removeObject(m_systemEditor);
262 delete m_externalToolManager;
263 m_externalToolManager = 0;
264 delete m_messageManager;
265 m_messageManager = 0;
266 delete m_shortcutSettings;
267 m_shortcutSettings = 0;
268 delete m_generalSettings;
269 m_generalSettings = 0;
270 delete m_toolSettings;
272 delete m_mimeTypeSettings;
273 m_mimeTypeSettings = 0;
274 delete m_systemEditor;
280 delete m_uniqueIDManager;
281 m_uniqueIDManager = 0;
284 //we need to delete editormanager and statusbarmanager explicitly before the end of the destructor,
285 //because they might trigger stuff that tries to access data from editorwindow, like removeContextWidget
287 // All modes are now gone
288 OutputPaneManager::destroy();
290 // Now that the OutputPaneManager is gone, is a good time to delete the view
291 pm->removeObject(m_outputView);
294 delete m_editorManager;
296 delete m_statusBarManager;
297 m_statusBarManager = 0;
298 delete m_progressManager;
299 m_progressManager = 0;
300 pm->removeObject(m_coreImpl);
304 delete m_rightPaneWidget;
305 m_rightPaneWidget = 0;
307 delete m_modeManager;
309 delete m_mimeDatabase;
312 delete m_helpManager;
316 bool MainWindow::init(QString *errorMessage)
318 Q_UNUSED(errorMessage)
320 if (!mimeDatabase()->addMimeTypes(QLatin1String(":/core/editormanager/BinFiles.mimetypes.xml"), errorMessage))
323 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
324 pm->addObject(m_coreImpl);
325 m_statusBarManager->init();
326 m_modeManager->init();
327 m_progressManager->init();
329 pm->addObject(m_generalSettings);
330 pm->addObject(m_shortcutSettings);
331 pm->addObject(m_toolSettings);
332 pm->addObject(m_mimeTypeSettings);
333 pm->addObject(m_systemEditor);
335 // Add widget to the bottom, we create the view here instead of inside the
336 // OutputPaneManager, since the StatusBarManager needs to be initialized before
337 m_outputView = new Core::StatusBarWidget;
338 m_outputView->setWidget(OutputPaneManager::instance()->buttonsWidget());
339 m_outputView->setPosition(Core::StatusBarWidget::Second);
340 pm->addObject(m_outputView);
341 m_messageManager->init();
345 void MainWindow::extensionsInitialized()
347 m_editorManager->init();
348 m_statusBarManager->extensionsInitalized();
349 OutputPaneManager::instance()->init();
350 m_vcsManager->extensionsInitialized();
351 m_navigationWidget->setFactories(ExtensionSystem::PluginManager::instance()->getObjects<INavigationWidgetFactory>());
353 // reading the shortcut settings must be done after all shortcuts have been registered
354 m_actionManager->initialize();
359 emit m_coreImpl->coreAboutToOpen();
361 emit m_coreImpl->coreOpened();
364 void MainWindow::closeEvent(QCloseEvent *event)
366 emit m_coreImpl->saveSettingsRequested();
370 QList<IFile*> notSaved = fileManager()->saveModifiedFiles(fileManager()->modifiedFiles(), &cancelled);
371 if (cancelled || !notSaved.isEmpty()) {
376 const QList<ICoreListener *> listeners =
377 ExtensionSystem::PluginManager::instance()->getObjects<ICoreListener>();
378 foreach (ICoreListener *listener, listeners) {
379 if (!listener->coreAboutToClose()) {
385 emit m_coreImpl->coreAboutToClose();
389 m_navigationWidget->closeSubWidgets();
394 // Check for desktop file manager file drop events
396 static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
400 // Extract dropped files from Mime data.
403 const QList<QUrl> urls = d->urls();
406 // Try to find local files
407 bool hasFiles = false;
408 const QList<QUrl>::const_iterator cend = urls.constEnd();
409 for (QList<QUrl>::const_iterator it = urls.constBegin(); it != cend; ++it) {
410 const QString fileName = it->toLocalFile();
411 if (!fileName.isEmpty()) {
414 files->push_back(fileName);
416 break; // No result list, sufficient for checking
423 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
425 if (isDesktopFileManagerDrop(event->mimeData()) && m_filesToOpenDelayed.isEmpty()) {
432 void MainWindow::dropEvent(QDropEvent *event)
435 if (isDesktopFileManagerDrop(event->mimeData(), &files)) {
437 m_filesToOpenDelayed.append(files);
438 QTimer::singleShot(50, this, SLOT(openDelayedFiles()));
444 void MainWindow::openDelayedFiles()
446 if (m_filesToOpenDelayed.isEmpty())
450 openFiles(m_filesToOpenDelayed, ICore::SwitchMode);
451 m_filesToOpenDelayed.clear();
454 IContext *MainWindow::currentContextObject() const
456 return m_activeContext;
459 QStatusBar *MainWindow::statusBar() const
461 return m_modeStack->statusBar();
464 void MainWindow::registerDefaultContainers()
466 ActionManagerPrivate *am = m_actionManager;
468 ActionContainer *menubar = am->createMenuBar(Constants::MENU_BAR);
470 #ifndef Q_WS_MAC // System menu bar on Mac
471 setMenuBar(menubar->menuBar());
473 menubar->appendGroup(Constants::G_FILE);
474 menubar->appendGroup(Constants::G_EDIT);
475 menubar->appendGroup(Constants::G_VIEW);
476 menubar->appendGroup(Constants::G_TOOLS);
477 menubar->appendGroup(Constants::G_WINDOW);
478 menubar->appendGroup(Constants::G_HELP);
481 ActionContainer *filemenu = am->createMenu(Constants::M_FILE);
482 menubar->addMenu(filemenu, Constants::G_FILE);
483 filemenu->menu()->setTitle(tr("&File"));
484 filemenu->appendGroup(Constants::G_FILE_NEW);
485 filemenu->appendGroup(Constants::G_FILE_OPEN);
486 filemenu->appendGroup(Constants::G_FILE_PROJECT);
487 filemenu->appendGroup(Constants::G_FILE_SAVE);
488 filemenu->appendGroup(Constants::G_FILE_CLOSE);
489 filemenu->appendGroup(Constants::G_FILE_PRINT);
490 filemenu->appendGroup(Constants::G_FILE_OTHER);
491 connect(filemenu->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowRecentFiles()));
495 ActionContainer *medit = am->createMenu(Constants::M_EDIT);
496 menubar->addMenu(medit, Constants::G_EDIT);
497 medit->menu()->setTitle(tr("&Edit"));
498 medit->appendGroup(Constants::G_EDIT_UNDOREDO);
499 medit->appendGroup(Constants::G_EDIT_COPYPASTE);
500 medit->appendGroup(Constants::G_EDIT_SELECTALL);
501 medit->appendGroup(Constants::G_EDIT_ADVANCED);
502 medit->appendGroup(Constants::G_EDIT_FIND);
503 medit->appendGroup(Constants::G_EDIT_OTHER);
506 ActionContainer *ac = am->createMenu(Constants::M_TOOLS);
507 menubar->addMenu(ac, Constants::G_TOOLS);
508 ac->menu()->setTitle(tr("&Tools"));
511 ActionContainer *mwindow = am->createMenu(Constants::M_WINDOW);
512 menubar->addMenu(mwindow, Constants::G_WINDOW);
513 mwindow->menu()->setTitle(tr("&Window"));
514 mwindow->appendGroup(Constants::G_WINDOW_SIZE);
515 mwindow->appendGroup(Constants::G_WINDOW_VIEWS);
516 mwindow->appendGroup(Constants::G_WINDOW_PANES);
517 mwindow->appendGroup(Constants::G_WINDOW_SPLIT);
518 mwindow->appendGroup(Constants::G_WINDOW_NAVIGATE);
519 mwindow->appendGroup(Constants::G_WINDOW_OTHER);
522 ac = am->createMenu(Constants::M_HELP);
523 menubar->addMenu(ac, Constants::G_HELP);
524 ac->menu()->setTitle(tr("&Help"));
525 ac->appendGroup(Constants::G_HELP_HELP);
526 ac->appendGroup(Constants::G_HELP_ABOUT);
529 static Command *createSeparator(ActionManager *am, QObject *parent,
531 const Context &context)
533 QAction *tmpaction = new QAction(parent);
534 tmpaction->setSeparator(true);
535 Command *cmd = am->registerAction(tmpaction, name, context);
539 void MainWindow::registerDefaultActions()
541 ActionManagerPrivate *am = m_actionManager;
542 ActionContainer *mfile = am->actionContainer(Constants::M_FILE);
543 ActionContainer *medit = am->actionContainer(Constants::M_EDIT);
544 ActionContainer *mtools = am->actionContainer(Constants::M_TOOLS);
545 ActionContainer *mwindow = am->actionContainer(Constants::M_WINDOW);
546 ActionContainer *mhelp = am->actionContainer(Constants::M_HELP);
548 Context globalContext(Constants::C_GLOBAL);
550 // File menu separators
551 Command *cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Save"), globalContext);
552 mfile->addAction(cmd, Constants::G_FILE_SAVE);
554 cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Print"), globalContext);
555 QIcon icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(Constants::ICON_CUT));
556 mfile->addAction(cmd, Constants::G_FILE_PRINT);
558 cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Close"), globalContext);
559 mfile->addAction(cmd, Constants::G_FILE_CLOSE);
561 cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Other"), globalContext);
562 mfile->addAction(cmd, Constants::G_FILE_OTHER);
564 // Edit menu separators
565 cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.CopyPaste"), globalContext);
566 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
568 cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.SelectAll"), globalContext);
569 medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
571 cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Find"), globalContext);
572 medit->addAction(cmd, Constants::G_EDIT_FIND);
574 cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Advanced"), globalContext);
575 medit->addAction(cmd, Constants::G_EDIT_ADVANCED);
577 // Return to editor shortcut: Note this requires Qt to fix up
578 // handling of shortcut overrides in menus, item views, combos....
579 m_focusToEditor = new QShortcut(this);
580 cmd = am->registerShortcut(m_focusToEditor, Constants::S_RETURNTOEDITOR, globalContext);
581 cmd->setDefaultKeySequence(QKeySequence(Qt::Key_Escape));
582 connect(m_focusToEditor, SIGNAL(activated()), this, SLOT(setFocusToEditor()));
585 icon = QIcon::fromTheme(QLatin1String("document-new"), QIcon(Constants::ICON_NEWFILE));
586 m_newAction = new QAction(icon, tr("&New File or Project..."), this);
587 cmd = am->registerAction(m_newAction, Constants::NEW, globalContext);
588 cmd->setDefaultKeySequence(QKeySequence::New);
589 mfile->addAction(cmd, Constants::G_FILE_NEW);
590 connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile()));
593 icon = QIcon::fromTheme(QLatin1String("document-open"), QIcon(Constants::ICON_OPENFILE));
594 m_openAction = new QAction(icon, tr("&Open File or Project..."), this);
595 cmd = am->registerAction(m_openAction, Constants::OPEN, globalContext);
596 cmd->setDefaultKeySequence(QKeySequence::Open);
597 mfile->addAction(cmd, Constants::G_FILE_OPEN);
598 connect(m_openAction, SIGNAL(triggered()), this, SLOT(openFile()));
601 m_openWithAction = new QAction(tr("Open File &With..."), this);
602 cmd = am->registerAction(m_openWithAction, Constants::OPEN_WITH, globalContext);
603 mfile->addAction(cmd, Constants::G_FILE_OPEN);
604 connect(m_openWithAction, SIGNAL(triggered()), this, SLOT(openFileWith()));
606 // File->Recent Files Menu
607 ActionContainer *ac = am->createMenu(Constants::M_FILE_RECENTFILES);
608 mfile->addMenu(ac, Constants::G_FILE_OPEN);
609 ac->menu()->setTitle(tr("Recent &Files"));
610 ac->setOnAllDisabledBehavior(ActionContainer::Show);
613 icon = QIcon::fromTheme(QLatin1String("document-save"), QIcon(Constants::ICON_SAVEFILE));
614 QAction *tmpaction = new QAction(icon, tr("&Save"), this);
615 tmpaction->setEnabled(false);
616 cmd = am->registerAction(tmpaction, Constants::SAVE, globalContext);
617 cmd->setDefaultKeySequence(QKeySequence::Save);
618 cmd->setAttribute(Command::CA_UpdateText);
619 cmd->setDefaultText(tr("&Save"));
620 mfile->addAction(cmd, Constants::G_FILE_SAVE);
623 icon = QIcon::fromTheme(QLatin1String("document-save-as"));
624 tmpaction = new QAction(icon, tr("Save &As..."), this);
625 tmpaction->setEnabled(false);
626 cmd = am->registerAction(tmpaction, Constants::SAVEAS, globalContext);
628 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
630 cmd->setAttribute(Command::CA_UpdateText);
631 cmd->setDefaultText(tr("Save &As..."));
632 mfile->addAction(cmd, Constants::G_FILE_SAVE);
635 m_saveAllAction = new QAction(tr("Save A&ll"), this);
636 cmd = am->registerAction(m_saveAllAction, Constants::SAVEALL, globalContext);
638 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
640 mfile->addAction(cmd, Constants::G_FILE_SAVE);
641 connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll()));
644 icon = QIcon::fromTheme(QLatin1String("document-print"));
645 tmpaction = new QAction(icon, tr("&Print..."), this);
646 tmpaction->setEnabled(false);
647 cmd = am->registerAction(tmpaction, Constants::PRINT, globalContext);
648 cmd->setDefaultKeySequence(QKeySequence::Print);
649 mfile->addAction(cmd, Constants::G_FILE_PRINT);
652 icon = QIcon::fromTheme(QLatin1String("application-exit"));
653 m_exitAction = new QAction(icon, tr("E&xit"), this);
654 cmd = am->registerAction(m_exitAction, Constants::EXIT, globalContext);
655 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Q")));
656 mfile->addAction(cmd, Constants::G_FILE_OTHER);
657 connect(m_exitAction, SIGNAL(triggered()), this, SLOT(exit()));
660 icon = QIcon::fromTheme(QLatin1String("edit-undo"), QIcon(Constants::ICON_UNDO));
661 tmpaction = new QAction(icon, tr("&Undo"), this);
662 cmd = am->registerAction(tmpaction, Constants::UNDO, globalContext);
663 cmd->setDefaultKeySequence(QKeySequence::Undo);
664 cmd->setAttribute(Command::CA_UpdateText);
665 cmd->setDefaultText(tr("&Undo"));
666 medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
667 tmpaction->setEnabled(false);
670 icon = QIcon::fromTheme(QLatin1String("edit-redo"), QIcon(Constants::ICON_REDO));
671 tmpaction = new QAction(icon, tr("&Redo"), this);
672 cmd = am->registerAction(tmpaction, Constants::REDO, globalContext);
673 cmd->setDefaultKeySequence(QKeySequence::Redo);
674 cmd->setAttribute(Command::CA_UpdateText);
675 cmd->setDefaultText(tr("&Redo"));
676 medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
677 tmpaction->setEnabled(false);
680 icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(Constants::ICON_CUT));
681 tmpaction = new QAction(icon, tr("Cu&t"), this);
682 cmd = am->registerAction(tmpaction, Constants::CUT, globalContext);
683 cmd->setDefaultKeySequence(QKeySequence::Cut);
684 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
685 tmpaction->setEnabled(false);
688 icon = QIcon::fromTheme(QLatin1String("edit-copy"), QIcon(Constants::ICON_COPY));
689 tmpaction = new QAction(icon, tr("&Copy"), this);
690 cmd = am->registerAction(tmpaction, Constants::COPY, globalContext);
691 cmd->setDefaultKeySequence(QKeySequence::Copy);
692 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
693 tmpaction->setEnabled(false);
696 icon = QIcon::fromTheme(QLatin1String("edit-paste"), QIcon(Constants::ICON_PASTE));
697 tmpaction = new QAction(icon, tr("&Paste"), this);
698 cmd = am->registerAction(tmpaction, Constants::PASTE, globalContext);
699 cmd->setDefaultKeySequence(QKeySequence::Paste);
700 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
701 tmpaction->setEnabled(false);
704 icon = QIcon::fromTheme(QLatin1String("edit-select-all"));
705 tmpaction = new QAction(icon, tr("Select &All"), this);
706 cmd = am->registerAction(tmpaction, Constants::SELECTALL, globalContext);
707 cmd->setDefaultKeySequence(QKeySequence::SelectAll);
708 medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
709 tmpaction->setEnabled(false);
712 icon = QIcon::fromTheme(QLatin1String("go-jump"));
713 tmpaction = new QAction(icon, tr("&Go To Line..."), this);
714 cmd = am->registerAction(tmpaction, Constants::GOTO, globalContext);
715 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+L")));
716 medit->addAction(cmd, Constants::G_EDIT_OTHER);
717 tmpaction->setEnabled(false);
720 mtools->appendGroup(Constants::G_TOOLS_OPTIONS);
721 cmd = createSeparator(am, this, QLatin1String("QtCreator.Tools.Sep.Options"), globalContext);
722 mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
723 m_optionsAction = new QAction(tr("&Options..."), this);
724 cmd = am->registerAction(m_optionsAction, Constants::OPTIONS, globalContext);
726 cmd->setDefaultKeySequence(QKeySequence("Ctrl+,"));
727 cmd->action()->setMenuRole(QAction::PreferencesRole);
729 mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
730 connect(m_optionsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog()));
734 m_minimizeAction = new QAction(tr("Minimize"), this);
735 cmd = am->registerAction(m_minimizeAction, Constants::MINIMIZE_WINDOW, globalContext);
736 cmd->setDefaultKeySequence(QKeySequence("Ctrl+M"));
737 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
738 connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(showMinimized()));
741 m_zoomAction = new QAction(tr("Zoom"), this);
742 cmd = am->registerAction(m_zoomAction, Constants::ZOOM_WINDOW, globalContext);
743 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
744 connect(m_zoomAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
747 cmd = createSeparator(am, this, QLatin1String("QtCreator.Window.Sep.Size"), globalContext);
748 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
751 // Show Sidebar Action
752 m_toggleSideBarAction = new QAction(QIcon(Constants::ICON_TOGGLE_SIDEBAR),
753 tr("Show Sidebar"), this);
754 m_toggleSideBarAction->setCheckable(true);
755 cmd = am->registerAction(m_toggleSideBarAction, Constants::TOGGLE_SIDEBAR, globalContext);
756 cmd->setAttribute(Command::CA_UpdateText);
758 cmd->setDefaultKeySequence(QKeySequence("Ctrl+0"));
760 cmd->setDefaultKeySequence(QKeySequence("Alt+0"));
762 connect(m_toggleSideBarAction, SIGNAL(triggered(bool)), this, SLOT(setSidebarVisible(bool)));
763 m_toggleSideBarButton->setDefaultAction(cmd->action());
764 mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS);
765 m_toggleSideBarAction->setEnabled(false);
768 // Full Screen Action
769 m_toggleFullScreenAction = new QAction(tr("Full Screen"), this);
770 m_toggleFullScreenAction->setCheckable(true);
771 cmd = am->registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext);
772 cmd->setDefaultKeySequence(QKeySequence("Ctrl+Shift+F11"));
773 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
774 connect(m_toggleFullScreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool)));
778 ActionContainer *mviews = am->createMenu(Constants::M_WINDOW_VIEWS);
779 mwindow->addMenu(mviews, Constants::G_WINDOW_VIEWS);
780 mviews->menu()->setTitle(tr("&Views"));
783 icon = QIcon::fromTheme(QLatin1String("help-about"));
785 tmpaction = new QAction(icon, tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
787 tmpaction = new QAction(icon, tr("About &Qt Creator..."), this);
789 cmd = am->registerAction(tmpaction, Constants::ABOUT_QTCREATOR, globalContext);
790 mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
791 tmpaction->setEnabled(true);
793 cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
795 connect(tmpaction, SIGNAL(triggered()), this, SLOT(aboutQtCreator()));
797 //About Plugins Action
798 tmpaction = new QAction(tr("About &Plugins..."), this);
799 cmd = am->registerAction(tmpaction, Constants::ABOUT_PLUGINS, globalContext);
800 mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
801 tmpaction->setEnabled(true);
803 cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
805 connect(tmpaction, SIGNAL(triggered()), this, SLOT(aboutPlugins()));
807 // tmpaction = new QAction(tr("About &Qt..."), this);
808 // cmd = am->registerAction(tmpaction, Constants:: ABOUT_QT, globalContext);
809 // mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
810 // tmpaction->setEnabled(true);
811 // connect(tmpaction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
813 #ifndef Q_WS_MAC // doesn't have the "About" actions in the Help menu
814 tmpaction = new QAction(this);
815 tmpaction->setSeparator(true);
816 cmd = am->registerAction(tmpaction, "QtCreator.Help.Sep.About", globalContext);
817 mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
821 void MainWindow::newFile()
823 showNewItemDialog(tr("New", "Title of dialog"), IWizard::allWizards(), QString());
826 void MainWindow::openFile()
828 openFiles(editorManager()->getOpenFileNames(), ICore::SwitchMode);
831 static QList<IFileFactory*> getNonEditorFileFactories()
833 const QList<IFileFactory*> allFileFactories =
834 ExtensionSystem::PluginManager::instance()->getObjects<IFileFactory>();
835 QList<IFileFactory*> nonEditorFileFactories;
836 foreach (IFileFactory *factory, allFileFactories) {
837 if (!qobject_cast<IEditorFactory *>(factory))
838 nonEditorFileFactories.append(factory);
840 return nonEditorFileFactories;
843 static IFileFactory *findFileFactory(const QList<IFileFactory*> &fileFactories,
844 const MimeDatabase *db,
847 if (const MimeType mt = db->findByFile(fi)) {
848 const QString type = mt.type();
849 foreach (IFileFactory *factory, fileFactories) {
850 if (factory->mimeTypes().contains(type))
857 // opens either an editor or loads a project
858 void MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags)
860 QList<IFileFactory*> nonEditorFileFactories = getNonEditorFileFactories();
862 foreach (const QString &fileName, fileNames) {
863 const QFileInfo fi(fileName);
864 const QString absoluteFilePath = fi.absoluteFilePath();
865 if (IFileFactory *fileFactory = findFileFactory(nonEditorFileFactories, mimeDatabase(), fi)) {
866 Core::IFile *file = fileFactory->open(absoluteFilePath);
867 if (!file && (flags & ICore::StopOnLoadFail))
869 if (file && (flags & ICore::SwitchMode))
870 Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
872 QFlags<EditorManager::OpenEditorFlag> emFlags;
873 if (flags & ICore::SwitchMode)
874 emFlags = EditorManager::ModeSwitch;
875 if (flags & ICore::CanContainLineNumbers)
876 emFlags |= EditorManager::CanContainLineNumber;
877 Core::IEditor *editor = editorManager()->openEditor(absoluteFilePath, QString(), emFlags);
878 if (!editor && (flags & ICore::StopOnLoadFail))
884 void MainWindow::setFocusToEditor()
886 bool focusWasMovedToEditor = false;
888 // give focus to the editor if we have one
889 if (IEditor *editor = m_editorManager->currentEditor()) {
890 if (qApp->focusWidget() != editor->widget()) {
891 editor->widget()->setFocus();
892 focusWasMovedToEditor = editor->widget()->hasFocus();
896 // check for some maximized pane which we want to unmaximize
897 if (OutputPanePlaceHolder::getCurrent()
898 && OutputPanePlaceHolder::getCurrent()->isVisible()
899 && OutputPanePlaceHolder::getCurrent()->isMaximized()) {
900 OutputPanePlaceHolder::getCurrent()->unmaximize();
904 if (focusWasMovedToEditor)
908 // check for some visible bar which we want to hide
910 (FindToolBarPlaceHolder::getCurrent() &&
911 FindToolBarPlaceHolder::getCurrent()->isVisible())
912 || (OutputPanePlaceHolder::getCurrent() &&
913 OutputPanePlaceHolder::getCurrent()->isVisible())
914 || (RightPanePlaceHolder::current() &&
915 RightPanePlaceHolder::current()->isVisible());
917 if (FindToolBarPlaceHolder::getCurrent())
918 FindToolBarPlaceHolder::getCurrent()->hide();
919 OutputPaneManager::instance()->slotHide();
920 RightPaneWidget::instance()->setShown(false);
924 // switch to edit mode if necessary
925 m_coreImpl->modeManager()->activateMode(QLatin1String(Constants::MODE_EDIT));
929 void MainWindow::showNewItemDialog(const QString &title,
930 const QList<IWizard *> &wizards,
931 const QString &defaultLocation)
933 // Scan for wizards matching the filter and pick one. Don't show
934 // dialog if there is only one.
936 switch (wizards.size()) {
940 wizard = wizards.front();
944 dlg.setWizards(wizards);
945 dlg.setWindowTitle(title);
946 wizard = dlg.showDialog();
954 QString path = defaultLocation;
955 if (path.isEmpty()) {
956 const FileManager *fm = m_coreImpl->fileManager();
957 switch (wizard->kind()) {
958 case IWizard::ProjectWizard:
959 // Project wizards: Check for projects directory or
960 // use last visited directory of file dialog. Never start
962 path = fm->useProjectsDirectory() ?
963 fm->projectsDirectory() :
964 fm->fileDialogLastVisitedDirectory();
967 path = fm->fileDialogInitialDirectory();
971 wizard->runWizard(path, this);
974 bool MainWindow::showOptionsDialog(const QString &category,
978 emit m_coreImpl->optionsDialogRequested();
981 SettingsDialog *dialog = SettingsDialog::getSettingsDialog(parent, category, page);
982 return dialog->execDialog();
985 void MainWindow::saveAll()
987 m_fileManager->saveModifiedFilesSilently(m_fileManager->modifiedFiles());
988 emit m_coreImpl->saveSettingsRequested();
991 void MainWindow::exit()
993 // this function is most likely called from a user action
994 // that is from an event handler of an object
995 // since on close we are going to delete everything
996 // so to prevent the deleting of that object we
998 QTimer::singleShot(0, this, SLOT(close()));
1001 void MainWindow::openFileWith()
1003 QStringList fileNames = editorManager()->getOpenFileNames();
1004 foreach (const QString &fileName, fileNames) {
1006 const QString editorId = editorManager()->getOpenWithEditorId(fileName, &isExternal);
1007 if (editorId.isEmpty())
1010 editorManager()->openExternalEditor(fileName, editorId);
1012 editorManager()->openEditor(fileName, editorId, Core::EditorManager::ModeSwitch);
1017 ActionManager *MainWindow::actionManager() const
1019 return m_actionManager;
1022 FileManager *MainWindow::fileManager() const
1024 return m_fileManager;
1027 UniqueIDManager *MainWindow::uniqueIDManager() const
1029 return m_uniqueIDManager;
1032 MessageManager *MainWindow::messageManager() const
1034 return m_messageManager;
1037 VcsManager *MainWindow::vcsManager() const
1039 return m_vcsManager;
1042 QSettings *MainWindow::settings(QSettings::Scope scope) const
1044 if (scope == QSettings::UserScope)
1047 return m_globalSettings;
1050 EditorManager *MainWindow::editorManager() const
1052 return m_editorManager;
1055 ProgressManager *MainWindow::progressManager() const
1057 return m_progressManager;
1060 ScriptManager *MainWindow::scriptManager() const
1062 return m_scriptManager;
1065 VariableManager *MainWindow::variableManager() const
1067 return m_variableManager.data();
1070 ModeManager *MainWindow::modeManager() const
1072 return m_modeManager;
1075 MimeDatabase *MainWindow::mimeDatabase() const
1077 return m_mimeDatabase;
1080 HelpManager *MainWindow::helpManager() const
1082 return m_helpManager;
1085 IContext *MainWindow::contextObject(QWidget *widget)
1087 return m_contextWidgets.value(widget);
1090 void MainWindow::addContextObject(IContext *context)
1094 QWidget *widget = context->widget();
1095 if (m_contextWidgets.contains(widget))
1098 m_contextWidgets.insert(widget, context);
1101 void MainWindow::removeContextObject(IContext *context)
1106 QWidget *widget = context->widget();
1107 if (!m_contextWidgets.contains(widget))
1110 m_contextWidgets.remove(widget);
1111 if (m_activeContext == context)
1112 updateContextObject(0);
1115 void MainWindow::changeEvent(QEvent *e)
1117 QMainWindow::changeEvent(e);
1118 if (e->type() == QEvent::ActivationChange) {
1119 if (isActiveWindow()) {
1120 if (debugMainWindow)
1121 qDebug() << "main window activated";
1122 emit windowActivated();
1124 } else if (e->type() == QEvent::WindowStateChange) {
1126 bool minimized = isMinimized();
1127 if (debugMainWindow)
1128 qDebug() << "main window state changed to minimized=" << minimized;
1129 m_minimizeAction->setEnabled(!minimized);
1130 m_zoomAction->setEnabled(!minimized);
1132 bool isFullScreen = (windowState() & Qt::WindowFullScreen) != 0;
1133 m_toggleFullScreenAction->setChecked(isFullScreen);
1138 void MainWindow::updateFocusWidget(QWidget *old, QWidget *now)
1142 // Prevent changing the context object just because the menu or a menu item is activated
1143 if (qobject_cast<QMenuBar*>(now) || qobject_cast<QMenu*>(now))
1146 IContext *newContext = 0;
1147 if (focusWidget()) {
1148 IContext *context = 0;
1149 QWidget *p = focusWidget();
1151 context = m_contextWidgets.value(p);
1153 newContext = context;
1156 p = p->parentWidget();
1159 updateContextObject(newContext);
1162 void MainWindow::updateContextObject(IContext *context)
1164 if (context == m_activeContext)
1166 emit m_coreImpl->contextAboutToChange(context);
1167 m_activeContext = context;
1169 if (debugMainWindow)
1170 qDebug() << "new context object =" << context << (context ? context->widget() : 0)
1171 << (context ? context->widget()->metaObject()->className() : 0);
1174 void MainWindow::resetContext()
1176 updateContextObject(0);
1179 void MainWindow::aboutToShutdown()
1181 disconnect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
1182 this, SLOT(updateFocusWidget(QWidget*,QWidget*)));
1183 m_activeContext = 0;
1187 static const char *settingsGroup = "MainWindow";
1188 static const char *colorKey = "Color";
1189 static const char *windowGeometryKey = "WindowGeometry";
1190 static const char *windowStateKey = "WindowState";
1192 // TODO compat for <= 2.1, remove later
1193 static const char *geometryKey = "Geometry";
1194 static const char *maxKey = "Maximized";
1195 static const char *fullScreenKey = "FullScreen";
1197 void MainWindow::readSettings()
1199 m_settings->beginGroup(QLatin1String(settingsGroup));
1201 if (m_overrideColor.isValid()) {
1202 Utils::StyleHelper::setBaseColor(m_overrideColor);
1203 // Get adapted base color.
1204 m_overrideColor = Utils::StyleHelper::baseColor();
1206 Utils::StyleHelper::setBaseColor(
1207 m_settings->value(QLatin1String(colorKey),
1208 QColor(Utils::StyleHelper::DEFAULT_BASE_COLOR)).value<QColor>());
1211 // TODO compat for <= 2.1, remove later
1212 if (m_settings->contains(QLatin1String(geometryKey))) {
1213 const QVariant geom = m_settings->value(QLatin1String(geometryKey));
1214 if (geom.isValid()) {
1215 setGeometry(geom.toRect());
1219 if (m_settings->value(QLatin1String(maxKey), false).toBool())
1220 setWindowState(Qt::WindowMaximized);
1221 setFullScreen(m_settings->value(QLatin1String(fullScreenKey), false).toBool());
1223 m_settings->remove(QLatin1String(geometryKey));
1224 m_settings->remove(QLatin1String(maxKey));
1225 m_settings->remove(QLatin1String(fullScreenKey));
1227 if (!restoreGeometry(m_settings->value(QLatin1String(windowGeometryKey)).toByteArray())) {
1230 restoreState(m_settings->value(QLatin1String(windowStateKey)).toByteArray());
1233 m_settings->endGroup();
1235 m_editorManager->readSettings();
1236 m_navigationWidget->restoreSettings(m_settings);
1237 m_rightPaneWidget->readSettings(m_settings);
1240 void MainWindow::writeSettings()
1242 m_settings->beginGroup(QLatin1String(settingsGroup));
1244 if (!(m_overrideColor.isValid() && Utils::StyleHelper::baseColor() == m_overrideColor))
1245 m_settings->setValue(QLatin1String(colorKey), Utils::StyleHelper::requestedBaseColor());
1247 m_settings->setValue(QLatin1String(windowGeometryKey), saveGeometry());
1248 m_settings->setValue(QLatin1String(windowStateKey), saveState());
1250 m_settings->endGroup();
1252 m_fileManager->saveSettings();
1253 m_actionManager->saveSettings(m_settings);
1254 m_editorManager->saveSettings();
1255 m_navigationWidget->saveSettings(m_settings);
1258 void MainWindow::updateAdditionalContexts(const Context &remove, const Context &add)
1260 foreach (const int context, remove) {
1264 int index = m_additionalContexts.indexOf(context);
1266 m_additionalContexts.removeAt(index);
1269 foreach (const int context, add) {
1273 if (!m_additionalContexts.contains(context))
1274 m_additionalContexts.prepend(context);
1280 bool MainWindow::hasContext(int context) const
1282 return m_actionManager->hasContext(context);
1285 void MainWindow::updateContext()
1289 if (m_activeContext)
1290 contexts.add(m_activeContext->context());
1292 contexts.add(m_additionalContexts);
1294 Context uniquecontexts;
1295 for (int i = 0; i < contexts.size(); ++i) {
1296 const int c = contexts.at(i);
1297 if (!uniquecontexts.contains(c))
1298 uniquecontexts.add(c);
1301 m_actionManager->setContext(uniquecontexts);
1302 emit m_coreImpl->contextChanged(m_activeContext, m_additionalContexts);
1305 void MainWindow::aboutToShowRecentFiles()
1307 ActionContainer *aci =
1308 m_actionManager->actionContainer(Constants::M_FILE_RECENTFILES);
1309 aci->menu()->clear();
1311 bool hasRecentFiles = false;
1312 foreach (const FileManager::RecentFile &file, m_fileManager->recentFiles()) {
1313 hasRecentFiles = true;
1314 QAction *action = aci->menu()->addAction(
1315 QDir::toNativeSeparators(Utils::withTildeHomePath(file.first)));
1316 action->setData(qVariantFromValue(file));
1317 connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile()));
1319 aci->menu()->setEnabled(hasRecentFiles);
1322 void MainWindow::openRecentFile()
1324 if (const QAction *action = qobject_cast<const QAction*>(sender())) {
1325 const FileManager::RecentFile file = action->data().value<FileManager::RecentFile>();
1326 editorManager()->openEditor(file.first, file.second, Core::EditorManager::ModeSwitch);
1330 void MainWindow::aboutQtCreator()
1332 if (!m_versionDialog) {
1333 m_versionDialog = new VersionDialog(this);
1334 connect(m_versionDialog, SIGNAL(finished(int)),
1335 this, SLOT(destroyVersionDialog()));
1337 m_versionDialog->show();
1340 void MainWindow::destroyVersionDialog()
1342 if (m_versionDialog) {
1343 m_versionDialog->deleteLater();
1344 m_versionDialog = 0;
1348 void MainWindow::aboutPlugins()
1350 PluginDialog dialog(this);
1354 QPrinter *MainWindow::printer() const
1357 m_printer = new QPrinter(QPrinter::HighResolution);
1361 void MainWindow::setFullScreen(bool on)
1363 if (bool(windowState() & Qt::WindowFullScreen) == on)
1367 setWindowState(windowState() | Qt::WindowFullScreen);
1368 //statusBar()->hide();
1369 //menuBar()->hide();
1371 setWindowState(windowState() & ~Qt::WindowFullScreen);
1372 //menuBar()->show();
1373 //statusBar()->show();
1377 // Display a warning with an additional button to open
1378 // the debugger settings dialog if settingsId is nonempty.
1380 bool MainWindow::showWarningWithOptions(const QString &title,
1381 const QString &text,
1382 const QString &details,
1383 const QString &settingsCategory,
1384 const QString &settingsId,
1389 QMessageBox msgBox(QMessageBox::Warning, title, text,
1390 QMessageBox::Ok, parent);
1391 if (!details.isEmpty())
1392 msgBox.setDetailedText(details);
1393 QAbstractButton *settingsButton = 0;
1394 if (!settingsId.isEmpty() || !settingsCategory.isEmpty())
1395 settingsButton = msgBox.addButton(tr("Settings..."), QMessageBox::AcceptRole);
1397 if (settingsButton && msgBox.clickedButton() == settingsButton) {
1398 return showOptionsDialog(settingsCategory, settingsId);