mainwindow.cpp 46 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11 12 13 14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
**
18 19 20 21 22 23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
con's avatar
con committed
25 26 27 28 29 30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
con's avatar
con committed
31
**
32
**************************************************************************/
con's avatar
con committed
33 34

#include "mainwindow.h"
35
#include "actioncontainer.h"
36
#include "command.h"
37
#include "actionmanager_p.h"
con's avatar
con committed
38 39 40 41 42 43
#include "coreimpl.h"
#include "coreconstants.h"
#include "editormanager.h"
#include "fancytabwidget.h"
#include "filemanager.h"
#include "generalsettings.h"
kh1's avatar
kh1 committed
44
#include "helpmanager.h"
con's avatar
con committed
45 46 47 48 49
#include "ifilefactory.h"
#include "messagemanager.h"
#include "modemanager.h"
#include "mimedatabase.h"
#include "newdialog.h"
50
#include "outputpanemanager.h"
con's avatar
con committed
51 52
#include "outputpane.h"
#include "plugindialog.h"
53
#include "progressmanager_p.h"
con's avatar
con committed
54 55 56
#include "progressview.h"
#include "shortcutsettings.h"
#include "vcsmanager.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
57
#include "ieditor.h"
hjk's avatar
hjk committed
58

59
#include "scriptmanager_p.h"
con's avatar
con committed
60 61 62
#include "settingsdialog.h"
#include "variablemanager.h"
#include "versiondialog.h"
con's avatar
con committed
63
#include "statusbarmanager.h"
con's avatar
con committed
64 65 66 67 68
#include "uniqueidmanager.h"
#include "manhattanstyle.h"
#include "navigationwidget.h"
#include "rightpane.h"
#include "editormanager/ieditorfactory.h"
69
#include "statusbarwidget.h"
con's avatar
con committed
70
#include "basefilewizard.h"
71
#include "ioutputpane.h"
72
#include "editormanager/systemeditor.h"
con's avatar
con committed
73 74

#include <coreplugin/findplaceholder.h>
75
#include <coreplugin/icorelistener.h>
76
#include <coreplugin/inavigationwidgetfactory.h>
77
#include <coreplugin/settingsdatabase.h>
78
#include <utils/pathchooser.h>
79
#include <utils/stylehelper.h>
80
#include <utils/stringutils.h>
81
#include <extensionsystem/pluginmanager.h>
con's avatar
con committed
82 83

#include <QtCore/QDebug>
84
#include <QtCore/QFileInfo>
con's avatar
con committed
85 86
#include <QtCore/QSettings>
#include <QtCore/QTimer>
87
#include <QtCore/QtPlugin>
88
#include <QtCore/QUrl>
89
#include <QtCore/QDir>
con's avatar
con committed
90 91 92

#include <QtGui/QApplication>
#include <QtGui/QCloseEvent>
93 94
#include <QtGui/QMenu>
#include <QtGui/QPixmap>
con's avatar
con committed
95
#include <QtGui/QPrinter>
96
#include <QtGui/QShortcut>
con's avatar
con committed
97
#include <QtGui/QStatusBar>
98
#include <QtGui/QWizard>
99
#include <QtGui/QToolButton>
100
#include <QtGui/QMessageBox>
101
#include <QtGui/QMenuBar>
con's avatar
con committed
102 103 104 105 106 107

/*
#ifdef Q_OS_UNIX
#include <signal.h>
extern "C" void handleSigInt(int sig)
{
108
    Q_UNUSED(sig)
109
    Core::ICore::instance()->exit();
con's avatar
con committed
110 111 112 113 114 115 116 117
    qDebug() << "SIGINT caught. Shutting down.";
}
#endif
*/

using namespace Core;
using namespace Core::Internal;

118
enum { debugMainWindow = 0 };
con's avatar
con committed
119 120

MainWindow::MainWindow() :
121
    EventFilteringMainWindow(),
con's avatar
con committed
122 123
    m_coreImpl(new CoreImpl(this)),
    m_uniqueIDManager(new UniqueIDManager()),
124
    m_additionalContexts(Constants::C_GLOBAL),
125
    m_settings(ExtensionSystem::PluginManager::instance()->settings()),
126 127
    m_globalSettings(new QSettings(QSettings::IniFormat, QSettings::SystemScope,
                             QLatin1String("Nokia"), QLatin1String("QtCreator"), this)),
128 129 130
    m_settingsDatabase(new SettingsDatabase(QFileInfo(m_settings->fileName()).path(),
                                            QLatin1String("QtCreator"),
                                            this)),
con's avatar
con committed
131
    m_printer(0),
132
    m_actionManager(new ActionManagerPrivate(this)),
con's avatar
con committed
133
    m_editorManager(0),
hjk's avatar
hjk committed
134
    m_fileManager(new FileManager(this)),
135
    m_progressManager(new ProgressManagerPrivate()),
136
    m_scriptManager(new ScriptManagerPrivate(this)),
Friedemann Kleint's avatar
Friedemann Kleint committed
137
    m_variableManager(new VariableManager),
hjk's avatar
hjk committed
138
    m_vcsManager(new VcsManager),
con's avatar
con committed
139
    m_statusBarManager(0),
con's avatar
con committed
140 141
    m_modeManager(0),
    m_mimeDatabase(new MimeDatabase),
