OSDN Git Service

Work around wrong click area of output buttons on Mac.
[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) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
30 **
31 **************************************************************************/
32
33 #include "mainwindow.h"
34 #include "actioncontainer.h"
35 #include "command.h"
36 #include "actionmanager_p.h"
37 #include "coreimpl.h"
38 #include "coreconstants.h"
39 #include "editormanager.h"
40 #include "externaltool.h"
41 #include "toolsettings.h"
42 #include "mimetypesettings.h"
43 #include "fancytabwidget.h"
44 #include "filemanager.h"
45 #include "generalsettings.h"
46 #include "helpmanager.h"
47 #include "ieditor.h"
48 #include "ifilefactory.h"
49 #include "messagemanager.h"
50 #include "modemanager.h"
51 #include "mimedatabase.h"
52 #include "newdialog.h"
53 #include "outputpanemanager.h"
54 #include "outputpane.h"
55 #include "plugindialog.h"
56 #include "progressmanager_p.h"
57 #include "progressview.h"
58 #include "shortcutsettings.h"
59 #include "vcsmanager.h"
60 #include "variablechooser.h"
61
62 #include "scriptmanager_p.h"
63 #include "settingsdialog.h"
64 #include "variablemanager.h"
65 #include "versiondialog.h"
66 #include "statusbarmanager.h"
67 #include "uniqueidmanager.h"
68 #include "manhattanstyle.h"
69 #include "navigationwidget.h"
70 #include "rightpane.h"
71 #include "editormanager/ieditorfactory.h"
72 #include "statusbarwidget.h"
73 #include "basefilewizard.h"
74 #include "ioutputpane.h"
75 #include "editormanager/systemeditor.h"
76
77 #include <coreplugin/findplaceholder.h>
78 #include <coreplugin/icorelistener.h>
79 #include <coreplugin/inavigationwidgetfactory.h>
80 #include <coreplugin/settingsdatabase.h>
81 #include <utils/pathchooser.h>
82 #include <utils/stylehelper.h>
83 #include <utils/stringutils.h>
84 #include <extensionsystem/pluginmanager.h>
85
86 #include <QtCore/QDebug>
87 #include <QtCore/QFileInfo>
88 #include <QtCore/QSettings>
89 #include <QtCore/QTimer>
90 #include <QtCore/QtPlugin>
91 #include <QtCore/QUrl>
92 #include <QtCore/QDir>
93 #include <QtCore/QFile>
94
95 #include <QtGui/QApplication>
96 #include <QtGui/QCloseEvent>
97 #include <QtGui/QMenu>
98 #include <QtGui/QPixmap>
99 #include <QtGui/QPrinter>
100 #include <QtGui/QShortcut>
101 #include <QtGui/QStatusBar>
102 #include <QtGui/QWizard>
103 #include <QtGui/QToolButton>
104 #include <QtGui/QMessageBox>
105 #include <QtGui/QMenuBar>
106 #include <QtGui/QPushButton>
107
108 /*
109 #ifdef Q_OS_UNIX
110 #include <signal.h>
111 extern "C" void handleSigInt(int sig)
112 {
113     Q_UNUSED(sig)
114     Core::ICore::instance()->exit();
115     qDebug() << "SIGINT caught. Shutting down.";
116 }
117 #endif
118 */
119
120 using namespace Core;
121 using namespace Core::Internal;
122
123 enum { debugMainWindow = 0 };
124
125 MainWindow::MainWindow() :
126     EventFilteringMainWindow(),
127     m_coreImpl(new CoreImpl(this)),
128     m_uniqueIDManager(new UniqueIDManager()),
129     m_additionalContexts(Constants::C_GLOBAL),
130     m_settings(ExtensionSystem::PluginManager::instance()->settings()),
131     m_globalSettings(new QSettings(QSettings::IniFormat, QSettings::SystemScope,
132                              QLatin1String("Nokia"), QLatin1String("QtCreator"), this)),
133     m_settingsDatabase(new SettingsDatabase(QFileInfo(m_settings->fileName()).path(),
134                                             QLatin1String("QtCreator"),
135                                             this)),
136     m_printer(0),
137     m_actionManager(new ActionManagerPrivate(this)),
138     m_editorManager(0),
139     m_externalToolManager(0),
140     m_fileManager(new FileManager(this)),
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_WS_MAC
168     m_minimizeAction(0),
169     m_zoomAction(0),
170 #endif
171     m_toggleSideBarButton(new QToolButton)
172 {
173     OutputPaneManager::create();
174
175     setWindowTitle(tr("Qt Creator"));
176 #ifndef Q_WS_MAC
177     QApplication::setWindowIcon(QIcon(QLatin1String(Constants::ICON_QTLOGO_128)));
178 #endif
179     QCoreApplication::setApplicationName(QLatin1String("QtCreator"));
180     QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));
181     QCoreApplication::setOrganizationName(QLatin1String("Nokia"));
182     QSettings::setDefaultFormat(QSettings::IniFormat);
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(m_coreImpl, this);
214     m_editorManager->hide();
215     m_externalToolManager = new ExternalToolManager(m_coreImpl);
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 MainWindow::~MainWindow()
256 {
257     ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
258     pm->removeObject(m_shortcutSettings);
259     pm->removeObject(m_generalSettings);
260     pm->removeObject(m_toolSettings);
261     pm->removeObject(m_mimeTypeSettings);
262     pm->removeObject(m_systemEditor);
263     delete m_externalToolManager;
264     m_externalToolManager = 0;
265     delete m_messageManager;
266     m_messageManager = 0;
267     delete m_shortcutSettings;
268     m_shortcutSettings = 0;
269     delete m_generalSettings;
270     m_generalSettings = 0;
271     delete m_toolSettings;
272     m_toolSettings = 0;
273     delete m_mimeTypeSettings;
274     m_mimeTypeSettings = 0;
275     delete m_systemEditor;
276     m_systemEditor = 0;
277     delete m_settings;
278     m_settings = 0;
279     delete m_printer;
280     m_printer = 0;
281     delete m_uniqueIDManager;
282     m_uniqueIDManager = 0;
283     delete m_vcsManager;
284     m_vcsManager = 0;
285     //we need to delete editormanager and statusbarmanager explicitly before the end of the destructor,
286     //because they might trigger stuff that tries to access data from editorwindow, like removeContextWidget
287
288     // All modes are now gone
289     OutputPaneManager::destroy();
290
291     // Now that the OutputPaneManager is gone, is a good time to delete the view
292     pm->removeObject(m_outputView);
293     delete m_outputView;
294
295     delete m_editorManager;
296     m_editorManager = 0;
297     delete m_statusBarManager;
298     m_statusBarManager = 0;
299     delete m_progressManager;
300     m_progressManager = 0;
301     pm->removeObject(m_coreImpl);
302     delete m_coreImpl;
303     m_coreImpl = 0;
304
305     delete m_rightPaneWidget;
306     m_rightPaneWidget = 0;
307
308     delete m_modeManager;
309     m_modeManager = 0;
310     delete m_mimeDatabase;
311     m_mimeDatabase = 0;
312
313     delete m_helpManager;
314     m_helpManager = 0;
315 }
316
317 bool MainWindow::init(QString *errorMessage)
318 {
319     Q_UNUSED(errorMessage)
320
321     if (!mimeDatabase()->addMimeTypes(QLatin1String(":/core/editormanager/BinFiles.mimetypes.xml"), errorMessage))
322         return false;
323
324     ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
325     pm->addObject(m_coreImpl);
326     m_statusBarManager->init();
327     m_modeManager->init();
328     m_progressManager->init();
329
330     pm->addObject(m_generalSettings);
331     pm->addObject(m_shortcutSettings);
332     pm->addObject(m_toolSettings);
333     pm->addObject(m_mimeTypeSettings);
334     pm->addObject(m_systemEditor);
335
336     // Add widget to the bottom, we create the view here instead of inside the
337     // OutputPaneManager, since the StatusBarManager needs to be initialized before
338     m_outputView = new Core::StatusBarWidget;
339     m_outputView->setWidget(OutputPaneManager::instance()->buttonsWidget());
340     m_outputView->setPosition(Core::StatusBarWidget::Second);
341     pm->addObject(m_outputView);
342     m_messageManager->init();
343     return true;
344 }
345
346 void MainWindow::extensionsInitialized()
347 {
348     m_editorManager->init();
349     m_statusBarManager->extensionsInitalized();
350     OutputPaneManager::instance()->init();
351     m_vcsManager->extensionsInitialized();
352     m_navigationWidget->setFactories(ExtensionSystem::PluginManager::instance()->getObjects<INavigationWidgetFactory>());
353
354     // reading the shortcut settings must be done after all shortcuts have been registered
355     m_actionManager->initialize();
356
357     readSettings();
358     updateContext();
359
360     emit m_coreImpl->coreAboutToOpen();
361     show();
362     emit m_coreImpl->coreOpened();
363 }
364
365 void MainWindow::closeEvent(QCloseEvent *event)
366 {
367     emit m_coreImpl->saveSettingsRequested();
368
369     // Save opened files
370     bool cancelled;
371     QList<IFile*> notSaved = fileManager()->saveModifiedFiles(fileManager()->modifiedFiles(), &cancelled);
372     if (cancelled || !notSaved.isEmpty()) {
373         event->ignore();
374         return;
375     }
376
377     const QList<ICoreListener *> listeners =
378         ExtensionSystem::PluginManager::instance()->getObjects<ICoreListener>();
379     foreach (ICoreListener *listener, listeners) {
380         if (!listener->coreAboutToClose()) {
381             event->ignore();
382             return;
383         }
384     }
385
386     emit m_coreImpl->coreAboutToClose();
387
388     writeSettings();
389
390     m_navigationWidget->closeSubWidgets();
391
392     event->accept();
393 }
394
395 // Check for desktop file manager file drop events
396
397 static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
398 {
399     if (files)
400         files->clear();
401     // Extract dropped files from Mime data.
402     if (!d->hasUrls())
403         return false;
404     const QList<QUrl> urls = d->urls();
405     if (urls.empty())
406         return false;
407     // Try to find local files
408     bool hasFiles = false;
409     const QList<QUrl>::const_iterator cend = urls.constEnd();
410     for (QList<QUrl>::const_iterator it = urls.constBegin(); it != cend; ++it) {
411         const QString fileName = it->toLocalFile();
412         if (!fileName.isEmpty()) {
413             hasFiles = true;
414             if (files) {
415                 files->push_back(fileName);
416             } else {
417                 break; // No result list, sufficient for checking
418             }
419         }
420     }
421     return hasFiles;
422 }
423
424 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
425 {
426     if (isDesktopFileManagerDrop(event->mimeData()) && m_filesToOpenDelayed.isEmpty()) {
427         event->accept();
428     } else {
429         event->ignore();
430     }
431 }
432
433 void MainWindow::dropEvent(QDropEvent *event)
434 {
435     QStringList files;
436     if (isDesktopFileManagerDrop(event->mimeData(), &files)) {
437         event->accept();
438         m_filesToOpenDelayed.append(files);
439         QTimer::singleShot(50, this, SLOT(openDelayedFiles()));
440     } else {
441         event->ignore();
442     }
443 }
444
445 void MainWindow::openDelayedFiles()
446 {
447     if (m_filesToOpenDelayed.isEmpty())
448         return;
449     activateWindow();
450     raise();
451     openFiles(m_filesToOpenDelayed, ICore::SwitchMode);
452     m_filesToOpenDelayed.clear();
453 }
454
455 IContext *MainWindow::currentContextObject() const
456 {
457     return m_activeContext;
458 }
459
460 QStatusBar *MainWindow::statusBar() const
461 {
462     return m_modeStack->statusBar();
463 }
464
465 void MainWindow::registerDefaultContainers()
466 {
467     ActionManagerPrivate *am = m_actionManager;
468
469     ActionContainer *menubar = am->createMenuBar(Constants::MENU_BAR);
470
471 #ifndef Q_WS_MAC // System menu bar on Mac
472     setMenuBar(menubar->menuBar());
473 #endif
474     menubar->appendGroup(Constants::G_FILE);
475     menubar->appendGroup(Constants::G_EDIT);
476     menubar->appendGroup(Constants::G_VIEW);
477     menubar->appendGroup(Constants::G_TOOLS);
478     menubar->appendGroup(Constants::G_WINDOW);
479     menubar->appendGroup(Constants::G_HELP);
480
481     // File Menu
482     ActionContainer *filemenu = am->createMenu(Constants::M_FILE);
483     menubar->addMenu(filemenu, Constants::G_FILE);
484     filemenu->menu()->setTitle(tr("&File"));
485     filemenu->appendGroup(Constants::G_FILE_NEW);
486     filemenu->appendGroup(Constants::G_FILE_OPEN);
487     filemenu->appendGroup(Constants::G_FILE_PROJECT);
488     filemenu->appendGroup(Constants::G_FILE_SAVE);
489     filemenu->appendGroup(Constants::G_FILE_CLOSE);
490     filemenu->appendGroup(Constants::G_FILE_PRINT);
491     filemenu->appendGroup(Constants::G_FILE_OTHER);
492     connect(filemenu->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowRecentFiles()));
493
494
495     // Edit Menu
496     ActionContainer *medit = am->createMenu(Constants::M_EDIT);
497     menubar->addMenu(medit, Constants::G_EDIT);
498     medit->menu()->setTitle(tr("&Edit"));
499     medit->appendGroup(Constants::G_EDIT_UNDOREDO);
500     medit->appendGroup(Constants::G_EDIT_COPYPASTE);
501     medit->appendGroup(Constants::G_EDIT_SELECTALL);
502     medit->appendGroup(Constants::G_EDIT_ADVANCED);
503     medit->appendGroup(Constants::G_EDIT_FIND);
504     medit->appendGroup(Constants::G_EDIT_OTHER);
505
506     // Tools Menu
507     ActionContainer *ac = am->createMenu(Constants::M_TOOLS);
508     menubar->addMenu(ac, Constants::G_TOOLS);
509     ac->menu()->setTitle(tr("&Tools"));
510
511     // Window Menu
512     ActionContainer *mwindow = am->createMenu(Constants::M_WINDOW);
513     menubar->addMenu(mwindow, Constants::G_WINDOW);
514     mwindow->menu()->setTitle(tr("&Window"));
515     mwindow->appendGroup(Constants::G_WINDOW_SIZE);
516     mwindow->appendGroup(Constants::G_WINDOW_VIEWS);
517     mwindow->appendGroup(Constants::G_WINDOW_PANES);
518     mwindow->appendGroup(Constants::G_WINDOW_SPLIT);
519     mwindow->appendGroup(Constants::G_WINDOW_NAVIGATE);
520     mwindow->appendGroup(Constants::G_WINDOW_OTHER);
521
522     // Help Menu
523     ac = am->createMenu(Constants::M_HELP);
524     menubar->addMenu(ac, Constants::G_HELP);
525     ac->menu()->setTitle(tr("&Help"));
526     ac->appendGroup(Constants::G_HELP_HELP);
527     ac->appendGroup(Constants::G_HELP_ABOUT);
528 }
529
530 static Command *createSeparator(ActionManager *am, QObject *parent,
531                                 const QString &name,
532                                 const Context &context)
533 {
534     QAction *tmpaction = new QAction(parent);
535     tmpaction->setSeparator(true);
536     Command *cmd = am->registerAction(tmpaction, name, context);
537     return cmd;
538 }
539
540 void MainWindow::registerDefaultActions()
541 {
542     ActionManagerPrivate *am = m_actionManager;
543     ActionContainer *mfile = am->actionContainer(Constants::M_FILE);
544     ActionContainer *medit = am->actionContainer(Constants::M_EDIT);
545     ActionContainer *mtools = am->actionContainer(Constants::M_TOOLS);
546     ActionContainer *mwindow = am->actionContainer(Constants::M_WINDOW);
547     ActionContainer *mhelp = am->actionContainer(Constants::M_HELP);
548
549     Context globalContext(Constants::C_GLOBAL);
550
551     // File menu separators
552     Command *cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Save"), globalContext);
553     mfile->addAction(cmd, Constants::G_FILE_SAVE);
554
555     cmd =  createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Print"), globalContext);
556     QIcon icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(Constants::ICON_CUT));
557     mfile->addAction(cmd, Constants::G_FILE_PRINT);
558
559     cmd =  createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Close"), globalContext);
560     mfile->addAction(cmd, Constants::G_FILE_CLOSE);
561
562     cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Other"), globalContext);
563     mfile->addAction(cmd, Constants::G_FILE_OTHER);
564
565     // Edit menu separators
566     cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.CopyPaste"), globalContext);
567     medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
568
569     cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.SelectAll"), globalContext);
570     medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
571
572     cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Find"), globalContext);
573     medit->addAction(cmd, Constants::G_EDIT_FIND);
574
575     cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Advanced"), globalContext);
576     medit->addAction(cmd, Constants::G_EDIT_ADVANCED);
577
578     // Return to editor shortcut: Note this requires Qt to fix up
579     // handling of shortcut overrides in menus, item views, combos....
580     m_focusToEditor = new QShortcut(this);
581     cmd = am->registerShortcut(m_focusToEditor, Constants::S_RETURNTOEDITOR, globalContext);
582     cmd->setDefaultKeySequence(QKeySequence(Qt::Key_Escape));
583     connect(m_focusToEditor, SIGNAL(activated()), this, SLOT(setFocusToEditor()));
584
585     // New File Action
586     icon = QIcon::fromTheme(QLatin1String("document-new"), QIcon(Constants::ICON_NEWFILE));
587     m_newAction = new QAction(icon, tr("&New File or Project..."), this);
588     cmd = am->registerAction(m_newAction, Constants::NEW, globalContext);
589     cmd->setDefaultKeySequence(QKeySequence::New);
590     mfile->addAction(cmd, Constants::G_FILE_NEW);
591     connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile()));
592
593     // Open Action
594     icon = QIcon::fromTheme(QLatin1String("document-open"), QIcon(Constants::ICON_OPENFILE));
595     m_openAction = new QAction(icon, tr("&Open File or Project..."), this);
596     cmd = am->registerAction(m_openAction, Constants::OPEN, globalContext);
597     cmd->setDefaultKeySequence(QKeySequence::Open);
598     mfile->addAction(cmd, Constants::G_FILE_OPEN);
599     connect(m_openAction, SIGNAL(triggered()), this, SLOT(openFile()));
600
601     // Open With Action
602     m_openWithAction = new QAction(tr("Open File &With..."), this);
603     cmd = am->registerAction(m_openWithAction, Constants::OPEN_WITH, globalContext);
604     mfile->addAction(cmd, Constants::G_FILE_OPEN);
605     connect(m_openWithAction, SIGNAL(triggered()), this, SLOT(openFileWith()));
606
607     // File->Recent Files Menu
608     ActionContainer *ac = am->createMenu(Constants::M_FILE_RECENTFILES);
609     mfile->addMenu(ac, Constants::G_FILE_OPEN);
610     ac->menu()->setTitle(tr("Recent &Files"));
611     ac->setOnAllDisabledBehavior(ActionContainer::Show);
612
613     // Save Action
614     icon = QIcon::fromTheme(QLatin1String("document-save"), QIcon(Constants::ICON_SAVEFILE));
615     QAction *tmpaction = new QAction(icon, tr("&Save"), this);
616     tmpaction->setEnabled(false);
617     cmd = am->registerAction(tmpaction, Constants::SAVE, globalContext);
618     cmd->setDefaultKeySequence(QKeySequence::Save);
619     cmd->setAttribute(Command::CA_UpdateText);
620     cmd->setDefaultText(tr("&Save"));
621     mfile->addAction(cmd, Constants::G_FILE_SAVE);
622
623     // Save As Action
624     icon = QIcon::fromTheme(QLatin1String("document-save-as"));
625     tmpaction = new QAction(icon, tr("Save &As..."), this);
626     tmpaction->setEnabled(false);
627     cmd = am->registerAction(tmpaction, Constants::SAVEAS, globalContext);
628 #ifdef Q_WS_MAC
629     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
630 #endif
631     cmd->setAttribute(Command::CA_UpdateText);
632     cmd->setDefaultText(tr("Save &As..."));
633     mfile->addAction(cmd, Constants::G_FILE_SAVE);
634
635     // SaveAll Action
636     m_saveAllAction = new QAction(tr("Save A&ll"), this);
637     cmd = am->registerAction(m_saveAllAction, Constants::SAVEALL, globalContext);
638 #ifndef Q_WS_MAC
639     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
640 #endif
641     mfile->addAction(cmd, Constants::G_FILE_SAVE);
642     connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll()));
643
644     // Print Action
645     icon = QIcon::fromTheme(QLatin1String("document-print"));
646     tmpaction = new QAction(icon, tr("&Print..."), this);
647     tmpaction->setEnabled(false);
648     cmd = am->registerAction(tmpaction, Constants::PRINT, globalContext);
649     cmd->setDefaultKeySequence(QKeySequence::Print);
650     mfile->addAction(cmd, Constants::G_FILE_PRINT);
651
652     // Exit Action
653     icon = QIcon::fromTheme(QLatin1String("application-exit"));
654     m_exitAction = new QAction(icon, tr("E&xit"), this);
655     cmd = am->registerAction(m_exitAction, Constants::EXIT, globalContext);
656     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Q")));
657     mfile->addAction(cmd, Constants::G_FILE_OTHER);
658     connect(m_exitAction, SIGNAL(triggered()), this, SLOT(exit()));
659
660     // Undo Action
661     icon = QIcon::fromTheme(QLatin1String("edit-undo"), QIcon(Constants::ICON_UNDO));
662     tmpaction = new QAction(icon, tr("&Undo"), this);
663     cmd = am->registerAction(tmpaction, Constants::UNDO, globalContext);
664     cmd->setDefaultKeySequence(QKeySequence::Undo);
665     cmd->setAttribute(Command::CA_UpdateText);
666     cmd->setDefaultText(tr("&Undo"));
667     medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
668     tmpaction->setEnabled(false);
669
670     // Redo Action
671     icon = QIcon::fromTheme(QLatin1String("edit-redo"), QIcon(Constants::ICON_REDO));
672     tmpaction = new QAction(icon, tr("&Redo"), this);
673     cmd = am->registerAction(tmpaction, Constants::REDO, globalContext);
674     cmd->setDefaultKeySequence(QKeySequence::Redo);
675     cmd->setAttribute(Command::CA_UpdateText);
676     cmd->setDefaultText(tr("&Redo"));
677     medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
678     tmpaction->setEnabled(false);
679
680     // Cut Action
681     icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(Constants::ICON_CUT));
682     tmpaction = new QAction(icon, tr("Cu&t"), this);
683     cmd = am->registerAction(tmpaction, Constants::CUT, globalContext);
684     cmd->setDefaultKeySequence(QKeySequence::Cut);
685     medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
686     tmpaction->setEnabled(false);
687
688     // Copy Action
689     icon = QIcon::fromTheme(QLatin1String("edit-copy"), QIcon(Constants::ICON_COPY));
690     tmpaction = new QAction(icon, tr("&Copy"), this);
691     cmd = am->registerAction(tmpaction, Constants::COPY, globalContext);
692     cmd->setDefaultKeySequence(QKeySequence::Copy);
693     medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
694     tmpaction->setEnabled(false);
695
696     // Paste Action
697     icon = QIcon::fromTheme(QLatin1String("edit-paste"), QIcon(Constants::ICON_PASTE));
698     tmpaction = new QAction(icon, tr("&Paste"), this);
699     cmd = am->registerAction(tmpaction, Constants::PASTE, globalContext);
700     cmd->setDefaultKeySequence(QKeySequence::Paste);
701     medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
702     tmpaction->setEnabled(false);
703
704     // Select All
705     icon = QIcon::fromTheme(QLatin1String("edit-select-all"));
706     tmpaction = new QAction(icon, tr("Select &All"), this);
707     cmd = am->registerAction(tmpaction, Constants::SELECTALL, globalContext);
708     cmd->setDefaultKeySequence(QKeySequence::SelectAll);
709     medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
710     tmpaction->setEnabled(false);
711
712     // Goto Action
713     icon = QIcon::fromTheme(QLatin1String("go-jump"));
714     tmpaction = new QAction(icon, tr("&Go to Line..."), this);
715     cmd = am->registerAction(tmpaction, Constants::GOTO, globalContext);
716     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+L")));
717     medit->addAction(cmd, Constants::G_EDIT_OTHER);
718     tmpaction->setEnabled(false);
719
720     // Options Action
721     mtools->appendGroup(Constants::G_TOOLS_OPTIONS);
722     cmd = createSeparator(am, this, QLatin1String("QtCreator.Tools.Sep.Options"), globalContext);
723     mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
724     m_optionsAction = new QAction(tr("&Options..."), this);
725     cmd = am->registerAction(m_optionsAction, Constants::OPTIONS, globalContext);
726 #ifdef Q_WS_MAC
727     cmd->setDefaultKeySequence(QKeySequence("Ctrl+,"));
728     cmd->action()->setMenuRole(QAction::PreferencesRole);
729 #endif
730     mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
731     connect(m_optionsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog()));
732
733 #ifdef Q_WS_MAC
734     // Minimize Action
735     m_minimizeAction = new QAction(tr("Minimize"), this);
736     cmd = am->registerAction(m_minimizeAction, Constants::MINIMIZE_WINDOW, globalContext);
737     cmd->setDefaultKeySequence(QKeySequence("Ctrl+M"));
738     mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
739     connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(showMinimized()));
740
741     // Zoom Action
742     m_zoomAction = new QAction(tr("Zoom"), this);
743     cmd = am->registerAction(m_zoomAction, Constants::ZOOM_WINDOW, globalContext);
744     mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
745     connect(m_zoomAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
746
747     // Window separator
748     cmd = createSeparator(am, this, QLatin1String("QtCreator.Window.Sep.Size"), globalContext);
749     mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
750 #endif
751
752     // Show Sidebar Action
753     m_toggleSideBarAction = new QAction(QIcon(Constants::ICON_TOGGLE_SIDEBAR),
754                                         tr("Show Sidebar"), this);
755     m_toggleSideBarAction->setCheckable(true);
756     cmd = am->registerAction(m_toggleSideBarAction, Constants::TOGGLE_SIDEBAR, globalContext);
757     cmd->setAttribute(Command::CA_UpdateText);
758 #ifdef Q_WS_MAC
759     cmd->setDefaultKeySequence(QKeySequence("Ctrl+0"));
760 #else
761     cmd->setDefaultKeySequence(QKeySequence("Alt+0"));
762 #endif
763     connect(m_toggleSideBarAction, SIGNAL(triggered(bool)), this, SLOT(setSidebarVisible(bool)));
764     m_toggleSideBarButton->setDefaultAction(cmd->action());
765     mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS);
766     m_toggleSideBarAction->setEnabled(false);
767
768 #ifndef Q_WS_MAC
769     // Full Screen Action
770     m_toggleFullScreenAction = new QAction(tr("Full Screen"), this);
771     m_toggleFullScreenAction->setCheckable(true);
772     cmd = am->registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext);
773     cmd->setDefaultKeySequence(QKeySequence("Ctrl+Shift+F11"));
774     mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
775     connect(m_toggleFullScreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool)));
776 #endif
777
778     // Window->Views
779     ActionContainer *mviews = am->createMenu(Constants::M_WINDOW_VIEWS);
780     mwindow->addMenu(mviews, Constants::G_WINDOW_VIEWS);
781     mviews->menu()->setTitle(tr("&Views"));
782
783     // About IDE Action
784     icon = QIcon::fromTheme(QLatin1String("help-about"));
785 #ifdef Q_WS_MAC
786     tmpaction = new QAction(icon, tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
787 #else
788     tmpaction = new QAction(icon, tr("About &Qt Creator..."), this);
789 #endif
790     cmd = am->registerAction(tmpaction, Constants::ABOUT_QTCREATOR, globalContext);
791     mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
792     tmpaction->setEnabled(true);
793 #ifdef Q_WS_MAC
794     cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
795 #endif
796     connect(tmpaction, SIGNAL(triggered()), this,  SLOT(aboutQtCreator()));
797
798     //About Plugins Action
799     tmpaction = new QAction(tr("About &Plugins..."), this);
800     cmd = am->registerAction(tmpaction, Constants::ABOUT_PLUGINS, globalContext);
801     mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
802     tmpaction->setEnabled(true);
803 #ifdef Q_WS_MAC
804     cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
805 #endif
806     connect(tmpaction, SIGNAL(triggered()), this,  SLOT(aboutPlugins()));
807     // About Qt Action
808 //    tmpaction = new QAction(tr("About &Qt..."), this);
809 //    cmd = am->registerAction(tmpaction, Constants:: ABOUT_QT, globalContext);
810 //    mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
811 //    tmpaction->setEnabled(true);
812 //    connect(tmpaction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
813     // About sep
814 #ifndef Q_WS_MAC // doesn't have the "About" actions in the Help menu
815     tmpaction = new QAction(this);
816     tmpaction->setSeparator(true);
817     cmd = am->registerAction(tmpaction, "QtCreator.Help.Sep.About", globalContext);
818     mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
819 #endif
820 }
821
822 void MainWindow::newFile()
823 {
824     showNewItemDialog(tr("New", "Title of dialog"), IWizard::allWizards(), QString());
825 }
826
827 void MainWindow::openFile()
828 {
829     openFiles(editorManager()->getOpenFileNames(), ICore::SwitchMode);
830 }
831
832 static QList<IFileFactory*> getNonEditorFileFactories()
833 {
834     const QList<IFileFactory*> allFileFactories =
835         ExtensionSystem::PluginManager::instance()->getObjects<IFileFactory>();
836     QList<IFileFactory*> nonEditorFileFactories;
837     foreach (IFileFactory *factory, allFileFactories) {
838         if (!qobject_cast<IEditorFactory *>(factory))
839             nonEditorFileFactories.append(factory);
840     }
841     return nonEditorFileFactories;
842 }
843
844 static IFileFactory *findFileFactory(const QList<IFileFactory*> &fileFactories,
845                                      const MimeDatabase *db,
846                                      const QFileInfo &fi)
847 {
848     if (const MimeType mt = db->findByFile(fi)) {
849         const QString type = mt.type();
850         foreach (IFileFactory *factory, fileFactories) {
851             if (factory->mimeTypes().contains(type))
852                 return factory;
853         }
854     }
855     return 0;
856 }
857
858 // opens either an editor or loads a project
859 void MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags)
860 {
861     QList<IFileFactory*> nonEditorFileFactories = getNonEditorFileFactories();
862
863     foreach (const QString &fileName, fileNames) {
864         const QFileInfo fi(fileName);
865         const QString absoluteFilePath = fi.absoluteFilePath();
866         if (IFileFactory *fileFactory = findFileFactory(nonEditorFileFactories, mimeDatabase(), fi)) {
867             Core::IFile *file = fileFactory->open(absoluteFilePath);
868             if (!file && (flags & ICore::StopOnLoadFail))
869                 return;
870             if (file && (flags & ICore::SwitchMode))
871                 Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
872         } else {
873             QFlags<EditorManager::OpenEditorFlag> emFlags;
874             if (flags & ICore::SwitchMode)
875                 emFlags = EditorManager::ModeSwitch;
876             if (flags & ICore::CanContainLineNumbers)
877                 emFlags |=  EditorManager::CanContainLineNumber;
878             Core::IEditor *editor = editorManager()->openEditor(absoluteFilePath, QString(), emFlags);
879             if (!editor && (flags & ICore::StopOnLoadFail))
880                 return;
881         }
882     }
883 }
884
885 void MainWindow::setFocusToEditor()
886 {
887     bool focusWasMovedToEditor = false;
888
889     // give focus to the editor if we have one
890     if (IEditor *editor = m_editorManager->currentEditor()) {
891         if (qApp->focusWidget() != editor->widget()) {
892             editor->widget()->setFocus();
893             focusWasMovedToEditor = editor->widget()->hasFocus();
894         }
895     }
896
897     // check for some maximized pane which we want to unmaximize
898     if (OutputPanePlaceHolder::getCurrent()
899         && OutputPanePlaceHolder::getCurrent()->isVisible()
900         && OutputPanePlaceHolder::getCurrent()->isMaximized()) {
901         OutputPanePlaceHolder::getCurrent()->unmaximize();
902         return;
903     }
904
905     if (focusWasMovedToEditor)
906         return;
907
908
909     // check for some visible bar which we want to hide
910     bool stuffVisible =
911             (FindToolBarPlaceHolder::getCurrent() &&
912              FindToolBarPlaceHolder::getCurrent()->isVisible())
913             || (OutputPanePlaceHolder::getCurrent() &&
914                 OutputPanePlaceHolder::getCurrent()->isVisible())
915             || (RightPanePlaceHolder::current() &&
916                 RightPanePlaceHolder::current()->isVisible());
917     if (stuffVisible) {
918         if (FindToolBarPlaceHolder::getCurrent())
919             FindToolBarPlaceHolder::getCurrent()->hide();
920         OutputPaneManager::instance()->slotHide();
921         RightPaneWidget::instance()->setShown(false);
922         return;
923     }
924
925     // switch to edit mode if necessary
926     m_coreImpl->modeManager()->activateMode(QLatin1String(Constants::MODE_EDIT));
927
928 }
929
930 void MainWindow::showNewItemDialog(const QString &title,
931                                           const QList<IWizard *> &wizards,
932                                           const QString &defaultLocation)
933 {
934     // Scan for wizards matching the filter and pick one. Don't show
935     // dialog if there is only one.
936     IWizard *wizard = 0;
937     switch (wizards.size()) {
938     case 0:
939         break;
940     case 1:
941         wizard = wizards.front();
942         break;
943     default: {
944         NewDialog dlg(this);
945         dlg.setWizards(wizards);
946         dlg.setWindowTitle(title);
947         wizard = dlg.showDialog();
948     }
949         break;
950     }
951
952     if (!wizard)
953         return;
954
955     QString path = defaultLocation;
956     if (path.isEmpty()) {
957         const FileManager *fm = m_coreImpl->fileManager();
958         switch (wizard->kind()) {
959         case IWizard::ProjectWizard:
960             // Project wizards: Check for projects directory or
961             // use last visited directory of file dialog. Never start
962             // at current.
963             path = fm->useProjectsDirectory() ?
964                        fm->projectsDirectory() :
965                        fm->fileDialogLastVisitedDirectory();
966             break;
967         default:
968             path = fm->fileDialogInitialDirectory();
969             break;
970         }
971     }
972     wizard->runWizard(path, this);
973 }
974
975 bool MainWindow::showOptionsDialog(const QString &category,
976                                    const QString &page,
977                                    QWidget *parent)
978 {
979     emit m_coreImpl->optionsDialogRequested();
980     if (!parent)
981         parent = this;
982     SettingsDialog *dialog = SettingsDialog::getSettingsDialog(parent, category, page);
983     return dialog->execDialog();
984 }
985
986 void MainWindow::saveAll()
987 {
988     m_fileManager->saveModifiedFilesSilently(m_fileManager->modifiedFiles());
989     emit m_coreImpl->saveSettingsRequested();
990 }
991
992 void MainWindow::exit()
993 {
994     // this function is most likely called from a user action
995     // that is from an event handler of an object
996     // since on close we are going to delete everything
997     // so to prevent the deleting of that object we
998     // just append it
999     QTimer::singleShot(0, this,  SLOT(close()));
1000 }
1001
1002 void MainWindow::openFileWith()
1003 {
1004     QStringList fileNames = editorManager()->getOpenFileNames();
1005     foreach (const QString &fileName, fileNames) {
1006         bool isExternal;
1007         const QString editorId = editorManager()->getOpenWithEditorId(fileName, &isExternal);
1008         if (editorId.isEmpty())
1009             continue;
1010         if (isExternal) {
1011             editorManager()->openExternalEditor(fileName, editorId);
1012         } else {
1013             editorManager()->openEditor(fileName, editorId, Core::EditorManager::ModeSwitch);
1014         }
1015     }
1016 }
1017
1018 ActionManager *MainWindow::actionManager() const
1019 {
1020     return m_actionManager;
1021 }
1022
1023 FileManager *MainWindow::fileManager() const
1024 {
1025     return m_fileManager;
1026 }
1027
1028 UniqueIDManager *MainWindow::uniqueIDManager() const
1029 {
1030     return m_uniqueIDManager;
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_WS_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     // TODO compat for <= 2.1, remove later
1213     if (m_settings->contains(QLatin1String(geometryKey))) {
1214         const QVariant geom = m_settings->value(QLatin1String(geometryKey));
1215         if (geom.isValid()) {
1216             setGeometry(geom.toRect());
1217         } else {
1218             resize(1024, 700);
1219         }
1220         if (m_settings->value(QLatin1String(maxKey), false).toBool())
1221             setWindowState(Qt::WindowMaximized);
1222         setFullScreen(m_settings->value(QLatin1String(fullScreenKey), false).toBool());
1223
1224         m_settings->remove(QLatin1String(geometryKey));
1225         m_settings->remove(QLatin1String(maxKey));
1226         m_settings->remove(QLatin1String(fullScreenKey));
1227     } else {
1228         if (!restoreGeometry(m_settings->value(QLatin1String(windowGeometryKey)).toByteArray())) {
1229             resize(1024, 700);
1230         }
1231         restoreState(m_settings->value(QLatin1String(windowStateKey)).toByteArray());
1232     }
1233
1234     m_settings->endGroup();
1235
1236     m_editorManager->readSettings();
1237     m_navigationWidget->restoreSettings(m_settings);
1238     m_rightPaneWidget->readSettings(m_settings);
1239 }
1240
1241 void MainWindow::writeSettings()
1242 {
1243     m_settings->beginGroup(QLatin1String(settingsGroup));
1244
1245     if (!(m_overrideColor.isValid() && Utils::StyleHelper::baseColor() == m_overrideColor))
1246         m_settings->setValue(QLatin1String(colorKey), Utils::StyleHelper::requestedBaseColor());
1247
1248     m_settings->setValue(QLatin1String(windowGeometryKey), saveGeometry());
1249     m_settings->setValue(QLatin1String(windowStateKey), saveState());
1250
1251     m_settings->endGroup();
1252
1253     m_fileManager->saveSettings();
1254     m_actionManager->saveSettings(m_settings);
1255     m_editorManager->saveSettings();
1256     m_navigationWidget->saveSettings(m_settings);
1257 }
1258
1259 void MainWindow::updateAdditionalContexts(const Context &remove, const Context &add)
1260 {
1261     foreach (const int context, remove) {
1262         if (context == 0)
1263             continue;
1264
1265         int index = m_additionalContexts.indexOf(context);
1266         if (index != -1)
1267             m_additionalContexts.removeAt(index);
1268     }
1269
1270     foreach (const int context, add) {
1271         if (context == 0)
1272             continue;
1273
1274         if (!m_additionalContexts.contains(context))
1275             m_additionalContexts.prepend(context);
1276     }
1277
1278     updateContext();
1279 }
1280
1281 bool MainWindow::hasContext(int context) const
1282 {
1283     return m_actionManager->hasContext(context);
1284 }
1285
1286 void MainWindow::updateContext()
1287 {
1288     Context contexts;
1289
1290     if (m_activeContext)
1291         contexts.add(m_activeContext->context());
1292
1293     contexts.add(m_additionalContexts);
1294
1295     Context uniquecontexts;
1296     for (int i = 0; i < contexts.size(); ++i) {
1297         const int c = contexts.at(i);
1298         if (!uniquecontexts.contains(c))
1299             uniquecontexts.add(c);
1300     }
1301
1302     m_actionManager->setContext(uniquecontexts);
1303     emit m_coreImpl->contextChanged(m_activeContext, m_additionalContexts);
1304 }
1305
1306 void MainWindow::aboutToShowRecentFiles()
1307 {
1308     ActionContainer *aci =
1309         m_actionManager->actionContainer(Constants::M_FILE_RECENTFILES);
1310     aci->menu()->clear();
1311
1312     bool hasRecentFiles = false;
1313     foreach (const FileManager::RecentFile &file, m_fileManager->recentFiles()) {
1314         hasRecentFiles = true;
1315         QAction *action = aci->menu()->addAction(
1316                     QDir::toNativeSeparators(Utils::withTildeHomePath(file.first)));
1317         action->setData(qVariantFromValue(file));
1318         connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile()));
1319     }
1320     aci->menu()->setEnabled(hasRecentFiles);
1321
1322     // add the Clear Menu item
1323     if (hasRecentFiles) {
1324         aci->menu()->addSeparator();
1325         QAction *action = aci->menu()->addAction(QCoreApplication::translate(
1326                                                      "Core", Core::Constants::TR_CLEAR_MENU));
1327         connect(action, SIGNAL(triggered()), m_fileManager, SLOT(clearRecentFiles()));
1328     }
1329 }
1330
1331 void MainWindow::openRecentFile()
1332 {
1333     if (const QAction *action = qobject_cast<const QAction*>(sender())) {
1334         const FileManager::RecentFile file = action->data().value<FileManager::RecentFile>();
1335         editorManager()->openEditor(file.first, file.second, Core::EditorManager::ModeSwitch);
1336     }
1337 }
1338
1339 void MainWindow::aboutQtCreator()
1340 {
1341     if (!m_versionDialog) {
1342         m_versionDialog = new VersionDialog(this);
1343         connect(m_versionDialog, SIGNAL(finished(int)),
1344                 this, SLOT(destroyVersionDialog()));
1345     }
1346     m_versionDialog->show();
1347 }
1348
1349 void MainWindow::destroyVersionDialog()
1350 {
1351     if (m_versionDialog) {
1352         m_versionDialog->deleteLater();
1353         m_versionDialog = 0;
1354     }
1355 }
1356
1357 void MainWindow::aboutPlugins()
1358 {
1359     PluginDialog dialog(this);
1360     dialog.exec();
1361 }
1362
1363 QPrinter *MainWindow::printer() const
1364 {
1365     if (!m_printer)
1366         m_printer = new QPrinter(QPrinter::HighResolution);
1367     return m_printer;
1368 }
1369
1370 void MainWindow::setFullScreen(bool on)
1371 {
1372     if (bool(windowState() & Qt::WindowFullScreen) == on)
1373         return;
1374
1375     if (on) {
1376         setWindowState(windowState() | Qt::WindowFullScreen);
1377         //statusBar()->hide();
1378         //menuBar()->hide();
1379     } else {
1380         setWindowState(windowState() & ~Qt::WindowFullScreen);
1381         //menuBar()->show();
1382         //statusBar()->show();
1383     }
1384 }
1385
1386 // Display a warning with an additional button to open
1387 // the debugger settings dialog if settingsId is nonempty.
1388
1389 bool MainWindow::showWarningWithOptions(const QString &title,
1390                                         const QString &text,
1391                                         const QString &details,
1392                                         const QString &settingsCategory,
1393                                         const QString &settingsId,
1394                                         QWidget *parent)
1395 {
1396     if (parent == 0)
1397         parent = this;
1398     QMessageBox msgBox(QMessageBox::Warning, title, text,
1399                        QMessageBox::Ok, parent);
1400     if (!details.isEmpty())
1401         msgBox.setDetailedText(details);
1402     QAbstractButton *settingsButton = 0;
1403     if (!settingsId.isEmpty() || !settingsCategory.isEmpty())
1404         settingsButton = msgBox.addButton(tr("Settings..."), QMessageBox::AcceptRole);
1405     msgBox.exec();
1406     if (settingsButton && msgBox.clickedButton() == settingsButton) {
1407         return showOptionsDialog(settingsCategory, settingsId);
1408     }
1409     return false;
1410 }