main.cpp 20.1 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
Eike Ziller's avatar
Eike Ziller committed
3 4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
Eike Ziller's avatar
Eike Ziller committed
12 13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** use the contact form at http://www.qt.io/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18 19 20 21 22 23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
Eike Ziller's avatar
Eike Ziller committed
25 26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
con's avatar
con committed
27 28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
con's avatar
con committed
30

31
#include "../tools/qtcreatorcrashhandler/crashhandlersetup.h"
con's avatar
con committed
32

33
#include <app/app_version.h>
con's avatar
con committed
34
#include <extensionsystem/iplugin.h>
35
#include <extensionsystem/pluginerroroverview.h>
Yuchen Deng's avatar
Yuchen Deng committed
36 37
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
38
#include <qtsingleapplication.h>
39
#include <utils/fileutils.h>
Christian Kandeler's avatar
Christian Kandeler committed
40
#include <utils/hostosinfo.h>
con's avatar
con committed
41

42 43 44 45
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QLibraryInfo>
46
#include <QLoggingCategory>
47
#include <QSettings>
48
#include <QStyle>
49 50 51 52 53 54
#include <QTextStream>
#include <QThreadPool>
#include <QTimer>
#include <QTranslator>
#include <QUrl>
#include <QVariant>
con's avatar
con committed
55

56
#include <QNetworkProxyFactory>
57

58 59
#include <QApplication>
#include <QMessageBox>
60
#include <QStandardPaths>
61
#include <QTemporaryDir>
con's avatar
con committed
62

Marco Bubke's avatar
Marco Bubke committed
63 64 65 66
#ifdef ENABLE_QT_BREAKPAD
#include <qtsystemexceptionhandler.h>
#endif

67 68
using namespace ExtensionSystem;

69
enum { OptionIndent = 4, DescriptionIndent = 34 };
con's avatar
con committed
70

71 72 73
const char appNameC[] = "Qt Creator";
const char corePluginNameC[] = "Core";
const char fixedOptionsC[] =
con's avatar
con committed
74 75
" [OPTION]... [FILE]...\n"
"Options:\n"
76 77
"    -help                         Display this help\n"
"    -version                      Display program version\n"
78 79
"    -client                       Attempt to connect to already running first instance\n"
"    -settingspath <path>          Override the default path where user settings are stored\n"
80
"    -pid <pid>                    Attempt to connect to instance given by pid\n"
81 82
"    -block                        Block until editor is closed\n"
"    -pluginpath <path>            Add a custom search path for plugins\n";
con's avatar
con committed
83

84 85 86 87 88 89 90 91 92 93 94
const char HELP_OPTION1[] = "-h";
const char HELP_OPTION2[] = "-help";
const char HELP_OPTION3[] = "/h";
const char HELP_OPTION4[] = "--help";
const char VERSION_OPTION[] = "-version";
const char CLIENT_OPTION[] = "-client";
const char SETTINGS_OPTION[] = "-settingspath";
const char TEST_OPTION[] = "-test";
const char PID_OPTION[] = "-pid";
const char BLOCK_OPTION[] = "-block";
const char PLUGINPATH_OPTION[] = "-pluginpath";
con's avatar
con committed
95

96
typedef QList<PluginSpec *> PluginSpecSet;
con's avatar
con committed
97 98

// Helpers for displaying messages. Note that there is no console on Windows.
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
99
#ifdef Q_OS_WIN
con's avatar
con committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
// Format as <pre> HTML
static inline void toHtml(QString &t)
{
    t.replace(QLatin1Char('&'), QLatin1String("&amp;"));
    t.replace(QLatin1Char('<'), QLatin1String("&lt;"));
    t.replace(QLatin1Char('>'), QLatin1String("&gt;"));
    t.insert(0, QLatin1String("<html><pre>"));
    t.append(QLatin1String("</pre></html>"));
}

static void displayHelpText(QString t) // No console on Windows.
{
    toHtml(t);
    QMessageBox::information(0, QLatin1String(appNameC), t);
}

static void displayError(const QString &t) // No console on Windows.
{
    QMessageBox::critical(0, QLatin1String(appNameC), t);
}

#else

static void displayHelpText(const QString &t)
{
125
    qWarning("%s", qPrintable(t));
con's avatar
con committed
126 127 128 129
}

static void displayError(const QString &t)
{
130
    qCritical("%s", qPrintable(t));
con's avatar
con committed
131 132 133 134
}

#endif