kh1's avatar
kh1 committed
142
    m_helpManager(new HelpManager),
con's avatar
con committed
143 144
    m_navigationWidget(0),
    m_rightPaneWidget(0),
145
    m_versionDialog(0),
con's avatar
con committed
146 147 148
    m_activeContext(0),
    m_generalSettings(new GeneralSettings),
    m_shortcutSettings(new ShortcutSettings),
149
    m_systemEditor(new SystemEditor),
con's avatar
con committed
150 151 152 153 154 155 156 157
    m_focusToEditor(0),
    m_newAction(0),
    m_openAction(0),
    m_openWithAction(0),
    m_saveAllAction(0),
    m_exitAction(0),
    m_optionsAction(0),
    m_toggleSideBarAction(0),
hjk's avatar
hjk committed
158
    m_toggleFullScreenAction(0),
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
159
#ifdef Q_WS_MAC
con's avatar
con committed
160 161 162 163 164
    m_minimizeAction(0),
    m_zoomAction(0),
#endif
    m_toggleSideBarButton(new QToolButton)
{
165 166
    OutputPaneManager::create();

con's avatar
con committed
167
    setWindowTitle(tr("Qt Creator"));
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
168
#ifndef Q_WS_MAC
169
    QApplication::setWindowIcon(QIcon(QLatin1String(Constants::ICON_QTLOGO_128)));
170
#endif
171 172 173 174
    QCoreApplication::setApplicationName(QLatin1String("QtCreator"));
    QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));
    QCoreApplication::setOrganizationName(QLatin1String("Nokia"));
    QSettings::setDefaultFormat(QSettings::IniFormat);
175
    QString baseName = QApplication::style()->objectName();
con's avatar
con committed
176
#ifdef Q_WS_X11
177
    if (baseName == QLatin1String("windows")) {
178 179 180 181
        // Sometimes we get the standard windows 95 style as a fallback
        // e.g. if we are running on a KDE4 desktop
        QByteArray desktopEnvironment = qgetenv("DESKTOP_SESSION");
        if (desktopEnvironment == "kde")
182
            baseName = QLatin1String("plastique");
183
        else
184
            baseName = QLatin1String("cleanlooks");
185 186 187 188
    }
#endif
    qApp->setStyle(new ManhattanStyle(baseName));

con's avatar
con committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202
    setDockNestingEnabled(true);

    setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
    setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);

    registerDefaultContainers();
    registerDefaultActions();

    m_navigationWidget = new NavigationWidget(m_toggleSideBarAction);
    m_rightPaneWidget = new RightPaneWidget();

    m_modeStack = new FancyTabWidget(this);
    m_modeManager = new ModeManager(this, m_modeStack);
    m_modeManager->addWidget(m_progressManager->progressView());
con's avatar
con committed
203
    m_statusBarManager = new StatusBarManager(this);
con's avatar
con committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    m_messageManager = new MessageManager;
    m_editorManager = new EditorManager(m_coreImpl, this);
    m_editorManager->hide();
    setCentralWidget(m_modeStack);

    connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
            this, SLOT(updateFocusWidget(QWidget*,QWidget*)));
    // Add a small Toolbutton for toggling the navigation widget
    statusBar()->insertPermanentWidget(0, m_toggleSideBarButton);

//    setUnifiedTitleAndToolBarOnMac(true);
#ifdef Q_OS_UNIX
     //signal(SIGINT, handleSigInt);
#endif

    statusBar()->setProperty("p_styled", true);
220
    setAcceptDrops(true);
con's avatar
con committed
221 222
}

223
void MainWindow::setSidebarVisible(bool visible)
con's avatar
con committed
224 225
{
    if (NavigationWidgetPlaceHolder::current()) {
226
        if (m_navigationWidget->isSuppressed() && visible) {
con's avatar
con committed
227 228 229
            m_navigationWidget->setShown(true);
            m_navigationWidget->setSuppressed(false);
        } else {
230
            m_navigationWidget->setShown(visible);
con's avatar
con committed
231 232 233 234 235 236
        }
    }
}

void MainWindow::setSuppressNavigationWidget(bool suppress)
{
hjk's avatar
hjk committed
237
    if (NavigationWidgetPlaceHolder::current())
con's avatar
con committed
238 239 240
        m_navigationWidget->setSuppressed(suppress);
}

241 242 243 244 245
void MainWindow::setOverrideColor(const QColor &color)
{
    m_overrideColor = color;
}

