コード例 #1
0
ファイル: shx.cpp プロジェクト: ForNeVeR/leechcraft
	void Plugin::handleFinished ()
	{
		auto proc = qobject_cast<QProcess*> (sender ());
		proc->deleteLater ();

		const auto entryObj = Process2Entry_.take (proc);
		if (!entryObj)
		{
			qWarning () << Q_FUNC_INFO
					<< "no entry for process"
					<< proc;
			return;
		}
#ifdef Q_OS_WIN32
		auto out = QString::fromUtf16 (reinterpret_cast<const ushort*> (proc->readAllStandardOutput ().constData ()));
#else
		auto out = QString::fromUtf8 (proc->readAllStandardOutput ());
#endif
		const auto& err = proc->readAllStandardError ();

		if (!err.isEmpty ())
#ifdef Q_OS_WIN32
			out.prepend (tr ("Error: %1").arg (QString::fromUtf16 (reinterpret_cast<const ushort*> (err.constData ()))) + "\n");
#else
			out.prepend (tr ("Error: %1").arg (QString::fromUtf8 (err)) + "\n");
#endif

		const auto entry = qobject_cast<ICLEntry*> (entryObj);
		AzothProxy_->OpenChat (entry->GetEntryID (),
				entry->GetParentAccount ()->GetAccountID (),
				out);
	}
コード例 #2
0
ファイル: shx.cpp プロジェクト: mirok0/leechcraft
	void Plugin::handleFinished ()
	{
		auto proc = qobject_cast<QProcess*> (sender ());
		proc->deleteLater ();

		if (!Process2Chat_.contains (proc))
		{
			qWarning () << Q_FUNC_INFO
					<< "no chat for process"
					<< proc;
			return;
		}
#ifdef Q_OS_WIN32
		auto out = QString::fromUtf16 (reinterpret_cast<const ushort*> (proc->readAllStandardOutput ().constData ()));
#else
		auto out = QString::fromUtf8 (proc->readAllStandardOutput ());
#endif
		const auto& err = proc->readAllStandardError ();

		if (!err.isEmpty ())
#ifdef Q_OS_WIN32
			out.prepend (tr ("Error: %1").arg (QString::fromUtf16 (reinterpret_cast<const ushort*> (err.constData ()))) + "\n");
#else
			out.prepend (tr ("Error: %1").arg (QString::fromUtf8 (err)) + "\n");
#endif

		QMetaObject::invokeMethod (Process2Chat_.take (proc),
				"prepareMessageText",
				Q_ARG (QString, out));
	}