135
static void printVersion(const PluginSpec *coreplugin)
con's avatar
con committed
136 137 138 139
{
    QString version;
    QTextStream str(&version);
    str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
140
    PluginManager::formatPluginVersions(str);
con's avatar
con committed
141 142 143 144
    str << '\n' << coreplugin->copyright() << '\n';
    displayHelpText(version);
}

145
static void printHelp(const QString &a0)
con's avatar
con committed
146 147 148
{
    QString help;
    QTextStream str(&help);
Yuchen Deng's avatar
Yuchen Deng committed
149
    str << "Usage: " << a0 << fixedOptionsC;
150 151
    PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
    PluginManager::formatPluginOptions(str, OptionIndent, DescriptionIndent);
con's avatar
con committed
152 153 154 155 156 157 158 159
    displayHelpText(help);
}

static inline QString msgCoreLoadFailure(const QString &why)
{
    return QCoreApplication::translate("Application", "Failed to load core: %1").arg(why);
}

160
static inline int askMsgSendFailed()
con's avatar
con committed
161
{
162
    return QMessageBox::question(0, QApplication::translate("Application","Could not send message"),
163
                                 QCoreApplication::translate("Application", "Unable to send command line arguments to the already running instance. "
164 165 166
                                                             "It appears to be not responding. Do you want to start a new instance of Creator?"),
                                 QMessageBox::Yes | QMessageBox::No | QMessageBox::Retry,
                                 QMessageBox::Retry);
con's avatar
con committed
167 168
}

169 170 171 172 173 174 175 176
// taken from utils/fileutils.cpp. We can not use utils here since that depends app_version.h.
static bool copyRecursively(const QString &srcFilePath,
                            const QString &tgtFilePath)
{
    QFileInfo srcFileInfo(srcFilePath);
    if (srcFileInfo.isDir()) {
        QDir targetDir(tgtFilePath);
        targetDir.cdUp();
177
        if (!targetDir.mkdir(Utils::FileName::fromString(tgtFilePath).fileName()))
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
            return false;
        QDir sourceDir(srcFilePath);
        QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
        foreach (const QString &fileName, fileNames) {
            const QString newSrcFilePath
                    = srcFilePath + QLatin1Char('/') + fileName;
            const QString newTgtFilePath
                    = tgtFilePath + QLatin1Char('/') + fileName;
            if (!copyRecursively(newSrcFilePath, newTgtFilePath))
                return false;
        }
    } else {
        if (!QFile::copy(srcFilePath, tgtFilePath))
            return false;
    }
    return true;
}

Eike Ziller's avatar
Eike Ziller committed
196
static inline QStringList getPluginPaths()
con's avatar
con committed
197 198 199 200 201
{
    QStringList rc;
    // Figure out root:  Up one from 'bin'
    QDir rootDir = QApplication::applicationDirPath();
    rootDir.cdUp();
202
    const QString rootDirPath = rootDir.canonicalPath();
203
#if !defined(Q_OS_MAC)
204
    // 1) "plugins" (Win/Linux)
con's avatar
con committed
205
    QString pluginPath = rootDirPath;
206
    pluginPath += QLatin1Char('/');
207
    pluginPath += QLatin1String(IDE_LIBRARY_BASENAME);
208
    pluginPath += QLatin1String("/qtcreator/plugins");
con's avatar
con committed
209
    rc.push_back(pluginPath);
210
#else
211
    // 2) "PlugIns" (OS X)
212
    QString pluginPath = rootDirPath;
213
    pluginPath += QLatin1String("/PlugIns");
con's avatar
con committed
214
    rc.push_back(pluginPath);
215
#endif
216 217
    // 3) <localappdata>/plugins/<ideversion>
    //    where <localappdata> is e.g.
218 219 220
    //    "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
    //    "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux
    //    "~/Library/Application Support/QtProject/Qt Creator" on Mac
221 222 223 224
    pluginPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
    pluginPath += QLatin1String("/data");
#endif
225 226 227
    pluginPath += QLatin1Char('/')
            + QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)
            + QLatin1Char('/');
228 229 230 231 232 233
#if !defined(Q_OS_MAC)
    pluginPath += QLatin1String("qtcreator");
#else
    pluginPath += QLatin1String("Qt Creator");
#endif
    pluginPath += QLatin1String("/plugins/");
234 235
    pluginPath += QLatin1String(Core::Constants::IDE_VERSION_LONG);
    rc.push_back(pluginPath);