con's avatar
con committed
246 247
MainWindow::~MainWindow()
{
248 249 250
    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
    pm->removeObject(m_shortcutSettings);
    pm->removeObject(m_generalSettings);
251
    pm->removeObject(m_systemEditor);
con's avatar
con committed
252 253 254 255 256 257
    delete m_messageManager;
    m_messageManager = 0;
    delete m_shortcutSettings;
    m_shortcutSettings = 0;
    delete m_generalSettings;
    m_generalSettings = 0;
258 259
    delete m_systemEditor;
    m_systemEditor = 0;
con's avatar
con committed
260 261 262 263 264 265 266 267
    delete m_settings;
    m_settings = 0;
    delete m_printer;
    m_printer = 0;
    delete m_uniqueIDManager;
    m_uniqueIDManager = 0;
    delete m_vcsManager;
    m_vcsManager = 0;
con's avatar
con committed
268
    //we need to delete editormanager and statusbarmanager explicitly before the end of the destructor,
con's avatar
con committed
269 270 271
    //because they might trigger stuff that tries to access data from editorwindow, like removeContextWidget

    // All modes are now gone
272
    OutputPaneManager::destroy();
con's avatar
con committed
273

274
    // Now that the OutputPaneManager is gone, is a good time to delete the view
275
    pm->removeObject(m_outputView);
con's avatar
con committed
276 277 278 279
    delete m_outputView;

    delete m_editorManager;
    m_editorManager = 0;
con's avatar
con committed
280 281
    delete m_statusBarManager;
    m_statusBarManager = 0;
con's avatar
con committed
282 283
    delete m_progressManager;
    m_progressManager = 0;
284
    pm->removeObject(m_coreImpl);
con's avatar
con committed
285 286 287 288 289 290 291 292 293 294
    delete m_coreImpl;
    m_coreImpl = 0;

    delete m_rightPaneWidget;
    m_rightPaneWidget = 0;

    delete m_modeManager;
    m_modeManager = 0;
    delete m_mimeDatabase;
    m_mimeDatabase = 0;
kh1's avatar
kh1 committed
295 296 297

    delete m_helpManager;
    m_helpManager = 0;
con's avatar
con committed
298 299
}

300
bool MainWindow::init(QString *errorMessage)
con's avatar
con committed
301
{
302
    Q_UNUSED(errorMessage)
303

304 305 306
    if (!mimeDatabase()->addMimeTypes(QLatin1String(":/core/editormanager/BinFiles.mimetypes.xml"), errorMessage))
        return false;

307 308
    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
    pm->addObject(m_coreImpl);
con's avatar
con committed
309
    m_statusBarManager->init();
con's avatar
con committed
310 311
    m_modeManager->init();
    m_progressManager->init();
con's avatar
con committed
312

313 314
    pm->addObject(m_generalSettings);
    pm->addObject(m_shortcutSettings);
315 316
    pm->addObject(m_systemEditor);

con's avatar
con committed
317

318
    // Add widget to the bottom, we create the view here instead of inside the
Tobias Hunger's avatar
Tobias Hunger committed
319
    // OutputPaneManager, since the StatusBarManager needs to be initialized before
320
    m_outputView = new Core::StatusBarWidget;
321
    m_outputView->setWidget(OutputPaneManager::instance()->buttonsWidget());
322
    m_outputView->setPosition(Core::StatusBarWidget::Second);
323
    pm->addObject(m_outputView);
324
    m_messageManager->init();
con's avatar
con committed
325 326 327 328 329 330
    return true;
}

void MainWindow::extensionsInitialized()
{
    m_editorManager->init();
con's avatar
con committed
331
    m_statusBarManager->extensionsInitalized();
332
    OutputPaneManager::instance()->init();
333
    m_vcsManager->extensionsInitialized();
334 335
    m_navigationWidget->setFactories(ExtensionSystem::PluginManager::instance()->getObjects<INavigationWidgetFactory>());

336 337 338
    // reading the shortcut settings must be done after all shortcuts have been registered
    m_actionManager->initialize();

con's avatar
con committed
339 340 341
    readSettings();
    updateContext();

342 343
    emit m_coreImpl->coreAboutToOpen();
    show();
con's avatar
con committed
344 345 346 347 348 349 350 351 352
    emit m_coreImpl->coreOpened();
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    emit m_coreImpl->saveSettingsRequested();

    // Save opened files
    bool cancelled;
353 354
    QList<IFile*> notSaved = fileManager()->saveModifiedFiles(fileManager()->modifiedFiles(), &cancelled);
    if (cancelled || !notSaved.isEmpty()) {
con's avatar
con committed
355 356 357 358 359
        event->ignore();
        return;
    }

    const QList<ICoreListener *> listeners =
360
        ExtensionSystem::PluginManager::instance()->getObjects<ICoreListener>();
con's avatar
con committed
361 362 363 364 365 366 367 368
    foreach (ICoreListener *listener, listeners) {
        if (!listener->coreAboutToClose()) {
            event->ignore();
            return;
        }
    }

    emit m_coreImpl->coreAboutToClose();
369

con's avatar
con committed
370
    writeSettings();
371 372 373

    m_navigationWidget->closeSubWidgets();

con's avatar
con committed
374 375 376
    event->accept();
}

377 378 379 380 381 382 383
// Check for desktop file manager file drop events

static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
{
    if (files)
        files->clear();
    // Extract dropped files from Mime data.
384
    if (!d->hasUrls())
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
        return false;
    const QList<QUrl> urls = d->urls();
    if (urls.empty())
        return false;
    // Try to find local files
    bool hasFiles = false;
    const QList<QUrl>::const_iterator cend = urls.constEnd();
    for (QList<QUrl>::const_iterator it = urls.constBegin(); it != cend; ++it) {
        const QString fileName = it->toLocalFile();
        if (!fileName.isEmpty()) {
            hasFiles = true;
            if (files) {
                files->push_back(fileName);
            } else {
                break; // No result list, sufficient for checking
            }
        }
    }
    return hasFiles;
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
408
    if (isDesktopFileManagerDrop(event->mimeData()) && m_filesToOpenDelayed.isEmpty()) {
409 410 411 412 413 414 415 416 417 418 419
        event->accept();
    } else {
        event->ignore();
    }
}