コード例 #3
0
ファイル: translator.cpp プロジェクト: denix56/Apertium-GP
//TODO: add support of URL
void Translator::translateHtml(QString filePath, QDir &docDir)
{
    QFileInfo fileInfo(filePath);
    auto cmd = new QProcess(this);

    QTemporaryFile tmpDoc("document.html");
    cmd->setWorkingDirectory(QDir(DATALOCATION).absoluteFilePath("apertium-all-dev/bin"));
    QStringList args;
    qApp->processEvents();
    //deshtml
#ifdef Q_OS_WIN
    //windows bug with backslash
    //use replace to fix windows bug
    args << "/u" << "/c" << "type" << "\"" + filePath.replace('/', QDir::separator()) + "\""
         << "|" << "apertium-deshtml";
    cmd->setNativeArguments(args.join(' '));
    cmd->start("cmd.exe");
#endif
    cmd->waitForFinished();
    cmd->waitForReadyRead();
    if (!tmpDoc.open()) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    tmpDoc.setTextModeEnabled(true);
    tmpDoc.write(notLinuxTranslate(cmd->readAllStandardOutput()).toUtf8());
    tmpDoc.close();
    //rehtml
    //FIXME: rehtml or rehtml-noent???
    args.clear();
#ifdef Q_OS_WIN
    args << "/u" << "/c" << "type" << "\"" + tmpDoc.fileName().replace('/', QDir::separator()) + "\""
         << "|" << "apertium-rehtml";
    cmd->setNativeArguments(args.join(' '));
    cmd->start("cmd.exe");
#endif
    cmd->waitForFinished();
    cmd->waitForReadyRead();
    QString trFilePath = docDir.absoluteFilePath(fileInfo.baseName() + "_" +
                                                 parent->getCurrentSourceLang()
                                                 + "-" + parent->getCurrentTargetLang() + "." + fileInfo.suffix());
    QFile newDoc(trFilePath);
    if (!newDoc.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    newDoc.write(cmd->readAllStandardOutput());
    newDoc.close();
    emit fileTranslated(trFilePath);
    cmd->deleteLater();
    //#else
    //    // cmd->start("ar", QStringList() << "x" << "data.tmp");
    //#endif
}
コード例 #4
0
ファイル: myprocess.cpp プロジェクト: slyshykO/qgit
void MyProcess::on_readyReadStandardOutput() {
	if (canceling)
		return;

	if (receiver)
		emit procDataReady(readAllStandardOutput());

	else if (runOutput)
		runOutput->append(readAllStandardOutput());
}
コード例 #5
0
ファイル: dataloader.cpp プロジェクト: rhaschke/qgit
ulong DataLoader::readNewData(bool lastBuffer) {

	/*
	   QByteArray copy c'tor uses shallow copy, but there is a deep copy in
	   QProcess::readStdout(), from an internal buffers list to return value.

	   Qt uses a select() to detect new data is ready, copies immediately the
	   data to the heap with a read() and stores the pointer to new data in a
	   pointer list, from qprocess_unix.cpp:

		const int basize = 4096;
		QByteArray *ba = new QByteArray(basize);
		n = ::read(fd, ba->data(), basize);
		buffer->append(ba); // added to a QPtrList<QByteArray> pointer list

	   When we call QProcess::readStdout() data from buffers pointed by the
	   pointer list is memcpy() to the function return value, from qprocess.cpp:

		....
		return buf->readAll(); // memcpy() here
	*/
	QByteArray* ba = new QByteArray(readAllStandardOutput());
	if (lastBuffer)
		ba->append('\0'); // be sure stream is null terminated

	if (ba->size() == 0) {
		delete ba;
		return 0;
	}
	fh->rowData.append(ba);
	parseSingleBuffer(*ba);
	return ba->size();
}
コード例 #6
0
void ShapeKnotsProcess::stdOut()
{
    QByteArray bytes = readAllStandardOutput();
    QStringList lines = QString(bytes).split("\n");
    foreach (QString text, lines) {
        emit line(text);
    }
コード例 #7
0
ファイル: translator.cpp プロジェクト: denix56/Apertium-GP
/*!
 * \brief Translating txt files not on Linux.
 *
 * \warning There are some problems with translating of documents
 * on Windows platform. All document translation functions should be rewrited.
 */
void Translator::translateTxt(QString filePath, QDir &docDir)
{
    QFile f(filePath);
    QFileInfo fileInfo(filePath);
    QTemporaryFile tmpDoc(fileInfo.baseName());
    auto cmd = new QProcess(this);
#ifdef Q_OS_WIN
    cmd->setWorkingDirectory(QDir(DATALOCATION).absoluteFilePath("apertium-all-dev/bin"));
#endif
    qApp->processEvents();
    //destxt
    cmd->start("cmd.exe", QStringList() << "/u" << "/c" << "type" << "\"" + filePath.replace('/',
                                                                                             QDir::separator()) + "\""
               << "|" << "apertium-destxt");
    cmd->waitForFinished();
    cmd->waitForReadyRead();
    if (!tmpDoc.open()) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    tmpDoc.setTextModeEnabled(true);
    tmpDoc.write(notLinuxTranslate(cmd->readAllStandardOutput()).toUtf8());
    //retxt
    cmd->start("cmd.exe", QStringList() << "/u" << "/c" << "type" << "\"" +
               tmpDoc.fileName().replace('/', QDir::separator())
               + "\"" << "|" << "apertium-retxt");
    cmd->waitForFinished();
    cmd->waitForReadyRead();
    QString trFilePath = docDir.absoluteFilePath(fileInfo.baseName() + "_" +
                                                 parent->getCurrentSourceLang()
                                                 + "-" + parent->getCurrentTargetLang() + "." + fileInfo.suffix());
    QFile newDoc(trFilePath);
    if (!newDoc.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    newDoc.write(cmd->readAllStandardOutput());
    newDoc.close();
    emit fileTranslated(trFilePath);
    cmd->deleteLater();
}
コード例 #8
0
/*
  Filter the output from the uploader to make it more
  meaningful/useful for the user.  Check for upload progress
  And pass it to the upload dialog.
*/
void Uploader::filterOutput( )
{
  QString output(readAllStandardOutput());
  QRegExp re("upload progress: (\\d+)%");
  int pos = 0;
  bool matched = false;
  while((pos = re.indexIn(output, pos)) != -1)
  {
    int progress = re.cap(1).toInt();
    if(progress != uploaderProgress->value())
      uploaderProgress->setValue(progress);
	  pos += re.matchedLength();
    matched = true;
  }
  if(!matched)
    qDebug("upload output: %s", qPrintable(output));
}
コード例 #9
0
ファイル: ipprocess.cpp プロジェクト: tailored/qiptables
QString IpProcess::executeSynchronous(const QString &program, const QStringList &arguments)
{
    QString empty("");
    QString result("");

    printCmdLine(program, arguments);

    if (arguments.count() > 0)
    {
        start(program, arguments);
    }
    else
    {
        start(program);
    }

    if (! waitForStarted())
        return empty;

    closeWriteChannel();

    int secondsToWait = 30;
    if (! waitForFinished(secondsToWait * 1000))
        return empty;

    // exit code of zero means command completed ok
    // and that output is from stdout - error output is on stderrs
    if ( (exitCode() == 0) && (errStr.isEmpty()) )
    {
        result = QString(QString(readAllStandardOutput()));
    }
    else
    {
        result = QString(QString(readAllStandardError()));
    }

    if (result.isEmpty())
    {
        // result = parseErrorCode();
    }

    // Send the result of executing the command
    emit cmdOutput(program, arguments, exitCode(), result);

    return QString(result);
}
コード例 #10
0
ファイル: pluginprocess.cpp プロジェクト: pdautry/PTRS
void PluginProcess::SLOT_FINISHED(int exitCode, QProcess::ExitStatus exitStatus)
{   LOG_DEBUG(QString("SLOT_FINISHED(%1,%2) called.").arg(exitCode).arg(exitStatus));
    switch (exitStatus) {
    case QProcess::NormalExit:
        if(exitCode == 0)
        {
            _calculation->Slot_computed(QUrl::fromPercentEncoding(readAllStandardOutput()).toUtf8());
        }
        else
        {   LOG_ERROR(QString("Process crashed (exit_code=%1).").arg(exitCode));
            // crash calculation
            _calculation->Slot_crashed(readAllStandardError());
        }
        break;
    case QProcess::CrashExit:
        LOG_ERROR(QString("Process crashed (exit_code=%1).").arg(exitCode));
        // crash calculation
        _calculation->Slot_crashed(readAllStandardError());
        break;
    }
}
コード例 #11
0
ファイル: dbgdriver.cpp プロジェクト: isdamir/kdbg
void DebuggerDriver::slotReceiveOutput()
{
    QByteArray data = readAllStandardOutput();

    /*
     * The debugger should be running (processing a command) at this point.
     * If it is not, it is still idle because we haven't received the
     * bytesWritten signal yet, in which case there must be an active command
     * which is not commited.
     */
    if (m_state == DScommandSent || m_state == DScommandSentLow) {
	ASSERT(m_activeCmd != 0);
	ASSERT(!m_activeCmd->m_committed);
	/*
	 * We received output before we got signal bytesWritten. Collect this
	 * output, it will be processed by commandRead when it gets the
	 * acknowledgment for the uncommitted command.
	 */
	m_delayedOutput.push(data);
	return;
    }
    processOutput(data);
}
コード例 #12
0
ファイル: myprocess.cpp プロジェクト: elemem/ExMplayer
void MyProcess::readStdOut() {
	genericRead( readAllStandardOutput() );
}
コード例 #13
0
ファイル: OMProcess.cpp プロジェクト: SemiSQ/OpenModelica
void OMProcess::onReadyRead()
{
    QString msg = "["+_appName+"] : "+QString(readAllStandardOutput());
    InfoSender::instance()->send(Info(msg));
}
コード例 #14
0
ファイル: hashtypechecker.cpp プロジェクト: c3stbon/johnny
void HashTypeChecker::parseJohnAnswer(int exitCode, QProcess::ExitStatus exitStatus)
{
    // John --show=types didn't terminate successfully, so the input is probably incorrect(and not properly formatted)
    // or useless ! We might have terminated the process because the user changed session file or maybe it crashed.
    // We shouldn't parse the input in those cases to avoid errors.
    if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) {
        return;
    }

    // Parse John's output when process finished it's work
    QString johnOutput = readAllStandardOutput();
    QStringList uniqueTypesInFile;
    QStringList detailedTypesPerRow;
    QList<Hash> hashesAllInfos;
    QStringList lines = johnOutput.split(QRegExp("\\r?\\n"), QString::SkipEmptyParts);
    for (int i = 0; i < lines.size(); i++) {
        QString currentLine = lines[i];
        if (currentLine.length() >= 3) {
            // Field_separator can be set by john and the right way to find
            // it is by looking at the last character of the line
            QChar field_separator = currentLine[currentLine.length()-1];
            currentLine.remove(currentLine.length()-3, 3);
            QStringList fields = currentLine.split(field_separator, QString::KeepEmptyParts);
            // Each valid line from john is gonna have at least 7 fields
            if (fields.length() >= 7) {
                Hash hash;
                int currentIndex = 0;
                hash.login = fields[currentIndex++];
                hash.ciphertext = fields[currentIndex++];
                hash.uid = fields[currentIndex++];
                hash.gid = fields[currentIndex++];
                hash.gecos = fields[currentIndex++];
                hash.home = fields[currentIndex++];
                hash.shell = fields[currentIndex++];

                int nbOfFieldsForValidFormats = 4;
                // For each valid formats, which are separated by separator, empty string
                // separator (ex: '::')
                QStringList typesOnly;
                while ((currentIndex + nbOfFieldsForValidFormats) < fields.length()) {
                    HashFormat format;
                    format.label = fields[currentIndex++];
                    typesOnly.append(format.label);
                    // Keep track of non-duplicate formats's label in the file
                    if (!uniqueTypesInFile.contains(format.label)) {
                        uniqueTypesInFile.append(format.label);
                    }

                    format.isFormatDisabled = (fields[currentIndex++] == "0" ? false : true);
                    format.isFormatDynamic = (fields[currentIndex++] == "0" ? false : true);
                    format.isUsingCypherTextAsIs = (fields[currentIndex++] == "0" ? false : true);

                    // Canonical hash(es) fields
                    for (; currentIndex < fields.length(); currentIndex++) {
                        if (!fields[currentIndex].isEmpty()) {
                            format.canonicalHashes.append(fields[currentIndex]);
                        } else {
                            currentIndex++;
                            break;
                        }
                    }
                    hash.listFormats.push_back(format);
                }

                detailedTypesPerRow.append(typesOnly.join(","));

                hashesAllInfos.append(hash);
            }
        }
    }
    // We emit signal to view(s) that are listening that something changed
    // (ex : MainWindow)
    emit updateHashTypes(m_passwordFiles,uniqueTypesInFile,detailedTypesPerRow);
}
コード例 #15
0
ファイル: frontend.cpp プロジェクト: AlexanderStein/kscope4
/**
 * Reads data written on the standard output by the controlled process.
 * This is a private slot called attached to the readyReadStdout() signal of
 * the controlled process, which means that it is called whenever data is
 * ready to be read from the process' stream.
 * The method reads whatever data is queued, and sends it to be interpreted
 * by parseStdout().
 */
void Frontend::slotReadStdout()
{
	char* pLocalBuf;
	QString sToken;
	bool bTokenEnded;
	ParserDelim delim;

	// Do nothing if waiting for process to die
	if (m_bKilled)
		return;

	QByteArray ba = readAllStandardOutput();
	int nSize = ba.length();

	pLocalBuf = ba.data();

	// Iterate over the given buffer
	while (nSize > 0) {
		// Create a new token, if the last iteration has completed one
		if (m_pCurToken == NULL)
			m_pCurToken = new FrontendToken();

		// Extract text until the requested delimiter
		bTokenEnded = tokenize(&pLocalBuf, &nSize, sToken, delim);

		// Add the extracted text to the current token
		m_pCurToken->m_sData += sToken;

		// If the buffer has ended before the requested delimiter, we need
		// to wait for more output from the process
		if (!bTokenEnded)
			return;

		// Call the process-specific parser function
		switch (parseStdout(m_pCurToken->m_sData, delim)) {
		case DiscardToken:
			// Token should not be saved
			delete m_pCurToken;
			break;

		case AcceptToken:
			// Store token in linked list
			addToken(m_pCurToken);
			break;

		case RecordReady:
			// Store token, and notify the target object that an entry can
			// be read
			m_nRecords++;
			addToken(m_pCurToken);
			emit dataReady(m_pHeadToken);

			// Delete all tokens in the entry
			removeRecord();
			break;

		case Abort:
			kill();
			nSize = 0;
			break;
		}

		m_pCurToken = NULL;
	}
}
コード例 #16
0
ファイル: translator.cpp プロジェクト: denix56/Apertium-GP
void Translator::translateXlsx(QString filePath, QDir &docDir)
{
    QFileInfo fileInfo(filePath);
    QTemporaryDir dir(docDir.absoluteFilePath(fileInfo.baseName() + ".XXXXXX"));
    auto cmd = new QProcess(this);
    QDir exep (qApp->applicationDirPath());
#ifndef Q_OS_LINUX
    cmd->start(exep.absoluteFilePath("7z"), QStringList() << "t" << fileInfo.absoluteFilePath());
#endif
    cmd->waitForReadyRead();
    QString res = cmd->readAllStandardOutput();
    if (res.contains("ERROR")) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    cmd->waitForFinished();
    cmd->start(exep.absoluteFilePath("7z"), QStringList() << "x" << "-y" << fileInfo.absoluteFilePath()
               << "-o" + dir.path());
    cmd->waitForReadyRead();
    cmd->waitForFinished();
    QStringList args;
    //for (QString sheetName : sheetDir.entryList(QStringList() << "sheet*.xml")) {
    QFile sheet (QDir(dir.path() + "/xl").absoluteFilePath("sharedStrings.xml"));
    QTemporaryFile tmpSheet(sheet.fileName());
    cmd->setWorkingDirectory(QDir(DATALOCATION).absoluteFilePath("apertium-all-dev/bin"));

    qApp->processEvents();
    //desxlsx
    args << "/u" << "/c" << "type" << "\"" + sheet.fileName().replace('/', QDir::separator()) + "\""
         << "|" << "apertium-desxlsx";
    cmd->setNativeArguments(args.join(' '));
    args.clear();
    cmd->start("cmd.exe");
    cmd->waitForReadyRead();
    cmd->waitForFinished();
    if (!tmpSheet.open()) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    tmpSheet.setTextModeEnabled(true);
    tmpSheet.write(notLinuxTranslate(cmd->readAllStandardOutput()).toUtf8());
    tmpSheet.close();
    //rexlsx
    args << "/u" << "/c" << "type" << "\"" + tmpSheet.fileName().replace('/', QDir::separator()) + "\""
         << "|" << "apertium-rexlsx";
    cmd->setNativeArguments(args.join(" "));
    args.clear();
    cmd->start("cmd.exe");
    cmd->waitForReadyRead();
    if (!sheet.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    sheet.write(cmd->readAllStandardOutput());
    cmd->waitForFinished();

    sheet.close();
    cmd->setWorkingDirectory(dir.path());
    QString trFilePath = docDir.absoluteFilePath(fileInfo.baseName() + "_" +
                                                 parent->getCurrentSourceLang()
                                                 + "-" + parent->getCurrentTargetLang() + "." + fileInfo.suffix());
    QFile(trFilePath).remove();
    args << "a" << "-tzip" << "-y"
         << "\"" + trFilePath + "\""
         << "\"" + dir.path() + "/*\"";
    cmd->setNativeArguments(args.join(' '));
    cmd->start(exep.absoluteFilePath("7z"));
    cmd->waitForFinished();
    emit fileTranslated(trFilePath);
    cmd->deleteLater();
}
コード例 #17
0
ファイル: translator.cpp プロジェクト: denix56/Apertium-GP
void Translator::translateDocx(QString filePath, QDir &docDir)
{
    QFileInfo fileInfo(filePath);
    QTemporaryDir dir(docDir.absoluteFilePath(fileInfo.baseName() + ".XXXXXX"));
    auto cmd = new QProcess(this);
    QDir exep (qApp->applicationDirPath());
    cmd->start(exep.absoluteFilePath("7z"), QStringList() << "t" << fileInfo.absoluteFilePath());
    cmd->waitForReadyRead();
    if (cmd->readAllStandardOutput().contains("ERROR")) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    cmd->waitForFinished();
    cmd->start(exep.absoluteFilePath("7z"), QStringList() << "x" << "-y" << fileInfo.absoluteFilePath()
               << "-o" + dir.path());
    cmd->waitForReadyRead();
    cmd->waitForFinished();

    QTemporaryFile tmpDoc("document.xml");
    QFile doc(dir.path() + "/word/document.xml");
    cmd->setWorkingDirectory(QDir(DATALOCATION).absoluteFilePath("apertium-all-dev/bin"));
    QStringList args;
    qApp->processEvents();
    //deswxml
#ifdef Q_OS_WIN
    //windows bug with backslash
    //use replace to fix windows bug
    args << "/u" << "/c" << "type" << "\"" + doc.fileName().replace('/', QDir::separator()) + "\""
         << "|" << "apertium-deswxml";
    cmd->setNativeArguments(args.join(' '));
    cmd->start("cmd.exe");
#endif
    cmd->waitForFinished();
    cmd->waitForReadyRead();
    if (!tmpDoc.open()) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    tmpDoc.setTextModeEnabled(true);
    tmpDoc.write(notLinuxTranslate(cmd->readAllStandardOutput()).toUtf8());
    tmpDoc.close();
    //rewxml
    args.clear();
#ifdef Q_OS_WIN
    args << "/u" << "/c" << "type" << "\"" + tmpDoc.fileName().replace('/', QDir::separator()) + "\""
         << "|" << "apertium-rewxml";
    cmd->setNativeArguments(args.join(' '));
    cmd->start("cmd.exe");
#endif
    cmd->waitForFinished();
    cmd->waitForReadyRead();
    if (!doc.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
        emit fileTranslateRejected();
        cmd->deleteLater();
        return;
    }
    doc.write(cmd->readAllStandardOutput());
    doc.close();
    cmd->setWorkingDirectory(dir.path());
    QString trFilePath = docDir.absoluteFilePath(fileInfo.baseName() + "_" +
                                                 parent->getCurrentSourceLang()
                                                 + "-" + parent->getCurrentTargetLang() + "." + fileInfo.suffix());
    cmd->start(exep.absoluteFilePath("7z"), QStringList() << "a" << "-tzip" << "-y"
               << trFilePath << dir.path() + "/*");
    cmd->waitForFinished();
    emit fileTranslated(trFilePath);
    cmd->deleteLater();
}
コード例 #18
0
ファイル: FileEnvProcess.cpp プロジェクト: DeepBlue14/rqt_ide
void FileEnvProcess::redirectError()
{
    cout << "\n>>" << endl;
    outputLocTePtr->append((readAllStandardOutput()) );
}
コード例 #19
0
void Kleo::SymCryptRunProcessBase::slotReadyReadStandardOutput() {
  mOutput += readAllStandardOutput();
}
コード例 #20
0
bool ExportSpreadsheet::exportSpreadsheet(const analysisdriver::SimpleProject& project)
{
    //Make sure a QApplication exists
    openstudio::Application::instance().application();

    //get the project's directory
    openstudio::path projectPath = project.projectDir();

    LOG_FREE(Debug, "ExportSpreadsheet", "Starting export of projectPath:" << toString(projectPath));

    openstudio::path rubyPath;
#if defined(Q_OS_WIN)
    rubyPath = getOpenStudioEmbeddedRubyPath() / toPath("bin/ruby.exe");
#else
    rubyPath = "ruby";
#endif

    openstudio::path rubyIncludePath = getOpenStudioRubyIncludePath();
    if (!boost::filesystem::exists(rubyIncludePath)) {
        LOG_FREE(Error, "ExportSpreadsheet", "Ruby include path '" << rubyIncludePath << "' cannot be found.");
        return false;
    }

    openstudio::path scriptPath = getOpenStudioRubyScriptsPath() / openstudio::toPath("openstudio/analysisdriver/ExportToSpreadsheet.rb");
    if (!boost::filesystem::exists(scriptPath)) {
        LOG_FREE(Error, "ExportSpreadsheet", "ExportToSpreadsheet script '" << scriptPath << "' cannot be found.");
        return false;
    }

    QStringList args;
    args << "-I";
    args << openstudio::toQString(rubyIncludePath);
    args << openstudio::toQString(scriptPath);
    args << openstudio::toQString(projectPath);

    auto p = new QProcess();
    p->start(toQString(rubyPath), args);

    if (!p->waitForStarted(30000)) {
        p->terminate();
        p->deleteLater();
        LOG_FREE(Error, "ExportSpreadsheet", "Process failed to start");
        return false;
    }

    if (!p->waitForFinished(300000)) {
        p->terminate();
        p->deleteLater();
        LOG_FREE(Error, "ExportSpreadsheet", "Process failed to complete");
        return false;
    }

    QByteArray error = p->readAllStandardError();
    std::string errorString = toString(QString(error));
    LOG_FREE(Debug, "ExportSpreadsheet", "StandardError:" << std::endl << errorString);
    QByteArray output = p->readAllStandardOutput();
    std::string outputString = toString(QString(output));
    LOG_FREE(Debug, "ExportSpreadsheet", "StandardOutput:" << std::endl << outputString);

    // remove previous export
    openstudio::path exportPath = projectPath / toPath("analysis_spreadsheet_export");
    openstudio::path modelMeasuresCSV = exportPath / toPath("spreadsheet_model_measures_export.csv");
    openstudio::path energyplusMeasuresCSV = exportPath / toPath("spreadsheet_energyplus_measures_export.csv");
    openstudio::path reportingMeasuresCSV = exportPath / toPath("spreadsheet_reporting_measures_export.csv");
    openstudio::path outputsCSV = exportPath / toPath("spreadsheet_outputs_export.csv");

    bool result = ((p->exitStatus() == QProcess::NormalExit) &&
                   boost::filesystem::exists(modelMeasuresCSV) &&
                   boost::filesystem::exists(energyplusMeasuresCSV) &&
                   boost::filesystem::exists(reportingMeasuresCSV) &&
                   boost::filesystem::exists(outputsCSV));

    p->deleteLater();
    return result;
}