summaryrefslogtreecommitdiff
path: root/src/app/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/main.cpp')
-rw-r--r--src/app/main.cpp285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/app/main.cpp b/src/app/main.cpp
new file mode 100644
index 0000000000..0247b1dde3
--- /dev/null
+++ b/src/app/main.cpp
@@ -0,0 +1,285 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception version
+** 1.2, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include "qtsingleapplication.h"
+
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/pluginspec.h>
+#include <extensionsystem/iplugin.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QApplication>
+#include <QtGui/QMainWindow>
+
+#ifdef Q_OS_DARWIN
+# include <sys/resource.h>
+#endif
+
+enum { OptionIndent =4, DescriptionIndent = 24 };
+
+static const char *appNameC = "Qt Creator";
+static const char *corePluginNameC = "Core";
+static const char *fixedOptionsC =
+" [OPTION]... [FILE]...\n"
+"Options:\n"
+" -help Display this help\n"
+" -version Display program version\n"
+" -client Attempt to connect to already running instance\n";
+
+static const char *HELP_OPTION1 = "-h";
+static const char *HELP_OPTION2 = "-help";
+static const char *HELP_OPTION3 = "/h";
+static const char *HELP_OPTION4 = "--help";
+static const char *VERSION_OPTION = "-version";
+static const char *CLIENT_OPTION = "-client";
+
+typedef QSet<ExtensionSystem::PluginSpec *> PluginSpecSet;
+
+// Helpers for displaying messages. Note that there is no console on Windows.
+#ifdef Q_WS_WIN
+// 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)
+{
+ qWarning(t.toUtf8().constData());
+}
+
+static void displayError(const QString &t)
+{
+ qCritical(t.toUtf8().constData());
+}
+
+#endif
+
+static void printVersion(const ExtensionSystem::PluginSpec *coreplugin,
+ const ExtensionSystem::PluginManager &pm)
+{
+ QString version;
+ QTextStream str(&version);
+ str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
+ pm.formatPluginVersions(str);
+ str << '\n' << coreplugin->copyright() << '\n';
+ displayHelpText(version);
+}
+
+static void printHelp(const QString &a0, const ExtensionSystem::PluginManager &pm)
+{
+ QString help;
+ QTextStream str(&help);
+ str << "Usage: " << a0 << fixedOptionsC;
+ ExtensionSystem::PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
+ pm.formatPluginOptions(str, OptionIndent, DescriptionIndent);
+ displayHelpText(help);
+}
+
+static inline QString msgCoreLoadFailure(const QString &why)
+{
+ return QCoreApplication::translate("Application", "Failed to load core: %1").arg(why);
+}
+
+static inline QString msgSendArgumentFailed()
+{
+ return QCoreApplication::translate("Application", "Unable to send command line arguments to the already running instance. It appears to be not responding.");
+}
+
+// Prepare a remote argument: If it is a relative file, add the current directory
+// since the the central instance might be running in a different directory.
+
+static inline QString prepareRemoteArgument(const QString &a)
+{
+ QFileInfo fi(a);
+ if (!fi.exists())
+ return a;
+ if (fi.isRelative())
+ return fi.absoluteFilePath();
+ return a;
+}
+
+// Send the arguments to an already running instance of Qt Creator
+static bool sendArguments(SharedTools::QtSingleApplication &app, const QStringList &arguments)
+{
+ if (!arguments.empty()) {
+ // Send off arguments
+ const QStringList::const_iterator acend = arguments.constEnd();
+ for (QStringList::const_iterator it = arguments.constBegin(); it != acend; ++it) {
+ if (!app.sendMessage(prepareRemoteArgument(*it))) {
+ displayError(msgSendArgumentFailed());
+ return false;
+ }
+ }
+ }
+ // Special empty argument means: Show and raise (the slot just needs to be triggered)
+ if (!app.sendMessage(QString())) {
+ displayError(msgSendArgumentFailed());
+ return false;
+ }
+ return true;
+}
+
+static inline QStringList getPluginPaths()
+{
+ QStringList rc;
+ // Figure out root: Up one from 'bin'
+ QDir rootDir = QApplication::applicationDirPath();
+ rootDir.cdUp();
+ const QString rootDirPath = rootDir.canonicalPath();
+ // 1) "lib" dir
+ QString pluginPath = rootDirPath;
+ pluginPath += QDir::separator();
+ pluginPath += QLatin1String("lib");
+ rc.push_back(pluginPath);
+ // 2) "PlugIns"
+ pluginPath = rootDirPath;
+ pluginPath += QDir::separator();
+ pluginPath += QLatin1String("PlugIns");
+ rc.push_back(pluginPath);
+ return rc;
+}
+
+int main(int argc, char **argv)
+{
+#ifdef Q_OS_DARWIN
+ // increase the number of file that can be opened in Qt Creator.
+ struct rlimit rl;
+ getrlimit(RLIMIT_NOFILE, &rl);
+ rl.rlim_cur = rl.rlim_max;
+ setrlimit(RLIMIT_NOFILE, &rl);
+#endif
+
+ SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);
+ // Load
+ ExtensionSystem::PluginManager pluginManager;
+ pluginManager.setFileExtension(QLatin1String("pluginspec"));
+
+ const QStringList pluginPaths = getPluginPaths();
+ pluginManager.setPluginPaths(pluginPaths);
+
+ const QStringList arguments = app.arguments();
+ QMap<QString,QString> foundAppOptions;
+ if (arguments.size() > 1) {
+ QMap<QString,bool> appOptions;
+ 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);
+ QString errorMessage;
+ if (!pluginManager.parseOptions(arguments,
+ appOptions,
+ &foundAppOptions,
+ &errorMessage)) {
+ displayError(errorMessage);
+ printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
+ return -1;
+ }
+ }
+
+ const PluginSpecSet plugins = pluginManager.plugins();
+ ExtensionSystem::PluginSpec *coreplugin = 0;
+ foreach (ExtensionSystem::PluginSpec *spec, plugins) {
+ if (spec->name() == QLatin1String(corePluginNameC)) {
+ coreplugin = spec;
+ break;
+ }
+ }
+ if (!coreplugin) {
+ const QString reason = QCoreApplication::translate("Application", "Couldn't find 'Core.pluginspec' in %1").arg(pluginPaths.join(QLatin1String(",")));
+ displayError(msgCoreLoadFailure(reason));
+ return 1;
+ }
+ if (coreplugin->hasError()) {
+ displayError(msgCoreLoadFailure(coreplugin->errorString()));
+ return 1;
+ }
+ if (foundAppOptions.contains(QLatin1String(VERSION_OPTION))) {
+ printVersion(coreplugin, pluginManager);
+ return 0;
+ }
+ if (foundAppOptions.contains(QLatin1String(HELP_OPTION1))
+ || foundAppOptions.contains(QLatin1String(HELP_OPTION2))
+ || foundAppOptions.contains(QLatin1String(HELP_OPTION3))
+ || foundAppOptions.contains(QLatin1String(HELP_OPTION4))) {
+ printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
+ return 0;
+ }
+
+ const bool isFirstInstance = !app.isRunning();
+ if (!isFirstInstance && foundAppOptions.contains(QLatin1String(CLIENT_OPTION)))
+ return sendArguments(app, pluginManager.arguments()) ? 0 : -1;
+
+ pluginManager.loadPlugins();
+ if (coreplugin->hasError()) {
+ displayError(msgCoreLoadFailure(coreplugin->errorString()));
+ return 1;
+ }
+ if (isFirstInstance) {
+ // Set up lock and remote arguments for the first instance only.
+ // Silently fallback to unconnected instances for any subsequent
+ // instances.
+ app.initialize();
+ QObject::connect(&app, SIGNAL(messageReceived(QString)), coreplugin->plugin(), SLOT(remoteArgument(QString)));
+ }
+ QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(), SLOT(remoteArgument(QString)));
+
+ // Do this after the event loop has started
+ QTimer::singleShot(100, &pluginManager, SLOT(startTests()));
+ return app.exec();
+}