void MainSettingsDialog::fillAllAutoProfilesTable()
{
    for (int i = ui->autoProfileTableWidget->rowCount()-1; i >= 0; i--)
    {
        ui->autoProfileTableWidget->removeRow(i);
    }

    //QStringList tableHeader;
    //tableHeader << tr("Active") << tr("GUID") << tr("Profile") << tr("Application") << tr("Default?")
    //            << tr("Instance");
    //ui->autoProfileTableWidget->setHorizontalHeaderLabels(tableHeader);

    ui->autoProfileTableWidget->horizontalHeader()->setVisible(true);

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
    ui->autoProfileTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
#else
    ui->autoProfileTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
#endif

    ui->autoProfileTableWidget->hideColumn(5);

    int i = 0;

    AutoProfileInfo *info = allDefaultProfile;

    ui->autoProfileTableWidget->insertRow(i);
    QTableWidgetItem *item = new QTableWidgetItem();
    item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked);
    ui->autoProfileTableWidget->setItem(i, 0, item);

    QString deviceName = info->getDeviceName();
    QString guidDisplay = info->getGUID();
    if (!deviceName.isEmpty())
    {
        guidDisplay = QString("%1 ").arg(info->getDeviceName());
        guidDisplay.append(QString("(%1)").arg(info->getGUID()));
    }
    item = new QTableWidgetItem(guidDisplay);
    item->setFlags(item->flags() & ~Qt::ItemIsEditable);
    item->setData(Qt::UserRole, info->getGUID());
    item->setToolTip(info->getGUID());
    ui->autoProfileTableWidget->setItem(i, 1, item);

    QFileInfo profilePath(info->getProfileLocation());
    item = new QTableWidgetItem(profilePath.fileName());
    item->setFlags(item->flags() & ~Qt::ItemIsEditable);
    item->setData(Qt::UserRole, info->getProfileLocation());
    item->setToolTip(info->getProfileLocation());
    ui->autoProfileTableWidget->setItem(i, 2, item);

    QFileInfo exeInfo(info->getExe());
    item = new QTableWidgetItem(exeInfo.fileName());
    item->setFlags(item->flags() & ~Qt::ItemIsEditable);
    item->setData(Qt::UserRole, info->getExe());
    item->setToolTip(info->getExe());
    ui->autoProfileTableWidget->setItem(i, 3, item);

    item = new QTableWidgetItem("Default");
    item->setData(Qt::UserRole, "default");
    ui->autoProfileTableWidget->setItem(i, 4, item);

    item = new QTableWidgetItem("Instance");
    item->setData(Qt::UserRole, QVariant::fromValue<AutoProfileInfo*>(info));
    ui->autoProfileTableWidget->setItem(i, 5, item);

    i++;

    QListIterator<AutoProfileInfo*> iterDefaults(defaultList);
    while (iterDefaults.hasNext())
    {
        AutoProfileInfo *info = iterDefaults.next();
        ui->autoProfileTableWidget->insertRow(i);

        QTableWidgetItem *item = new QTableWidgetItem();
        item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked);
        ui->autoProfileTableWidget->setItem(i, 0, item);

        QString deviceName = info->getDeviceName();
        QString guidDisplay = info->getGUID();
        if (!deviceName.isEmpty())
        {
            guidDisplay = QString("%1 ").arg(info->getDeviceName());
            guidDisplay.append(QString("(%1)").arg(info->getGUID()));
        }

        item = new QTableWidgetItem(guidDisplay);
        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        item->setData(Qt::UserRole, info->getGUID());
        item->setToolTip(info->getGUID());
        ui->autoProfileTableWidget->setItem(i, 1, item);

        QFileInfo profilePath(info->getProfileLocation());
        item = new QTableWidgetItem(profilePath.fileName());
        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        item->setData(Qt::UserRole, info->getProfileLocation());
        item->setToolTip(info->getProfileLocation());
        ui->autoProfileTableWidget->setItem(i, 2, item);

        QFileInfo exeInfo(info->getExe());
        item = new QTableWidgetItem(exeInfo.fileName());
        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        item->setData(Qt::UserRole, info->getExe());
        item->setToolTip(info->getExe());
        ui->autoProfileTableWidget->setItem(i, 3, item);

        item = new QTableWidgetItem("Default");
        item->setData(Qt::UserRole, "default");
        ui->autoProfileTableWidget->setItem(i, 4, item);

        item = new QTableWidgetItem("Instance");
        item->setData(Qt::UserRole, QVariant::fromValue<AutoProfileInfo*>(info));
        ui->autoProfileTableWidget->setItem(i, 5, item);

        i++;
    }

    QListIterator<AutoProfileInfo*> iter(profileList);
    while (iter.hasNext())
    {
        AutoProfileInfo *info = iter.next();
        ui->autoProfileTableWidget->insertRow(i);

        QTableWidgetItem *item = new QTableWidgetItem();
        item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked);
        ui->autoProfileTableWidget->setItem(i, 0, item);

        QString deviceName = info->getDeviceName();
        QString guidDisplay = info->getGUID();
        if (!deviceName.isEmpty())
        {
            guidDisplay = QString("%1 ").arg(info->getDeviceName());
            guidDisplay.append(QString("(%1)").arg(info->getGUID()));
        }
        item = new QTableWidgetItem(guidDisplay);
        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        item->setData(Qt::UserRole, info->getGUID());
        item->setToolTip(info->getGUID());
        ui->autoProfileTableWidget->setItem(i, 1, item);

        QFileInfo profilePath(info->getProfileLocation());
        item = new QTableWidgetItem(profilePath.fileName());
        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        item->setData(Qt::UserRole, info->getProfileLocation());
        item->setToolTip(info->getProfileLocation());
        ui->autoProfileTableWidget->setItem(i, 2, item);

        QFileInfo exeInfo(info->getExe());
        item = new QTableWidgetItem(exeInfo.fileName());
        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        item->setData(Qt::UserRole, info->getExe());
        item->setToolTip(info->getExe());
        ui->autoProfileTableWidget->setItem(i, 3, item);

        item = new QTableWidgetItem();
        item->setData(Qt::UserRole, "");
        ui->autoProfileTableWidget->setItem(i, 4, item);

        item = new QTableWidgetItem("Instance");
        item->setData(Qt::UserRole, QVariant::fromValue<AutoProfileInfo*>(info));
        ui->autoProfileTableWidget->setItem(i, 5, item);

        i++;
    }
}
Beispiel #2
0
void UTLauncher::startServerBrowser()
{
    splashTimer.singleShot(2000, this, SLOT(closeSplash()));

    if(!settings.value("StartMinimized", false).toBool()) {
        browser->show();
    } else {
        qApp->setQuitOnLastWindowClosed(false); // workaround for app not starting
    }
    browser->setMOTD(bootstrap.MOTD());
    
    auto hasEditorSupport = [=] {
        QString editorPath = bootstrap.editorExePath();
        QString projectPath = bootstrap.projectPath();
        return QFile::exists(editorPath) && QFile::exists(projectPath);
    };
    
    auto openSettings = [=](bool mandatoryEditor = false) {
        ConfigDialog dialog(settings, mandatoryEditor);
        dialog.exec();
        browser->setEditorSupport(hasEditorSupport());
        
        browser->setHideOnClose(settings.value("MinimizeToTrayOnClose").toBool());
    };
    
    connect(browser, &ServerBrowser::openServer, [=](QString url, bool spectate, bool inEditor) {

        if(inEditor) {
            QString editorPath = bootstrap.editorExePath();
            QString projectPath = bootstrap.projectPath();
            if(!editorPath.length() || !projectPath.length()) {
                openSettings(true);
                return;
            }
            QProcess::startDetached(editorPath, QStringList() << projectPath << "-GAME" << (url + (spectate?"?SpectatorOnly=1":"")) );
        } else {
            QString exePath = bootstrap.programExePath();
            if(!exePath.length()) {
                openSettings();
                return;
            }
            const auto serverEntry = browser->serverEntryFromAddress(url);
            auto launch = [=] {
                qDebug() << "Launching!!\n";
              QProcess::startDetached(exePath, QStringList()
#ifdef LAUNCH_WITH_UE4
                << "UnrealTournament"
#endif
                << (url + (spectate?"?SpectatorOnly=1":"")) 
                << "-SaveToUserDir");
            };
                        
            if(serverEntry) {
                if(bootstrap.isStockMap(serverEntry->map)) {
                    launch();
                    return;
                }
                

                QString exePath = bootstrap.programExePath();
                QFileInfo exeInfo(exePath);
                auto contentDir = QDir(exeInfo.dir());
                contentDir.cdUp();
                contentDir.cdUp();
                contentDir.cd("Content");
                auto zipFilePath = contentDir.absoluteFilePath(serverEntry->map + ".zip");
                
                if(QFile::exists(zipFilePath)) {
                    launch();
                    return;
                }

                Download mapDownload;
                mapDownload.setTarget("https://ut.rushbase.net/customcontent/Data/" + serverEntry->map + ".zip");
                QProgressDialog dialog("Downloading map: " + serverEntry->map, "Cancel", 0, 100);
                
                QFile zipFile(zipFilePath);
                zipFile.open(QIODevice::WriteOnly);
                
                int httpCode = 200;
                connect(&mapDownload, &Download::error, [&](int code) {
                    httpCode = code;
                    if(code != 200) {
                        zipFile.remove();
                        QMessageBox::critical(nullptr, "Unable to download map", QString("Got code %1 while trying to download map:<br>%2").arg(code).arg(serverEntry->map));
                    }
                });
                
                connect(&mapDownload, &Download::chunk, [&](QByteArray chunk) {
                    qDebug() << "Reading!\n";
                    zipFile.write(chunk);
                });
                connect(&mapDownload, &Download::progress, [&](double progress) {
                    dialog.setValue(100*progress);
                    if(progress == 1.0) {
                        dialog.accept();
                    }
                });
                
                
                mapDownload.download();
                qDebug() << "Downloading map " << serverEntry->map;
                if(!dialog.exec() || httpCode != 200) {
                    zipFile.remove(); // remove unfinished download
                    return;
                }
                zipFile.close();
                
                QProgressDialog installDialog("Installing map: " + serverEntry->map, "", 0, 100);
                installDialog.setWindowModality(Qt::ApplicationModal);
                installDialog.show();
                installDialog.setValue(0);
                
                qDebug() << "Installed!!\n";
                QuaZip zip(zipFilePath);
                
                auto textCodec = QTextCodec::codecForName("TSCII");
                zip.setFileNameCodec(textCodec);
                zip.setCommentCodec(textCodec);
                zip.open(QuaZip::mdUnzip);

                QuaZipFile file(&zip);

                size_t totalSize = 0;
                for(bool f=zip.goToFirstFile(); f; f=zip.goToNextFile()) {
                    QuaZipFileInfo info;
                    zip.getCurrentFileInfo(&info);
                    totalSize += info.uncompressedSize;
                }
                qDebug() << "Total size " << totalSize;
                size_t accumulatedSize = 0;
                /* TODO!!!!: this whole thing needs to be redone asynchronously */
                for(bool f=zip.goToFirstFile(); f; f=zip.goToNextFile()) {
                    file.open(QIODevice::ReadOnly);
                    //same functionality as QIODevice::readData() -- data is a char*, maxSize is qint64
                    //file.readData(data,maxSize);
                    QString filename = file.getActualFileName();
                    if(file.isOpen()) {
                        qApp->processEvents();
                        qDebug() << installDialog.isVisible() << installDialog.value();
                        if(!installDialog.isVisible() && installDialog.value() != 100 && installDialog.value() != -1)
                            return;
                        bool isDir = (filename.right(1) == "/");
                        if(isDir) {
                            contentDir.mkpath(filename);
                        } else {
                            QFile f(contentDir.absoluteFilePath(filename));
                            f.open(QIODevice::WriteOnly);
                            auto data = file.readAll();
                            accumulatedSize += data.size();
                            qDebug() << accumulatedSize;
                            installDialog.setValue(100 * (double)accumulatedSize / totalSize);
                            qApp->processEvents();
                            qDebug() << installDialog.isVisible() << installDialog.value();
                            if(!installDialog.isVisible() && installDialog.value() != 100 && installDialog.value() != -1)
                                return;

                            f.write(data);
                        }
                        qDebug() << file.getActualFileName() << isDir;
                        
                        //do something with the data
                        if(file.isOpen())
                            file.close();
                        qApp->processEvents();
                        qDebug() << installDialog.isVisible() << installDialog.value();
                        if(!installDialog.isVisible() && installDialog.value() != 100 && installDialog.value() != -1)
                            return;
                    }
                    else {
                        qDebug() << "Cannot open" << filename << "inside zip";;
                    }
                }
                qDebug() << "Closing zip\n";
                zip.close();

                launch();
            }            
        }
    });
    
    disconnect(&bootstrap, &Bootstrap::ready, this, &UTLauncher::prepareConfig);
    
    connect(&bootstrap, &Bootstrap::ready, this, [=] {
        browser->setMOTD(bootstrap.MOTD());
    });
    
    connect(browser, &ServerBrowser::openSettings, openSettings);
    
    browser->setEditorSupport(hasEditorSupport());
    
    browser->setHideOnClose(settings.value("MinimizeToTrayOnClose", false).toBool());
    
    systemTray.setToolTip("UTLauncher");
    auto systemTrayMenu = new QMenu(browser);
    
    auto showBrowser = new QAction(awesome->icon(fa::listalt), "Server List", this);
    connect(showBrowser, &QAction::triggered, [=]() {
        browser->showNormal();
        browser->raise();
        browser->activateWindow();
    });
    
    auto runUTAction = new QAction(awesome->icon( fa::gamepad ),"Run UT", this);
    connect(runUTAction, &QAction::triggered, [=]() {
        QString exePath = bootstrap.programExePath();
        if(!exePath.length()) {
            browser->show();
            openSettings();
            return;
        }
        QProcess::startDetached(exePath
#ifdef LAUNCH_WITH_UE4
        , QStringList() << "UnrealTournament" << "-SaveToUserDir"
#endif
        );
    });

    auto runEditorAction = new QAction(awesome->icon( fa::code ),"Run Editor", this);
    connect(runEditorAction, &QAction::triggered, [=]() {
        QString editorPath = bootstrap.editorExePath();
        QString projectPath = bootstrap.projectPath();
        QProcess::startDetached(editorPath, QStringList() << projectPath);
    });
    

    auto quitAction = new QAction(awesome->icon( fa::signout ),"Quit", this);
    connect(quitAction, &QAction::triggered, [=]() {
        QApplication::quit();
    });
    
    systemTrayMenu->addAction(showBrowser);
    systemTrayMenu->addSeparator();
    systemTrayMenu->addAction(runUTAction);
    systemTrayMenu->addAction(runEditorAction);
    systemTrayMenu->addSeparator();
    systemTrayMenu->addAction(quitAction);
    
    systemTray.setContextMenu(systemTrayMenu);
    systemTray.show();
    
    connect(&systemTray, &QSystemTrayIcon::activated, [=](QSystemTrayIcon::ActivationReason reason) {
        qApp->setQuitOnLastWindowClosed(true);
        
        runEditorAction->setVisible(hasEditorSupport());
        
        switch(reason) {
            
            case QSystemTrayIcon::Trigger:
            {
                if(browser->isHidden()) {
                    browser->show();
                } else {
                    browser->hide();
                }
                break;
            }

        }
    });
    
}
Beispiel #3
0
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString serialPortName;
    QString serialPortFriendlyName;
    QString sisFile;
    QString exeFile;
    QStringList cmdLine;
    QStringList args = QCoreApplication::arguments();
    QTextStream outstream(stdout);
    QTextStream errstream(stderr);
    QString uploadLocalFile;
    QString uploadRemoteFile;
    QString downloadRemoteFile;
    QString downloadLocalFile;
    int loglevel=1;
    int timeout=0;
    bool crashlog = true;
    QString crashlogpath;
    QListIterator<QString> it(args);
    it.next(); //skip name of program
    while (it.hasNext()) {
        QString arg = it.next();

        if (arg.startsWith("-")) {
            if (arg == "--portname" || arg == "-p") {
                CHECK_PARAMETER_EXISTS
                serialPortName = it.next();
            }
            else if (arg == "--portfriendlyname" || arg == "-f") {
                CHECK_PARAMETER_EXISTS
                serialPortFriendlyName = it.next();
            }
            else if (arg == "--sis" || arg == "-s") {
                CHECK_PARAMETER_EXISTS
                sisFile = it.next();
                if (!QFileInfo(sisFile).exists()) {
                    errstream << "Sis file (" << sisFile << ") doesn't exist" << endl;
                    return 1;
                }
            }
            else if (arg == "--upload" || arg == "-u") {
                CHECK_PARAMETER_EXISTS
                uploadLocalFile = it.next();
                if (!QFileInfo(uploadLocalFile).exists()) {
                    errstream << "Executable file (" << uploadLocalFile << ") doesn't exist" << endl;
                    return 1;
                }
                CHECK_PARAMETER_EXISTS
                uploadRemoteFile = it.next();
            }
            else if (arg == "--download" || arg == "-d") {
                CHECK_PARAMETER_EXISTS
                downloadRemoteFile = it.next();
                CHECK_PARAMETER_EXISTS
                downloadLocalFile = it.next();
            }
            else if (arg == "--timeout" || arg == "-t") {
                CHECK_PARAMETER_EXISTS
                bool ok;
                timeout = it.next().toInt(&ok);
                if (!ok) {
                    errstream << "Timeout must be specified in milliseconds" << endl;
                    return 1;
                }
            }
            else if (arg == "--verbose" || arg == "-v")
                loglevel=2;
            else if (arg == "--quiet" || arg == "-q")
                loglevel=0;
            else if (arg == "--nocrashlog")
                crashlog = false;
            else if (arg == "--crashlogpath") {
                CHECK_PARAMETER_EXISTS
                crashlogpath = it.next();
            }
            else
                errstream << "unknown command line option " << arg << endl;
        } else {
            exeFile = arg;
            while(it.hasNext()) {
                cmdLine.append(it.next());
            }
        }
    }

    if (exeFile.isEmpty() && sisFile.isEmpty() &&
        (uploadLocalFile.isEmpty() || uploadRemoteFile.isEmpty()) &&
        (downloadLocalFile.isEmpty() || downloadRemoteFile.isEmpty())) {
        printUsage(outstream, args[0]);
        return 1;
    }

    if (!uploadLocalFile.isEmpty() && (!downloadLocalFile.isEmpty() || !downloadRemoteFile.isEmpty())) {
        errstream << "Upload option can't be used together with download" << endl;
        printUsage(outstream, args[0]);
        return 1;
    }

    if (serialPortName.isEmpty()) {
        if (loglevel > 0)
            outstream << "Detecting serial ports" << endl;
        foreach (const SerialPortId &id, enumerateSerialPorts(loglevel)) {
            if (loglevel > 0)
                outstream << "Port Name: " << id.portName << ", "
                     << "Friendly Name:" << id.friendlyName << endl;
            if (!id.friendlyName.isEmpty()
                    && serialPortFriendlyName.isEmpty()
                    && (id.friendlyName.contains("symbian", Qt::CaseInsensitive)
                        || id.friendlyName.contains("s60", Qt::CaseInsensitive)
                        || id.friendlyName.contains("nokia", Qt::CaseInsensitive))) {
                serialPortName = id.portName;
                break;
            } else if (!id.friendlyName.isEmpty()
                    && !serialPortFriendlyName.isEmpty()
                    && id.friendlyName.contains(serialPortFriendlyName)) {
                serialPortName = id.portName;
                break;
            }
        }
        if (serialPortName.isEmpty()) {
            errstream << "No phone found, ensure USB cable is connected or specify manually with -p" << endl;
            return 1;
        }
    }

    QScopedPointer<trk::Launcher> launcher;
    launcher.reset(new trk::Launcher(trk::Launcher::ActionPingOnly));
    QFileInfo exeInfo(exeFile);
    QFileInfo uploadInfo(uploadLocalFile);
    if (!sisFile.isEmpty()) {
        launcher->addStartupActions(trk::Launcher::ActionCopyInstall);
        launcher->setCopyFileName(sisFile, "c:\\data\\testtemp.sis");
        launcher->setInstallFileName("c:\\data\\testtemp.sis");
    }
    else if (!uploadLocalFile.isEmpty() && uploadInfo.exists()) {
        launcher->addStartupActions(trk::Launcher::ActionCopy);
        launcher->setCopyFileName(uploadLocalFile, uploadRemoteFile);
    }
    if (!exeFile.isEmpty()) {
        launcher->addStartupActions(trk::Launcher::ActionRun);
        launcher->setFileName(QString("c:\\sys\\bin\\") + exeInfo.fileName());
        launcher->setCommandLineArgs(cmdLine);
    }
    if (!downloadRemoteFile.isEmpty() && !downloadLocalFile.isEmpty()) {
        launcher->addStartupActions(trk::Launcher::ActionDownload);
        launcher->setDownloadFileName(downloadRemoteFile, downloadLocalFile);
    }
    if (loglevel > 0)
        outstream << "Connecting to target via " << serialPortName << endl;
    launcher->setTrkServerName(serialPortName);

    if (loglevel > 1)
        launcher->setVerbose(1);

    TrkSignalHandler handler;
    handler.setLogLevel(loglevel);
    handler.setCrashLogging(crashlog);
    handler.setCrashLogPath(crashlogpath);

    QObject::connect(launcher.data(), SIGNAL(copyingStarted()), &handler, SLOT(copyingStarted()));
    QObject::connect(launcher.data(), SIGNAL(canNotConnect(const QString &)), &handler, SLOT(canNotConnect(const QString &)));
    QObject::connect(launcher.data(), SIGNAL(canNotCreateFile(const QString &, const QString &)), &handler, SLOT(canNotCreateFile(const QString &, const QString &)));
    QObject::connect(launcher.data(), SIGNAL(canNotWriteFile(const QString &, const QString &)), &handler, SLOT(canNotWriteFile(const QString &, const QString &)));
    QObject::connect(launcher.data(), SIGNAL(canNotCloseFile(const QString &, const QString &)), &handler, SLOT(canNotCloseFile(const QString &, const QString &)));
    QObject::connect(launcher.data(), SIGNAL(installingStarted()), &handler, SLOT(installingStarted()));
    QObject::connect(launcher.data(), SIGNAL(canNotInstall(const QString &, const QString &)), &handler, SLOT(canNotInstall(const QString &, const QString &)));
    QObject::connect(launcher.data(), SIGNAL(installingFinished()), &handler, SLOT(installingFinished()));
    QObject::connect(launcher.data(), SIGNAL(startingApplication()), &handler, SLOT(startingApplication()));
    QObject::connect(launcher.data(), SIGNAL(applicationRunning(uint)), &handler, SLOT(applicationRunning(uint)));
    QObject::connect(launcher.data(), SIGNAL(canNotRun(const QString &)), &handler, SLOT(canNotRun(const QString &)));
    QObject::connect(launcher.data(), SIGNAL(applicationOutputReceived(const QString &)), &handler, SLOT(applicationOutputReceived(const QString &)));
    QObject::connect(launcher.data(), SIGNAL(copyProgress(int)), &handler, SLOT(copyProgress(int)));
    QObject::connect(launcher.data(), SIGNAL(stateChanged(int)), &handler, SLOT(stateChanged(int)));
    QObject::connect(launcher.data(), SIGNAL(processStopped(uint,uint,uint,QString)), &handler, SLOT(stopped(uint,uint,uint,QString)));
    QObject::connect(launcher.data(), SIGNAL(libraryLoaded(trk::Library)), &handler, SLOT(libraryLoaded(trk::Library)));
    QObject::connect(launcher.data(), SIGNAL(libraryUnloaded(trk::Library)), &handler, SLOT(libraryUnloaded(trk::Library)));
    QObject::connect(launcher.data(), SIGNAL(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &)), &handler, SLOT(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &)));
    QObject::connect(&handler, SIGNAL(resume(uint,uint)), launcher.data(), SLOT(resumeProcess(uint,uint)));
    QObject::connect(&handler, SIGNAL(terminate()), launcher.data(), SLOT(terminate()));
    QObject::connect(&handler, SIGNAL(getRegistersAndCallStack(uint,uint)), launcher.data(), SLOT(getRegistersAndCallStack(uint,uint)));
    QObject::connect(launcher.data(), SIGNAL(finished()), &handler, SLOT(finished()));

    QObject::connect(OsSignalConverter::instance(), SIGNAL(terminate()), launcher.data(), SLOT(terminate()), Qt::QueuedConnection);

    QTimer timer;
    timer.setSingleShot(true);
    QObject::connect(&timer, SIGNAL(timeout()), &handler, SLOT(timeout()));
    if (timeout > 0) {
        timer.start(timeout);
    }

    QString errorMessage;
    if (!launcher->startServer(&errorMessage)) {
        errstream << errorMessage << endl;
        return 1;
    }

    return a.exec();
}