void MainWindow::dropEvent(QDropEvent *event)
{
    QStringList files;
    if (isDesktopFileManagerDrop(event->mimeData(), &files)) {
        event->accept();
420 421
        m_filesToOpenDelayed.append(files);
        QTimer::singleShot(50, this, SLOT(openDelayedFiles()));
422 423 424 425 426
    } else {
        event->ignore();
    }
}

427 428 429 430 431 432 433 434 435 436
void MainWindow::openDelayedFiles()
{
    if (m_filesToOpenDelayed.isEmpty())
        return;
    activateWindow();
    raise();
    openFiles(m_filesToOpenDelayed, ICore::SwitchMode);
    m_filesToOpenDelayed.clear();
}

con's avatar
con committed
437 438 439 440 441 442 443 444 445 446 447 448
IContext *MainWindow::currentContextObject() const
{
    return m_activeContext;
}

QStatusBar *MainWindow::statusBar() const
{
    return m_modeStack->statusBar();
}

void MainWindow::registerDefaultContainers()
{
449
    ActionManagerPrivate *am = m_actionManager;
con's avatar
con committed
450

451
    ActionContainer *menubar = am->createMenuBar(Constants::MENU_BAR);
con's avatar
con committed
452 453 454 455 456 457 458 459 460 461 462

#ifndef Q_WS_MAC // System menu bar on Mac
    setMenuBar(menubar->menuBar());
#endif
    menubar->appendGroup(Constants::G_FILE);
    menubar->appendGroup(Constants::G_EDIT);
    menubar->appendGroup(Constants::G_VIEW);
    menubar->appendGroup(Constants::G_TOOLS);
    menubar->appendGroup(Constants::G_WINDOW);
    menubar->appendGroup(Constants::G_HELP);

463
    // File Menu
464
    ActionContainer *filemenu = am->createMenu(Constants::M_FILE);
con's avatar
con committed
465 466 467 468 469 470 471 472 473 474 475 476
    menubar->addMenu(filemenu, Constants::G_FILE);
    filemenu->menu()->setTitle(tr("&File"));
    filemenu->appendGroup(Constants::G_FILE_NEW);
    filemenu->appendGroup(Constants::G_FILE_OPEN);
    filemenu->appendGroup(Constants::G_FILE_PROJECT);
    filemenu->appendGroup(Constants::G_FILE_SAVE);
    filemenu->appendGroup(Constants::G_FILE_CLOSE);
    filemenu->appendGroup(Constants::G_FILE_PRINT);
    filemenu->appendGroup(Constants::G_FILE_OTHER);
    connect(filemenu->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowRecentFiles()));


477
    // Edit Menu
478
    ActionContainer *medit = am->createMenu(Constants::M_EDIT);
con's avatar
con committed
479 480 481 482 483
    menubar->addMenu(medit, Constants::G_EDIT);
    medit->menu()->setTitle(tr("&Edit"));
    medit->appendGroup(Constants::G_EDIT_UNDOREDO);
    medit->appendGroup(Constants::G_EDIT_COPYPASTE);
    medit->appendGroup(Constants::G_EDIT_SELECTALL);
484
    medit->appendGroup(Constants::G_EDIT_ADVANCED);
485
    medit->appendGroup(Constants::G_EDIT_FIND);
con's avatar
con committed
486 487
    medit->appendGroup(Constants::G_EDIT_OTHER);

488
    // Tools Menu
489
    ActionContainer *ac = am->createMenu(Constants::M_TOOLS);
con's avatar
con committed
490 491 492
    menubar->addMenu(ac, Constants::G_TOOLS);
    ac->menu()->setTitle(tr("&Tools"));

493
    // Window Menu
494
    ActionContainer *mwindow = am->createMenu(Constants::M_WINDOW);
con's avatar
con committed
495 496 497
    menubar->addMenu(mwindow, Constants::G_WINDOW);
    mwindow->menu()->setTitle(tr("&Window"));
    mwindow->appendGroup(Constants::G_WINDOW_SIZE);
498
    mwindow->appendGroup(Constants::G_WINDOW_VIEWS);
con's avatar
con committed
499 500 501 502 503
    mwindow->appendGroup(Constants::G_WINDOW_PANES);
    mwindow->appendGroup(Constants::G_WINDOW_SPLIT);
    mwindow->appendGroup(Constants::G_WINDOW_NAVIGATE);
    mwindow->appendGroup(Constants::G_WINDOW_OTHER);

504
    // Help Menu
con's avatar
con committed
505 506 507
    ac = am->createMenu(Constants::M_HELP);
    menubar->addMenu(ac, Constants::G_HELP);
    ac->menu()->setTitle(tr("&Help"));
508 509
    ac->appendGroup(Constants::G_HELP_HELP);
    ac->appendGroup(Constants::G_HELP_ABOUT);
con's avatar
con committed
510 511
}

512 513
static Command *createSeparator(ActionManager *am, QObject *parent,
                                const QString &name,
514
                                const Context &context)
