Пример #1
0
bool Ingridients::saveData(QString& fileName) {
    QJsonObject saveObj;
    QFile saveFile(fileName);

    PRINT_DEBUG("Saving all ingridients");

    if ( !saveFile.open(QIODevice::WriteOnly) ) {
        PRINT_WARN("Couldn't open save file.");

        return false;
    }

    saveItems(saveObj);
    saveFood(saveObj);
    saveDish(saveObj);

    QJsonDocument saveDoc(saveObj);

    if ( !fileName.right(5).compare(".json") ) {
        saveFile.write(saveDoc.toJson());
    } else {
        saveFile.write(saveDoc.toBinaryData());
    }

    return true;
}
Пример #2
0
void WorkspaceSerializer::Write(const QString& fileName, const SignalData& data, const PlotInfo& plotInfo, bool writeValues /*= true*/)
{
	QJsonObject json;
	json["background"] = plotInfo.getBackgroundColor().name();
	if (writeValues)
	{
		if (auto domain = data.getDomain())
			json["domain"] = domain->name;
	}
	
	QJsonArray signArray;
	data.onSignals([&](const Signal& signal){
		QJsonObject signObj;
		signObj["name"] = signal.name;
		signObj["color"] = signal.graphic.color.name();
		signObj["visible"] = signal.graphic.visible;
		signObj["range"] = ToJsonArray(QVector < qreal > {signal.graphic.rangeLower, signal.graphic.rangeUpper});
		if (writeValues)
			signObj["values"] = ToJsonArray(signal.y);
		signObj["ticks"] = ToJsonArray(signal.graphic.ticks);
		signObj["tickLabels"] = ToJsonArray(signal.graphic.tickLabels);
		signArray.push_back(std::move(signObj));
	});
	json["signals"] = signArray;
	
	QJsonDocument saveDoc(json);
	QFile outF(fileName);
	outF.open(QIODevice::WriteOnly);
	outF.write(saveDoc.toJson(QJsonDocument::Indented));
}
Пример #3
0
void ApiInfo::createInstance()
      {
      if (_instance)
            return;

      QFile f(apiInfoLocation());
      QByteArray clientId;
      if (f.open(QIODevice::ReadOnly)) {
            const QByteArray saveData = f.readAll();
            const QJsonDocument d(QJsonDocument::fromBinaryData(saveData));
            QJsonObject saveObject = d.object();
            clientId = saveObject["clientId"].toString().toLatin1();
            f.close();
            }
      else {
            clientId = genClientId();
            // Save the generated ID
            if (f.open(QIODevice::WriteOnly)) {
                  QJsonObject saveObject;
                  saveObject["clientId"] = QString(clientId);
                  QJsonDocument saveDoc(saveObject);
                  f.write(saveDoc.toBinaryData());
                  f.close();
                  }
            }

      QByteArray apiKey("0b19809bab331d70fb9983a0b9866290");
      _instance = new ApiInfo(clientId, apiKey);
      }
Пример #4
0
void CBAttachmentsProvider::saveAttributes(){
    QFile saveFile(attributePath());
    if (!saveFile.open(QIODevice::WriteOnly)) {
            qWarning("Couldn't open save file.");
    }
    QJsonDocument saveDoc(QJsonArray::fromVariantList(attributes));
    saveFile.write(saveDoc.toJson());
}
Пример #5
0
bool MultiObjPathPlanningInfo::saveToFile( QString filename ) {
    QFile saveFile(filename);

    if( false == saveFile.open(QIODevice::WriteOnly) ) {
        qWarning("Couldn't open file.");
        return false;
    }

    QJsonObject infoObject;
    write(infoObject);
    QJsonDocument saveDoc(infoObject);
    saveFile.write(saveDoc.toJson());
    return true;

}
Пример #6
0
bool LoginManager::save()
      {
      if (_accessToken.isEmpty() || _refreshToken.isEmpty())
            return true;
      QFile saveFile(dataPath + "/cred.dat");
      if (!saveFile.open(QIODevice::WriteOnly))
            return false;
      QJsonObject saveObject;
      saveObject["accessToken"] = _accessToken;
      saveObject["refreshToken"] = _refreshToken;
      QJsonDocument saveDoc(saveObject);
      saveFile.write(saveDoc.toBinaryData());
      saveFile.close();
      return true;
      }
