1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@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 "documentmanager.h"
45 #include "generalsettings.h"
46 #include "helpmanager.h"
48 #include "idocumentfactory.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"
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 "externaltoolmanager.h"
76 #include "editormanager/systemeditor.h"
78 #include <app/app_version.h>
79 #include <coreplugin/findplaceholder.h>
80 #include <coreplugin/icorelistener.h>
81 #include <coreplugin/inavigationwidgetfactory.h>
82 #include <coreplugin/settingsdatabase.h>
83 #include <utils/pathchooser.h>
84 #include <utils/stylehelper.h>
85 #include <utils/stringutils.h>
86 #include <extensionsystem/pluginmanager.h>
98 #include <QApplication>
99 #include <QCloseEvent>
104 #include <QStatusBar>
106 #include <QToolButton>
107 #include <QMessageBox>
109 #include <QPushButton>
114 extern "C" void handleSigInt(int sig)
118 qDebug() << "SIGINT caught. Shutting down.";
123 using namespace Core;
124 using namespace Core::Internal;
126 enum { debugMainWindow = 0 };
128 MainWindow::MainWindow() :
129 EventFilteringMainWindow(),
130 m_coreImpl(new ICore(this)),
131 m_additionalContexts(Constants::C_GLOBAL),
132 m_settings(ExtensionSystem::PluginManager::instance()->settings()),
133 m_globalSettings(ExtensionSystem::PluginManager::instance()->globalSettings()),
134 m_settingsDatabase(new SettingsDatabase(QFileInfo(m_settings->fileName()).path(),
135 QLatin1String("QtCreator"),
138 m_actionManager(new ActionManagerPrivate(this)),
140 m_externalToolManager(0),
141 m_progressManager(new ProgressManagerPrivate()),
142 m_scriptManager(new ScriptManagerPrivate(this)),
143 m_variableManager(new VariableManager),
144 m_vcsManager(new VcsManager),
145 m_statusBarManager(0),
147 m_mimeDatabase(new MimeDatabase),
148 m_helpManager(new HelpManager),
149 m_navigationWidget(0),
150 m_rightPaneWidget(0),
153 m_generalSettings(new GeneralSettings),
154 m_shortcutSettings(new ShortcutSettings),
155 m_toolSettings(new ToolSettings),
156 m_mimeTypeSettings(new MimeTypeSettings),
157 m_systemEditor(new SystemEditor),
165 m_toggleSideBarAction(0),
166 m_toggleFullScreenAction(0),
171 m_toggleSideBarButton(new QToolButton)
173 (void) new DocumentManager(this);
174 OutputPaneManager::create();
176 setWindowTitle(tr("Qt Creator"));
178 QApplication::setWindowIcon(QIcon(QLatin1String(Constants::ICON_QTLOGO_128)));
180 QCoreApplication::setApplicationName(QLatin1String("QtCreator"));
181 QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));
182 QCoreApplication::setOrganizationName(QLatin1String(Constants::IDE_SETTINGSVARIANT_STR));
183 QString baseName = QApplication::style()->objectName();
185 if (baseName == QLatin1String("windows")) {
186 // Sometimes we get the standard windows 95 style as a fallback
187 // e.g. if we are running on a KDE4 desktop
188 QByteArray desktopEnvironment = qgetenv("DESKTOP_SESSION");
189 if (desktopEnvironment == "kde")
190 baseName = QLatin1String("plastique");
192 baseName = QLatin1String("cleanlooks");
195 qApp->setStyle(new ManhattanStyle(baseName));
197 setDockNestingEnabled(true);
199 setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
200 setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
202 registerDefaultContainers();
203 registerDefaultActions();
205 m_navigationWidget = new NavigationWidget(m_toggleSideBarAction);
206 m_rightPaneWidget = new RightPaneWidget();
208 m_modeStack = new FancyTabWidget(this);
209 m_modeManager = new ModeManager(this, m_modeStack);
210 m_modeManager->addWidget(m_progressManager->progressView());
211 m_statusBarManager = new StatusBarManager(this);
212 m_messageManager = new MessageManager;
213 m_editorManager = new EditorManager(this);
214 m_editorManager->hide();
215 m_externalToolManager = new ExternalToolManager();
216 setCentralWidget(m_modeStack);
218 connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
219 this, SLOT(updateFocusWidget(QWidget*,QWidget*)));
220 // Add a small Toolbutton for toggling the navigation widget
221 statusBar()->insertPermanentWidget(0, m_toggleSideBarButton);
223 // setUnifiedTitleAndToolBarOnMac(true);
225 //signal(SIGINT, handleSigInt);
228 statusBar()->setProperty("p_styled", true);
229 setAcceptDrops(true);
232 void MainWindow::setSidebarVisible(bool visible)
234 if (NavigationWidgetPlaceHolder::current()) {
235 if (m_navigationWidget->isSuppressed() && visible) {
236 m_navigationWidget->setShown(true);
237 m_navigationWidget->setSuppressed(false);
239 m_navigationWidget->setShown(visible);
244 void MainWindow::setSuppressNavigationWidget(bool suppress)
246 if (NavigationWidgetPlaceHolder::current())
247 m_navigationWidget->setSuppressed(suppress);
250 void MainWindow::setOverrideColor(const QColor &color)
252 m_overrideColor = color;
255 bool MainWindow::isPresentationModeEnabled()
257 return m_actionManager->isPresentationModeEnabled();
260 void MainWindow::setPresentationModeEnabled(bool enabled)
262 m_actionManager->setPresentationModeEnabled(enabled);
265 MainWindow::~MainWindow()
267 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
268 pm->removeObject(m_shortcutSettings);
269 pm->removeObject(m_generalSettings);
270 pm->removeObject(m_toolSettings);
271 pm->removeObject(m_mimeTypeSettings);
272 pm->removeObject(m_systemEditor);
273 delete m_externalToolManager;
274 m_externalToolManager = 0;
275 delete m_messageManager;
276 m_messageManager = 0;
277 delete m_shortcutSettings;
278 m_shortcutSettings = 0;
279 delete m_generalSettings;
280 m_generalSettings = 0;
281 delete m_toolSettings;
283 delete m_mimeTypeSettings;
284 m_mimeTypeSettings = 0;
285 delete m_systemEditor;
293 //we need to delete editormanager and statusbarmanager explicitly before the end of the destructor,
294 //because they might trigger stuff that tries to access data from editorwindow, like removeContextWidget
296 // All modes are now gone
297 OutputPaneManager::destroy();
299 // Now that the OutputPaneManager is gone, is a good time to delete the view
300 pm->removeObject(m_outputView);
303 delete m_editorManager;
305 delete m_statusBarManager;
306 m_statusBarManager = 0;
307 delete m_progressManager;
308 m_progressManager = 0;
309 pm->removeObject(m_coreImpl);
313 delete m_rightPaneWidget;
314 m_rightPaneWidget = 0;
316 delete m_modeManager;
318 delete m_mimeDatabase;
321 delete m_helpManager;
325 bool MainWindow::init(QString *errorMessage)
327 Q_UNUSED(errorMessage)
329 if (!mimeDatabase()->addMimeTypes(QLatin1String(":/core/editormanager/BinFiles.mimetypes.xml"), errorMessage))
332 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
333 pm->addObject(m_coreImpl);
334 m_statusBarManager->init();
335 m_modeManager->init();
336 m_progressManager->init();
338 pm->addObject(m_generalSettings);
339 pm->addObject(m_shortcutSettings);
340 pm->addObject(m_toolSettings);
341 pm->addObject(m_mimeTypeSettings);
342 pm->addObject(m_systemEditor);
344 // Add widget to the bottom, we create the view here instead of inside the
345 // OutputPaneManager, since the StatusBarManager needs to be initialized before
346 m_outputView = new Core::StatusBarWidget;
347 m_outputView->setWidget(OutputPaneManager::instance()->buttonsWidget());
348 m_outputView->setPosition(Core::StatusBarWidget::Second);
349 pm->addObject(m_outputView);
350 m_messageManager->init();
354 void MainWindow::extensionsInitialized()
356 m_editorManager->init();
357 m_statusBarManager->extensionsInitalized();
358 OutputPaneManager::instance()->init();
359 m_vcsManager->extensionsInitialized();
360 m_navigationWidget->setFactories(ExtensionSystem::PluginManager::instance()->getObjects<INavigationWidgetFactory>());
362 // reading the shortcut settings must be done after all shortcuts have been registered
363 m_actionManager->initialize();
368 emit m_coreImpl->coreAboutToOpen();
370 emit m_coreImpl->coreOpened();
373 void MainWindow::closeEvent(QCloseEvent *event)
375 emit m_coreImpl->saveSettingsRequested();
379 QList<IDocument*> notSaved = DocumentManager::saveModifiedDocuments(DocumentManager::modifiedDocuments(), &cancelled);
380 if (cancelled || !notSaved.isEmpty()) {
385 const QList<ICoreListener *> listeners =
386 ExtensionSystem::PluginManager::instance()->getObjects<ICoreListener>();
387 foreach (ICoreListener *listener, listeners) {
388 if (!listener->coreAboutToClose()) {
394 emit m_coreImpl->coreAboutToClose();
398 m_navigationWidget->closeSubWidgets();
403 // Check for desktop file manager file drop events
405 static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
409 // Extract dropped files from Mime data.
412 const QList<QUrl> urls = d->urls();
415 // Try to find local files
416 bool hasFiles = false;
417 const QList<QUrl>::const_iterator cend = urls.constEnd();
418 for (QList<QUrl>::const_iterator it = urls.constBegin(); it != cend; ++it) {
419 const QString fileName = it->toLocalFile();
420 if (!fileName.isEmpty()) {
423 files->push_back(fileName);
425 break; // No result list, sufficient for checking
432 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
434 if (isDesktopFileManagerDrop(event->mimeData()) && m_filesToOpenDelayed.isEmpty()) {
441 void MainWindow::dropEvent(QDropEvent *event)
444 if (isDesktopFileManagerDrop(event->mimeData(), &files)) {
446 m_filesToOpenDelayed.append(files);
447 QTimer::singleShot(50, this, SLOT(openDelayedFiles()));
453 void MainWindow::openDelayedFiles()
455 if (m_filesToOpenDelayed.isEmpty())
459 openFiles(m_filesToOpenDelayed, ICore::SwitchMode);
460 m_filesToOpenDelayed.clear();
463 IContext *MainWindow::currentContextObject() const
465 return m_activeContext;
468 QStatusBar *MainWindow::statusBar() const
470 return m_modeStack->statusBar();
473 void MainWindow::registerDefaultContainers()
475 ActionManagerPrivate *am = m_actionManager;
477 ActionContainer *menubar = am->createMenuBar(Constants::MENU_BAR);
479 #ifndef Q_OS_MAC // System menu bar on Mac
480 setMenuBar(menubar->menuBar());
482 menubar->appendGroup(Constants::G_FILE);
483 menubar->appendGroup(Constants::G_EDIT);
484 menubar->appendGroup(Constants::G_VIEW);
485 menubar->appendGroup(Constants::G_TOOLS);
486 menubar->appendGroup(Constants::G_WINDOW);
487 menubar->appendGroup(Constants::G_HELP);
490 ActionContainer *filemenu = am->createMenu(Constants::M_FILE);
491 menubar->addMenu(filemenu, Constants::G_FILE);
492 filemenu->menu()->setTitle(tr("&File"));
493 filemenu->appendGroup(Constants::G_FILE_NEW);
494 filemenu->appendGroup(Constants::G_FILE_OPEN);
495 filemenu->appendGroup(Constants::G_FILE_PROJECT);
496 filemenu->appendGroup(Constants::G_FILE_SAVE);
497 filemenu->appendGroup(Constants::G_FILE_CLOSE);
498 filemenu->appendGroup(Constants::G_FILE_PRINT);
499 filemenu->appendGroup(Constants::G_FILE_OTHER);
500 connect(filemenu->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowRecentFiles()));
504 ActionContainer *medit = am->createMenu(Constants::M_EDIT);
505 menubar->addMenu(medit, Constants::G_EDIT);
506 medit->menu()->setTitle(tr("&Edit"));
507 medit->appendGroup(Constants::G_EDIT_UNDOREDO);
508 medit->appendGroup(Constants::G_EDIT_COPYPASTE);
509 medit->appendGroup(Constants::G_EDIT_SELECTALL);
510 medit->appendGroup(Constants::G_EDIT_ADVANCED);
511 medit->appendGroup(Constants::G_EDIT_FIND);
512 medit->appendGroup(Constants::G_EDIT_OTHER);
515 ActionContainer *ac = am->createMenu(Constants::M_TOOLS);
516 menubar->addMenu(ac, Constants::G_TOOLS);
517 ac->menu()->setTitle(tr("&Tools"));
520 ActionContainer *mwindow = am->createMenu(Constants::M_WINDOW);
521 menubar->addMenu(mwindow, Constants::G_WINDOW);
522 mwindow->menu()->setTitle(tr("&Window"));
523 mwindow->appendGroup(Constants::G_WINDOW_SIZE);
524 mwindow->appendGroup(Constants::G_WINDOW_VIEWS);
525 mwindow->appendGroup(Constants::G_WINDOW_PANES);
526 mwindow->appendGroup(Constants::G_WINDOW_SPLIT);
527 mwindow->appendGroup(Constants::G_WINDOW_NAVIGATE);
528 mwindow->appendGroup(Constants::G_WINDOW_OTHER);
531 ac = am->createMenu(Constants::M_HELP);
532 menubar->addMenu(ac, Constants::G_HELP);
533 ac->menu()->setTitle(tr("&Help"));
534 ac->appendGroup(Constants::G_HELP_HELP);
535 ac->appendGroup(Constants::G_HELP_ABOUT);
538 static Command *createSeparator(ActionManager *am, QObject *parent,
539 const Id &id, const Context &context)
541 QAction *tmpaction = new QAction(parent);
542 tmpaction->setSeparator(true);
543 Command *cmd = am->registerAction(tmpaction, id, context);
547 void MainWindow::registerDefaultActions()
549 ActionManagerPrivate *am = m_actionManager;
550 ActionContainer *mfile = am->actionContainer(Constants::M_FILE);
551 ActionContainer *medit = am->actionContainer(Constants::M_EDIT);
552 ActionContainer *mtools = am->actionContainer(Constants::M_TOOLS);
553 ActionContainer *mwindow = am->actionContainer(Constants::M_WINDOW);
554 ActionContainer *mhelp = am->actionContainer(Constants::M_HELP);
556 Context globalContext(Constants::C_GLOBAL);
558 // File menu separators
559 Command *cmd = createSeparator(am, this, Id("QtCreator.File.Sep.Save"), globalContext);
560 mfile->addAction(cmd, Constants::G_FILE_SAVE);
562 cmd = createSeparator(am, this, Id("QtCreator.File.Sep.Print"), globalContext);
563 QIcon icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(QLatin1String(Constants::ICON_CUT)));
564 mfile->addAction(cmd, Constants::G_FILE_PRINT);
566 cmd = createSeparator(am, this, Id("QtCreator.File.Sep.Close"), globalContext);
567 mfile->addAction(cmd, Constants::G_FILE_CLOSE);
569 cmd = createSeparator(am, this, Id("QtCreator.File.Sep.Other"), globalContext);
570 mfile->addAction(cmd, Constants::G_FILE_OTHER);
572 // Edit menu separators
573 cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.CopyPaste"), globalContext);
574 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
576 cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.SelectAll"), globalContext);
577 medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
579 cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.Find"), globalContext);
580 medit->addAction(cmd, Constants::G_EDIT_FIND);
582 cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.Advanced"), globalContext);
583 medit->addAction(cmd, Constants::G_EDIT_ADVANCED);
585 // Return to editor shortcut: Note this requires Qt to fix up
586 // handling of shortcut overrides in menus, item views, combos....
587 m_focusToEditor = new QShortcut(this);
588 cmd = am->registerShortcut(m_focusToEditor, Constants::S_RETURNTOEDITOR, globalContext);
589 cmd->setDefaultKeySequence(QKeySequence(Qt::Key_Escape));
590 connect(m_focusToEditor, SIGNAL(activated()), this, SLOT(setFocusToEditor()));
593 icon = QIcon::fromTheme(QLatin1String("document-new"), QIcon(QLatin1String(Constants::ICON_NEWFILE)));
594 m_newAction = new QAction(icon, tr("&New File or Project..."), this);
595 cmd = am->registerAction(m_newAction, Constants::NEW, globalContext);
596 cmd->setDefaultKeySequence(QKeySequence::New);
597 mfile->addAction(cmd, Constants::G_FILE_NEW);
598 connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile()));
601 icon = QIcon::fromTheme(QLatin1String("document-open"), QIcon(QLatin1String(Constants::ICON_OPENFILE)));
602 m_openAction = new QAction(icon, tr("&Open File or Project..."), this);
603 cmd = am->registerAction(m_openAction, Constants::OPEN, globalContext);
604 cmd->setDefaultKeySequence(QKeySequence::Open);
605 mfile->addAction(cmd, Constants::G_FILE_OPEN);
606 connect(m_openAction, SIGNAL(triggered()), this, SLOT(openFile()));
609 m_openWithAction = new QAction(tr("Open File &With..."), this);
610 cmd = am->registerAction(m_openWithAction, Constants::OPEN_WITH, globalContext);
611 mfile->addAction(cmd, Constants::G_FILE_OPEN);
612 connect(m_openWithAction, SIGNAL(triggered()), this, SLOT(openFileWith()));
614 // File->Recent Files Menu
615 ActionContainer *ac = am->createMenu(Constants::M_FILE_RECENTFILES);
616 mfile->addMenu(ac, Constants::G_FILE_OPEN);
617 ac->menu()->setTitle(tr("Recent &Files"));
618 ac->setOnAllDisabledBehavior(ActionContainer::Show);
621 icon = QIcon::fromTheme(QLatin1String("document-save"), QIcon(QLatin1String(Constants::ICON_SAVEFILE)));
622 QAction *tmpaction = new QAction(icon, tr("&Save"), this);
623 tmpaction->setEnabled(false);
624 cmd = am->registerAction(tmpaction, Constants::SAVE, globalContext);
625 cmd->setDefaultKeySequence(QKeySequence::Save);
626 cmd->setAttribute(Command::CA_UpdateText);
627 cmd->setDescription(tr("Save"));
628 mfile->addAction(cmd, Constants::G_FILE_SAVE);
631 icon = QIcon::fromTheme(QLatin1String("document-save-as"));
632 tmpaction = new QAction(icon, tr("Save &As..."), this);
633 tmpaction->setEnabled(false);
634 cmd = am->registerAction(tmpaction, Constants::SAVEAS, globalContext);
636 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
638 cmd->setAttribute(Command::CA_UpdateText);
639 cmd->setDescription(tr("Save As..."));
640 mfile->addAction(cmd, Constants::G_FILE_SAVE);
643 m_saveAllAction = new QAction(tr("Save A&ll"), this);
644 cmd = am->registerAction(m_saveAllAction, Constants::SAVEALL, globalContext);
646 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
648 mfile->addAction(cmd, Constants::G_FILE_SAVE);
649 connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll()));
652 icon = QIcon::fromTheme(QLatin1String("document-print"));
653 tmpaction = new QAction(icon, tr("&Print..."), this);
654 tmpaction->setEnabled(false);
655 cmd = am->registerAction(tmpaction, Constants::PRINT, globalContext);
656 cmd->setDefaultKeySequence(QKeySequence::Print);
657 mfile->addAction(cmd, Constants::G_FILE_PRINT);
660 icon = QIcon::fromTheme(QLatin1String("application-exit"));
661 m_exitAction = new QAction(icon, tr("E&xit"), this);
662 cmd = am->registerAction(m_exitAction, Constants::EXIT, globalContext);
663 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Q")));
664 mfile->addAction(cmd, Constants::G_FILE_OTHER);
665 connect(m_exitAction, SIGNAL(triggered()), this, SLOT(exit()));
668 icon = QIcon::fromTheme(QLatin1String("edit-undo"), QIcon(QLatin1String(Constants::ICON_UNDO)));
669 tmpaction = new QAction(icon, tr("&Undo"), this);
670 cmd = am->registerAction(tmpaction, Constants::UNDO, globalContext);
671 cmd->setDefaultKeySequence(QKeySequence::Undo);
672 cmd->setAttribute(Command::CA_UpdateText);
673 cmd->setDescription(tr("Undo"));
674 medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
675 tmpaction->setEnabled(false);
678 icon = QIcon::fromTheme(QLatin1String("edit-redo"), QIcon(QLatin1String(Constants::ICON_REDO)));
679 tmpaction = new QAction(icon, tr("&Redo"), this);
680 cmd = am->registerAction(tmpaction, Constants::REDO, globalContext);
681 cmd->setDefaultKeySequence(QKeySequence::Redo);
682 cmd->setAttribute(Command::CA_UpdateText);
683 cmd->setDescription(tr("Redo"));
684 medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
685 tmpaction->setEnabled(false);
688 icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(QLatin1String(Constants::ICON_CUT)));
689 tmpaction = new QAction(icon, tr("Cu&t"), this);
690 cmd = am->registerAction(tmpaction, Constants::CUT, globalContext);
691 cmd->setDefaultKeySequence(QKeySequence::Cut);
692 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
693 tmpaction->setEnabled(false);
696 icon = QIcon::fromTheme(QLatin1String("edit-copy"), QIcon(QLatin1String(Constants::ICON_COPY)));
697 tmpaction = new QAction(icon, tr("&Copy"), this);
698 cmd = am->registerAction(tmpaction, Constants::COPY, globalContext);
699 cmd->setDefaultKeySequence(QKeySequence::Copy);
700 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
701 tmpaction->setEnabled(false);
704 icon = QIcon::fromTheme(QLatin1String("edit-paste"), QIcon(QLatin1String(Constants::ICON_PASTE)));
705 tmpaction = new QAction(icon, tr("&Paste"), this);
706 cmd = am->registerAction(tmpaction, Constants::PASTE, globalContext);
707 cmd->setDefaultKeySequence(QKeySequence::Paste);
708 medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
709 tmpaction->setEnabled(false);
712 icon = QIcon::fromTheme(QLatin1String("edit-select-all"));
713 tmpaction = new QAction(icon, tr("Select &All"), this);
714 cmd = am->registerAction(tmpaction, Constants::SELECTALL, globalContext);
715 cmd->setDefaultKeySequence(QKeySequence::SelectAll);
716 medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
717 tmpaction->setEnabled(false);
720 icon = QIcon::fromTheme(QLatin1String("go-jump"));
721 tmpaction = new QAction(icon, tr("&Go to Line..."), this);
722 cmd = am->registerAction(tmpaction, Constants::GOTO, globalContext);
723 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+L")));
724 medit->addAction(cmd, Constants::G_EDIT_OTHER);
725 tmpaction->setEnabled(false);
728 mtools->appendGroup(Constants::G_TOOLS_OPTIONS);
729 cmd = createSeparator(am, this, Id("QtCreator.Tools.Sep.Options"), globalContext);
730 mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
731 m_optionsAction = new QAction(tr("&Options..."), this);
732 cmd = am->registerAction(m_optionsAction, Constants::OPTIONS, globalContext);
734 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+,")));
735 cmd->action()->setMenuRole(QAction::PreferencesRole);
737 mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
738 connect(m_optionsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog()));
742 m_minimizeAction = new QAction(tr("Minimize"), this);
743 cmd = am->registerAction(m_minimizeAction, Constants::MINIMIZE_WINDOW, globalContext);
744 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+M")));
745 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
746 connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(showMinimized()));
749 m_zoomAction = new QAction(tr("Zoom"), this);
750 cmd = am->registerAction(m_zoomAction, Constants::ZOOM_WINDOW, globalContext);
751 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
752 connect(m_zoomAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
755 cmd = createSeparator(am, this, Id("QtCreator.Window.Sep.Size"), globalContext);
756 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
759 // Show Sidebar Action
760 m_toggleSideBarAction = new QAction(QIcon(QLatin1String(Constants::ICON_TOGGLE_SIDEBAR)),
761 tr("Show Sidebar"), this);
762 m_toggleSideBarAction->setCheckable(true);
763 cmd = am->registerAction(m_toggleSideBarAction, Constants::TOGGLE_SIDEBAR, globalContext);
764 cmd->setAttribute(Command::CA_UpdateText);
766 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+0")));
768 cmd->setDefaultKeySequence(QKeySequence(tr("Alt+0")));
770 connect(m_toggleSideBarAction, SIGNAL(triggered(bool)), this, SLOT(setSidebarVisible(bool)));
771 m_toggleSideBarButton->setDefaultAction(cmd->action());
772 mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS);
773 m_toggleSideBarAction->setEnabled(false);
776 // Full Screen Action
777 m_toggleFullScreenAction = new QAction(tr("Full Screen"), this);
778 m_toggleFullScreenAction->setCheckable(true);
779 cmd = am->registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext);
780 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
781 mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
782 connect(m_toggleFullScreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool)));
786 ActionContainer *mviews = am->createMenu(Constants::M_WINDOW_VIEWS);
787 mwindow->addMenu(mviews, Constants::G_WINDOW_VIEWS);
788 mviews->menu()->setTitle(tr("&Views"));
791 icon = QIcon::fromTheme(QLatin1String("help-about"));
793 tmpaction = new QAction(icon, tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
795 tmpaction = new QAction(icon, tr("About &Qt Creator..."), this);
797 cmd = am->registerAction(tmpaction, Constants::ABOUT_QTCREATOR, globalContext);
798 mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
799 tmpaction->setEnabled(true);
801 cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
803 connect(tmpaction, SIGNAL(triggered()), this, SLOT(aboutQtCreator()));
805 //About Plugins Action
806 tmpaction = new QAction(tr("About &Plugins..."), this);
807 cmd = am->registerAction(tmpaction, Constants::ABOUT_PLUGINS, globalContext);
808 mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
809 tmpaction->setEnabled(true);
811 cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
813 connect(tmpaction, SIGNAL(triggered()), this, SLOT(aboutPlugins()));
815 // tmpaction = new QAction(tr("About &Qt..."), this);
816 // cmd = am->registerAction(tmpaction, Constants:: ABOUT_QT, globalContext);
817 // mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
818 // tmpaction->setEnabled(true);
819 // connect(tmpaction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
821 #ifndef Q_OS_MAC // doesn't have the "About" actions in the Help menu
822 tmpaction = new QAction(this);
823 tmpaction->setSeparator(true);
824 cmd = am->registerAction(tmpaction, "QtCreator.Help.Sep.About", globalContext);
825 mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
829 void MainWindow::newFile()
831 showNewItemDialog(tr("New", "Title of dialog"), IWizard::allWizards(), QString());
834 void MainWindow::openFile()
836 openFiles(editorManager()->getOpenFileNames(), ICore::SwitchMode);
839 static QList<IDocumentFactory*> getNonEditorDocumentFactories()
841 const QList<IDocumentFactory*> allFileFactories =
842 ExtensionSystem::PluginManager::instance()->getObjects<IDocumentFactory>();
843 QList<IDocumentFactory*> nonEditorFileFactories;
844 foreach (IDocumentFactory *factory, allFileFactories) {
845 if (!qobject_cast<IEditorFactory *>(factory))
846 nonEditorFileFactories.append(factory);
848 return nonEditorFileFactories;
851 static IDocumentFactory *findDocumentFactory(const QList<IDocumentFactory*> &fileFactories,
852 const MimeDatabase *db,
855 if (const MimeType mt = db->findByFile(fi)) {
856 const QString type = mt.type();
857 foreach (IDocumentFactory *factory, fileFactories) {
858 if (factory->mimeTypes().contains(type))
865 // opens either an editor or loads a project
866 void MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags)
868 QList<IDocumentFactory*> nonEditorFileFactories = getNonEditorDocumentFactories();
870 foreach (const QString &fileName, fileNames) {
871 const QFileInfo fi(fileName);
872 const QString absoluteFilePath = fi.absoluteFilePath();
873 if (IDocumentFactory *documentFactory = findDocumentFactory(nonEditorFileFactories, mimeDatabase(), fi)) {
874 Core::IDocument *document = documentFactory->open(absoluteFilePath);
875 if (!document && (flags & ICore::StopOnLoadFail))
877 if (document && (flags & ICore::SwitchMode))
878 ModeManager::activateMode(QLatin1String(Core::Constants::MODE_EDIT));
880 QFlags<EditorManager::OpenEditorFlag> emFlags;
881 if (flags & ICore::SwitchMode)
882 emFlags = EditorManager::ModeSwitch;
883 if (flags & ICore::CanContainLineNumbers)
884 emFlags |= EditorManager::CanContainLineNumber;
885 Core::IEditor *editor = editorManager()->openEditor(absoluteFilePath, Id(), emFlags);
886 if (!editor && (flags & ICore::StopOnLoadFail))
892 void MainWindow::setFocusToEditor()
894 bool focusWasMovedToEditor = false;
896 // give focus to the editor if we have one
897 if (IEditor *editor = m_editorManager->currentEditor()) {
898 if (qApp->focusWidget() != editor->widget()->focusWidget()) {
899 QWidget *w = editor->widget()->focusWidget();
901 w = editor->widget();
903 focusWasMovedToEditor = w->hasFocus();
907 // check for some maximized pane which we want to unmaximize
908 if (OutputPanePlaceHolder::getCurrent()
909 && OutputPanePlaceHolder::getCurrent()->isVisible()
910 && OutputPanePlaceHolder::getCurrent()->isMaximized()) {
911 OutputPanePlaceHolder::getCurrent()->unmaximize();
915 if (focusWasMovedToEditor)
918 // check for some visible bar which we want to hide
920 (FindToolBarPlaceHolder::getCurrent() &&
921 FindToolBarPlaceHolder::getCurrent()->isVisible())
922 || (OutputPanePlaceHolder::getCurrent() &&
923 OutputPanePlaceHolder::getCurrent()->isVisible())
924 || (RightPanePlaceHolder::current() &&
925 RightPanePlaceHolder::current()->isVisible());
927 if (FindToolBarPlaceHolder::getCurrent())
928 FindToolBarPlaceHolder::getCurrent()->hide();
929 OutputPaneManager::instance()->slotHide();
930 RightPaneWidget::instance()->setShown(false);
934 // switch to edit mode if necessary
935 ModeManager::activateMode(QLatin1String(Constants::MODE_EDIT));
938 void MainWindow::showNewItemDialog(const QString &title,
939 const QList<IWizard *> &wizards,
940 const QString &defaultLocation,
941 const QVariantMap &extraVariables)
943 // Scan for wizards matching the filter and pick one. Don't show
944 // dialog if there is only one.
946 QString selectedPlatform;
947 switch (wizards.size()) {
951 wizard = wizards.front();
955 dlg.setWizards(wizards);
956 dlg.setWindowTitle(title);
957 wizard = dlg.showDialog();
958 selectedPlatform = dlg.selectedPlatform();
966 QString path = defaultLocation;
967 if (path.isEmpty()) {
968 switch (wizard->kind()) {
969 case IWizard::ProjectWizard:
970 // Project wizards: Check for projects directory or
971 // use last visited directory of file dialog. Never start
973 path = DocumentManager::useProjectsDirectory() ?
974 DocumentManager::projectsDirectory() :
975 DocumentManager::fileDialogLastVisitedDirectory();
978 path = DocumentManager::fileDialogInitialDirectory();
982 wizard->runWizard(path, this, selectedPlatform, extraVariables);
985 bool MainWindow::showOptionsDialog(const QString &category,
989 emit m_coreImpl->optionsDialogRequested();
992 SettingsDialog *dialog = SettingsDialog::getSettingsDialog(parent, category, page);
993 return dialog->execDialog();
996 void MainWindow::saveAll()
998 DocumentManager::saveModifiedDocumentsSilently(DocumentManager::modifiedDocuments());
999 emit m_coreImpl->saveSettingsRequested();
1002 void MainWindow::exit()
1004 // this function is most likely called from a user action
1005 // that is from an event handler of an object
1006 // since on close we are going to delete everything
1007 // so to prevent the deleting of that object we
1009 QTimer::singleShot(0, this, SLOT(close()));
1012 void MainWindow::openFileWith()
1014 QStringList fileNames = editorManager()->getOpenFileNames();
1015 foreach (const QString &fileName, fileNames) {
1017 const Id editorId = editorManager()->getOpenWithEditorId(fileName, &isExternal);
1018 if (!editorId.isValid())
1021 editorManager()->openExternalEditor(fileName, editorId);
1023 editorManager()->openEditor(fileName, editorId, Core::EditorManager::ModeSwitch);
1028 ActionManager *MainWindow::actionManager() const
1030 return m_actionManager;
1033 MessageManager *MainWindow::messageManager() const
1035 return m_messageManager;
1038 VcsManager *MainWindow::vcsManager() const
1040 return m_vcsManager;
1043 QSettings *MainWindow::settings(QSettings::Scope scope) const
1045 if (scope == QSettings::UserScope)
1048 return m_globalSettings;
1051 EditorManager *MainWindow::editorManager() const
1053 return m_editorManager;
1056 ProgressManager *MainWindow::progressManager() const
1058 return m_progressManager;
1061 ScriptManager *MainWindow::scriptManager() const
1063 return m_scriptManager;
1066 VariableManager *MainWindow::variableManager() const
1068 return m_variableManager.data();
1071 ModeManager *MainWindow::modeManager() const
1073 return m_modeManager;
1076 MimeDatabase *MainWindow::mimeDatabase() const
1078 return m_mimeDatabase;
1081 HelpManager *MainWindow::helpManager() const
1083 return m_helpManager;
1086 IContext *MainWindow::contextObject(QWidget *widget)
1088 return m_contextWidgets.value(widget);
1091 void MainWindow::addContextObject(IContext *context)
1095 QWidget *widget = context->widget();
1096 if (m_contextWidgets.contains(widget))
1099 m_contextWidgets.insert(widget, context);
1102 void MainWindow::removeContextObject(IContext *context)
1107 QWidget *widget = context->widget();
1108 if (!m_contextWidgets.contains(widget))
1111 m_contextWidgets.remove(widget);
1112 if (m_activeContext == context)
1113 updateContextObject(0);
1116 void MainWindow::changeEvent(QEvent *e)
1118 QMainWindow::changeEvent(e);
1119 if (e->type() == QEvent::ActivationChange) {
1120 if (isActiveWindow()) {
1121 if (debugMainWindow)
1122 qDebug() << "main window activated";
1123 emit windowActivated();
1125 } else if (e->type() == QEvent::WindowStateChange) {
1127 bool minimized = isMinimized();
1128 if (debugMainWindow)
1129 qDebug() << "main window state changed to minimized=" << minimized;
1130 m_minimizeAction->setEnabled(!minimized);
1131 m_zoomAction->setEnabled(!minimized);
1133 bool isFullScreen = (windowState() & Qt::WindowFullScreen) != 0;
1134 m_toggleFullScreenAction->setChecked(isFullScreen);
1139 void MainWindow::updateFocusWidget(QWidget *old, QWidget *now)
1143 // Prevent changing the context object just because the menu or a menu item is activated
1144 if (qobject_cast<QMenuBar*>(now) || qobject_cast<QMenu*>(now))
1147 IContext *newContext = 0;
1148 if (focusWidget()) {
1149 IContext *context = 0;
1150 QWidget *p = focusWidget();
1152 context = m_contextWidgets.value(p);
1154 newContext = context;
1157 p = p->parentWidget();
1160 updateContextObject(newContext);
1163 void MainWindow::updateContextObject(IContext *context)
1165 if (context == m_activeContext)
1167 emit m_coreImpl->contextAboutToChange(context);
1168 m_activeContext = context;
1170 if (debugMainWindow)
1171 qDebug() << "new context object =" << context << (context ? context->widget() : 0)
1172 << (context ? context->widget()->metaObject()->className() : 0);
1175 void MainWindow::resetContext()
1177 updateContextObject(0);
1180 void MainWindow::aboutToShutdown()
1182 disconnect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
1183 this, SLOT(updateFocusWidget(QWidget*,QWidget*)));
1184 m_activeContext = 0;
1188 static const char settingsGroup[] = "MainWindow";
1189 static const char colorKey[] = "Color";
1190 static const char windowGeometryKey[] = "WindowGeometry";
1191 static const char windowStateKey[] = "WindowState";
1193 // TODO compat for <= 2.1, remove later
1194 static const char geometryKey[] = "Geometry";
1195 static const char maxKey[] = "Maximized";
1196 static const char fullScreenKey[] = "FullScreen";
1198 void MainWindow::readSettings()
1200 m_settings->beginGroup(QLatin1String(settingsGroup));
1202 if (m_overrideColor.isValid()) {
1203 Utils::StyleHelper::setBaseColor(m_overrideColor);
1204 // Get adapted base color.
1205 m_overrideColor = Utils::StyleHelper::baseColor();
1207 Utils::StyleHelper::setBaseColor(
1208 m_settings->value(QLatin1String(colorKey),
1209 QColor(Utils::StyleHelper::DEFAULT_BASE_COLOR)).value<QColor>());
1212 if (!restoreGeometry(m_settings->value(QLatin1String(windowGeometryKey)).toByteArray())) {
1213 resize(1008, 700); // size without window decoration
1215 restoreState(m_settings->value(QLatin1String(windowStateKey)).toByteArray());
1217 m_settings->endGroup();
1219 m_editorManager->readSettings();
1220 m_navigationWidget->restoreSettings(m_settings);
1221 m_rightPaneWidget->readSettings(m_settings);
1224 void MainWindow::writeSettings()
1226 m_settings->beginGroup(QLatin1String(settingsGroup));
1228 if (!(m_overrideColor.isValid() && Utils::StyleHelper::baseColor() == m_overrideColor))
1229 m_settings->setValue(QLatin1String(colorKey), Utils::StyleHelper::requestedBaseColor());
1231 m_settings->setValue(QLatin1String(windowGeometryKey), saveGeometry());
1232 m_settings->setValue(QLatin1String(windowStateKey), saveState());
1234 m_settings->endGroup();
1236 DocumentManager::saveSettings();
1237 m_actionManager->saveSettings(m_settings);
1238 m_editorManager->saveSettings();
1239 m_navigationWidget->saveSettings(m_settings);
1242 void MainWindow::updateAdditionalContexts(const Context &remove, const Context &add)
1244 foreach (const int context, remove) {
1248 int index = m_additionalContexts.indexOf(context);
1250 m_additionalContexts.removeAt(index);
1253 foreach (const int context, add) {
1257 if (!m_additionalContexts.contains(context))
1258 m_additionalContexts.prepend(context);
1264 bool MainWindow::hasContext(int context) const
1266 return m_actionManager->hasContext(context);
1269 void MainWindow::updateContext()
1273 if (m_activeContext)
1274 contexts.add(m_activeContext->context());
1276 contexts.add(m_additionalContexts);
1278 Context uniquecontexts;
1279 for (int i = 0; i < contexts.size(); ++i) {
1280 const int c = contexts.at(i);
1281 if (!uniquecontexts.contains(c))
1282 uniquecontexts.add(c);
1285 m_actionManager->setContext(uniquecontexts);
1286 emit m_coreImpl->contextChanged(m_activeContext, m_additionalContexts);
1289 void MainWindow::aboutToShowRecentFiles()
1291 ActionContainer *aci =
1292 m_actionManager->actionContainer(Constants::M_FILE_RECENTFILES);
1293 aci->menu()->clear();
1295 bool hasRecentFiles = false;
1296 foreach (const DocumentManager::RecentFile &file, DocumentManager::recentFiles()) {
1297 hasRecentFiles = true;
1298 QAction *action = aci->menu()->addAction(
1299 QDir::toNativeSeparators(Utils::withTildeHomePath(file.first)));
1300 action->setData(qVariantFromValue(file));
1301 connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile()));
1303 aci->menu()->setEnabled(hasRecentFiles);
1305 // add the Clear Menu item
1306 if (hasRecentFiles) {
1307 aci->menu()->addSeparator();
1308 QAction *action = aci->menu()->addAction(QCoreApplication::translate(
1309 "Core", Core::Constants::TR_CLEAR_MENU));
1310 connect(action, SIGNAL(triggered()), DocumentManager::instance(), SLOT(clearRecentFiles()));
1314 void MainWindow::openRecentFile()
1316 if (const QAction *action = qobject_cast<const QAction*>(sender())) {
1317 const DocumentManager::RecentFile file = action->data().value<DocumentManager::RecentFile>();
1318 editorManager()->openEditor(file.first, file.second, Core::EditorManager::ModeSwitch);
1322 void MainWindow::aboutQtCreator()
1324 if (!m_versionDialog) {
1325 m_versionDialog = new VersionDialog(this);
1326 connect(m_versionDialog, SIGNAL(finished(int)),
1327 this, SLOT(destroyVersionDialog()));
1329 m_versionDialog->show();
1332 void MainWindow::destroyVersionDialog()
1334 if (m_versionDialog) {
1335 m_versionDialog->deleteLater();
1336 m_versionDialog = 0;
1340 void MainWindow::aboutPlugins()
1342 PluginDialog dialog(this);
1346 QPrinter *MainWindow::printer() const
1349 m_printer = new QPrinter(QPrinter::HighResolution);
1353 void MainWindow::setFullScreen(bool on)
1355 if (bool(windowState() & Qt::WindowFullScreen) == on)
1359 setWindowState(windowState() | Qt::WindowFullScreen);
1360 //statusBar()->hide();
1361 //menuBar()->hide();
1363 setWindowState(windowState() & ~Qt::WindowFullScreen);
1364 //menuBar()->show();
1365 //statusBar()->show();
1369 // Display a warning with an additional button to open
1370 // the debugger settings dialog if settingsId is nonempty.
1372 bool MainWindow::showWarningWithOptions(const QString &title,
1373 const QString &text,
1374 const QString &details,
1375 const QString &settingsCategory,
1376 const QString &settingsId,
1381 QMessageBox msgBox(QMessageBox::Warning, title, text,
1382 QMessageBox::Ok, parent);
1383 if (!details.isEmpty())
1384 msgBox.setDetailedText(details);
1385 QAbstractButton *settingsButton = 0;
1386 if (!settingsId.isEmpty() || !settingsCategory.isEmpty())
1387 settingsButton = msgBox.addButton(tr("Settings..."), QMessageBox::AcceptRole);
1389 if (settingsButton && msgBox.clickedButton() == settingsButton) {
1390 return showOptionsDialog(settingsCategory, settingsId);