con's avatar
con committed
236 237 238
    return rc;
}

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
static QSettings *createUserSettings()
{
    return new QSettings(QSettings::IniFormat, QSettings::UserScope,
                         QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
                         QLatin1String("QtCreator"));
}

static inline QSettings *userSettings()
{
    QSettings *settings = createUserSettings();
    const QString fromVariant = QLatin1String(Core::Constants::IDE_COPY_SETTINGS_FROM_VARIANT_STR);
    if (fromVariant.isEmpty())
        return settings;

    // Copy old settings to new ones:
    QFileInfo pathFi = QFileInfo(settings->fileName());
    if (pathFi.exists()) // already copied.
        return settings;

    QDir destDir = pathFi.absolutePath();
    if (!destDir.exists())
        destDir.mkpath(pathFi.absolutePath());

    QDir srcDir = destDir;
    srcDir.cdUp();
    if (!srcDir.cd(fromVariant))
        return settings;

    if (srcDir == destDir) // Nothing to copy and no settings yet
        return settings;

    QStringList entries = srcDir.entryList();
    foreach (const QString &file, entries) {
        const QString lowerFile = file.toLower();
        if (lowerFile.startsWith(QLatin1String("profiles.xml"))
                || lowerFile.startsWith(QLatin1String("toolchains.xml"))
                || lowerFile.startsWith(QLatin1String("qtversion.xml"))
                || lowerFile.startsWith(QLatin1String("devices.xml"))
277
                || lowerFile.startsWith(QLatin1String("debuggers.xml"))
278 279 280 281 282 283 284 285 286 287 288
                || lowerFile.startsWith(QLatin1String("qtcreator.")))
            QFile::copy(srcDir.absoluteFilePath(file), destDir.absoluteFilePath(file));
        if (file == QLatin1String("qtcreator"))
            copyRecursively(srcDir.absoluteFilePath(file), destDir.absoluteFilePath(file));
    }

    // Make sure to use the copied settings:
    delete settings;
    return createUserSettings();
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
289 290 291 292 293 294
#ifdef Q_OS_MAC
#  define SHARE_PATH "/../Resources"
#else
#  define SHARE_PATH "/../share/qtcreator"
#endif

con's avatar
con committed
295 296
int main(int argc, char **argv)
{
297
#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
298 299
    if (Utils::HostOsInfo().isWindowsHost()
            && !qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO")) {
300
        qputenv("QT_DEVICE_PIXEL_RATIO", "auto");
301
    }
302 303
#else
    qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
304 305
#endif // < Qt 5.6

306
    QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false"));
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
307
#ifdef Q_OS_MAC
con's avatar
con committed
308 309 310
    // increase the number of file that can be opened in Qt Creator.
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE, &rl);
311 312

    rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
con's avatar
con committed
313 314 315 316
    setrlimit(RLIMIT_NOFILE, &rl);
#endif

    SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
317

318 319
    if (Utils::HostOsInfo().isWindowsHost()
            && !qFuzzyCompare(qApp->devicePixelRatio(), 1.0)
320 321 322 323
            && QApplication::style()->objectName().startsWith(
                QLatin1String("windows"), Qt::CaseInsensitive)) {
        QApplication::setStyle(QLatin1String("fusion"));
    }
324 325 326
    const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
    QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));

327
    CrashHandlerSetup setupCrashHandler; // Display a backtrace once a serious signal is delivered.
328

Marco Bubke's avatar
Marco Bubke committed
329 330 331 332
#ifdef ENABLE_QT_BREAKPAD
    QtSystemExceptionHandler systemExceptionHandler;
#endif

333 334
    app.setAttribute(Qt::AA_UseHighDpiPixmaps);

335
    // Manually determine -settingspath command line option
336
    // We can't use the regular way of the plugin manager, because that needs to parse plugin meta data
337 338
    // but the settings path can influence which plugins are enabled
    QString settingsPath;
339
    QStringList customPluginPaths;
Yuchen Deng's avatar
Yuchen Deng committed
340
    QStringList arguments = app.arguments(); // adapted arguments list is passed to plugin manager later
341
    QMutableStringListIterator it(arguments);
342
    bool testOptionProvided = false;
