mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-12 20:08:48 +01:00
634 lines
22 KiB
C++
634 lines
22 KiB
C++
/**
|
|
******************************************************************************
|
|
*
|
|
* @file main.cpp
|
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
|
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
|
|
* @brief
|
|
* @see The GNU Public License (GPL) Version 3
|
|
* @defgroup
|
|
* @{
|
|
*
|
|
*****************************************************************************/
|
|
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
The GCS locale is set to the system locale by default unless the "hidden" setting General/Locale has a value.
|
|
The user can not change General/Locale from the Options dialog.
|
|
|
|
The GCS language will default to the GCS locale unless the General/OverrideLanguage has a value.
|
|
The user can change General/OverrideLanguage to any available language from the Options dialog.
|
|
|
|
Both General/Locale and General/OverrideLanguage can be set from the command line or through the the factory defaults file.
|
|
|
|
The -D option is used to permanently set a user setting.
|
|
|
|
The -reset switch will clear all the user settings and will trigger a reload of the factory defaults.
|
|
|
|
You can combine it with the -config-file=<file> command line argument to quickly switch between multiple settings files.
|
|
|
|
[code]
|
|
openpilotgcs -reset -config-file ./MyOpenPilotGCS.xml
|
|
[/code]
|
|
|
|
Relative paths are relative to <install dir>/share/openpilotgcs/default_configurations/
|
|
|
|
The specified file will be used to load the factory defaults from but only when the user settings are empty.
|
|
If the user settings are not empty the file will not be used.
|
|
This switch is useful on the 1st run when the user settings are empty or in combination with -reset.
|
|
|
|
|
|
Quickly switch configurations
|
|
|
|
[code]
|
|
openpilotgcs -reset -config-file <relative or absolute path>
|
|
[/code]
|
|
|
|
Configuring GCS from installer
|
|
|
|
The -D option is used to permanently set a user setting.
|
|
|
|
If the user chooses to start GCS at the end of the installer:
|
|
|
|
[code]
|
|
openpilotgcs -D General/OverrideLanguage=de
|
|
[/code]
|
|
|
|
If the user chooses not to start GCS at the end of the installer, you still need to configure GCS.
|
|
In that case you can use -exit-after-config
|
|
|
|
[code]
|
|
openpilotgcs -D General/OverrideLanguage=de -exit-after-config
|
|
[/code]
|
|
|
|
*/
|
|
|
|
#include "qtsingleapplication.h"
|
|
#include "utils/xmlconfig.h"
|
|
#include "gcssplashscreen.h"
|
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
#include <extensionsystem/pluginspec.h>
|
|
#include <extensionsystem/iplugin.h>
|
|
|
|
#include <QtCore/QDir>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QElapsedTimer>
|
|
#include <QtCore/QTextStream>
|
|
#include <QtCore/QFileInfo>
|
|
#include <QtCore/QDebug>
|
|
#include <QtCore/QTimer>
|
|
#include <QtCore/QLibraryInfo>
|
|
#include <QtCore/QTranslator>
|
|
#include <QtCore/QSettings>
|
|
#include <QtCore/QVariant>
|
|
|
|
#include <QMessageBox>
|
|
#include <QtWidgets/QApplication>
|
|
#include <QMainWindow>
|
|
#include <QSplashScreen>
|
|
|
|
namespace {
|
|
typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;
|
|
typedef QMap<QString, bool> AppOptions;
|
|
typedef QMap<QString, QString> AppOptionValues;
|
|
|
|
const int OptionIndent = 4;
|
|
const int DescriptionIndent = 24;
|
|
|
|
const QLatin1String APP_NAME("OpenPilot GCS");
|
|
|
|
const QLatin1String CORE_PLUGIN_NAME("Core");
|
|
|
|
const QLatin1String SETTINGS_ORG_NAME("OpenPilot");
|
|
const QLatin1String SETTINGS_APP_NAME("OpenPilotGCS_config");
|
|
|
|
#ifdef Q_OS_MAC
|
|
const QLatin1String SHARE_PATH("/../Resources");
|
|
#else
|
|
const QLatin1String SHARE_PATH("/../share/openpilotgcs");
|
|
#endif
|
|
|
|
const char *DEFAULT_CONFIG_FILENAME = "OpenPilotGCS.xml";
|
|
|
|
const char *fixedOptionsC = " [OPTION]... [FILE]...\n"
|
|
"Options:\n"
|
|
" -help Display this help\n"
|
|
" -version Display application version\n"
|
|
" -no-splash Don't display splash screen\n"
|
|
" -client Attempt to connect to already running instance\n"
|
|
" -D <key>=<value> Permanently set a user setting, e.g: -D General/OverrideLanguage=de\n"
|
|
" -reset Reset user settings to factory defaults.\n"
|
|
" -config-file <file> Specify alternate factory defaults settings file (used with -reset)\n"
|
|
" -exit-after-config Exit after manipulating configuration settings\n";
|
|
|
|
const QLatin1String HELP1_OPTION("-h");
|
|
const QLatin1String HELP2_OPTION("-help");
|
|
const QLatin1String HELP3_OPTION("/h");
|
|
const QLatin1String HELP4_OPTION("--help");
|
|
const QLatin1String VERSION_OPTION("-version");
|
|
const QLatin1String NO_SPLASH_OPTION("-no-splash");
|
|
const QLatin1String CLIENT_OPTION("-client");
|
|
const QLatin1String CONFIG_OPTION("-D");
|
|
const QLatin1String RESET_OPTION("-reset");
|
|
const QLatin1String CONFIG_FILE_OPTION("-config-file");
|
|
const QLatin1String EXIT_AFTER_CONFIG_OPTION("-exit-after-config");
|
|
|
|
// Helpers for displaying messages. Note that there is no console on Windows.
|
|
void displayHelpText(QString t)
|
|
{
|
|
#ifdef Q_OS_WIN
|
|
// No console on Windows. (???)
|
|
// TODO there is a console on windows and popups are not always desired
|
|
t.replace(QLatin1Char('&'), QLatin1String("&"));
|
|
t.replace(QLatin1Char('<'), QLatin1String("<"));
|
|
t.replace(QLatin1Char('>'), QLatin1String(">"));
|
|
t.insert(0, QLatin1String("<html><pre>"));
|
|
t.append(QLatin1String("</pre></html>"));
|
|
QMessageBox::information(0, APP_NAME, t);
|
|
#else
|
|
qWarning("%s", qPrintable(t));
|
|
#endif
|
|
}
|
|
|
|
void displayError(const QString &t)
|
|
{
|
|
#ifdef Q_OS_WIN
|
|
// No console on Windows. (???)
|
|
// TODO there is a console on windows and popups are not always desired
|
|
QMessageBox::critical(0, APP_NAME, t);
|
|
#else
|
|
qCritical("%s", qPrintable(t));
|
|
#endif
|
|
}
|
|
|
|
void printVersion(const ExtensionSystem::PluginSpec *corePlugin, const ExtensionSystem::PluginManager &pm)
|
|
{
|
|
QString version;
|
|
QTextStream str(&version);
|
|
|
|
str << '\n' << APP_NAME << ' ' << corePlugin->version() << " based on Qt " << qVersion() << "\n\n";
|
|
pm.formatPluginVersions(str);
|
|
str << '\n' << corePlugin->copyright() << '\n';
|
|
displayHelpText(version);
|
|
}
|
|
|
|
void printHelp(const QString &appExecName, const ExtensionSystem::PluginManager &pm)
|
|
{
|
|
QString help;
|
|
QTextStream str(&help);
|
|
|
|
str << "Usage: " << appExecName << fixedOptionsC;
|
|
ExtensionSystem::PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
|
|
pm.formatPluginOptions(str, OptionIndent, DescriptionIndent);
|
|
displayHelpText(help);
|
|
}
|
|
|
|
inline QString msgCoreLoadFailure(const QString &reason)
|
|
{
|
|
return QCoreApplication::translate("Application", "Failed to load core plug-in, reason is: %1").arg(reason);
|
|
}
|
|
|
|
inline QString msgSendArgumentFailed()
|
|
{
|
|
return QCoreApplication::translate("Application",
|
|
"Unable to send command line arguments to the already running instance. It appears to be not responding.");
|
|
}
|
|
|
|
void mainMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
|
{
|
|
Q_UNUSED(context);
|
|
QFile file(QDir::tempPath() + "/gcs.log");
|
|
|
|
if (file.open(QIODevice::Append | QIODevice::Text)) {
|
|
QTextStream out(&file);
|
|
out << QTime::currentTime().toString("hh:mm:ss.zzz ");
|
|
|
|
switch (type) {
|
|
case QtDebugMsg:
|
|
out << "DBG: ";
|
|
break;
|
|
case QtWarningMsg:
|
|
out << "WRN: ";
|
|
break;
|
|
case QtCriticalMsg:
|
|
out << "CRT: ";
|
|
break;
|
|
case QtFatalMsg:
|
|
out << "FTL: ";
|
|
break;
|
|
}
|
|
|
|
out << msg << '\n';
|
|
out.flush();
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
inline QString prepareRemoteArgument(const QString &arg)
|
|
{
|
|
QFileInfo fi(arg);
|
|
|
|
if (!fi.exists()) {
|
|
return arg;
|
|
}
|
|
if (fi.isRelative()) {
|
|
return fi.absoluteFilePath();
|
|
}
|
|
return arg;
|
|
}
|
|
|
|
// Send the arguments to an already running instance of application
|
|
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;
|
|
}
|
|
|
|
void systemInit()
|
|
{
|
|
#ifdef Q_OS_MAC
|
|
// increase the number of file that can be opened in application
|
|
struct rlimit rl;
|
|
getrlimit(RLIMIT_NOFILE, &rl);
|
|
rl.rlim_cur = rl.rlim_max;
|
|
setrlimit(RLIMIT_NOFILE, &rl);
|
|
QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
|
|
#endif
|
|
#ifdef Q_OS_LINUX
|
|
QApplication::setAttribute(Qt::AA_X11InitThreads, true);
|
|
#endif
|
|
}
|
|
|
|
void logInit()
|
|
{
|
|
qInstallMessageHandler(mainMessageOutput);
|
|
QFile file(QDir::tempPath() + "/gcs.log");
|
|
if (file.exists()) {
|
|
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
// erase old log
|
|
}
|
|
}
|
|
}
|
|
|
|
inline QStringList getPluginPaths()
|
|
{
|
|
QStringList rc;
|
|
// Figure out root: Up one from 'bin'
|
|
QDir rootDir = QApplication::applicationDirPath();
|
|
|
|
rootDir.cdUp();
|
|
const QString rootDirPath = rootDir.canonicalPath();
|
|
// 1) "plugins" (Win/Linux)
|
|
QString pluginPath = rootDirPath;
|
|
pluginPath += QLatin1Char('/');
|
|
pluginPath += QLatin1String(GCS_LIBRARY_BASENAME);
|
|
pluginPath += QLatin1Char('/');
|
|
pluginPath += QLatin1String("openpilotgcs");
|
|
pluginPath += QLatin1Char('/');
|
|
pluginPath += QLatin1String("plugins");
|
|
rc.push_back(pluginPath);
|
|
// 2) "PlugIns" (OS X)
|
|
pluginPath = rootDirPath;
|
|
pluginPath += QLatin1Char('/');
|
|
pluginPath += QLatin1String("Plugins");
|
|
rc.push_back(pluginPath);
|
|
return rc;
|
|
}
|
|
|
|
AppOptions options()
|
|
{
|
|
AppOptions appOptions;
|
|
|
|
appOptions.insert(HELP1_OPTION, false);
|
|
appOptions.insert(HELP2_OPTION, false);
|
|
appOptions.insert(HELP3_OPTION, false);
|
|
appOptions.insert(HELP4_OPTION, false);
|
|
appOptions.insert(VERSION_OPTION, false);
|
|
appOptions.insert(NO_SPLASH_OPTION, false);
|
|
appOptions.insert(CLIENT_OPTION, false);
|
|
appOptions.insert(CONFIG_OPTION, true);
|
|
appOptions.insert(RESET_OPTION, false);
|
|
appOptions.insert(CONFIG_FILE_OPTION, true);
|
|
appOptions.insert(EXIT_AFTER_CONFIG_OPTION, false);
|
|
return appOptions;
|
|
}
|
|
|
|
AppOptionValues parseCommandLine(SharedTools::QtSingleApplication &app,
|
|
ExtensionSystem::PluginManager &pluginManager, QString &errorMessage)
|
|
{
|
|
AppOptionValues appOptionValues;
|
|
const QStringList arguments = app.arguments();
|
|
|
|
if (arguments.size() > 1) {
|
|
AppOptions appOptions = options();
|
|
pluginManager.parseOptions(arguments, appOptions, &appOptionValues, &errorMessage);
|
|
}
|
|
return appOptionValues;
|
|
}
|
|
|
|
void loadFactoryDefaults(QSettings &settings, AppOptionValues &appOptionValues)
|
|
{
|
|
QDir directory(QCoreApplication::applicationDirPath() + SHARE_PATH + QString("/default_configurations"));
|
|
|
|
qDebug() << "Looking for factory defaults configuration files in:" << directory.absolutePath();
|
|
|
|
QString fileName;
|
|
|
|
// check if command line option -config-file contains a file name
|
|
QString commandLine = appOptionValues.value(CONFIG_FILE_OPTION);
|
|
if (!commandLine.isEmpty()) {
|
|
QFileInfo fi(commandLine);
|
|
if (fi.isRelative()) {
|
|
// file name specified on command line has a relative path
|
|
commandLine = directory.absolutePath() + QDir::separator() + commandLine;
|
|
}
|
|
if (QFile::exists(commandLine)) {
|
|
fileName = commandLine;
|
|
qDebug() << "Configuration file" << fileName << "specified on command line will be loaded.";
|
|
} else {
|
|
qWarning() << "Configuration file" << commandLine << "specified on command line does not exist.";
|
|
}
|
|
}
|
|
|
|
if (fileName.isEmpty()) {
|
|
// check default file
|
|
if (QFile::exists(directory.absolutePath() + QDir::separator() + DEFAULT_CONFIG_FILENAME)) {
|
|
// use default file name
|
|
fileName = directory.absolutePath() + QDir::separator() + DEFAULT_CONFIG_FILENAME;
|
|
qDebug() << "Default configuration file" << fileName << "will be loaded.";
|
|
} else {
|
|
qWarning() << "No default configuration file found in" << directory.absolutePath();
|
|
}
|
|
}
|
|
|
|
if (fileName.isEmpty()) {
|
|
// TODO should we exit violently?
|
|
qCritical() << "No default configuration file found!";
|
|
return;
|
|
}
|
|
|
|
// create settings from file
|
|
QSettings qs(fileName, XmlConfig::XmlSettingsFormat);
|
|
|
|
// transfer loaded settings to application settings
|
|
QStringList keys = qs.allKeys();
|
|
foreach(QString key, keys) {
|
|
settings.setValue(key, qs.value(key));
|
|
}
|
|
|
|
qDebug() << "Configuration file" << fileName << "was loaded.";
|
|
}
|
|
|
|
void overrideSettings(QSettings &settings, int argc, char * *argv)
|
|
{
|
|
// Options like -D My/setting=test
|
|
QRegExp rx("([^=]+)=(.*)");
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
if (CONFIG_OPTION == QString(argv[i])) {
|
|
if (rx.indexIn(argv[++i]) > -1) {
|
|
QString key = rx.cap(1);
|
|
QString value = rx.cap(2);
|
|
qDebug() << "User setting" << key << "set to value" << value;
|
|
settings.setValue(key, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
settings.sync();
|
|
}
|
|
|
|
void loadTranslators(QString language, QTranslator &translator, QTranslator &qtTranslator)
|
|
{
|
|
const QString &creatorTrPath = QCoreApplication::applicationDirPath() + SHARE_PATH
|
|
+ QLatin1String("/translations");
|
|
|
|
if (translator.load(QLatin1String("openpilotgcs_") + language, creatorTrPath)) {
|
|
const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
|
const QString &qtTrFile = QLatin1String("qt_") + language;
|
|
// Binary installer puts Qt tr files into creatorTrPath
|
|
if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, creatorTrPath)) {
|
|
QCoreApplication::installTranslator(&translator);
|
|
QCoreApplication::installTranslator(&qtTranslator);
|
|
} else {
|
|
// unload()
|
|
translator.load(QString());
|
|
}
|
|
}
|
|
}
|
|
} // namespace anonymous
|
|
|
|
int main(int argc, char * *argv)
|
|
{
|
|
QElapsedTimer timer;
|
|
|
|
timer.start();
|
|
|
|
// low level init
|
|
systemInit();
|
|
|
|
#ifdef QT_NO_DEBUG
|
|
// logInit();
|
|
#endif
|
|
|
|
// create application
|
|
SharedTools::QtSingleApplication app(APP_NAME, argc, argv);
|
|
|
|
// initialize the plugin manager
|
|
ExtensionSystem::PluginManager pluginManager;
|
|
pluginManager.setFileExtension(QLatin1String("pluginspec"));
|
|
pluginManager.setPluginPaths(getPluginPaths());
|
|
|
|
// parse command line
|
|
qDebug() << "Command line" << app.arguments();
|
|
QString errorMessage;
|
|
AppOptionValues appOptionValues = parseCommandLine(app, pluginManager, errorMessage);
|
|
if (!errorMessage.isEmpty()) {
|
|
// this will display two popups : one error popup + one usage string popup
|
|
// TODO merge two popups into one.
|
|
displayError(errorMessage);
|
|
printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
|
|
return -1;
|
|
}
|
|
|
|
// load user settings
|
|
// Must be done before any QSettings class is created
|
|
// keep this in sync with the MainWindow ctor in coreplugin/mainwindow.cpp
|
|
QString settingsPath = QCoreApplication::applicationDirPath() + SHARE_PATH;
|
|
qDebug() << "Loading system settings from" << settingsPath;
|
|
QSettings::setPath(XmlConfig::XmlSettingsFormat, QSettings::SystemScope, settingsPath);
|
|
qDebug() << "Loading user settings from" << SETTINGS_ORG_NAME << "/" << SETTINGS_APP_NAME;
|
|
QSettings settings(XmlConfig::XmlSettingsFormat, QSettings::UserScope, SETTINGS_ORG_NAME, SETTINGS_APP_NAME);
|
|
|
|
// need to reset all user settings?
|
|
if (appOptionValues.contains(RESET_OPTION)) {
|
|
qDebug() << "Resetting user settings!";
|
|
settings.clear();
|
|
}
|
|
|
|
// check if we have user settings
|
|
if (!settings.allKeys().count()) {
|
|
// no user settings, load the factory defaults
|
|
qDebug() << "No user settings found, loading factory defaults...";
|
|
loadFactoryDefaults(settings, appOptionValues);
|
|
}
|
|
|
|
// override settings with command line provided values
|
|
// take notice that the overridden values will be saved in the user settings and will continue to be effective
|
|
// in subsequent GCS runs
|
|
overrideSettings(settings, argc, argv);
|
|
|
|
// initialize GCS locale
|
|
// use the value defined by the General/Locale setting or default to system Locale.
|
|
// the General/Locale setting is not available in the Options dialog, it is a hidden setting but can still be changed:
|
|
// - through the command line
|
|
// - editing the factory defaults XML file before 1st launch
|
|
// - editing the user XML file
|
|
QString localeName = settings.value("General/Locale", QLocale::system().name()).toString();
|
|
QLocale::setDefault(localeName);
|
|
|
|
// some debugging
|
|
qDebug() << "main - system locale:" << QLocale::system().name();
|
|
qDebug() << "main - GCS locale:" << QLocale().name();
|
|
|
|
// load translation file
|
|
// the language used is defined by the General/OverrideLanguage setting (defaults to GCS locale)
|
|
// if the translation file for the given language is not found, GCS will default to built in English.
|
|
QString language = settings.value("General/OverrideLanguage", localeName).toString();
|
|
qDebug() << "main - language:" << language;
|
|
QTranslator translator;
|
|
QTranslator qtTranslator;
|
|
loadTranslators(language, translator, qtTranslator);
|
|
|
|
app.setProperty("qtc_locale", localeName); // Do we need this?
|
|
|
|
if (appOptionValues.contains(EXIT_AFTER_CONFIG_OPTION)) {
|
|
qDebug() << "main - exiting after config!";
|
|
return 0;
|
|
}
|
|
|
|
// open the splash screen
|
|
GCSSplashScreen *splash = 0;
|
|
if (!appOptionValues.contains(NO_SPLASH_OPTION)) {
|
|
splash = new GCSSplashScreen();
|
|
// show splash
|
|
splash->showProgressMessage(QObject::tr("Application starting..."));
|
|
splash->show();
|
|
// connect to track progress of plugin manager
|
|
QObject::connect(&pluginManager, SIGNAL(pluginAboutToBeLoaded(ExtensionSystem::PluginSpec *)), splash,
|
|
SLOT(showPluginLoadingProgress(ExtensionSystem::PluginSpec *)));
|
|
}
|
|
|
|
// find and load core plugin
|
|
const PluginSpecSet plugins = pluginManager.plugins();
|
|
ExtensionSystem::PluginSpec *coreplugin = 0;
|
|
foreach(ExtensionSystem::PluginSpec * spec, plugins) {
|
|
if (spec->name() == CORE_PLUGIN_NAME) {
|
|
coreplugin = spec;
|
|
break;
|
|
}
|
|
}
|
|
if (!coreplugin) {
|
|
QString nativePaths = QDir::toNativeSeparators(getPluginPaths().join(QLatin1String(",")));
|
|
const QString reason = QCoreApplication::translate("Application", "Could not find 'Core.pluginspec' in %1").arg(
|
|
nativePaths);
|
|
displayError(msgCoreLoadFailure(reason));
|
|
return 1;
|
|
}
|
|
if (coreplugin->hasError()) {
|
|
displayError(msgCoreLoadFailure(coreplugin->errorString()));
|
|
return 1;
|
|
}
|
|
|
|
if (appOptionValues.contains(VERSION_OPTION)) {
|
|
printVersion(coreplugin, pluginManager);
|
|
return 0;
|
|
}
|
|
if (appOptionValues.contains(HELP1_OPTION) || appOptionValues.contains(HELP2_OPTION)
|
|
|| appOptionValues.contains(HELP3_OPTION) || appOptionValues.contains(HELP4_OPTION)) {
|
|
printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
|
|
return 0;
|
|
}
|
|
|
|
const bool isFirstInstance = !app.isRunning();
|
|
if (!isFirstInstance && appOptionValues.contains(CLIENT_OPTION)) {
|
|
return sendArguments(app, pluginManager.arguments()) ? 0 : -1;
|
|
}
|
|
|
|
pluginManager.loadPlugins();
|
|
|
|
if (coreplugin->hasError()) {
|
|
displayError(msgCoreLoadFailure(coreplugin->errorString()));
|
|
return 1;
|
|
}
|
|
|
|
{
|
|
QStringList errors;
|
|
foreach(ExtensionSystem::PluginSpec * p, pluginManager.plugins()) {
|
|
if (p->hasError()) {
|
|
errors.append(p->errorString());
|
|
}
|
|
}
|
|
if (!errors.isEmpty()) {
|
|
QMessageBox::warning(0,
|
|
QCoreApplication::translate("Application", "OpenPilot GCS - Plugin loader messages"),
|
|
errors.join(QString::fromLatin1("\n\n")));
|
|
}
|
|
}
|
|
|
|
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()));
|
|
|
|
if (splash) {
|
|
// close and delete splash
|
|
splash->close();
|
|
delete splash;
|
|
}
|
|
|
|
qDebug() << "main - main took" << timer.elapsed() << "ms";
|
|
|
|
int ret = app.exec();
|
|
|
|
qDebug() << "main - GCS ran for" << timer.elapsed() << "ms";
|
|
|
|
return ret;
|
|
}
|