con's avatar
con committed
515 516 517
{
    QAction *tmpaction = new QAction(parent);
    tmpaction->setSeparator(true);
con's avatar
con committed
518
    Command *cmd = am->registerAction(tmpaction, name, context);
con's avatar
con committed
519 520 521 522 523
    return cmd;
}

void MainWindow::registerDefaultActions()
{
524
    ActionManagerPrivate *am = m_actionManager;
525 526 527 528 529
    ActionContainer *mfile = am->actionContainer(Constants::M_FILE);
    ActionContainer *medit = am->actionContainer(Constants::M_EDIT);
    ActionContainer *mtools = am->actionContainer(Constants::M_TOOLS);
    ActionContainer *mwindow = am->actionContainer(Constants::M_WINDOW);
    ActionContainer *mhelp = am->actionContainer(Constants::M_HELP);
con's avatar
con committed
530

531 532
    Context globalContext(Constants::C_GLOBAL);

con's avatar
con committed
533
    // File menu separators
534
    Command *cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Save"), globalContext);
con's avatar
con committed
535 536
    mfile->addAction(cmd, Constants::G_FILE_SAVE);

537
    cmd =  createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Print"), globalContext);
538
    QIcon icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(Constants::ICON_CUT));
con's avatar
con committed
539 540
    mfile->addAction(cmd, Constants::G_FILE_PRINT);

541
    cmd =  createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Close"), globalContext);
con's avatar
con committed
542 543
    mfile->addAction(cmd, Constants::G_FILE_CLOSE);

544
    cmd = createSeparator(am, this, QLatin1String("QtCreator.File.Sep.Other"), globalContext);
con's avatar
con committed
545 546 547
    mfile->addAction(cmd, Constants::G_FILE_OTHER);

    // Edit menu separators
548
    cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.CopyPaste"), globalContext);
con's avatar
con committed
549 550
    medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);

551
    cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.SelectAll"), globalContext);
con's avatar
con committed
552 553
    medit->addAction(cmd, Constants::G_EDIT_SELECTALL);

554
    cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Find"), globalContext);
con's avatar
con committed
555 556
    medit->addAction(cmd, Constants::G_EDIT_FIND);

557
    cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Advanced"), globalContext);
558
    medit->addAction(cmd, Constants::G_EDIT_ADVANCED);
con's avatar
con committed
559

560
    // Tools menu separators
561
    cmd = createSeparator(am, this, QLatin1String("QtCreator.Tools.Sep.Options"), globalContext);
con's avatar
con committed
562 563
    mtools->addAction(cmd, Constants::G_DEFAULT_THREE);

564
    // Return to editor shortcut: Note this requires Qt to fix up
con's avatar
con committed
565 566
    // handling of shortcut overrides in menus, item views, combos....
    m_focusToEditor = new QShortcut(this);
567
    cmd = am->registerShortcut(m_focusToEditor, Constants::S_RETURNTOEDITOR, globalContext);
con's avatar
con committed
568 569 570
    cmd->setDefaultKeySequence(QKeySequence(Qt::Key_Escape));
    connect(m_focusToEditor, SIGNAL(activated()), this, SLOT(setFocusToEditor()));

571
    // New File Action
572 573
    icon = QIcon::fromTheme(QLatin1String("document-new"), QIcon(Constants::ICON_NEWFILE));
    m_newAction = new QAction(icon, tr("&New File or Project..."), this);
574
    cmd = am->registerAction(m_newAction, Constants::NEW, globalContext);
con's avatar
con committed
575 576 577 578
    cmd->setDefaultKeySequence(QKeySequence::New);
    mfile->addAction(cmd, Constants::G_FILE_NEW);
    connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile()));

579
    // Open Action
580 581
    icon = QIcon::fromTheme(QLatin1String("document-open"), QIcon(Constants::ICON_OPENFILE));
    m_openAction = new QAction(icon, tr("&Open File or Project..."), this);
582
    cmd = am->registerAction(m_openAction, Constants::OPEN, globalContext);
con's avatar
con committed
583 584 585 586
    cmd->setDefaultKeySequence(QKeySequence::Open);
    mfile->addAction(cmd, Constants::G_FILE_OPEN);
    connect(m_openAction, SIGNAL(triggered()), this, SLOT(openFile()));

587
    // Open With Action
588
    m_openWithAction = new QAction(tr("Open File &With..."), this);
589
    cmd = am->registerAction(m_openWithAction, Constants::OPEN_WITH, globalContext);
con's avatar
con committed
590 591 592
    mfile->addAction(cmd, Constants::G_FILE_OPEN);
    connect(m_openWithAction, SIGNAL(triggered()), this, SLOT(openFileWith()));

593
    // File->Recent Files Menu
594
    ActionContainer *ac = am->createMenu(Constants::M_FILE_RECENTFILES);
con's avatar
con committed
595
    mfile->addMenu(ac, Constants::G_FILE_OPEN);
596
    ac->menu()->setTitle(tr("Recent &Files"));
597
    ac->setOnAllDisabledBehavior(ActionContainer::Show);
con's avatar
con committed
598

599
    // Save Action
600 601
    icon = QIcon::fromTheme(QLatin1String("document-save"), QIcon(Constants::ICON_SAVEFILE));
    QAction *tmpaction = new QAction(icon, tr("&Save"), this);
602
    cmd = am->registerAction(tmpaction, Constants::SAVE, globalContext);