343 344 345 346 347 348 349 350
    while (it.hasNext()) {
        const QString &arg = it.next();
        if (arg == QLatin1String(SETTINGS_OPTION)) {
            it.remove();
            if (it.hasNext()) {
                settingsPath = QDir::fromNativeSeparators(it.next());
                it.remove();
            }
351 352 353 354 355 356
        } else if (arg == QLatin1String(PLUGINPATH_OPTION)) {
            it.remove();
            if (it.hasNext()) {
                customPluginPaths << QDir::fromNativeSeparators(it.next());
                it.remove();
            }
357 358
        } else if (arg == QLatin1String(TEST_OPTION)) {
            testOptionProvided = true;
359 360
        }
    }
361
    QScopedPointer<QTemporaryDir> temporaryCleanSettingsDir;
362
    if (settingsPath.isEmpty() && testOptionProvided) {
363 364 365 366 367 368
        const QString settingsPathTemplate = QDir::cleanPath(QDir::tempPath()
            + QString::fromLatin1("/qtc-test-settings-XXXXXX"));
        temporaryCleanSettingsDir.reset(new QTemporaryDir(settingsPathTemplate));
        if (!temporaryCleanSettingsDir->isValid())
            return 1;
        settingsPath = temporaryCleanSettingsDir->path();
369
    }
370 371 372
    if (!settingsPath.isEmpty())
        QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, settingsPath);

373
    // Must be done before any QSettings class is created
con's avatar
con committed
374
    QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
Yuchen Deng's avatar
Yuchen Deng committed
375
                       QCoreApplication::applicationDirPath() + QLatin1String(SHARE_PATH));
376
    QSettings::setDefaultFormat(QSettings::IniFormat);
377
    // plugin manager takes control of this settings object
378 379
    QSettings *settings = userSettings();

380
    QSettings *globalSettings = new QSettings(QSettings::IniFormat, QSettings::SystemScope,
381 382
                                              QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
                                              QLatin1String("QtCreator"));
383
    PluginManager pluginManager;
384
    PluginManager::setPluginIID(QLatin1String("org.qt-project.Qt.QtCreatorPlugin"));
385 386
    PluginManager::setGlobalSettings(globalSettings);
    PluginManager::setSettings(settings);
387

388 389 390 391
    QTranslator translator;
    QTranslator qtTranslator;
    QStringList uiLanguages;
    uiLanguages = QLocale::system().uiLanguages();
392
    QString overrideLanguage = settings->value(QLatin1String("General/OverrideLanguage")).toString();
393 394
    if (!overrideLanguage.isEmpty())
        uiLanguages.prepend(overrideLanguage);
395
    const QString &creatorTrPath = QCoreApplication::applicationDirPath()
Yuchen Deng's avatar
Yuchen Deng committed
396
            + QLatin1String(SHARE_PATH "/translations");
397
    foreach (QString locale, uiLanguages) {
Liang Qi's avatar
Liang Qi committed
398
        locale = QLocale(locale).name();
399 400 401 402 403 404 405 406 407 408
        if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
            const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
            const QString &qtTrFile = QLatin1String("qt_") + locale;
            // Binary installer puts Qt tr files into creatorTrPath
            if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, creatorTrPath)) {
                app.installTranslator(&translator);
                app.installTranslator(&qtTranslator);
                app.setProperty("qtc_locale", locale);
                break;
            }
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
409
            translator.load(QString()); // unload()
410 411 412 413 414 415
        } else if (locale == QLatin1String("C") /* overrideLanguage == "English" */) {
            // use built-in
            break;
        } else if (locale.startsWith(QLatin1String("en")) /* "English" is built-in */) {
            // use built-in
            break;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
416 417 418
        }
    }

419
    // Make sure we honor the system's proxy settings
Eike Ziller's avatar
Eike Ziller committed
420
    QNetworkProxyFactory::setUseSystemConfiguration(true);
421

con's avatar
con committed
422
    // Load
423
    const QStringList pluginPaths = getPluginPaths() + customPluginPaths;
424
    PluginManager::setPluginPaths(pluginPaths);
hjk's avatar
hjk committed
425
    QMap<QString, QString> foundAppOptions;
