Example #1
0
bool ItemEditor::start()
{
    // create temp file
    QTemporaryFile tmpfile;
    const auto suffix = getFileSuffixFromMime(m_mime);
    if ( !openTemporaryFile(&tmpfile, suffix) ) {
        log("Failed to create temporary file for external editor", LogError);
        return false;
    }

    const auto fileName = tmpfile.fileName();

    // write text to temp file
    tmpfile.write(m_data);

    // Close file before launching editor (this is required on Windows).
    tmpfile.setAutoRemove(false);
    tmpfile.close();

    // monitor file
    m_info.setFile(fileName);
    m_lastmodified = m_info.lastModified();
    m_lastSize = m_info.size();
    m_timer->start(500);
    connect( m_timer, &QTimer::timeout,
             this, &ItemEditor::onTimer );

    // create editor process
    m_editor = new QProcess(this);
    connectProcessFinished(m_editor, this, &ItemEditor::close);
    connectProcessError(m_editor, this, &ItemEditor::onError);

    // use native path for filename to edit
    const auto nativeFilePath = QDir::toNativeSeparators( m_info.absoluteFilePath() );
    const auto cmd = m_editorcmd.arg('"' + nativeFilePath + '"');

    // execute editor
    m_editor->start(cmd, QIODevice::ReadOnly);
    m_editor->closeWriteChannel();
    m_editor->closeReadChannel(QProcess::StandardOutput);

    return m_editor->waitForStarted(10000);
}
Example #2
0
void Action::start()
{
    closeSubCommands();

    if ( m_currentLine + 1 >= m_cmds.size() ) {
        finish();
        return;
    }

    ++m_currentLine;
    const QList<QStringList> &cmds = m_cmds[m_currentLine];

    Q_ASSERT( !cmds.isEmpty() );

    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    if (m_id != -1)
        env.insert("COPYQ_ACTION_ID", QString::number(m_id));
    if ( !m_name.isEmpty() )
        env.insert("COPYQ_ACTION_NAME", m_name);

    for (int i = 0; i < cmds.size(); ++i) {
        auto process = new QProcess(this);
        m_processes.push_back(process);
        process->setProcessEnvironment(env);
        if ( !m_workingDirectoryPath.isEmpty() )
            process->setWorkingDirectory(m_workingDirectoryPath);

        connectProcessError(process, this, &Action::onSubProcessError);
        connect( process, &QProcess::readyReadStandardError,
                 this, &Action::onSubProcessErrorOutput );
    }

    pipeThroughProcesses(m_processes.begin(), m_processes.end());

    QProcess *lastProcess = m_processes.back();
    connect( lastProcess, &QProcess::started,
             this, &Action::onSubProcessStarted );
    connectProcessFinished( lastProcess, this, &Action::onSubProcessFinished );
    connect( lastProcess, &QProcess::readyReadStandardOutput,
             this, &Action::onSubProcessOutput );

    // Writing directly to stdin of a process on Windows can hang the app.
    QProcess *firstProcess = m_processes.front();
    connect( firstProcess, &QProcess::started,
             this, &Action::writeInput, Qt::QueuedConnection );
    connect( firstProcess, &QProcess::bytesWritten,
             this, &Action::onBytesWritten, Qt::QueuedConnection );

    const bool needWrite = !m_input.isEmpty();
    if (m_processes.size() == 1) {
        const auto mode =
                (needWrite && m_readOutput) ? QIODevice::ReadWrite
              : needWrite ? QIODevice::WriteOnly
              : m_readOutput ? QIODevice::ReadOnly
              : QIODevice::NotOpen;
        startProcess(firstProcess, cmds.first(), mode);
    } else {
        auto it = m_processes.begin();
        auto cmdIt = cmds.constBegin();
        startProcess(*it, *cmdIt, needWrite ? QIODevice::ReadWrite : QIODevice::ReadOnly);
        for (++it, ++cmdIt; it != m_processes.end() - 1; ++it, ++cmdIt)
            startProcess(*it, *cmdIt, QIODevice::ReadWrite);
        startProcess(lastProcess, cmds.last(), m_readOutput ? QIODevice::ReadWrite : QIODevice::WriteOnly);
    }
}