Пример #7
0
void BtsSpawnClient::startClient()
{
	if(isClientReady() || (p->clientProc && p->clientProc->state() == QProcess::Starting))
		return;

	QJsonObject configObject;
	configObject.insert("storage_path", getDataPath());
	configObject.insert("use_gui", false);

	QJsonObject webuiObject;
	webuiObject.insert("listen", QString("%1:%2").arg(p->host).arg(p->port));
	webuiObject.insert("login", p->username);
	webuiObject.insert("password", p->password);
	webuiObject.insert("api_key", BtsGlobal::getApiKey().toString());

	configObject.insert("webui", webuiObject);

	p->configFile.open();
	QJsonDocument saveDoc(configObject);
	p->configFile.write(saveDoc.toJson());
	p->configFile.close();

	p->configFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner);

	p->cur_port = p->port;
	p->cur_password = p->password;
	p->cur_username = p->username;

	p->clientProc = new QProcess(this);
	connect(p->clientProc, SIGNAL(finished(int)), this, SLOT(procFinished(int)));
	connect(p->clientProc, SIGNAL(finished(int)), p->clientProc, SLOT(deleteLater()));
	connect(p->clientProc, SIGNAL(started()), this, SLOT(procStarted()));

#ifdef Q_OS_WIN
# define ARG_PREFIX "/"
#else
# define ARG_PREFIX "--"
#endif

	p->clientProc->setProgram(BtsGlobal::getBtsyncExecutablePath());
	p->clientProc->setArguments(QStringList()
	                            << ARG_PREFIX "nodaemon"
	                            << ARG_PREFIX "config" << p->configFile.fileName());

	p->clientProc->setProcessChannelMode(QProcess::ForwardedChannels);

	p->clientProc->start();
}
Пример #8
0
void initWindow::guardar()
{
    QFile saveFile(QStringLiteral("save.json"));


       if (!saveFile.open(QIODevice::WriteOnly)) {
           qWarning("Couldn't open save file.");
           return ;
       }

       QJsonObject estructura;
       write(estructura);
       if(estructura.empty())
           exit(0);
       QJsonDocument saveDoc(estructura);
       saveFile.write(saveDoc.toJson());

}
Пример #9
0
void MetaDataWriter::save()
{
    QFile saveFile(m_filename);
    QJsonObject top, jsonClst;

    if (!saveFile.open(QIODevice::WriteOnly))
    {
        qWarning("dressr.json could not be opened for writing!");
        return;
    }

    m_closet->write(jsonClst);

    top["Closet"] = jsonClst;

    QJsonDocument saveDoc(top);
    saveFile.write(saveDoc.toJson());
}
ConfigurationDialog::ConfigurationDialog(const CFGManager *cfg, QWidget *parent) :
        Dialog("Configuration", "", parent)
{
    this->cfg = cfg;
    setFixedSize(350, 500);
    text->hide();
    connect(cfg, SIGNAL(errorMessage(QString)),
            this, SLOT(showMessage(QString)));
    connect(this, SIGNAL(okPressed()), this, SLOT(accept()));
    connect(this, SIGNAL(okPressed()), cfg, SLOT(saveDoc()));
    connect(this, SIGNAL(cancelPressed()), cfg, SLOT(undoDoc()));
    tabs = new QTabWidget();
    mainLayout->addWidget(tabs, 4, 0, 1, 4);

    createDatabaseTab();
    createSpreadSheetTab();
    createSecurityTab();
}
Пример #11
0
bool ImpedanceLog::saveLog() {

    QFile saveFile(logFile.absoluteFilePath());

    if (!saveFile.open(QIODevice::WriteOnly)) {
        qWarning("Couldn't open save file.");
        return false;
    }

    QJsonObject json;
    json["log"] = log;

    QJsonDocument saveDoc(json);
    saveFile.write(saveDoc.toJson());

    cout << "Log saved." << endl;
    return true;
}
UserEntryCache::~UserEntryCache() {
    if (modified_m) {
        if (file_name_m == "") {
            return;
        }
        QJsonObject obj{};
        obj["cache"] = cache_m;
        obj["script_path"] = script_path_m;
        obj["touched_unixtime"] = QJsonValue(qint64(QDateTime::currentDateTime().toTime_t()));

        QJsonDocument saveDoc(obj);
        QFile saveFile(file_name_m);
        if (!saveFile.open(QIODevice::WriteOnly)) {
            MainWindow::mw->show_status_bar_massage(QObject::tr("Could not save user entry cache file.") + file_name_m, 2000);
            return;
        }
        saveFile.write(saveDoc.toJson());
    }
}
Пример #13
0
//! [4]
bool Game::saveGame(Game::SaveFormat saveFormat) const
{
    QFile saveFile(saveFormat == Json
        ? QStringLiteral("save.json")
        : QStringLiteral("save.dat"));

    if (!saveFile.open(QIODevice::WriteOnly)) {
        qWarning("Couldn't open save file.");
        return false;
    }

    QJsonObject gameObject;
    write(gameObject);
    QJsonDocument saveDoc(gameObject);
    saveFile.write(saveFormat == Json
        ? saveDoc.toJson()
        : saveDoc.toBinaryData());

    return true;
}
Пример #14
0
bool Storage::saveToFile(QString fileName, QJsonObject data, bool saveJson)
{
    QFile saveFile(saveJson
                   ? QStringLiteral("%1.json").arg(fileName)
                   : QStringLiteral("%1.dat").arg(fileName));

    if (!saveFile.open(QIODevice::WriteOnly)) {
        qWarning("Couldn't open save file.");
        return false;
    }



    QJsonDocument saveDoc(data);
    saveFile.write(saveJson == Json
                   ? saveDoc.toJson()
                   : saveDoc.toBinaryData());

    return true;
}
Пример #15
0
bool SiteResponseModel::saveJson()
{
    QJsonObject json;

    json["notes"] = m_notes->toPlainText();
    json["method"] = (int) m_method;
    json["hasResults"] = m_hasResults;
    json["system"] = (int) Units::instance()->system();

    json["randNumGen"] = m_randNumGen->toJson();
    json["siteProfile"] = m_siteProfile->toJson();
    json["motionLibrary"] = m_motionLibrary->toJson();
    json["outputCatalog"] = m_outputCatalog->toJson();

    switch (m_method) {
    case SiteResponseModel::EquivalentLinear:
        json["calculator"] = qobject_cast<EquivalentLinearCalculator*>(m_calculator)->toJson();
        break;
    case SiteResponseModel::FrequencyDependent:
        json["calculator"] = qobject_cast<FrequencyDependentCalculator*>(m_calculator)->toJson();
        break;
    case SiteResponseModel::LinearElastic:
    default:
        break;
    }

    QFile file(m_fileName);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning("Couldn't open save file.");
        return false;
    }

    QJsonDocument saveDoc(json);
    file.write(saveDoc.toJson(QJsonDocument::Indented));

    setModified(false);
    return true;
}
bool StageSettingDialog::saveStageSettingss(SaveFormat saveFormat) const
{

    QFile saveFile(saveFormat == Json
                   ? QStringLiteral("save.json")
                   : QStringLiteral("save.dat"));

    if (!saveFile.open(QIODevice::WriteOnly))
    {
        qWarning("Couldn't open save File");
        return false;
    }

    QJsonObject settingObject;
    write(settingObject);

    QJsonDocument saveDoc(settingObject);
    saveFile.write(saveFormat == Json
                   ? saveDoc.toJson()
                   : saveDoc.toBinaryData());

    return true;
}
Пример #17
0
/**
 * @brief NoteEditScene::saveJson 指定したパスにjson情報を保存する
 * @param path
 */
