OSDN Git Service

New File Dialog: Choose right default project for adding
[qt-creator-jp/qt-creator-jp.git] / src / plugins / coreplugin / mainwindow.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
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.
18 **
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.
22 **
23 ** Other Usage
24 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "mainwindow.h"
34 #include "actioncontainer.h"
35 #include "command.h"
36 #include "actionmanager_p.h"
37 #include "icore.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"
47 #include "ieditor.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"
61
62 #include "scriptmanager_p.h"
63 #include "settingsdialog.h"
64 #include "variablemanager.h"
65 #include "versiondialog.h"
66 #include "statusbarmanager.h"
67 #include "id.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"
77
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>
87
88 #include <QDebug>
89 #include <QFileInfo>
90 #include <QSettings>
91 #include <QTimer>
92 #include <QtPlugin>
93 #include <QUrl>
94 #include <QDir>
95 #include <QFile>
96 #include <QMimeData>
97
98 #include <QApplication>
99 #include <QCloseEvent>
100 #include <QMenu>
101 #include <QPixmap>
102 #include <QPrinter>
103 #include <QShortcut>
104 #include <QStatusBar>
105 #include <QWizard>
106 #include <QToolButton>
107 #include <QMessageBox>
108 #include <QMenuBar>
109 #include <QPushButton>
110
111 /*
112 #ifdef Q_OS_UNIX
113 #include <signal.h>
114 extern "C" void handleSigInt(int sig)
115 {
116     Q_UNUSED(sig)
117     Core::ICore::exit();
118     qDebug() << "SIGINT caught. Shutting down.";
119 }
120 #endif
121 */
122
123 using namespace Core;
124 using namespace Core::Internal;
125
126 enum { debugMainWindow = 0 };
127
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"),
136                                             this)),
137     m_printer(0),
138     m_actionManager(new ActionManagerPrivate(this)),
139     m_editorManager(0),
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),
146     m_modeManager(0),
147     m_mimeDatabase(new MimeDatabase),
148     m_helpManager(new HelpManager),
149     m_navigationWidget(0),
150     m_rightPaneWidget(0),
151     m_versionDialog(0),
152     m_activeContext(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),
158     m_focusToEditor(0),
159     m_newAction(0),
160     m_openAction(0),
161     m_openWithAction(0),
162     m_saveAllAction(0),
163     m_exitAction(0),
164     m_optionsAction(0),
165     m_toggleSideBarAction(0),
166     m_toggleFullScreenAction(0),
167 #ifdef Q_OS_MAC
168     m_minimizeAction(0),
169     m_zoomAction(0),
170 #endif
171     m_toggleSideBarButton(new QToolButton)
172 {
173     (void) new DocumentManager(this);
174     OutputPaneManager::create();
175
176     setWindowTitle(tr("Qt Creator"));
177 #ifndef Q_OS_MAC
178     QApplication::setWindowIcon(QIcon(QLatin1String(Constants::ICON_QTLOGO_128)));
179 #endif
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();
184 #ifdef Q_WS_X11
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");
191         else
192             baseName = QLatin1String("cleanlooks");
193     }
194 #endif
195     qApp->setStyle(new ManhattanStyle(baseName));
196
197     setDockNestingEnabled(true);
198
199     setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
200     setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
201
202     registerDefaultContainers();
203     registerDefaultActions();
204
205     m_navigationWidget = new NavigationWidget(m_toggleSideBarAction);
206     m_rightPaneWidget = new RightPaneWidget();
207
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);
217
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);
222
223 //    setUnifiedTitleAndToolBarOnMac(true);
224 #ifdef Q_OS_UNIX
225      //signal(SIGINT, handleSigInt);
226 #endif
227
228     statusBar()->setProperty("p_styled", true);
229     setAcceptDrops(true);
230 }
231
232 void MainWindow::setSidebarVisible(bool visible)
233 {
234     if (NavigationWidgetPlaceHolder::current()) {
235         if (m_navigationWidget->isSuppressed() && visible) {
236             m_navigationWidget->setShown(true);
237             m_navigationWidget->setSuppressed(false);
238         } else {
239             m_navigationWidget->setShown(visible);
240         }
241     }
242 }
243
244 void MainWindow::setSuppressNavigationWidget(bool suppress)
245 {
246     if (NavigationWidgetPlaceHolder::current())
247         m_navigationWidget->setSuppressed(suppress);
248 }
249
250 void MainWindow::setOverrideColor(const QColor &color)
251 {
252     m_overrideColor = color;
253 }
254
255 bool MainWindow::isPresentationModeEnabled()
256 {
257     return m_actionManager->isPresentationModeEnabled();
258 }
259
260 void MainWindow::setPresentationModeEnabled(bool enabled)
261 {
262     m_actionManager->setPresentationModeEnabled(enabled);
263 }
264
265 MainWindow::~MainWindow()
266 {
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;
282     m_toolSettings = 0;
283     delete m_mimeTypeSettings;
284     m_mimeTypeSettings = 0;
285     delete m_systemEditor;
286     m_systemEditor = 0;
287     delete m_settings;
288     m_settings = 0;
289     delete m_printer;
290     m_printer = 0;
291     delete m_vcsManager;
292     m_vcsManager = 0;
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
295
296     // All modes are now gone
297     OutputPaneManager::destroy();
298
299     // Now that the OutputPaneManager is gone, is a good time to delete the view
300     pm->removeObject(m_outputView);
301     delete m_outputView;
302
303     delete m_editorManager;
304     m_editorManager = 0;
305     delete m_statusBarManager;
306     m_statusBarManager = 0;
307     delete m_progressManager;
308     m_progressManager = 0;
309     pm->removeObject(m_coreImpl);
310     delete m_coreImpl;
311     m_coreImpl = 0;
312
313     delete m_rightPaneWidget;
314     m_rightPaneWidget = 0;
315
316     delete m_modeManager;
317     m_modeManager = 0;
318     delete m_mimeDatabase;
319     m_mimeDatabase = 0;
320
321     delete m_helpManager;
322     m_helpManager = 0;
323 }
324
325 bool MainWindow::init(QString *errorMessage)
326 {
327     Q_UNUSED(errorMessage)
328
329     if (!mimeDatabase()->addMimeTypes(QLatin1String(":/core/editormanager/BinFiles.mimetypes.xml"), errorMessage))
330         return false;
331
332     ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
333     pm->addObject(m_coreImpl);
334     m_statusBarManager->init();
335     m_modeManager->init();
336     m_progressManager->init();
337
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);
343
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();
351     return true;
352 }
353
354 void MainWindow::extensionsInitialized()
355 {
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>());
361
362     // reading the shortcut settings must be done after all shortcuts have been registered
363     m_actionManager->initialize();
364
365     readSettings();
366     updateContext();
367
368     emit m_coreImpl->coreAboutToOpen();
369     show();
370     emit m_coreImpl->coreOpened();
371 }
372
373 void MainWindow::closeEvent(QCloseEvent *event)
374 {
375     emit m_coreImpl->saveSettingsRequested();
376
377     // Save opened files
378     bool cancelled;
379     QList<IDocument*> notSaved = DocumentManager::saveModifiedDocuments(DocumentManager::modifiedDocuments(), &cancelled);
380     if (cancelled || !notSaved.isEmpty()) {
381         event->ignore();
382         return;
383     }
384
385     const QList<ICoreListener *> listeners =
386         ExtensionSystem::PluginManager::instance()->getObjects<ICoreListener>();
387     foreach (ICoreListener *listener, listeners) {
388         if (!listener->coreAboutToClose()) {
389             event->ignore();
390             return;
391         }
392     }
393
394     emit m_coreImpl->coreAboutToClose();
395
396     writeSettings();
397
398     m_navigationWidget->closeSubWidgets();
399
400     event->accept();
401 }
402
403 // Check for desktop file manager file drop events
404
405 static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
406 {
407     if (files)
408         files->clear();
409     // Extract dropped files from Mime data.
410     if (!d->hasUrls())
411         return false;
412     const QList<QUrl> urls = d->urls();
413     if (urls.empty())
414         return false;
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()) {
421             hasFiles = true;
422             if (files) {
423                 files->push_back(fileName);
424             } else {
425                 break; // No result list, sufficient for checking
426             }
427         }
428     }
429     return hasFiles;
430 }
431
432 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
433 {
434     if (isDesktopFileManagerDrop(event->mimeData()) && m_filesToOpenDelayed.isEmpty()) {
435         event->accept();
436     } else {
437         event->ignore();
438     }
439 }
440
441 void MainWindow::dropEvent(QDropEvent *event)
442 {
443     QStringList files;
444     if (isDesktopFileManagerDrop(event->mimeData(), &files)) {
445         event->accept();
446         m_filesToOpenDelayed.append(files);
447         QTimer::singleShot(50, this, SLOT(openDelayedFiles()));
448     } else {
449         event->ignore();
450     }
451 }
452
453 void MainWindow::openDelayedFiles()
454 {
455     if (m_filesToOpenDelayed.isEmpty())
456         return;
457     activateWindow();
458     raise();
459     openFiles(m_filesToOpenDelayed, ICore::SwitchMode);
460     m_filesToOpenDelayed.clear();
461 }
462
463 IContext *MainWindow::currentContextObject() const
464 {
465     return m_activeContext;
466 }
467
468 QStatusBar *MainWindow::statusBar() const
469 {
470     return m_modeStack->statusBar();
471 }
472
473 void MainWindow::registerDefaultContainers()
474 {
475     ActionManagerPrivate *am = m_actionManager;
476
477     ActionContainer *menubar = am->createMenuBar(Constants::MENU_BAR);
478
479 #ifndef Q_OS_MAC // System menu bar on Mac
480     setMenuBar(menubar->menuBar());
481 #endif
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);
488
489     // File Menu
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()));
501
502
503     // Edit Menu
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);
513
514     // Tools Menu
515     ActionContainer *ac = am->createMenu(Constants::M_TOOLS);
516     menubar->addMenu(ac, Constants::G_TOOLS);
517     ac->menu()->setTitle(tr("&Tools"));
518
519     // Window Menu
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);
529
530     // Help Menu
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);
536 }
537
538 static Command *createSeparator(ActionManager *am, QObject *parent,
539                                 const Id &id, const Context &context)
540 {
541     QAction *tmpaction = new QAction(parent);
542     tmpaction->setSeparator(true);
543     Command *cmd = am->registerAction(tmpaction, id, context);
544     return cmd;
545 }
546
547 void MainWindow::registerDefaultActions()
548 {
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);
555
556     Context globalContext(Constants::C_GLOBAL);
557
558     // File menu separators
559     Command *cmd = createSeparator(am, this, Id("QtCreator.File.Sep.Save"), globalContext);
560     mfile->addAction(cmd, Constants::G_FILE_SAVE);
561
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);
565
566     cmd =  createSeparator(am, this, Id("QtCreator.File.Sep.Close"), globalContext);
567     mfile->addAction(cmd, Constants::G_FILE_CLOSE);
568
569     cmd = createSeparator(am, this, Id("QtCreator.File.Sep.Other"), globalContext);
570     mfile->addAction(cmd, Constants::G_FILE_OTHER);
571
572     // Edit menu separators
573     cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.CopyPaste"), globalContext);
574     medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
575
576     cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.SelectAll"), globalContext);
577     medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
578
579     cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.Find"), globalContext);
580     medit->addAction(cmd, Constants::G_EDIT_FIND);
581
582     cmd = createSeparator(am, this, Id("QtCreator.Edit.Sep.Advanced"), globalContext);
583     medit->addAction(cmd, Constants::G_EDIT_ADVANCED);
584
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()));
591
592     // New File Action
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()));
599
600     // Open Action
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()));
607
608     // Open With Action
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()));
613
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);
619
620     // Save Action
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);
629
630     // Save As Action
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);
635 #ifdef Q_OS_MAC
636     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
637 #endif
638     cmd->setAttribute(Command::CA_UpdateText);
639     cmd->setDescription(tr("Save As..."));
640     mfile->addAction(cmd, Constants::G_FILE_SAVE);
641
642     // SaveAll Action
643     m_saveAllAction = new QAction(tr("Save A&ll"), this);
644     cmd = am->registerAction(m_saveAllAction, Constants::SAVEALL, globalContext);
645 #ifndef Q_OS_MAC
646     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
647 #endif
648     mfile->addAction(cmd, Constants::G_FILE_SAVE);
649     connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll()));
650
651     // Print Action
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);
658
659     // Exit Action
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()));
666
667     // Undo Action
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);
676
677     // Redo Action
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);
686
687     // Cut Action
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);
694
695     // Copy Action
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);
702
703     // Paste Action
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);
710
711     // Select All
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);
718
719     // Goto Action
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);
726
727     // Options Action
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);
733 #ifdef Q_OS_MAC
734     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+,")));
735     cmd->action()->setMenuRole(QAction::PreferencesRole);
736 #endif
737     mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
738     connect(m_optionsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog()));
739
740 #ifdef Q_OS_MAC
741     // Minimize Action
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()));
747
748     // Zoom Action
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()));
753
754     // Window separator
755     cmd = createSeparator(am, this, Id("QtCreator.Window.Sep.Size"), globalContext);
756     mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
757 #endif
758
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);
765 #ifdef Q_OS_MAC
766     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+0")));
767 #else
768     cmd->setDefaultKeySequence(QKeySequence(tr("Alt+0")));
769 #endif
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);
774
775 #ifndef Q_OS_MAC
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)));
783 #endif
784
785     // Window->Views
786     ActionContainer *mviews = am->createMenu(Constants::M_WINDOW_VIEWS);
787     mwindow->addMenu(mviews, Constants::G_WINDOW_VIEWS);
788     mviews->menu()->setTitle(tr("&Views"));
789
790     // About IDE Action
791     icon = QIcon::fromTheme(QLatin1String("help-about"));
792 #ifdef Q_OS_MAC
793     tmpaction = new QAction(icon, tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
794 #else
795     tmpaction = new QAction(icon, tr("About &Qt Creator..."), this);
796 #endif
797     cmd = am->registerAction(tmpaction, Constants::ABOUT_QTCREATOR, globalContext);
798     mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
799     tmpaction->setEnabled(true);
800 #ifdef Q_OS_MAC
801     cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
802 #endif
803     connect(tmpaction, SIGNAL(triggered()), this,  SLOT(aboutQtCreator()));
804
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);
810 #ifdef Q_OS_MAC
811     cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
812 #endif
813     connect(tmpaction, SIGNAL(triggered()), this,  SLOT(aboutPlugins()));
814     // About Qt Action
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()));
820     // About sep
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);
826 #endif
827 }
828
829 void MainWindow::newFile()
830 {
831     showNewItemDialog(tr("New", "Title of dialog"), IWizard::allWizards(), QString());
832 }
833
834 void MainWindow::openFile()
835 {
836     openFiles(editorManager()->getOpenFileNames(), ICore::SwitchMode);
837 }
838
839 static QList<IDocumentFactory*> getNonEditorDocumentFactories()
840 {
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);
847     }
848     return nonEditorFileFactories;
849 }
850
851 static IDocumentFactory *findDocumentFactory(const QList<IDocumentFactory*> &fileFactories,
852                                      const MimeDatabase *db,
853                                      const QFileInfo &fi)
854 {
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))
859                 return factory;
860         }
861     }
862     return 0;
863 }
864
865 // opens either an editor or loads a project
866 void MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags)
867 {
868     QList<IDocumentFactory*> nonEditorFileFactories = getNonEditorDocumentFactories();
869
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))
876                 return;
877             if (document && (flags & ICore::SwitchMode))
878                 ModeManager::activateMode(QLatin1String(Core::Constants::MODE_EDIT));
879         } else {
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))
887                 return;
888         }
889     }
890 }
891
892 void MainWindow::setFocusToEditor()
893 {
894     bool focusWasMovedToEditor = false;
895
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();
900             if (!w)
901                 w = editor->widget();
902             w->setFocus();
903             focusWasMovedToEditor = w->hasFocus();
904         }
905     }
906
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();
912         return;
913     }
914
915     if (focusWasMovedToEditor)
916         return;
917
918     // check for some visible bar which we want to hide
919     bool stuffVisible =
920             (FindToolBarPlaceHolder::getCurrent() &&
921              FindToolBarPlaceHolder::getCurrent()->isVisible())
922             || (OutputPanePlaceHolder::getCurrent() &&
923                 OutputPanePlaceHolder::getCurrent()->isVisible())
924             || (RightPanePlaceHolder::current() &&
925                 RightPanePlaceHolder::current()->isVisible());
926     if (stuffVisible) {
927         if (FindToolBarPlaceHolder::getCurrent())
928             FindToolBarPlaceHolder::getCurrent()->hide();
929         OutputPaneManager::instance()->slotHide();
930         RightPaneWidget::instance()->setShown(false);
931         return;
932     }
933
934     // switch to edit mode if necessary
935     ModeManager::activateMode(QLatin1String(Constants::MODE_EDIT));
936 }
937
938 void MainWindow::showNewItemDialog(const QString &title,
939                                           const QList<IWizard *> &wizards,
940                                           const QString &defaultLocation,
941                                           const QVariantMap &extraVariables)
942 {
943     // Scan for wizards matching the filter and pick one. Don't show
944     // dialog if there is only one.
945     IWizard *wizard = 0;
946     QString selectedPlatform;
947     switch (wizards.size()) {
948     case 0:
949         break;
950     case 1:
951         wizard = wizards.front();
952         break;
953     default: {
954         NewDialog dlg(this);
955         dlg.setWizards(wizards);
956         dlg.setWindowTitle(title);
957         wizard = dlg.showDialog();
958         selectedPlatform = dlg.selectedPlatform();
959     }
960         break;
961     }
962
963     if (!wizard)
964         return;
965
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
972             // at current.
973             path = DocumentManager::useProjectsDirectory() ?
974                        DocumentManager::projectsDirectory() :
975                        DocumentManager::fileDialogLastVisitedDirectory();
976             break;
977         default:
978             path = DocumentManager::fileDialogInitialDirectory();
979             break;
980         }
981     }
982     wizard->runWizard(path, this, selectedPlatform, extraVariables);
983 }
984
985 bool MainWindow::showOptionsDialog(const QString &category,
986                                    const QString &page,
987                                    QWidget *parent)
988 {
989     emit m_coreImpl->optionsDialogRequested();
990     if (!parent)
991         parent = this;
992     SettingsDialog *dialog = SettingsDialog::getSettingsDialog(parent, category, page);
993     return dialog->execDialog();
994 }
995
996 void MainWindow::saveAll()
997 {
998     DocumentManager::saveModifiedDocumentsSilently(DocumentManager::modifiedDocuments());
999     emit m_coreImpl->saveSettingsRequested();
1000 }
1001
1002 void MainWindow::exit()
1003 {
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
1008     // just append it
1009     QTimer::singleShot(0, this,  SLOT(close()));
1010 }
1011
1012 void MainWindow::openFileWith()
1013 {
1014     QStringList fileNames = editorManager()->getOpenFileNames();
1015     foreach (const QString &fileName, fileNames) {
1016         bool isExternal;
1017         const Id editorId = editorManager()->getOpenWithEditorId(fileName, &isExternal);
1018         if (!editorId.isValid())
1019             continue;
1020         if (isExternal) {
1021             editorManager()->openExternalEditor(fileName, editorId);
1022         } else {
1023             editorManager()->openEditor(fileName, editorId, Core::EditorManager::ModeSwitch);
1024         }
1025     }
1026 }
1027
1028 ActionManager *MainWindow::actionManager() const
1029 {
1030     return m_actionManager;
1031 }
1032
1033 MessageManager *MainWindow::messageManager() const
1034 {
1035     return m_messageManager;
1036 }
1037
1038 VcsManager *MainWindow::vcsManager() const
1039 {
1040     return m_vcsManager;
1041 }
1042
1043 QSettings *MainWindow::settings(QSettings::Scope scope) const
1044 {
1045     if (scope == QSettings::UserScope)
1046         return m_settings;
1047     else
1048         return m_globalSettings;
1049 }
1050
1051 EditorManager *MainWindow::editorManager() const
1052 {
1053     return m_editorManager;
1054 }
1055
1056 ProgressManager *MainWindow::progressManager() const
1057 {
1058     return m_progressManager;
1059 }
1060
1061 ScriptManager *MainWindow::scriptManager() const
1062 {
1063      return m_scriptManager;
1064 }
1065
1066 VariableManager *MainWindow::variableManager() const
1067 {
1068      return m_variableManager.data();
1069 }
1070
1071 ModeManager *MainWindow::modeManager() const
1072 {
1073     return m_modeManager;
1074 }
1075
1076 MimeDatabase *MainWindow::mimeDatabase() const
1077 {
1078     return m_mimeDatabase;
1079 }
1080
1081 HelpManager *MainWindow::helpManager() const
1082 {
1083     return m_helpManager;
1084 }
1085
1086 IContext *MainWindow::contextObject(QWidget *widget)
1087 {
1088     return m_contextWidgets.value(widget);
1089 }
1090
1091 void MainWindow::addContextObject(IContext *context)
1092 {
1093     if (!context)
1094         return;
1095     QWidget *widget = context->widget();
1096     if (m_contextWidgets.contains(widget))
1097         return;
1098
1099     m_contextWidgets.insert(widget, context);
1100 }
1101
1102 void MainWindow::removeContextObject(IContext *context)
1103 {
1104     if (!context)
1105         return;
1106
1107     QWidget *widget = context->widget();
1108     if (!m_contextWidgets.contains(widget))
1109         return;
1110
1111     m_contextWidgets.remove(widget);
1112     if (m_activeContext == context)
1113         updateContextObject(0);
1114 }
1115
1116 void MainWindow::changeEvent(QEvent *e)
1117 {
1118     QMainWindow::changeEvent(e);
1119     if (e->type() == QEvent::ActivationChange) {
1120         if (isActiveWindow()) {
1121             if (debugMainWindow)
1122                 qDebug() << "main window activated";
1123             emit windowActivated();
1124         }
1125     } else if (e->type() == QEvent::WindowStateChange) {
1126 #ifdef Q_OS_MAC
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);
1132 #else
1133         bool isFullScreen = (windowState() & Qt::WindowFullScreen) != 0;
1134         m_toggleFullScreenAction->setChecked(isFullScreen);
1135 #endif
1136     }
1137 }
1138
1139 void MainWindow::updateFocusWidget(QWidget *old, QWidget *now)
1140 {
1141     Q_UNUSED(old)
1142
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))
1145         return;
1146
1147     IContext *newContext = 0;
1148     if (focusWidget()) {
1149         IContext *context = 0;
1150         QWidget *p = focusWidget();
1151         while (p) {
1152             context = m_contextWidgets.value(p);
1153             if (context) {
1154                 newContext = context;
1155                 break;
1156             }
1157             p = p->parentWidget();
1158         }
1159     }
1160     updateContextObject(newContext);
1161 }
1162
1163 void MainWindow::updateContextObject(IContext *context)
1164 {
1165     if (context == m_activeContext)
1166         return;
1167     emit m_coreImpl->contextAboutToChange(context);
1168     m_activeContext = context;
1169     updateContext();
1170     if (debugMainWindow)
1171         qDebug() << "new context object =" << context << (context ? context->widget() : 0)
1172                  << (context ? context->widget()->metaObject()->className() : 0);
1173 }
1174
1175 void MainWindow::resetContext()
1176 {
1177     updateContextObject(0);
1178 }
1179
1180 void MainWindow::aboutToShutdown()
1181 {
1182     disconnect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
1183                this, SLOT(updateFocusWidget(QWidget*,QWidget*)));
1184     m_activeContext = 0;
1185     hide();
1186 }
1187
1188 static const char settingsGroup[] = "MainWindow";
1189 static const char colorKey[] = "Color";
1190 static const char windowGeometryKey[] = "WindowGeometry";
1191 static const char windowStateKey[] = "WindowState";
1192
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";
1197
1198 void MainWindow::readSettings()
1199 {
1200     m_settings->beginGroup(QLatin1String(settingsGroup));
1201
1202     if (m_overrideColor.isValid()) {
1203         Utils::StyleHelper::setBaseColor(m_overrideColor);
1204         // Get adapted base color.
1205         m_overrideColor = Utils::StyleHelper::baseColor();
1206     } else {
1207         Utils::StyleHelper::setBaseColor(
1208                 m_settings->value(QLatin1String(colorKey),
1209                                   QColor(Utils::StyleHelper::DEFAULT_BASE_COLOR)).value<QColor>());
1210     }
1211
1212     if (!restoreGeometry(m_settings->value(QLatin1String(windowGeometryKey)).toByteArray())) {
1213         resize(1008, 700); // size without window decoration
1214     }
1215     restoreState(m_settings->value(QLatin1String(windowStateKey)).toByteArray());
1216
1217     m_settings->endGroup();
1218
1219     m_editorManager->readSettings();
1220     m_navigationWidget->restoreSettings(m_settings);
1221     m_rightPaneWidget->readSettings(m_settings);
1222 }
1223
1224 void MainWindow::writeSettings()
1225 {
1226     m_settings->beginGroup(QLatin1String(settingsGroup));
1227
1228     if (!(m_overrideColor.isValid() && Utils::StyleHelper::baseColor() == m_overrideColor))
1229         m_settings->setValue(QLatin1String(colorKey), Utils::StyleHelper::requestedBaseColor());
1230
1231     m_settings->setValue(QLatin1String(windowGeometryKey), saveGeometry());
1232     m_settings->setValue(QLatin1String(windowStateKey), saveState());
1233
1234     m_settings->endGroup();
1235
1236     DocumentManager::saveSettings();
1237     m_actionManager->saveSettings(m_settings);
1238     m_editorManager->saveSettings();
1239     m_navigationWidget->saveSettings(m_settings);
1240 }
1241
1242 void MainWindow::updateAdditionalContexts(const Context &remove, const Context &add)
1243 {
1244     foreach (const int context, remove) {
1245         if (context == 0)
1246             continue;
1247
1248         int index = m_additionalContexts.indexOf(context);
1249         if (index != -1)
1250             m_additionalContexts.removeAt(index);
1251     }
1252
1253     foreach (const int context, add) {
1254         if (context == 0)
1255             continue;
1256
1257         if (!m_additionalContexts.contains(context))
1258             m_additionalContexts.prepend(context);
1259     }
1260
1261     updateContext();
1262 }
1263
1264 bool MainWindow::hasContext(int context) const
1265 {
1266     return m_actionManager->hasContext(context);
1267 }
1268
1269 void MainWindow::updateContext()
1270 {
1271     Context contexts;
1272
1273     if (m_activeContext)
1274         contexts.add(m_activeContext->context());
1275
1276     contexts.add(m_additionalContexts);
1277
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);
1283     }
1284
1285     m_actionManager->setContext(uniquecontexts);
1286     emit m_coreImpl->contextChanged(m_activeContext, m_additionalContexts);
1287 }
1288
1289 void MainWindow::aboutToShowRecentFiles()
1290 {
1291     ActionContainer *aci =
1292         m_actionManager->actionContainer(Constants::M_FILE_RECENTFILES);
1293     aci->menu()->clear();
1294
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()));
1302     }
1303     aci->menu()->setEnabled(hasRecentFiles);
1304
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()));
1311     }
1312 }
1313
1314 void MainWindow::openRecentFile()
1315 {
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);
1319     }
1320 }
1321
1322 void MainWindow::aboutQtCreator()
1323 {
1324     if (!m_versionDialog) {
1325         m_versionDialog = new VersionDialog(this);
1326         connect(m_versionDialog, SIGNAL(finished(int)),
1327                 this, SLOT(destroyVersionDialog()));
1328     }
1329     m_versionDialog->show();
1330 }
1331
1332 void MainWindow::destroyVersionDialog()
1333 {
1334     if (m_versionDialog) {
1335         m_versionDialog->deleteLater();
1336         m_versionDialog = 0;
1337     }
1338 }
1339
1340 void MainWindow::aboutPlugins()
1341 {
1342     PluginDialog dialog(this);
1343     dialog.exec();
1344 }
1345
1346 QPrinter *MainWindow::printer() const
1347 {
1348     if (!m_printer)
1349         m_printer = new QPrinter(QPrinter::HighResolution);
1350     return m_printer;
1351 }
1352
1353 void MainWindow::setFullScreen(bool on)
1354 {
1355     if (bool(windowState() & Qt::WindowFullScreen) == on)
1356         return;
1357
1358     if (on) {
1359         setWindowState(windowState() | Qt::WindowFullScreen);
1360         //statusBar()->hide();
1361         //menuBar()->hide();
1362     } else {
1363         setWindowState(windowState() & ~Qt::WindowFullScreen);
1364         //menuBar()->show();
1365         //statusBar()->show();
1366     }
1367 }
1368
1369 // Display a warning with an additional button to open
1370 // the debugger settings dialog if settingsId is nonempty.
1371
1372 bool MainWindow::showWarningWithOptions(const QString &title,
1373                                         const QString &text,
1374                                         const QString &details,
1375                                         const QString &settingsCategory,
1376                                         const QString &settingsId,
1377                                         QWidget *parent)
1378 {
1379     if (parent == 0)
1380         parent = this;
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);
1388     msgBox.exec();
1389     if (settingsButton && msgBox.clickedButton() == settingsButton) {
1390         return showOptionsDialog(settingsCategory, settingsId);
1391     }
1392     return false;
1393 }