con's avatar
con committed
603
    cmd->setDefaultKeySequence(QKeySequence::Save);
con's avatar
con committed
604
    cmd->setAttribute(Command::CA_UpdateText);
con's avatar
con committed
605 606 607
    cmd->setDefaultText(tr("&Save"));
    mfile->addAction(cmd, Constants::G_FILE_SAVE);

608
    // Save As Action
609 610
    icon = QIcon::fromTheme(QLatin1String("document-save-as"));
    tmpaction = new QAction(icon, tr("Save &As..."), this);
611
    cmd = am->registerAction(tmpaction, Constants::SAVEAS, globalContext);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
612
#ifdef Q_WS_MAC
con's avatar
con committed
613 614
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
#endif
con's avatar
con committed
615
    cmd->setAttribute(Command::CA_UpdateText);
con's avatar
con committed
616 617 618
    cmd->setDefaultText(tr("Save &As..."));
    mfile->addAction(cmd, Constants::G_FILE_SAVE);

619
    // SaveAll Action
con's avatar
con committed
620
    m_saveAllAction = new QAction(tr("Save A&ll"), this);
621
    cmd = am->registerAction(m_saveAllAction, Constants::SAVEALL, globalContext);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
622
#ifndef Q_WS_MAC
con's avatar
con committed
623 624 625 626 627
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+S")));
#endif
    mfile->addAction(cmd, Constants::G_FILE_SAVE);
    connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll()));

628
    // Print Action
629 630
    icon = QIcon::fromTheme(QLatin1String("document-print"));
    tmpaction = new QAction(icon, tr("&Print..."), this);
631
    cmd = am->registerAction(tmpaction, Constants::PRINT, globalContext);
632
    cmd->setDefaultKeySequence(QKeySequence::Print);
con's avatar
con committed
633 634
    mfile->addAction(cmd, Constants::G_FILE_PRINT);

635
    // Exit Action
636 637
    icon = QIcon::fromTheme(QLatin1String("application-exit"));
    m_exitAction = new QAction(icon, tr("E&xit"), this);
638
    cmd = am->registerAction(m_exitAction, Constants::EXIT, globalContext);
con's avatar
con committed
639 640 641 642
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Q")));
    mfile->addAction(cmd, Constants::G_FILE_OTHER);
    connect(m_exitAction, SIGNAL(triggered()), this, SLOT(exit()));

643
    // Undo Action
644 645
    icon = QIcon::fromTheme(QLatin1String("edit-undo"), QIcon(Constants::ICON_UNDO));
    tmpaction = new QAction(icon, tr("&Undo"), this);
646
    cmd = am->registerAction(tmpaction, Constants::UNDO, globalContext);
con's avatar
con committed
647
    cmd->setDefaultKeySequence(QKeySequence::Undo);
con's avatar
con committed
648
    cmd->setAttribute(Command::CA_UpdateText);
con's avatar
con committed
649 650
    cmd->setDefaultText(tr("&Undo"));
    medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
651
    tmpaction->setEnabled(false);
con's avatar
con committed
652

653
    // Redo Action
654 655
    icon = QIcon::fromTheme(QLatin1String("edit-redo"), QIcon(Constants::ICON_REDO));
    tmpaction = new QAction(icon, tr("&Redo"), this);
656
    cmd = am->registerAction(tmpaction, Constants::REDO, globalContext);
con's avatar
con committed
657
    cmd->setDefaultKeySequence(QKeySequence::Redo);
con's avatar
con committed
658
    cmd->setAttribute(Command::CA_UpdateText);
con's avatar
con committed
659 660
    cmd->setDefaultText(tr("&Redo"));
    medit->addAction(cmd, Constants::G_EDIT_UNDOREDO);
661
    tmpaction->setEnabled(false);
con's avatar
con committed
662

663
    // Cut Action
664 665
    icon = QIcon::fromTheme(QLatin1String("edit-cut"), QIcon(Constants::ICON_CUT));
    tmpaction = new QAction(icon, tr("Cu&t"), this);
666
    cmd = am->registerAction(tmpaction, Constants::CUT, globalContext);
con's avatar
con committed
667 668
    cmd->setDefaultKeySequence(QKeySequence::Cut);
    medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
669
    tmpaction->setEnabled(false);
con's avatar
con committed
670

671
    // Copy Action
672 673
    icon = QIcon::fromTheme(QLatin1String("edit-copy"), QIcon(Constants::ICON_COPY));
    tmpaction = new QAction(icon, tr("&Copy"), this);
674
    cmd = am->registerAction(tmpaction, Constants::COPY, globalContext);
con's avatar
con committed
675 676
    cmd->setDefaultKeySequence(QKeySequence::Copy);
    medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
677
    tmpaction->setEnabled(false);
con's avatar
con committed
678

679
    // Paste Action
680 681
    icon = QIcon::fromTheme(QLatin1String("edit-paste"), QIcon(Constants::ICON_PASTE));
    tmpaction = new QAction(icon, tr("&Paste"), this);
682
    cmd = am->registerAction(tmpaction, Constants::PASTE, globalContext);
con's avatar
con committed
683 684
    cmd->setDefaultKeySequence(QKeySequence::Paste);
    medit->addAction(cmd, Constants::G_EDIT_COPYPASTE);
