/************************************************************************** ** ** This file is part of Qt Simulator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (info@qt.nokia.com) ** ** ** GNU Lesser General Public License Usage ** ** 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. ** ** 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. ** ** Other Usage ** ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** If you have questions regarding the use of this file, please contact ** Nokia at info@qt.nokia.com. ** **************************************************************************/ #include "qtsingleapplication.h" #include "ui/mainwindow.h" #include "qsimulatordata_p.h" #include "messaging.h" #ifdef Q_OS_UNIX extern "C" { #include #include #include } #endif #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include #endif static void registerSimulator(const QString &location) { QSettings userSettings; QSettings *settings = &userSettings; #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) // If the system settings are writable, don't touch the user settings. // The reason is that a simulator started with sudo could otherwise create // a root-owned configuration file a user directory. QSettings systemSettings(QSettings::SystemScope, SIMULATOR_APP_VENDOR, SIMULATOR_APP_NAME); // QSettings::isWritable isn't reliable enough in 4.7, determine writability experimentally systemSettings.setValue(SIMULATOR_APP_LOCATION_KEY, QLatin1String("SETTABLE")); systemSettings.sync(); if (systemSettings.status() == QSettings::NoError) { settings = &systemSettings; if (userSettings.contains(SIMULATOR_APP_LOCATION_KEY)) userSettings.remove(SIMULATOR_APP_LOCATION_KEY); } #endif settings->beginGroup(SIMULATOR_APP_LOCATION_KEY); QString simulatorVersionString = simulatorVersion.toString(); QVariant value = settings->value(simulatorVersionString); if (!value.isValid() || settings->value(simulatorVersionString).toString() != location) settings->setValue(simulatorVersionString, location); settings->endGroup(); settings->beginGroup(SIMULATOR_APP_QT_VERSIONS_KEY); QList supportedQtVersion; supportedQtVersion << "4.7.4.0" << "4.7.4.1" << "4.8.0.0" << "4.8.0.1"; foreach(const QString &version, supportedQtVersion) { QList simulators; QVariant value = settings->value(version); if (value.isValid()) simulators = value.toStringList(); if (!simulators.contains(simulatorVersionString)) simulators.append(simulatorVersionString); settings->setValue(version, QVariant::fromValue(simulators)); } settings->endGroup(); const QString dataKey = QLatin1String(SIMULATOR_APP_DATA_KEY); QString appDataLocation = QDesktopServices::storageLocation(QDesktopServices::DataLocation); if (appDataLocation.isEmpty()) appDataLocation = location; value = settings->value(dataKey); if (!value.isValid() || settings->value(dataKey).toString() != appDataLocation) settings->setValue(dataKey, appDataLocation); } void cleanupUnusedSharedMemory() { #ifdef Q_OS_UNIX // This code depends on the implementation of QSharedMemory QDir tmp(QDir::tempPath()); QStringList possibleFiles = tmp.entryList(QStringList("qipc_sharedmemory_QTSIMULATORSHAREDMEMORY*"), QDir::Files); foreach (QString fileName, possibleFiles) { int unix_key = ::ftok(QFile::encodeName(tmp.absoluteFilePath(fileName)).constData(), 'Q'); // Get the number of current attachments int id = ::shmget(unix_key, 0, 0444); struct shmid_ds shmid_ds; if (0 != ::shmctl(id, IPC_STAT, &shmid_ds)) { qWarning("getting the number of current attachments failed"); continue; } // If there are no attachments then remove it. if (shmid_ds.shm_nattch == 0) { // mark for removal if (-1 == ::shmctl(id, IPC_RMID, &shmid_ds)) { qWarning("mark shared memory segment for removal failed"); continue; } // remove file if (!tmp.remove(fileName)) { qWarning("could not remove shared memory segment 'file'"); continue; } qDebug() << "superfluous shared memory segment removed"; } } #endif } int main(int argc, char **argv) { cleanupUnusedSharedMemory(); QCoreApplication::setOrganizationName(SIMULATOR_APP_VENDOR); QCoreApplication::setApplicationName(SIMULATOR_APP_NAME); SharedTools::QtSingleApplication app(SIMULATOR_APP_NAME + simulatorVersion.toString(), argc, argv); QDir::setCurrent(app.applicationDirPath()); QDir pluginsDir = QDir::current(); if (pluginsDir.cd("plugins")) QApplication::addLibraryPath(pluginsDir.absolutePath()); registerSimulator(app.applicationFilePath()); QStringList arguments; for (int i = 1; i < argc; ++i) { arguments += QString(argv[i]); } if (arguments.size() == 1) { if (arguments[0] == QLatin1String("-registeronly") || arguments[0] == QLatin1String("--registeronly")) { //As creation of the messaging folder takes ages, we do that when //registering the simulator Messaging m; m.setInitialData(); // Don't return directly. Otherwise we crash. QTimer::singleShot(1000, &app, SLOT(quit())); return app.exec(); } if (arguments[0] == QLatin1String("--version")) { QString output = "Qt Simulator version " + simulatorVersion.toString() + "\n"; #ifndef Q_OS_WIN QTextStream stream(stdout); stream << output; #else QMessageBox::information(0, app.applicationName(), output); #endif return EXIT_SUCCESS; } if (arguments[0] == QLatin1String("--help")) { QString output = "Usage: " + QString(argv[0]) + " [arguments]\n" "\n" "Arguments:\n" " --runscript : Execute a script file on a running Simulator instance\n" " --version: Report the Simulator's version\n"; #ifndef Q_OS_WIN QTextStream stream(stdout); stream << output; #else QMessageBox::information(0, app.applicationName(), output); #endif return EXIT_SUCCESS; } } bool isFirstInstance = !app.isRunning(); for (int a = 0; a < arguments.size(); ++a) { if (arguments[a] == QLatin1String("-runscript") || arguments[a] == QLatin1String("--runscript")) { if (isFirstInstance) { qWarning() << "Ignored --runscript: No running simulator found"; return EXIT_FAILURE; } if (a + 1 >= arguments.size()) { qWarning() << "Syntax: --runscript "; return EXIT_FAILURE; } const QString targetFile = arguments[a + 1]; ++a; if (!app.sendMessage(QString("runscript %1").arg(targetFile))) { qWarning() << "Could not send message to running simulator."; return EXIT_FAILURE; } else { return EXIT_SUCCESS; } } } if (!isFirstInstance) { app.sendMessage(QString("activate")); return 0; } qsrand(QDateTime::currentMSecsSinceEpoch()); app.initialize(); MainWindow main; app.setActivationWindow(&main); QObject::connect(&app, SIGNAL(messageReceived(QString)), &main, SLOT(handleMessage(QString))); main.show(); return app.exec(); }