con's avatar
con committed
426
    if (arguments.size() > 1) {
hjk's avatar
hjk committed
427
        QMap<QString, bool> appOptions;
con's avatar
con committed
428 429 430 431 432 433
        appOptions.insert(QLatin1String(HELP_OPTION1), false);
        appOptions.insert(QLatin1String(HELP_OPTION2), false);
        appOptions.insert(QLatin1String(HELP_OPTION3), false);
        appOptions.insert(QLatin1String(HELP_OPTION4), false);
        appOptions.insert(QLatin1String(VERSION_OPTION), false);
        appOptions.insert(QLatin1String(CLIENT_OPTION), false);
434
        appOptions.insert(QLatin1String(PID_OPTION), true);
435
        appOptions.insert(QLatin1String(BLOCK_OPTION), false);
con's avatar
con committed
436
        QString errorMessage;
437
        if (!PluginManager::parseOptions(arguments, appOptions, &foundAppOptions, &errorMessage)) {
con's avatar
con committed
438
            displayError(errorMessage);
439
            printHelp(QFileInfo(app.applicationFilePath()).baseName());
con's avatar
con committed
440 441 442 443
            return -1;
        }
    }

444 445 446
    const PluginSpecSet plugins = PluginManager::plugins();
    PluginSpec *coreplugin = 0;
    foreach (PluginSpec *spec, plugins) {
con's avatar
con committed
447 448 449 450 451 452
        if (spec->name() == QLatin1String(corePluginNameC)) {
            coreplugin = spec;
            break;
        }
    }
    if (!coreplugin) {
hjk's avatar
hjk committed
453
        QString nativePaths = QDir::toNativeSeparators(pluginPaths.join(QLatin1Char(',')));
454
        const QString reason = QCoreApplication::translate("Application", "Could not find Core plugin in %1").arg(nativePaths);
con's avatar
con committed
455 456 457
        displayError(msgCoreLoadFailure(reason));
        return 1;
    }
458 459 460 461 462
    if (!coreplugin->isEffectivelyEnabled()) {
        const QString reason = QCoreApplication::translate("Application", "Core plugin is disabled.");
        displayError(msgCoreLoadFailure(reason));
        return 1;
    }
con's avatar
con committed
463 464 465 466 467
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    if (foundAppOptions.contains(QLatin1String(VERSION_OPTION))) {
468
        printVersion(coreplugin);
con's avatar
con committed
469 470 471 472 473 474
        return 0;
    }
    if (foundAppOptions.contains(QLatin1String(HELP_OPTION1))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION2))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION3))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION4))) {
475
        printHelp(QFileInfo(app.applicationFilePath()).baseName());
con's avatar
con committed
476 477 478
        return 0;
    }

479 480 481 482 483 484 485 486 487
    qint64 pid = -1;
    if (foundAppOptions.contains(QLatin1String(PID_OPTION))) {
        QString pidString = foundAppOptions.value(QLatin1String(PID_OPTION));
        bool pidOk;
        qint64 tmpPid = pidString.toInt(&pidOk);
        if (pidOk)
            pid = tmpPid;
    }

488 489 490 491
    bool isBlock = foundAppOptions.contains(QLatin1String(BLOCK_OPTION));
    if (app.isRunning() && (pid != -1 || isBlock
                            || foundAppOptions.contains(QLatin1String(CLIENT_OPTION)))) {
        app.setBlock(isBlock);
492
        if (app.sendMessage(PluginManager::serializedArguments(), 5000 /*timeout*/, pid))
493 494 495
            return 0;

        // Message could not be send, maybe it was in the process of quitting
496
        if (app.isRunning(pid)) {
497 498
            // Nah app is still running, ask the user
            int button = askMsgSendFailed();
499
            while (button == QMessageBox::Retry) {
500
                if (app.sendMessage(PluginManager::serializedArguments(), 5000 /*timeout*/, pid))
501
                    return 0;
502
                if (!app.isRunning(pid)) // App quit while we were trying so start a new creator
503 504 505 506 507 508
                    button = QMessageBox::Yes;
                else
                    button = askMsgSendFailed();
            }
            if (button == QMessageBox::No)
                return -1;
509 510
        }
    }
con's avatar
con committed
511

512
    PluginManager::loadPlugins();
con's avatar
con committed
513 514 515 516
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
517

Orgad Shaneh's avatar
Orgad Shaneh committed
518
    // Set up remote arguments.
519 520
    QObject::connect(&app, SIGNAL(messageReceived(QString,QObject*)),
                     &pluginManager, SLOT(remoteArguments(QString,QObject*)));
Yuchen Deng's avatar
Yuchen Deng committed
521 522 523

    QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(),
                     SLOT(fileOpenRequest(QString)));
con's avatar
con committed
524

525 526 527
    // shutdown plugin manager on the exit
    QObject::connect(&app, SIGNAL(aboutToQuit()), &pluginManager, SLOT(shutdown()));

528
    return app.exec();
con's avatar
con committed
529
}