685
    tmpaction->setEnabled(false);
con's avatar
con committed
686

687
    // Select All
688 689
    icon = QIcon::fromTheme(QLatin1String("edit-select-all"));
    tmpaction = new QAction(icon, tr("&Select All"), this);
690
    cmd = am->registerAction(tmpaction, Constants::SELECTALL, globalContext);
con's avatar
con committed
691 692
    cmd->setDefaultKeySequence(QKeySequence::SelectAll);
    medit->addAction(cmd, Constants::G_EDIT_SELECTALL);
693
    tmpaction->setEnabled(false);
con's avatar
con committed
694

695
    // Goto Action
696 697
    icon = QIcon::fromTheme(QLatin1String("go-jump"));
    tmpaction = new QAction(icon, tr("&Go To Line..."), this);
698
    cmd = am->registerAction(tmpaction, Constants::GOTO, globalContext);
con's avatar
con committed
699 700
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+L")));
    medit->addAction(cmd, Constants::G_EDIT_OTHER);
701
    tmpaction->setEnabled(false);
con's avatar
con committed
702

703
    // Options Action
con's avatar
con committed
704
    m_optionsAction = new QAction(tr("&Options..."), this);
705
    cmd = am->registerAction(m_optionsAction, Constants::OPTIONS, globalContext);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
706
#ifdef Q_WS_MAC
con's avatar
con committed
707
    cmd->setDefaultKeySequence(QKeySequence("Ctrl+,"));
con's avatar
con committed
708
    cmd->action()->setMenuRole(QAction::PreferencesRole);
con's avatar
con committed
709 710 711 712
#endif
    mtools->addAction(cmd, Constants::G_DEFAULT_THREE);
    connect(m_optionsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog()));

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
713
#ifdef Q_WS_MAC
714
    // Minimize Action
con's avatar
con committed
715
    m_minimizeAction = new QAction(tr("Minimize"), this);
hjk's avatar
hjk committed
716
    cmd = am->registerAction(m_minimizeAction, Constants::MINIMIZE_WINDOW, globalContext);
con's avatar
con committed
717 718 719 720
    cmd->setDefaultKeySequence(QKeySequence("Ctrl+M"));
    mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
    connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(showMinimized()));

721
    // Zoom Action
con's avatar
con committed
722
    m_zoomAction = new QAction(tr("Zoom"), this);
hjk's avatar
hjk committed
723
    cmd = am->registerAction(m_zoomAction, Constants::ZOOM_WINDOW, globalContext);
con's avatar
con committed
724 725 726
    mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
    connect(m_zoomAction, SIGNAL(triggered()), this, SLOT(showMaximized()));

727
    // Window separator
hjk's avatar
hjk committed
728
    cmd = createSeparator(am, this, QLatin1String("QtCreator.Window.Sep.Size"), globalContext);
con's avatar
con committed
729 730 731
    mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
#endif

732
    // Show Sidebar Action
con's avatar
con committed
733
    m_toggleSideBarAction = new QAction(QIcon(Constants::ICON_TOGGLE_SIDEBAR),
734
                                        tr("Show Sidebar"), this);
735
    m_toggleSideBarAction->setCheckable(true);
736
    cmd = am->registerAction(m_toggleSideBarAction, Constants::TOGGLE_SIDEBAR, globalContext);
737
    cmd->setAttribute(Command::CA_UpdateText);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
738
#ifdef Q_WS_MAC
con's avatar
con committed
739 740 741 742
    cmd->setDefaultKeySequence(QKeySequence("Ctrl+0"));
#else
    cmd->setDefaultKeySequence(QKeySequence("Alt+0"));
#endif
743
    connect(m_toggleSideBarAction, SIGNAL(triggered(bool)), this, SLOT(setSidebarVisible(bool)));
con's avatar
con committed
744
    m_toggleSideBarButton->setDefaultAction(cmd->action());
745
    mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS);
con's avatar
con committed
746 747
    m_toggleSideBarAction->setEnabled(false);

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
748
#ifndef Q_WS_MAC
749 750
    // Full Screen Action
    m_toggleFullScreenAction = new QAction(tr("Full Screen"), this);
hjk's avatar
hjk committed
751
    m_toggleFullScreenAction->setCheckable(true);
752
    cmd = am->registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext);
hjk's avatar
hjk committed
753
    cmd->setDefaultKeySequence(QKeySequence("Ctrl+Shift+F11"));
754
    mwindow->addAction(cmd, Constants::G_WINDOW_SIZE);
755
    connect(m_toggleFullScreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool)));
756
#endif
hjk's avatar
hjk committed
757

758 759 760 761 762
    // Window->Views
    ActionContainer *mviews = am->createMenu(Constants::M_WINDOW_VIEWS);
    mwindow->addMenu(mviews, Constants::G_WINDOW_VIEWS);
    mviews->menu()->setTitle(tr("&Views"));

763
    // About IDE Action
