2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2016-01-15 14:58:39 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-07-04 14:16:26 +02:00
|
|
|
#include "../tools/qtcreatorcrashhandler/crashhandlersetup.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-08-29 16:27:26 +02:00
|
|
|
#include <app/app_version.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <extensionsystem/iplugin.h>
|
2011-08-29 15:59:31 +02:00
|
|
|
#include <extensionsystem/pluginerroroverview.h>
|
2011-10-22 22:19:46 +08:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
|
#include <extensionsystem/pluginspec.h>
|
2013-08-29 16:36:42 +02:00
|
|
|
#include <qtsingleapplication.h>
|
2015-01-10 23:40:32 +02:00
|
|
|
#include <utils/fileutils.h>
|
2013-10-07 11:06:41 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDebug>
|
|
|
|
|
#include <QDir>
|
2016-07-15 16:33:15 +02:00
|
|
|
#include <QFontDatabase>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QLibraryInfo>
|
2014-08-26 15:53:13 +02:00
|
|
|
#include <QLoggingCategory>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QSettings>
|
2015-04-20 12:36:12 +02:00
|
|
|
#include <QStyle>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QTextStream>
|
|
|
|
|
#include <QThreadPool>
|
|
|
|
|
#include <QTimer>
|
|
|
|
|
#include <QTranslator>
|
|
|
|
|
#include <QUrl>
|
|
|
|
|
#include <QVariant>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QNetworkProxyFactory>
|
2010-02-18 17:36:17 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QApplication>
|
|
|
|
|
#include <QMessageBox>
|
2014-08-28 17:33:47 +02:00
|
|
|
#include <QStandardPaths>
|
2014-12-10 10:27:42 +01:00
|
|
|
#include <QTemporaryDir>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-09-09 19:37:01 +02:00
|
|
|
#ifdef ENABLE_QT_BREAKPAD
|
|
|
|
|
#include <qtsystemexceptionhandler.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-06-18 11:34:15 +02:00
|
|
|
using namespace ExtensionSystem;
|
|
|
|
|
|
2010-10-25 18:02:27 +02:00
|
|
|
enum { OptionIndent = 4, DescriptionIndent = 34 };
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-09-26 13:01:29 +02:00
|
|
|
const char appNameC[] = "Qt Creator";
|
|
|
|
|
const char corePluginNameC[] = "Core";
|
|
|
|
|
const char fixedOptionsC[] =
|
2008-12-02 12:01:29 +01:00
|
|
|
" [OPTION]... [FILE]...\n"
|
|
|
|
|
"Options:\n"
|
2010-10-25 18:02:27 +02:00
|
|
|
" -help Display this help\n"
|
|
|
|
|
" -version Display program version\n"
|
2012-01-22 11:02:41 -05:00
|
|
|
" -client Attempt to connect to already running first instance\n"
|
|
|
|
|
" -settingspath <path> Override the default path where user settings are stored\n"
|
2013-03-11 18:15:49 +02:00
|
|
|
" -pid <pid> Attempt to connect to instance given by pid\n"
|
2013-06-25 14:20:45 +02:00
|
|
|
" -block Block until editor is closed\n"
|
|
|
|
|
" -pluginpath <path> Add a custom search path for plugins\n";
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-09-26 13:01:29 +02:00
|
|
|
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";
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-06-18 11:34:15 +02:00
|
|
|
typedef QList<PluginSpec *> PluginSpecSet;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
// Helpers for displaying messages. Note that there is no console on Windows.
|
|
|
|
|
|
2015-07-19 10:51:34 +03:00
|
|
|
// Format as <pre> HTML
|
|
|
|
|
static inline QString toHtml(const QString &t)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-07-19 10:51:34 +03:00
|
|
|
QString res = t;
|
|
|
|
|
res.replace(QLatin1Char('&'), QLatin1String("&"));
|
|
|
|
|
res.replace(QLatin1Char('<'), QLatin1String("<"));
|
|
|
|
|
res.replace(QLatin1Char('>'), QLatin1String(">"));
|
|
|
|
|
res.insert(0, QLatin1String("<html><pre>"));
|
|
|
|
|
res.append(QLatin1String("</pre></html>"));
|
|
|
|
|
return res;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void displayHelpText(const QString &t)
|
|
|
|
|
{
|
2015-07-19 10:51:34 +03:00
|
|
|
if (Utils::HostOsInfo::isWindowsHost())
|
|
|
|
|
QMessageBox::information(0, QLatin1String(appNameC), toHtml(t));
|
|
|
|
|
else
|
|
|
|
|
qWarning("%s", qPrintable(t));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void displayError(const QString &t)
|
|
|
|
|
{
|
2015-07-19 10:51:34 +03:00
|
|
|
if (Utils::HostOsInfo::isWindowsHost())
|
|
|
|
|
QMessageBox::critical(0, QLatin1String(appNameC), t);
|
|
|
|
|
else
|
|
|
|
|
qCritical("%s", qPrintable(t));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2012-06-18 11:34:15 +02:00
|
|
|
static void printVersion(const PluginSpec *coreplugin)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
QString version;
|
|
|
|
|
QTextStream str(&version);
|
|
|
|
|
str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
|
2012-06-18 11:34:15 +02:00
|
|
|
PluginManager::formatPluginVersions(str);
|
2008-12-02 12:01:29 +01:00
|
|
|
str << '\n' << coreplugin->copyright() << '\n';
|
|
|
|
|
displayHelpText(version);
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-18 11:34:15 +02:00
|
|
|
static void printHelp(const QString &a0)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
QString help;
|
|
|
|
|
QTextStream str(&help);
|
2011-10-22 22:19:46 +08:00
|
|
|
str << "Usage: " << a0 << fixedOptionsC;
|
2012-06-18 11:34:15 +02:00
|
|
|
PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
|
|
|
|
|
PluginManager::formatPluginOptions(str, OptionIndent, DescriptionIndent);
|
2008-12-02 12:01:29 +01:00
|
|
|
displayHelpText(help);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline QString msgCoreLoadFailure(const QString &why)
|
|
|
|
|
{
|
|
|
|
|
return QCoreApplication::translate("Application", "Failed to load core: %1").arg(why);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-24 17:07:37 +01:00
|
|
|
static inline int askMsgSendFailed()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2011-03-24 17:07:37 +01:00
|
|
|
return QMessageBox::question(0, QApplication::translate("Application","Could not send message"),
|
2011-10-05 20:13:49 +02:00
|
|
|
QCoreApplication::translate("Application", "Unable to send command line arguments to the already running instance. "
|
2011-03-24 17:07:37 +01:00
|
|
|
"It appears to be not responding. Do you want to start a new instance of Creator?"),
|
|
|
|
|
QMessageBox::Yes | QMessageBox::No | QMessageBox::Retry,
|
|
|
|
|
QMessageBox::Retry);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-11-10 15:51:57 +01:00
|
|
|
static const char *setHighDpiEnvironmentVariable()
|
2015-11-03 16:00:10 +01:00
|
|
|
{
|
|
|
|
|
const char* envVarName = 0;
|
|
|
|
|
static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO";
|
|
|
|
|
if (Utils::HostOsInfo().isWindowsHost()
|
|
|
|
|
&& !qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) // legacy in 5.6, but still functional
|
2015-11-10 15:51:57 +01:00
|
|
|
&& !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR")
|
2015-11-03 16:00:10 +01:00
|
|
|
&& !qEnvironmentVariableIsSet("QT_SCALE_FACTOR")
|
|
|
|
|
&& !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) {
|
2015-11-10 15:51:57 +01:00
|
|
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
2015-11-03 16:00:10 +01:00
|
|
|
}
|
|
|
|
|
return envVarName;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 14:35:41 +02:00
|
|
|
// 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();
|
2015-01-10 23:40:32 +02:00
|
|
|
if (!targetDir.mkdir(Utils::FileName::fromString(tgtFilePath).fileName()))
|
2012-10-08 14:35:41 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-07 10:41:52 +02:00
|
|
|
static inline QStringList getPluginPaths()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
QStringList rc;
|
|
|
|
|
// Figure out root: Up one from 'bin'
|
|
|
|
|
QDir rootDir = QApplication::applicationDirPath();
|
|
|
|
|
rootDir.cdUp();
|
2009-07-23 17:04:22 +02:00
|
|
|
const QString rootDirPath = rootDir.canonicalPath();
|
2015-07-19 10:51:34 +03:00
|
|
|
QString pluginPath;
|
|
|
|
|
if (Utils::HostOsInfo::isMacHost()) {
|
|
|
|
|
// 1) "PlugIns" (OS X)
|
|
|
|
|
pluginPath = rootDirPath + QLatin1String("/PlugIns");
|
|
|
|
|
rc.push_back(pluginPath);
|
|
|
|
|
} else {
|
|
|
|
|
// 2) "plugins" (Win/Linux)
|
|
|
|
|
pluginPath = rootDirPath;
|
|
|
|
|
pluginPath += QLatin1Char('/');
|
|
|
|
|
pluginPath += QLatin1String(IDE_LIBRARY_BASENAME);
|
|
|
|
|
pluginPath += QLatin1String("/qtcreator/plugins");
|
|
|
|
|
rc.push_back(pluginPath);
|
|
|
|
|
}
|
2011-08-29 16:27:26 +02:00
|
|
|
// 3) <localappdata>/plugins/<ideversion>
|
|
|
|
|
// where <localappdata> is e.g.
|
2012-11-28 19:54:34 +01:00
|
|
|
// "%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
|
2015-08-21 12:41:46 +02:00
|
|
|
pluginPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
|
2016-09-10 22:56:04 +03:00
|
|
|
if (Utils::HostOsInfo::isAnyUnixHost() && !Utils::HostOsInfo::isMacHost())
|
|
|
|
|
pluginPath += QLatin1String("/data");
|
2011-11-23 16:56:50 +01:00
|
|
|
pluginPath += QLatin1Char('/')
|
|
|
|
|
+ QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)
|
|
|
|
|
+ QLatin1Char('/');
|
2015-07-19 10:51:34 +03:00
|
|
|
pluginPath += QLatin1String(Utils::HostOsInfo::isMacHost() ? "Qt Creator" : "qtcreator");
|
2011-10-06 09:46:03 +02:00
|
|
|
pluginPath += QLatin1String("/plugins/");
|
2011-08-29 16:27:26 +02:00
|
|
|
pluginPath += QLatin1String(Core::Constants::IDE_VERSION_LONG);
|
|
|
|
|
rc.push_back(pluginPath);
|
2008-12-02 12:01:29 +01:00
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 14:35:41 +02:00
|
|
|
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"))
|
2013-09-03 12:31:28 +02:00
|
|
|
|| lowerFile.startsWith(QLatin1String("debuggers.xml"))
|
2012-10-08 14:35:41 +02:00
|
|
|
|| 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();
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-19 10:51:34 +03:00
|
|
|
static const char *SHARE_PATH =
|
|
|
|
|
Utils::HostOsInfo::isMacHost() ? "/../Resources" : "/../share/qtcreator";
|
2009-04-20 16:41:06 +02:00
|
|
|
|
2016-07-15 16:33:15 +02:00
|
|
|
void loadFonts()
|
|
|
|
|
{
|
2016-07-18 08:19:24 +02:00
|
|
|
const QDir dir(QCoreApplication::applicationDirPath() + QLatin1String(SHARE_PATH)
|
|
|
|
|
+ QLatin1String("/fonts/"));
|
2016-07-15 16:33:15 +02:00
|
|
|
|
2016-07-18 22:33:20 +02:00
|
|
|
foreach (const QFileInfo &fileInfo, dir.entryInfoList(QStringList("*.ttf"), QDir::Files))
|
2016-07-15 16:33:15 +02:00
|
|
|
QFontDatabase::addApplicationFont(fileInfo.absoluteFilePath());
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
|
{
|
2015-11-10 15:51:57 +01:00
|
|
|
const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable();
|
2015-08-19 09:54:26 +02:00
|
|
|
|
2016-08-24 13:31:26 +02:00
|
|
|
QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false\nqtc.*.info=false"));
|
|
|
|
|
|
2009-06-03 20:45:49 +02:00
|
|
|
#ifdef Q_OS_MAC
|
2008-12-02 12:01:29 +01:00
|
|
|
// increase the number of file that can be opened in Qt Creator.
|
|
|
|
|
struct rlimit rl;
|
|
|
|
|
getrlimit(RLIMIT_NOFILE, &rl);
|
2010-05-28 13:45:53 +02:00
|
|
|
|
|
|
|
|
rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
|
2008-12-02 12:01:29 +01:00
|
|
|
setrlimit(RLIMIT_NOFILE, &rl);
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-11-18 14:01:01 +01:00
|
|
|
SharedTools::QtSingleApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
|
2008-12-02 12:01:29 +01:00
|
|
|
SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);
|
2009-04-20 16:41:06 +02:00
|
|
|
|
2016-07-15 16:33:15 +02:00
|
|
|
loadFonts();
|
|
|
|
|
|
2015-11-03 16:00:10 +01:00
|
|
|
if (highDpiEnvironmentVariable)
|
|
|
|
|
qunsetenv(highDpiEnvironmentVariable);
|
|
|
|
|
|
2015-06-04 12:38:12 +02:00
|
|
|
if (Utils::HostOsInfo().isWindowsHost()
|
|
|
|
|
&& !qFuzzyCompare(qApp->devicePixelRatio(), 1.0)
|
2015-04-20 12:36:12 +02:00
|
|
|
&& QApplication::style()->objectName().startsWith(
|
|
|
|
|
QLatin1String("windows"), Qt::CaseInsensitive)) {
|
|
|
|
|
QApplication::setStyle(QLatin1String("fusion"));
|
|
|
|
|
}
|
2010-09-13 11:54:55 +02:00
|
|
|
const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
|
|
|
|
|
QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));
|
|
|
|
|
|
2016-11-02 11:17:37 +01:00
|
|
|
// Display a backtrace once a serious signal is delivered (Linux only).
|
|
|
|
|
const QString libexecPath = QCoreApplication::applicationDirPath() + "/../libexec/qtcreator";
|
|
|
|
|
CrashHandlerSetup setupCrashHandler(appNameC, CrashHandlerSetup::EnableRestart, libexecPath);
|
2012-07-04 14:16:26 +02:00
|
|
|
|
2010-09-09 19:37:01 +02:00
|
|
|
#ifdef ENABLE_QT_BREAKPAD
|
|
|
|
|
QtSystemExceptionHandler systemExceptionHandler;
|
|
|
|
|
#endif
|
|
|
|
|
|
2013-01-16 22:06:59 +01:00
|
|
|
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
|
|
|
|
2010-10-25 18:02:27 +02:00
|
|
|
// Manually determine -settingspath command line option
|
2014-08-26 17:29:38 +02:00
|
|
|
// We can't use the regular way of the plugin manager, because that needs to parse plugin meta data
|
2010-10-25 18:02:27 +02:00
|
|
|
// but the settings path can influence which plugins are enabled
|
|
|
|
|
QString settingsPath;
|
2013-06-25 14:20:45 +02:00
|
|
|
QStringList customPluginPaths;
|
2011-10-22 22:19:46 +08:00
|
|
|
QStringList arguments = app.arguments(); // adapted arguments list is passed to plugin manager later
|
2010-10-25 18:02:27 +02:00
|
|
|
QMutableStringListIterator it(arguments);
|
2013-09-03 15:17:24 +02:00
|
|
|
bool testOptionProvided = false;
|
2010-10-25 18:02:27 +02:00
|
|
|
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();
|
|
|
|
|
}
|
2013-06-25 14:20:45 +02:00
|
|
|
} else if (arg == QLatin1String(PLUGINPATH_OPTION)) {
|
|
|
|
|
it.remove();
|
|
|
|
|
if (it.hasNext()) {
|
|
|
|
|
customPluginPaths << QDir::fromNativeSeparators(it.next());
|
|
|
|
|
it.remove();
|
|
|
|
|
}
|
2013-09-03 15:17:24 +02:00
|
|
|
} else if (arg == QLatin1String(TEST_OPTION)) {
|
|
|
|
|
testOptionProvided = true;
|
2010-10-25 18:02:27 +02:00
|
|
|
}
|
|
|
|
|
}
|
2014-12-10 10:27:42 +01:00
|
|
|
QScopedPointer<QTemporaryDir> temporaryCleanSettingsDir;
|
2013-09-03 15:17:24 +02:00
|
|
|
if (settingsPath.isEmpty() && testOptionProvided) {
|
2014-12-10 10:27:42 +01:00
|
|
|
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();
|
2013-09-03 15:17:24 +02:00
|
|
|
}
|
2010-10-25 18:02:27 +02:00
|
|
|
if (!settingsPath.isEmpty())
|
|
|
|
|
QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, settingsPath);
|
|
|
|
|
|
2010-01-13 17:04:46 +01:00
|
|
|
// Must be done before any QSettings class is created
|
2010-01-14 16:35:44 +01:00
|
|
|
QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
|
2011-10-22 22:19:46 +08:00
|
|
|
QCoreApplication::applicationDirPath() + QLatin1String(SHARE_PATH));
|
2011-11-23 16:56:50 +01:00
|
|
|
QSettings::setDefaultFormat(QSettings::IniFormat);
|
2010-10-25 16:57:58 +02:00
|
|
|
// plugin manager takes control of this settings object
|
2012-10-08 14:35:41 +02:00
|
|
|
QSettings *settings = userSettings();
|
|
|
|
|
|
2011-10-26 14:46:29 +02:00
|
|
|
QSettings *globalSettings = new QSettings(QSettings::IniFormat, QSettings::SystemScope,
|
2011-11-23 16:56:50 +01:00
|
|
|
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
|
|
|
|
|
QLatin1String("QtCreator"));
|
2012-06-18 11:34:15 +02:00
|
|
|
PluginManager pluginManager;
|
2014-08-26 17:29:38 +02:00
|
|
|
PluginManager::setPluginIID(QLatin1String("org.qt-project.Qt.QtCreatorPlugin"));
|
2012-06-18 11:34:15 +02:00
|
|
|
PluginManager::setGlobalSettings(globalSettings);
|
|
|
|
|
PluginManager::setSettings(settings);
|
2010-10-25 16:57:58 +02:00
|
|
|
|
2012-03-26 12:30:33 +02:00
|
|
|
QTranslator translator;
|
|
|
|
|
QTranslator qtTranslator;
|
|
|
|
|
QStringList uiLanguages;
|
|
|
|
|
uiLanguages = QLocale::system().uiLanguages();
|
2013-01-12 23:10:52 +02:00
|
|
|
QString overrideLanguage = settings->value(QLatin1String("General/OverrideLanguage")).toString();
|
2012-03-26 12:30:33 +02:00
|
|
|
if (!overrideLanguage.isEmpty())
|
|
|
|
|
uiLanguages.prepend(overrideLanguage);
|
2009-06-10 13:27:05 +02:00
|
|
|
const QString &creatorTrPath = QCoreApplication::applicationDirPath()
|
2015-07-19 10:51:34 +03:00
|
|
|
+ QLatin1String(SHARE_PATH) + QLatin1String("/translations");
|
2012-05-31 12:22:12 +02:00
|
|
|
foreach (QString locale, uiLanguages) {
|
2012-11-23 11:06:46 +01:00
|
|
|
locale = QLocale(locale).name();
|
2012-03-26 12:30:33 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2009-04-20 16:41:06 +02:00
|
|
|
translator.load(QString()); // unload()
|
2012-03-26 12:30:33 +02:00
|
|
|
} 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;
|
2009-04-20 16:41:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-18 17:36:17 +01:00
|
|
|
// Make sure we honor the system's proxy settings
|
2011-12-08 11:48:58 +01:00
|
|
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
2014-11-27 15:16:57 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
// Load
|
2013-06-25 14:20:45 +02:00
|
|
|
const QStringList pluginPaths = getPluginPaths() + customPluginPaths;
|
2012-06-18 11:34:15 +02:00
|
|
|
PluginManager::setPluginPaths(pluginPaths);
|
2008-12-05 18:29:19 +01:00
|
|
|
QMap<QString, QString> foundAppOptions;
|
2008-12-02 12:01:29 +01:00
|
|
|
if (arguments.size() > 1) {
|
2008-12-05 18:29:19 +01:00
|
|
|
QMap<QString, bool> appOptions;
|
2008-12-02 12:01:29 +01:00
|
|
|
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);
|
2012-01-22 11:02:41 -05:00
|
|
|
appOptions.insert(QLatin1String(PID_OPTION), true);
|
2013-03-11 18:15:49 +02:00
|
|
|
appOptions.insert(QLatin1String(BLOCK_OPTION), false);
|
2008-12-02 12:01:29 +01:00
|
|
|
QString errorMessage;
|
2012-06-18 11:34:15 +02:00
|
|
|
if (!PluginManager::parseOptions(arguments, appOptions, &foundAppOptions, &errorMessage)) {
|
2008-12-02 12:01:29 +01:00
|
|
|
displayError(errorMessage);
|
2012-06-18 11:34:15 +02:00
|
|
|
printHelp(QFileInfo(app.applicationFilePath()).baseName());
|
2008-12-02 12:01:29 +01:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-18 11:34:15 +02:00
|
|
|
const PluginSpecSet plugins = PluginManager::plugins();
|
|
|
|
|
PluginSpec *coreplugin = 0;
|
|
|
|
|
foreach (PluginSpec *spec, plugins) {
|
2008-12-02 12:01:29 +01:00
|
|
|
if (spec->name() == QLatin1String(corePluginNameC)) {
|
|
|
|
|
coreplugin = spec;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!coreplugin) {
|
2014-08-23 01:19:53 +02:00
|
|
|
QString nativePaths = QDir::toNativeSeparators(pluginPaths.join(QLatin1Char(',')));
|
2014-08-26 17:29:38 +02:00
|
|
|
const QString reason = QCoreApplication::translate("Application", "Could not find Core plugin in %1").arg(nativePaths);
|
2008-12-02 12:01:29 +01:00
|
|
|
displayError(msgCoreLoadFailure(reason));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2015-03-30 17:08:05 +02:00
|
|
|
if (!coreplugin->isEffectivelyEnabled()) {
|
|
|
|
|
const QString reason = QCoreApplication::translate("Application", "Core plugin is disabled.");
|
|
|
|
|
displayError(msgCoreLoadFailure(reason));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
if (coreplugin->hasError()) {
|
|
|
|
|
displayError(msgCoreLoadFailure(coreplugin->errorString()));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (foundAppOptions.contains(QLatin1String(VERSION_OPTION))) {
|
2012-06-18 11:34:15 +02:00
|
|
|
printVersion(coreplugin);
|
2008-12-02 12:01:29 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (foundAppOptions.contains(QLatin1String(HELP_OPTION1))
|
|
|
|
|
|| foundAppOptions.contains(QLatin1String(HELP_OPTION2))
|
|
|
|
|
|| foundAppOptions.contains(QLatin1String(HELP_OPTION3))
|
|
|
|
|
|| foundAppOptions.contains(QLatin1String(HELP_OPTION4))) {
|
2012-06-18 11:34:15 +02:00
|
|
|
printHelp(QFileInfo(app.applicationFilePath()).baseName());
|
2008-12-02 12:01:29 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-22 11:02:41 -05:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-11 18:15:49 +02:00
|
|
|
bool isBlock = foundAppOptions.contains(QLatin1String(BLOCK_OPTION));
|
|
|
|
|
if (app.isRunning() && (pid != -1 || isBlock
|
|
|
|
|
|| foundAppOptions.contains(QLatin1String(CLIENT_OPTION)))) {
|
|
|
|
|
app.setBlock(isBlock);
|
2012-06-18 11:34:15 +02:00
|
|
|
if (app.sendMessage(PluginManager::serializedArguments(), 5000 /*timeout*/, pid))
|
2011-03-24 17:07:37 +01:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
// Message could not be send, maybe it was in the process of quitting
|
2012-01-22 11:02:41 -05:00
|
|
|
if (app.isRunning(pid)) {
|
2011-03-24 17:07:37 +01:00
|
|
|
// Nah app is still running, ask the user
|
|
|
|
|
int button = askMsgSendFailed();
|
2012-11-28 20:44:03 +02:00
|
|
|
while (button == QMessageBox::Retry) {
|
2012-06-18 11:34:15 +02:00
|
|
|
if (app.sendMessage(PluginManager::serializedArguments(), 5000 /*timeout*/, pid))
|
2011-03-24 17:07:37 +01:00
|
|
|
return 0;
|
2012-01-22 11:02:41 -05:00
|
|
|
if (!app.isRunning(pid)) // App quit while we were trying so start a new creator
|
2011-03-24 17:07:37 +01:00
|
|
|
button = QMessageBox::Yes;
|
|
|
|
|
else
|
|
|
|
|
button = askMsgSendFailed();
|
|
|
|
|
}
|
|
|
|
|
if (button == QMessageBox::No)
|
|
|
|
|
return -1;
|
2009-12-14 18:01:39 +01:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-06-18 11:34:15 +02:00
|
|
|
PluginManager::loadPlugins();
|
2008-12-02 12:01:29 +01:00
|
|
|
if (coreplugin->hasError()) {
|
|
|
|
|
displayError(msgCoreLoadFailure(coreplugin->errorString()));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2009-09-29 12:05:03 +02:00
|
|
|
|
2013-06-11 23:35:21 +03:00
|
|
|
// Set up remote arguments.
|
2016-05-31 22:35:43 +03:00
|
|
|
QObject::connect(&app, &SharedTools::QtSingleApplication::messageReceived,
|
|
|
|
|
&pluginManager, &PluginManager::remoteArguments);
|
2011-10-22 22:19:46 +08:00
|
|
|
|
|
|
|
|
QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(),
|
|
|
|
|
SLOT(fileOpenRequest(QString)));
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-09-27 14:58:12 +02:00
|
|
|
// shutdown plugin manager on the exit
|
2016-05-31 22:35:43 +03:00
|
|
|
QObject::connect(&app, &QCoreApplication::aboutToQuit, &pluginManager, &PluginManager::shutdown);
|
2010-09-27 14:58:12 +02:00
|
|
|
|
2015-06-10 16:14:51 +02:00
|
|
|
return app.exec();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|