void NoteEditScene::saveJson(QString path)
{
    //QString saveName = QFileDialog::getSaveFileName(this->views()[0], tr("Save File"), QDir::homePath(), tr("Json (*.json)"));

    QFile f(path);

    if(!f.open(QIODevice::WriteOnly))
    {
        qWarning("Couldn't open save.json");
        return;
    }
    //ソート
    qSort(noteList.begin(), noteList.end(), Note::compare);

    QVector< QVector< QSharedPointer<QJsonObject> > > lanes;
    for(int i=0;i < 9;i++)
    {
        QVector< QSharedPointer<QJsonObject> > lane;
        lanes.append(lane);
    }

    QHash<int, QSharedPointer<QJsonObject> > timeMap;

    for(Note* n : noteList)
    {
        qreal startTime = n->startTime();
        qreal endTime = n->endTime();
        int lane =n->laneNum();
        bool isLongNote = n->isLongNotes();
        bool isHold = n->isStar();

        QSharedPointer<QJsonObject> noteInfo(new QJsonObject);
        noteInfo->insert("starttime", startTime);
        noteInfo->insert("endtime", endTime);
        noteInfo->insert("longnote", isLongNote);
        noteInfo->insert("hold", isHold);
        noteInfo->insert("parallel", false);
        noteInfo->insert("lane", lane);


        //もしもハッシュの中に同じ時間のデータが存在する場合
        QHash<int, QSharedPointer<QJsonObject> >::iterator it = timeMap.find(startTime);
        if(it != timeMap.end() && it.key() == startTime)
        {
            noteInfo->insert("parallel", true);
            //発見したものも直す
            it.value()->insert("parallel",true);
        }
        else
        {
            timeMap.insert(startTime,noteInfo);
        }

        //lanesに追加
        lanes[lane].append(noteInfo);
    }


    QJsonObject saveObject;
    QJsonArray mainArray;
    for(QVector<QSharedPointer<QJsonObject> > v : lanes)
    {
        QSharedPointer<QJsonArray> array(new QJsonArray);
        for(QSharedPointer<QJsonObject> json : v)
        {
            array->append(*json);
        }
        mainArray.append(*array);
    }

    saveObject.insert("lane", mainArray);
    // QJsonオブジェクトをテキストの形にして、保存する
    QJsonDocument saveDoc(saveObject);
    f.write(saveDoc.toJson());
    f.close();
}
void VehicleTemplateExportDialog::saveTemplate(QString path)
{
    QJsonObject exportObject;

    QList<UAVObject *> objectsToExport;
    objectsToExport << StabilizationSettings::GetInstance(m_uavoManager);
    objectsToExport << StabilizationSettingsBank1::GetInstance(m_uavoManager);
    objectsToExport << StabilizationSettingsBank2::GetInstance(m_uavoManager);
    objectsToExport << StabilizationSettingsBank3::GetInstance(m_uavoManager);
    objectsToExport << MixerSettings::GetInstance(m_uavoManager);
    objectsToExport << EKFConfiguration::GetInstance(m_uavoManager);
    m_uavoManager->toJson(exportObject, objectsToExport);

    exportObject["type"]       = m_type;
    exportObject["subtype"]    = m_subType;
    exportObject["name"]       = ui->Name->text();
    exportObject["owner"]      = ui->Owner->text();
    exportObject["nick"]       = ui->ForumNick->text();
    exportObject["size"]       = ui->Size->text();
    exportObject["weight"]     = ui->Weight->text();
    exportObject["motor"]      = ui->Motor->text();
    exportObject["esc"]        = ui->Esc->text();
    exportObject["servo"]      = ui->Servo->text();
    exportObject["battery"]    = ui->Battery->text();
    exportObject["propeller"]  = ui->Propeller->text();
    exportObject["controller"] = ui->Controllers->currentText();
    exportObject["comment"]    = ui->Comment->document()->toPlainText();
    QUuid uuid = QUuid::createUuid();
    exportObject["uuid"]       = uuid.toString();

    if (!m_image.isNull()) {
        QByteArray bytes;
        QBuffer buffer(&bytes);
        buffer.open(QIODevice::WriteOnly);
        m_image.scaled(IMAGE_SCALE_WIDTH, IMAGE_SCALE_HEIGHT, Qt::KeepAspectRatio,
                       Qt::SmoothTransformation).save(&buffer, "PNG");
        exportObject["photo"] = QString::fromLatin1(bytes.toBase64().data());
    }

    QJsonDocument saveDoc(exportObject);

    const char *fileType = ".optmpl";

    QString fileName     = QString("%1-%2-%3%4")
                           .arg(fixFilenameString(ui->Name->text(), 20))
                           .arg(fixFilenameString(ui->Type->text(), 30))
                           .arg(fixFilenameString(uuid.toString().right(12)))
                           .arg(fileType);

    QString fullPath;
    if (path.isEmpty()) {
        fullPath = QString("%1%2%3").arg(QDir::homePath()).arg(QDir::separator()).arg(fileName);
        fullPath = QFileDialog::getSaveFileName(this, tr("Export settings"), fullPath, QString("%1 (*%2)").arg(tr("OPTemplates"), fileType));
    } else {
        fullPath = QString("%1%2%3").arg(path).arg(QDir::separator()).arg(fileName);
    }

    if (!fullPath.isEmpty()) {
        if (!fullPath.endsWith(fileType)) {
            fullPath.append(fileType);
        }
        QFile saveFile(fullPath);
        if (saveFile.open(QIODevice::WriteOnly)) {
            saveFile.write(saveDoc.toJson());
            saveFile.close();
        } else {
            QMessageBox::information(this, "Export", tr("Settings could not be exported to \n%1(%2).\nPlease try again.")
                                     .arg(QFileInfo(saveFile).absoluteFilePath(), saveFile.error()), QMessageBox::Ok);
        }
    }
}
Пример #19
0
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QCommandLineParser parser;
    parser.addHelpOption();
    parser.addOptions({
            { "nogui", QString("Using command line arguments, do not show GUI.") },
            { { "p", "path" }, QString("Path for job files or shape files."), QString("path") },
            { { "g", "align" }, QString("Input is not aligned. Find lowest cost alignment.") },
            { { "s", "sourceShape" }, QString("Path for source shape file."), QString("source") },
            { { "t", "targetShape" }, QString("Path for target shape file."), QString("target") },
            { { "a", "auto" }, QString("Automatically try to find initial correspondence. Not used for job files.") },
			{ { "j", "job" }, QString("Job file to load."), QString("job") },
			{ { "f", "folder" }, QString("Folder for a shape dataset."), QString("folder") },
            { { "z", "output" }, QString("Folder for output JSON file."), QString("output") },
			{ { "q", "quiet" }, QString("Skip visualization.") },
            { { "m", "asymmetry" }, QString("Ignore symmetry groups. Used for evaluation.") },

            /* Actual paramteres */
            { { "k", "k" }, QString("(k) parameter for DP search."), QString("k") },
            { { "o", "roundtrip" }, QString("Compute least cost from source to target, and target to source.") },
            { { "c", "cut" }, QString("Allow part cuts/joins.") },

			/* Experiments */
			{ { "e", "experiment" }, QString("Perform hard coded experiments.") },
	});

    if (!parser.parse(QCoreApplication::arguments())) {
        QString errorText = parser.errorText();
        std::cout << qPrintable(errorText);
        return CommandLineError;
    }
	else
		parser.process(a);

	QString path = parser.value("p");
	QDir::setCurrent(path);

	/// Experiments:
	if (parser.isSet("e"))
	{
		QVariantMap options;
        //options["k"].setValue(6);
        //options["isQuietMode"].setValue(true);
		options["isOutputMatching"].setValue(true);
		options["isSaveReport"].setValue(true);
		options["isLogJobs"].setValue(true);

		QString sourceShape = "C:/Development/GeoTopo/standalone/ChairWood2/Woodchair2.xml";
		QString targetShape = "C:/Development/GeoTopo/standalone/chairVK2110/chair2110.xml";

		srand(time(nullptr));

        for (int i = 0; i < 1; i++)
		{
			auto bp = QSharedPointer<BatchProcess>(new BatchProcess(sourceShape, targetShape, options));
			bp->jobUID = (double(rand()) / RAND_MAX) * 10;
			bp->run();

			for (auto & report : bp->jobReports){
				int time = report["search_time"].toInt();
				double c = report["min_cost"].toDouble();

				std::cout << "cost = " << c << " , time = " << time << std::endl;
			}

			//std::swap(sourceShape, targetShape);
		}

		return 0;
	}

    /// Process shape sets:
    if(parser.isSet("folder"))
    {
		QElapsedTimer timer; timer.start();

        QString dataset = parser.value("folder");
        QDir d("");
        QString dir_name = QDir(dataset).dirName();

		// 1) get sorted set of pairs to compare
        QVector< QPair<int, int> > shapePairs;
		auto folders = shapesInDataset(dataset);
		auto folderKeys = folders.keys();
		for (int i = 0; i < folderKeys.size(); i++)
			for (int j = i + 1; j < folderKeys.size(); j++)
                shapePairs << qMakePair(i,j);
		int shapePairsCount = shapePairs.size();
		int curShapePair = 0;

        QMap< QString,QPair<int,int> > pair_idx;

		// 2) perform correspondence for shape pairs
		{
			// Remove previous log file
			d.remove("log.txt");

			// go over pairs
			for (auto shapePair : shapePairs)
			{
				QProcess p;
                QString source = folders[folders.keys().at(shapePair.first)]["graphFile"].toString();
                QString target = folders[folders.keys().at(shapePair.second)]["graphFile"].toString();

				auto sg = QFileInfo(source).baseName();
				auto tg = QFileInfo(target).baseName();

                pair_idx[sg+tg] = qMakePair(shapePair.first, shapePair.second);

				std::cout << QString("Now: %1 / %2").arg(sg).arg(tg).leftJustified(35, ' ', true).toStdString();

				QStringList pargs;

                // Inputs
				pargs << "-s" << source << "-t" << target;	

                // Forward search options
                if (parser.isSet("o")) pargs << "-o";
                if (parser.isSet("k")) pargs << "-k" << parser.value("k");
				if (parser.isSet("q")) pargs << "-q";
                if (parser.isSet("c")) pargs << "-c";
                if (parser.isSet("m")) pargs << "-m";

                // Execute as a seperate process
				p.start(a.applicationFilePath(), pargs);
				p.waitForFinished(-1);

                // Show progress to user
				auto percent = (double(curShapePair++) / shapePairsCount) * 100.0;
				std::cout << QString("[%1 %] - %2 - ").arg((int)percent).arg(shapePairsCount-curShapePair).toStdString();
				int secPerPercent = (timer.elapsed() / 1000) / (percent + 1);
				int timeMinLeft = (secPerPercent * (100 - percent)) / 60;
				std::cout << QString("Time (%1s=%2m) ETA(%3m)\n").arg(timer.elapsed() / 1000).arg(timer.elapsed() / 60000).arg(timeMinLeft).toStdString();
			}
		}

		// 3) prepare results folder
		QString job_name = QString("job_%1").arg(QDateTime::currentDateTime().toString("dd_MM_yyyy_hh_mm_ss"));
		d.mkpath(job_name);

        // 4) collect all pair-wise results
		{
            // output sorted set of shape names
			{
                QFile file(d.absolutePath() + "/" + job_name + "/" + "_" + dir_name + "_shapes.txt");
				if (file.open(QIODevice::WriteOnly | QIODevice::Text)){
					QTextStream out(&file);
					for (int i = 0; i < folderKeys.size(); i++)
						out << QString("%1 %2\n").arg(i).arg(folderKeys.at(i));
				}
			}

			// read log and record the minimum costs and correspondence results
			{
				QFile ff(d.absolutePath() + "/" + "log.txt");
				ff.open(QFile::ReadOnly | QFile::Text);
				QTextStream in(&ff);
				auto datasetLogLines = in.readAll().split("\n", QString::SkipEmptyParts);

				// Record final results
                QJsonArray results;

                for(int idx = 0; idx < datasetLogLines.size(); idx++)
                {
                    // Read matching pair info
                    auto log_line = datasetLogLines[idx].split(",", QString::SkipEmptyParts);
                    QJsonObject matching;
                    matching["source"] = log_line.at(0);
                    matching["target"] = log_line.at(1);
                    matching["cost"] = log_line.at(2).toDouble();

                    // Get correspondence data
                    QString correspondenceFile = log_line.at(3);
                    bool isSwapped = (log_line.at(4).toInt() % 2) == 0;
                    QJsonArray correspondence;
                    {
                        // Open correspondence file
                        QFile cf(correspondenceFile);
                        cf.open(QFile::ReadOnly | QFile::Text);
                        QTextStream cfin(&cf);
                        auto corrLines = cfin.readAll().split("\n", QString::SkipEmptyParts);

                        // Read correspondence file (swapping if needed)
                        for (auto line : corrLines)
                        {
                            auto matched_pair = line.split(" ", QString::SkipEmptyParts);
                            QString sid = matched_pair.at(0);
                            QString tid = matched_pair.at(1);
                            if (isSwapped) std::swap(sid, tid);

                            QJsonArray part_pair;
                            part_pair.push_back(sid);
                            part_pair.push_back(tid);
                            correspondence.push_back(part_pair);
                        }
                    }
                    matching["correspondence"] = correspondence;

                    // Thumbnail files if any
                    QString correspondenceThumb = log_line.back();
                    if(correspondenceThumb != "null"){
                        QString targetThumb = QFileInfo(correspondenceThumb).fileName();
                        targetThumb = QString(d.absolutePath() + "/" + job_name + "/" + targetThumb);
                        QFile::copy(correspondenceThumb, targetThumb);
                        matching["thumbnail"] = targetThumb;
                    }

                    // indexing
                    auto sg = QFileInfo(log_line.at(0)).baseName();
                    auto tg = QFileInfo(log_line.at(1)).baseName();
                    auto pi = pair_idx[sg+tg];
                    matching["i"] = pi.first;
                    matching["j"] = pi.second;

                    // Record result
                    results.push_back(matching);
                }

				// Write all results in JSON format
				{
					QJsonDocument saveDoc(results);

                    QString jsonFilename = d.absolutePath() + "/" + job_name + "/_" + dir_name + "_corr.json";

                    // User specified output folder
                    if(parser.isSet("output")) jsonFilename = parser.value("output") + "/" + dir_name + "_corr.json";

                    QFile saveFile( jsonFilename );
                    saveFile.open( QIODevice::WriteOnly );
                    saveFile.write( saveDoc.toJson() );
				}
			}
		}

		return folders.size();
    }

	MainWindow w;
	//w.show();

    /// Here we perform the actual pair-wise correspondence:
    QString jobs_filename;

    if(parser.isSet("nogui") || parser.isSet("auto") || parser.isSet("sourceShape"))
    {
        if (parser.isSet("auto") || parser.isSet("sourceShape") || parser.isSet("targetShape"))
		{
			QString sourceShape = parser.value("sourceShape");
			QString targetShape = parser.value("targetShape");
			QVariantMap options;

            if(parser.isSet("g")) options["align"].setValue(true);
            if(parser.isSet("o")) options["roundtrip"].setValue(true);
            if(parser.isSet("k")) options["k"].setValue(parser.value("k").toInt());
			if(parser.isSet("q")) options["isQuietMode"].setValue(true);
            if(parser.isSet("c")) options["isAllowCutsJoins"].setValue(true);
            if(parser.isSet("m")) options["isIgnoreSymmetryGroups"].setValue(true);

            if(options["roundtrip"].toBool() || options["align"].toBool())
			{
				options["isManyTypesJobs"].setValue(true);
				options["isOutputMatching"].setValue(true);

				QTimer::singleShot(1, [sourceShape, targetShape, options]
				{
					int numJobs = 0;

					auto cur_options = options;

					QVector< QVector<QVariantMap> > reports;

					int numIter = 1;

					// Command line now only supports two tests.. GUI has more options
					if (cur_options["align"].toBool()) numIter = 2;

					for (int iter = 0; iter < numIter; iter++)
					{
						auto bp = QSharedPointer<BatchProcess>(new BatchProcess(sourceShape, targetShape, cur_options));

						bp->jobUID = numJobs++;
						bp->run();

						reports << bp->jobReports;

						if (cur_options["roundtrip"].toBool())
						{
							auto bp2 = QSharedPointer<BatchProcess>(new BatchProcess(targetShape, sourceShape, cur_options));

							bp2->jobUID = numJobs++;
							bp2->run();

							reports << bp2->jobReports;
						}

						cur_options["isFlip"].setValue(true);
					}

					// Look at reports
					double minEnergy = 1.0;
					int totalTime = 0;
					QVariantMap minJob;
					for (auto & reportVec : reports)
					{
						for (auto & report : reportVec)
						{
							totalTime += report["search_time"].toInt();

							double c = report["min_cost"].toDouble();
							if (c < minEnergy){
								minEnergy = c;
								minJob = report;
							}
						}
					}

					std::cout << "\nJobs computed: " << numJobs << "\n";
					std::cout << minEnergy << " - " << qPrintable(minJob["img_file"].toString());

					// Aggregate results
					{
						QFile file("log.txt");
						if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
						{
                            QString thumb_filename = minJob["img_file"].toString();

							QTextStream out(&file);
                            out << sourceShape << "," << targetShape << "," << minJob["min_cost"].toDouble() << ","
                                << minJob["match_file"].toString() << "," << minJob["job_uid"].toInt() << ","
                                << (thumb_filename.isEmpty() ? "null" : thumb_filename) << "\n";
						}
                    }
                }); // end of QTimer::singleShot
            }
            else
            {
                auto bp = new BatchProcess(sourceShape, targetShape, options);
                QObject::connect(bp, SIGNAL(allJobsFinished()), &w, SLOT(close()));
                QObject::connect(bp, SIGNAL(finished()), bp, SLOT(deleteLater()));
                bp->start();
            }

			return a.exec();
		}
		else
		{
			jobs_filename = parser.value("job");
			if (jobs_filename.isEmpty()){
				std::cout << "Please provide a job file.";
				return CommandLineError;
			}
		}

		std::cout << "Not enough arguments.";
		return CommandLineError;
    }
    else
	{
		jobs_filename = QFileDialog::getOpenFileName(&w, "Load Jobs", "", "Jobs File (*.json)");
    }

    QTimer::singleShot(0, [&] {
        BatchProcess * bp = new BatchProcess(jobs_filename);
        QObject::connect(bp, SIGNAL(allJobsFinished()), &w, SLOT(close()));
		QObject::connect(bp, SIGNAL(finished()), bp, SLOT(deleteLater()));
        bp->start();
    });

    return a.exec();
}