764
    icon = QIcon::fromTheme(QLatin1String("help-about"));
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
765
#ifdef Q_WS_MAC
766
    tmpaction = new QAction(icon, tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
con's avatar
con committed
767
#else
768
    tmpaction = new QAction(icon, tr("About &Qt Creator..."), this);
con's avatar
con committed
769
#endif
770
    cmd = am->registerAction(tmpaction, Constants::ABOUT_QTCREATOR, globalContext);
con's avatar
con committed
771 772
    mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
    tmpaction->setEnabled(true);
con's avatar
con committed
773 774 775
#ifdef Q_WS_MAC
    cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
#endif
con's avatar
con committed
776
    connect(tmpaction, SIGNAL(triggered()), this,  SLOT(aboutQtCreator()));
con's avatar
con committed
777

con's avatar
con committed
778 779
    //About Plugins Action
    tmpaction = new QAction(tr("About &Plugins..."), this);
780
    cmd = am->registerAction(tmpaction, Constants::ABOUT_PLUGINS, globalContext);
con's avatar
con committed
781 782
    mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
    tmpaction->setEnabled(true);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
783
#ifdef Q_WS_MAC
con's avatar
con committed
784 785 786
    cmd->action()->setMenuRole(QAction::ApplicationSpecificRole);
#endif
    connect(tmpaction, SIGNAL(triggered()), this,  SLOT(aboutPlugins()));
787
    // About Qt Action
con's avatar
con committed
788
//    tmpaction = new QAction(tr("About &Qt..."), this);
hjk's avatar
hjk committed
789
//    cmd = am->registerAction(tmpaction, Constants:: ABOUT_QT, globalContext);
con's avatar
con committed
790 791 792 793
//    mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
//    tmpaction->setEnabled(true);
//    connect(tmpaction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
    // About sep
con's avatar
con committed
794
#ifndef Q_WS_MAC // doesn't have the "About" actions in the Help menu
con's avatar
con committed
795 796
    tmpaction = new QAction(this);
    tmpaction->setSeparator(true);
hjk's avatar
hjk committed
797
    cmd = am->registerAction(tmpaction, "QtCreator.Help.Sep.About", globalContext);
con's avatar
con committed
798
    mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
con's avatar
con committed
799
#endif
con's avatar
con committed
800 801 802 803
}

void MainWindow::newFile()
{
804
    showNewItemDialog(tr("New", "Title of dialog"), IWizard::allWizards(), QString());
con's avatar
con committed
805 806 807 808
}

void MainWindow::openFile()
{
809
    openFiles(editorManager()->getOpenFileNames(), ICore::SwitchMode);
con's avatar
con committed
810 811 812 813
}

static QList<IFileFactory*> getNonEditorFileFactories()
{
814 815
    const QList<IFileFactory*> allFileFactories =
        ExtensionSystem::PluginManager::instance()->getObjects<IFileFactory>();
con's avatar
con committed
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
    QList<IFileFactory*> nonEditorFileFactories;
    foreach (IFileFactory *factory, allFileFactories) {
        if (!qobject_cast<IEditorFactory *>(factory))
            nonEditorFileFactories.append(factory);
    }
    return nonEditorFileFactories;
}

static IFileFactory *findFileFactory(const QList<IFileFactory*> &fileFactories,
                                     const MimeDatabase *db,
                                     const QFileInfo &fi)
{
    if (const MimeType mt = db->findByFile(fi)) {
        const QString type = mt.type();
        foreach (IFileFactory *factory, fileFactories) {
            if (factory->mimeTypes().contains(type))
                return factory;
        }
    }
    return 0;
}

// opens either an editor or loads a project
839
void MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags)
con's avatar
con committed
840 841 842 843 844 845 846
{
    QList<IFileFactory*> nonEditorFileFactories = getNonEditorFileFactories();

    foreach (const QString &fileName, fileNames) {
        const QFileInfo fi(fileName);
        const QString absoluteFilePath = fi.absoluteFilePath();
        if (IFileFactory *fileFactory = findFileFactory(nonEditorFileFactories, mimeDatabase(), fi)) {
847 848 849 850
            Core::IFile *file = fileFactory->open(absoluteFilePath);
            if (!file && (flags & ICore::StopOnLoadFail))
                return;
            if (file && (flags & ICore::SwitchMode))
851
                Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
con's avatar
con committed
852
        } else {
853
            QFlags<EditorManager::OpenEditorFlag> emFlags;
854
            if (flags & ICore::SwitchMode)
855
                emFlags = EditorManager::ModeSwitch;
856
            if (flags & ICore::CanContainLineNumbers)
857
                emFlags |=  EditorManager::CanContainLineNumber;
858 859 860
            Core::IEditor *editor = editorManager()->openEditor(absoluteFilePath, QString(), emFlags);
            if (!editor && (flags & ICore::StopOnLoadFail))
                return;
con's avatar
con committed
861 862 863 864 865 866
        }
    }
}

void MainWindow::setFocusToEditor()
{
mae's avatar
mae committed
867
    bool focusWasMovedToEditor = false;
con's avatar
con committed
868

mae's avatar
mae committed
869 870 871
    // give focus to the editor if we have one
    if (IEditor *editor = m_editorManager->currentEditor()) {
        if (qApp->focusWidget() != editor->widget()) {
872
            editor->widget()->setFocus();
mae's avatar
mae committed
873
            focusWasMovedToEditor = editor->widget()->hasFocus();
874
        }
con's avatar
con committed
875
    }
mae's avatar
mae committed
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907

    // check for some maximized pane which we want to unmaximize
    if (OutputPanePlaceHolder::getCurrent