예제 #1
0
void ItemEncryptedScriptable::copyEncryptedItems()
{
    const auto dataValueList = call("selectedItemsData").toList();
    QString text;
    for (const auto &dataValue : dataValueList) {
        if ( !text.isEmpty() )
            text.append('\n');

        const auto data = dataValue.toMap();
        const auto itemTextValue = data.value(mimeText);
        if ( itemTextValue.isValid() ) {
            text.append( getTextData(itemTextValue.toByteArray()) );
        } else {
            const auto encryptedBytes = data.value(mimeEncryptedData).toByteArray();
            if ( !encryptedBytes.isEmpty() ) {
                const auto itemData = decrypt(encryptedBytes);
                if (itemData.isEmpty())
                    return;
                const auto dataMap = call("unpack", QVariantList() << itemData).toMap();
                text.append( getTextData(dataMap) );
            }
        }
    }

    const auto args = QVariantList()
            << mimeText << text
            << mimeHidden << "1";
    call("copy", args);
    call("copySelection", args);
}
예제 #2
0
void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
	if (!ready())
		return;

	queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight));

	for (int i = 0; i < (int)tabs.size(); ++i) {
		if (i == active)
			continue;

		if (r.left + i * tabWidth > r.right || r.left + (i + 1) * tabWidth > r.right)
			continue;

		Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight);
		queueDD(kDDTabInactive, tabRect);
		queueDDText(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
	}

	if (active >= 0 &&
	        (r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
		Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
		const uint16 tabLeft = active * tabWidth;
		const uint16 tabRight =  MAX(r.right - tabRect.right, 0);
		queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF));
		queueDDText(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
	}
}
예제 #3
0
void CommandTester::startNext()
{
    Q_ASSERT(!m_action);

    m_abort = false;
    m_restart = false;

    if (!hasCommands())
        return;

    Command *command = &m_commands[0];

    if (command->matchCmd.isEmpty()) {
        commandPassed(true);
    } else {
        m_action = new Action(this);

        const QString text = getTextData(m_data);
        m_action->setInput(text.toUtf8());
        m_action->setData(m_data);

        const QString arg = getTextData(m_action->input());
        m_action->setCommand(command->matchCmd, QStringList(arg));

        connect(m_action, SIGNAL(actionFinished(Action*)), SLOT(actionFinished()));
        m_action->start();
    }
}
예제 #4
0
파일: itemtags.cpp 프로젝트: amosbird/CopyQ
bool ItemTagsLoader::matches(const QModelIndex &index, const QRegExp &re) const
{
    const QByteArray tagsData =
            index.data(contentType::data).toMap().value(mimeTags).toByteArray();
    const auto tags = getTextData(tagsData);
    return re.indexIn(tags) != -1;
}
예제 #5
0
void ActionDialog::createAction()
{
    const QString cmd = ui->commandEdit->command();

    if ( cmd.isEmpty() )
        return;

    const QString inputFormat = ui->comboBoxInputFormat->currentText();
    const QString input =
            ui->inputText->isVisible() ? ui->inputText->toPlainText() : QString();

    // Expression %1 in command is always replaced with item text.
    if ( m_capturedTexts.isEmpty() )
        m_capturedTexts.append(QString());
    m_capturedTexts[0] = getTextData(m_data);

    QScopedPointer<Action> act( new Action() );
    act->setCommand(cmd, m_capturedTexts);
    if (input.isEmpty() && !inputFormat.isEmpty())
        act->setInput(m_data, inputFormat);
    else
        act->setInput(input.toUtf8());
    act->setOutputFormat(ui->comboBoxOutputFormat->currentText());
    act->setItemSeparator(QRegExp(ui->separatorEdit->text()));
    act->setOutputTab(ui->comboBoxOutputTab->currentText());
    act->setIndex(m_index);
    act->setName(m_actionName);
    act->setData(m_data);
    emit accepted(act.take());

    close();
}
예제 #6
0
void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
	if (!ready())
		return;

	Common::Rect r2 = r;
	DrawData dd = kDDRadiobuttonDefault;

	if (checked)
		dd = kDDRadiobuttonSelected;

	if (state == kStateDisabled)
		dd = kDDRadiobuttonDisabled;

	const int checkBoxSize = MIN((int)r.height(), getFontHeight());

	r2.bottom = r2.top + checkBoxSize;
	r2.right = r2.left + checkBoxSize;

	queueDD(dd, r2);

	r2.left = r2.right + checkBoxSize;
	r2.right = r.right;

	queueDDText(getTextData(dd), getTextColor(dd), r2, str, false, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
}
예제 #7
0
void ItemEncryptedLoader::onGpgProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    QString error;

    if (m_gpgProcess != nullptr) {
        if (ui != nullptr) {
            if (exitStatus != QProcess::NormalExit)
                error = m_gpgProcess->errorString();
            else if (exitCode != 0)
                error = getTextData(m_gpgProcess->readAllStandardError());
            else if ( m_gpgProcess->error() != QProcess::UnknownError )
                error = m_gpgProcess->errorString();
            else if ( !keysExist() )
                error = ItemEncryptedLoader::tr("Failed to generate keys.");
        }

        m_gpgProcess->deleteLater();
        m_gpgProcess = nullptr;
    }

    // Export and import private key to a file in configuration.
    if ( status() == GpgGeneratingKeys && error.isEmpty() )
        error = exportImportGpgKeys();

    if (!error.isEmpty())
        error = ItemEncryptedLoader::tr("Error: %1").arg(error);

    m_gpgProcessStatus = GpgNotRunning;

    updateUi();
    ui->labelInfo->setText( error.isEmpty() ? ItemEncryptedLoader::tr("Done") : error );
}
예제 #8
0
RBox RDimensionData::getBoundingBox() const {
    if (dirty || !boundingBox.isValid()) {
        boundingBox = REntityData::getBoundingBox();
        getTextData();
        boundingBox.growToInclude(textData.getBoundingBox());
    }

    return boundingBox;
}
예제 #9
0
double RDimensionData::getDistanceTo(const RVector& point, bool limited, double range, bool draft) const {
    double ret1 = REntityData::getDistanceTo(point, limited, range, draft);
    getTextData();
    double ret2 = textData.getDistanceTo(point, limited, range, draft);
    if (RMath::isNaN(ret2)) {
        return ret1;
    }
    return qMin(ret1, ret2);
}
예제 #10
0
bool RDimensionData::intersectsWith(const RShape& shape) const {
    if (REntityData::intersectsWith(shape)) {
        return true;
    }
    getTextData();
    if(textData.intersectsWith(shape)) {
        return true;
    }
    return false;
}
예제 #11
0
void ActionDialog::on_comboBoxInputFormat_currentIndexChanged(const QString &format)
{
    setChangedByUser(ui->comboBoxInputFormat);

    bool show = format.toLower().startsWith(QString("text"));
    ui->inputText->setVisible(show);

    QString text;
    if ((show || format.isEmpty()) && !m_data.isEmpty() )
        text = getTextData( m_data, format.isEmpty() ? mimeText : format );
    ui->inputText->setPlainText(text);
}
예제 #12
0
int ModApiMainMenu::l_start(lua_State *L)
{
	GUIEngine* engine = getGuiEngine(L);
	sanity_check(engine != NULL);

	//update c++ gamedata from lua table

	bool valid = false;

	MainMenuData *data = engine->m_data;

	data->selected_world = getIntegerData(L, "selected_world",valid) -1;
	data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
	data->do_reconnect = getBoolData(L, "do_reconnect", valid);
	if (!data->do_reconnect) {
		data->name     = getTextData(L,"playername");
		data->password = getTextData(L,"password");
		data->address  = getTextData(L,"address");
		data->port     = getTextData(L,"port");
	}
	data->serverdescription = getTextData(L,"serverdescription");
	data->servername        = getTextData(L,"servername");

	//close menu next time
	engine->m_startgame = true;
	return 0;
}
예제 #13
0
void ClipboardClient::start(const QStringList &arguments)
{
    QScriptEngine engine;
    ScriptableProxy scriptableProxy(nullptr, nullptr);
    Scriptable scriptable(&engine, &scriptableProxy);

    const auto serverName = clipboardServerName();
    ClientSocket socket(serverName);

    connect( &socket, &ClientSocket::messageReceived,
             this, &ClipboardClient::onMessageReceived );
    connect( &socket, &ClientSocket::disconnected,
             this, &ClipboardClient::onDisconnected );
    connect( &socket, &ClientSocket::connectionFailed,
             this, &ClipboardClient::onConnectionFailed );

    connect( &scriptableProxy, &ScriptableProxy::sendMessage,
             &socket, &ClientSocket::sendMessage );

    connect( this, &ClipboardClient::functionCallResultReceived,
             &scriptableProxy, &ScriptableProxy::setFunctionCallReturnValue );
    connect( this, &ClipboardClient::inputDialogFinished,
             &scriptableProxy, &ScriptableProxy::setInputDialogResult );

    connect( &socket, &ClientSocket::disconnected,
             &scriptable, &Scriptable::abort );
    connect( &socket, &ClientSocket::disconnected,
             &scriptableProxy, &ScriptableProxy::clientDisconnected );

    connect( &scriptable, &Scriptable::finished,
             &scriptableProxy, &ScriptableProxy::clientDisconnected );

    bool hasActionId;
#if QT_VERSION < QT_VERSION_CHECK(5,5,0)
    auto actionId = qgetenv("COPYQ_ACTION_ID").toInt(&hasActionId);
#else
    auto actionId = qEnvironmentVariableIntValue("COPYQ_ACTION_ID", &hasActionId);
#endif
    const auto actionName = getTextData( qgetenv("COPYQ_ACTION_NAME") );

    if ( socket.start() ) {
        if (hasActionId)
            scriptable.setActionId(actionId);
        scriptable.setActionName(actionName);

        const int exitCode = scriptable.executeArguments(arguments);
        exit(exitCode);
    }
}
예제 #14
0
/**********************************************************
 * Widget drawing functions
 *********************************************************/
void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) {
	if (!ready())
		return;

	DrawData dd = kDDButtonIdle;

	if (state == kStateEnabled)
		dd = kDDButtonIdle;
	else if (state == kStateHighlight)
		dd = kDDButtonHover;
	else if (state == kStateDisabled)
		dd = kDDButtonDisabled;

	queueDD(dd, r, 0, hints & WIDGET_CLEARBG);
	queueDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
}
예제 #15
0
bool  AP_UnixClipboard::getSupportedData(T_AllowGet tFrom,
										 const void ** ppData, UT_uint32 * pLen,
										 const char **pszFormatFound)
{
	if (getData(tFrom, rtfszFormatsAccepted, (void**)ppData, pLen, pszFormatFound))
		return true;
	else if (getData (tFrom, htmlszFormatsAccepted, (void**)ppData, pLen, pszFormatFound))
		return true;
	else if (!vec_DynamicFormatsAccepted.empty() && getData(tFrom, &vec_DynamicFormatsAccepted[0], (void**)ppData, pLen, pszFormatFound))
		return true;  
	else if (getData(tFrom, imgszFormatsAccepted, (void**)ppData, pLen, pszFormatFound))
		return true;  
	else if (getTextData (tFrom, ppData, pLen, pszFormatFound))
		return true;
	return false;
}
예제 #16
0
파일: common.cpp 프로젝트: amosbird/CopyQ
QString textLabelForData(const QVariantMap &data, const QFont &font, const QString &format,
                         bool escapeAmpersands, int maxWidthPixels, int maxLines)
{
    QString label;

    const QString notes = data.value(mimeItemNotes).toString();

    if ( data.contains(mimeHidden) ) {
        label = QObject::tr("<HIDDEN>", "Label for hidden/secret clipboard content");
    } else if ( data.contains(mimeText) || data.contains(mimeUriList) ) {
        const QString text = getTextData(data);
        const int n = text.count(QChar('\n')) + 1;

        if (n > 1)
            label = QObject::tr("%1 (%n lines)", "Label for multi-line text in clipboard", n);
        else
            label = QString("%1");

        if (!format.isEmpty())
            label = format.arg(label);

        const QString textWithNotes = notes.isEmpty() ? text : notes + ": " + text;
        return elideText(textWithNotes, font, label, escapeAmpersands, maxWidthPixels, maxLines);
    } else if ( findFormatsWithPrefix(true, "image/", data) ) {
        label = QObject::tr("<IMAGE>", "Label for image in clipboard");
    } else if ( data.contains(mimeItems) ) {
        label = QObject::tr("<ITEMS>", "Label for copied items in clipboard");
    } else if ( findFormatsWithPrefix(false, COPYQ_MIME_PREFIX, data) ) {
        label = QObject::tr("<EMPTY>", "Label for empty clipboard");
    } else {
        label = QObject::tr("<DATA>", "Label for data in clipboard");
    }

    if (!notes.isEmpty()) {
        label = elideText(notes, font, QString(), escapeAmpersands, maxWidthPixels, maxLines)
                + ": " + label;
    }

    if (!format.isEmpty())
        label = format.arg(label);

    return label;
}
예제 #17
0
void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) {
	if (!ready())
		return;

	DrawData dd = kDDPopUpIdle;

	if (state == kStateEnabled)
		dd = kDDPopUpIdle;
	else if (state == kStateHighlight)
		dd = kDDPopUpHover;
	else if (state == kStateDisabled)
		dd = kDDPopUpDisabled;

	queueDD(dd, r);

	if (!sel.empty()) {
		Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
		queueDDText(getTextData(dd), getTextColor(dd), text, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
	}
}
예제 #18
0
int ModApiMainMenu::l_start(lua_State *L)
{
	GUIEngine* engine = getGuiEngine(L);
	assert(engine != 0);

	//update c++ gamedata from lua table

	bool valid = false;


	engine->m_data->selected_world		= getIntegerData(L, "selected_world",valid) -1;
	engine->m_data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
	engine->m_data->name				= getTextData(L,"playername");
	engine->m_data->password			= getTextData(L,"password");
	engine->m_data->address				= getTextData(L,"address");
	engine->m_data->port				= getTextData(L,"port");
	engine->m_data->serverdescription	= getTextData(L,"serverdescription");
	engine->m_data->servername			= getTextData(L,"servername");

	//close menu next time
	engine->m_startgame = true;
	return 0;
}
예제 #19
0
void ClipboardMonitor::onClipboardChanged(ClipboardMode mode)
{
    QVariantMap data = m_clipboard->data(mode, m_formats);
    auto clipboardData = mode == ClipboardMode::Clipboard
            ? &m_clipboardData : &m_selectionData;

    if ( hasSameData(data, *clipboardData) ) {
        COPYQ_LOG( QString("Ignoring unchanged %1")
                   .arg(mode == ClipboardMode::Clipboard ? "clipboard" : "selection") );
        return;
    }

    *clipboardData = data;

    COPYQ_LOG( QString("%1 changed, owner is \"%2\"")
               .arg(mode == ClipboardMode::Clipboard ? "Clipboard" : "Selection",
                    getTextData(data, mimeOwner)) );

    if (mode != ClipboardMode::Clipboard) {
        const QString modeName = mode == ClipboardMode::Selection
                ? "selection"
                : "find buffer";
        data.insert(mimeClipboardMode, modeName);
    }

    // add window title of clipboard owner
    if ( !data.contains(mimeOwner) && !data.contains(mimeWindowTitle) ) {
        PlatformPtr platform = createPlatformNativeInterface();
        PlatformWindowPtr currentWindow = platform->getCurrentWindow();
        if (currentWindow)
            data.insert( mimeWindowTitle, currentWindow->getTitle().toUtf8() );
    }

#ifdef HAS_MOUSE_SELECTIONS
    if ( (mode == ClipboardMode::Clipboard ? m_clipboardToSelection : m_selectionToClipboard)
        && !data.contains(mimeOwner) )
    {
        const auto text = getTextData(data);
        if ( !text.isEmpty() ) {
            const auto targetData = mode == ClipboardMode::Clipboard
                    ? &m_selectionData : &m_clipboardData;
            const auto targetText = getTextData(*targetData);
            emit synchronizeSelection(mode, text, qHash(targetText));
        }
    }
#endif

    // run automatic commands
    if ( anySessionOwnsClipboardData(data) ) {
        emit clipboardChanged(data, ClipboardOwnership::Own);
    } else if ( isClipboardDataHidden(data) ) {
        emit clipboardChanged(data, ClipboardOwnership::Hidden);
    } else {
        const auto defaultTab = m_clipboardTab.isEmpty() ? defaultClipboardTabName() : m_clipboardTab;
        setTextData(&data, defaultTab, mimeCurrentTab);


#ifdef HAS_MOUSE_SELECTIONS
        if (mode == ClipboardMode::Clipboard ? m_storeClipboard : m_storeSelection) {
#else
        if (m_storeClipboard) {
#endif
            setTextData(&data, m_clipboardTab, mimeOutputTab);
        }

        emit clipboardChanged(data, ClipboardOwnership::Foreign);
    }
}
예제 #20
0
string SSLClient::getData(string hdrdelm,string cntlnhdr)
{
	return getTextData(hdrdelm, cntlnhdr);
}
예제 #21
0
string SSLClient::getData(const string& hdrdelm, const string& cntlnhdr)
{
	return getTextData(hdrdelm, cntlnhdr);
}
예제 #22
0
QList<QSharedPointer<RShape> > RDimOrdinateData::getShapes(const RBox& queryBox) const {
    Q_UNUSED(queryBox)

    QList<QSharedPointer<RShape> > ret;

    // make sure that defaultAngle is valid, even if not used:
    defaultAngle = 0.0;

    // distance from entities (DIMEXO)
    double dimexo = getDimexo();

    RVector knee1;
    RVector knee2;
    RVector textOffsetV;   // normal vector in direction of text offset

    // vertical, measuring X
    if (isMeasuringXAxis()) {
        knee1.x = definingPoint.x;
        knee2.x = leaderEndPoint.x;

        if (definingPoint.y < leaderEndPoint.y) {
            knee1.y = leaderEndPoint.y - 0.36*2;
            if (knee1.y < definingPoint.y + 0.36) {
                knee1.y = definingPoint.y + 0.36;
            }

            knee2.y = leaderEndPoint.y - 0.36;
            textOffsetV = RVector(0,1);
        }
        else {
            knee1.y = leaderEndPoint.y + 0.36*2;
            if (knee1.y > definingPoint.y - 0.36) {
                knee1.y = definingPoint.y - 0.36;
            }

            knee2.y = leaderEndPoint.y + 0.36;
            textOffsetV = RVector(0,-1);
        }
    }

    // horizontal, measuring Y
    else {
        knee1.y = definingPoint.y;
        knee2.y = leaderEndPoint.y;

        if (definingPoint.x < leaderEndPoint.x) {
            knee1.x = leaderEndPoint.x - 0.36*2;
            if (knee1.x < definingPoint.x + 0.36) {
                knee1.x = definingPoint.x + 0.36;
            }

            knee2.x = leaderEndPoint.x - 0.36;
            textOffsetV = RVector(1,0);
        }
        else {
            knee1.x = leaderEndPoint.x + 0.36*2;
            if (knee1.x > definingPoint.x - 0.36) {
                knee1.x = definingPoint.x - 0.36;
            }

            knee2.x = leaderEndPoint.x + 0.36;
            textOffsetV = RVector(-1,0);
        }
    }

    RLine line;

    if (definingPoint.getDistanceTo(knee1) > dimexo) {
        line = RLine(definingPoint + textOffsetV*dimexo, knee1);
        ret.append(QSharedPointer<RLine>(new RLine(line)));
    }

    line = RLine(knee1, knee2);
    ret.append(QSharedPointer<RLine>(new RLine(line)));

    line = RLine(knee2, leaderEndPoint);
    ret.append(QSharedPointer<RLine>(new RLine(line)));

    double textHeight = getDimtxt();
    double dimgap = getDimgap();

    dimLineLength = RNANDOUBLE;
    //if (!middleOfText.isValid()) {
    //    middleOfText = RVector(0,0);
    //}
    RVector oldMot = textPositionCenter;
    textPositionCenter = RVector(0,0);
    getTextData();
    textPositionCenter = oldMot;

    //textData.getBoundingBox();

    RVector textPos;
    //if (textPosition.isValid() /*&& !autoText*/) {
    if (!autoTextPos) {
        textPos = textPositionCenter;
        //autoTextPos = false;
    } else {
        if (!isMeasuringXAxis()) {
            double labelWidth = textData.getWidth();
            textPos = leaderEndPoint + textOffsetV * (labelWidth/2.0+dimgap);
        }
        else {
            textPos = leaderEndPoint + textOffsetV * (textHeight/2.0+dimgap);
        }
        textPositionCenter = textPos;
        //middleOfText = RVector::invalid;
        //autoTextPos = true;
    }
    textData.move(textPos);

    return ret;
}
예제 #23
0
void ScriptableWorker::run()
{
    if ( hasLogLevel(LogDebug) ) {
        bool isEval = m_args.length() == Arguments::Rest + 2
                && m_args.at(Arguments::Rest) == "eval";

        for (int i = Arguments::Rest + (isEval ? 1 : 0); i < m_args.length(); ++i) {
            QString indent = isEval ? QString("EVAL:")
                                    : (QString::number(i - Arguments::Rest + 1) + " ");
            foreach (const QByteArray &line, m_args.at(i).split('\n')) {
                SCRIPT_LOG( indent + getTextData(line) );
                indent = "  ";
            }
        }
    }

    bool hasData;
    const quintptr id = m_args.at(Arguments::ActionId).toULongLong(&hasData);
    QVariantMap data;
    if (hasData)
        data = Action::data(id);

    const QString currentPath = getTextData(m_args.at(Arguments::CurrentPath));

    QScriptEngine engine;
    ScriptableProxy proxy(m_wnd, data);
    Scriptable scriptable(&proxy);
    scriptable.initEngine(&engine, currentPath, data);

    if (m_socket) {
        QObject::connect( proxy.signaler(), SIGNAL(sendMessage(QByteArray,int)),
                          m_socket, SLOT(sendMessage(QByteArray,int)) );

        QObject::connect( &scriptable, SIGNAL(sendMessage(QByteArray,int)),
                          m_socket, SLOT(sendMessage(QByteArray,int)) );
        QObject::connect( m_socket, SIGNAL(messageReceived(QByteArray,int)),
                          &scriptable, SLOT(setInput(QByteArray)) );

        QObject::connect( m_socket, SIGNAL(disconnected()),
                          &scriptable, SLOT(abort()) );
        QObject::connect( &scriptable, SIGNAL(destroyed()),
                          m_socket, SLOT(deleteAfterDisconnected()) );

        if ( m_socket->isClosed() ) {
            SCRIPT_LOG("TERMINATED");
            return;
        }

        m_socket->start();
    }

    QObject::connect( &scriptable, SIGNAL(requestApplicationQuit()),
                      qApp, SLOT(quit()) );

    QByteArray response;
    int exitCode;

    if ( m_args.length() <= Arguments::Rest ) {
        SCRIPT_LOG("Error: bad command syntax");
        exitCode = CommandBadSyntax;
    } else {
        const QString cmd = getTextData( m_args.at(Arguments::Rest) );

#ifdef HAS_TESTS
        if ( cmd == "flush" && m_args.length() == Arguments::Rest + 2 ) {
            log( "flush ID: " + getTextData(m_args.at(Arguments::Rest + 1)), LogAlways );
            scriptable.sendMessageToClient(QByteArray(), CommandFinished);
            return;
        }
#endif

        QScriptValue fn = engine.globalObject().property(cmd);
        if ( !fn.isFunction() ) {
            SCRIPT_LOG("Error: unknown command");
            const QString msg =
                    Scriptable::tr("Name \"%1\" doesn't refer to a function.").arg(cmd);
            response = createLogMessage(msg, LogError).toUtf8();
            exitCode = CommandError;
        } else {
            /* Special arguments:
             * "-"  read this argument from stdin
             * "--" read all following arguments without control sequences
             */
            QScriptValueList fnArgs;
            bool readRaw = false;
            for ( int i = Arguments::Rest + 1; i < m_args.length(); ++i ) {
                const QByteArray &arg = m_args.at(i);
                if (!readRaw && arg == "--") {
                    readRaw = true;
                } else {
                    const QScriptValue value = readRaw || arg != "-"
                            ? scriptable.newByteArray(arg)
                            : scriptable.input();
                    fnArgs.append(value);
                }
            }

            engine.evaluate(m_pluginScript);
            QScriptValue result = fn.call(QScriptValue(), fnArgs);

            if ( engine.hasUncaughtException() ) {
                const QString exceptionText =
                        QString("%1\n--- backtrace ---\n%2\n--- end backtrace ---")
                        .arg( engine.uncaughtException().toString(),
                              engine.uncaughtExceptionBacktrace().join("\n") );

                SCRIPT_LOG( QString("Error: Exception in command \"%1\": %2")
                             .arg(cmd, exceptionText) );

                response = createLogMessage(exceptionText, LogError).toUtf8();
                exitCode = CommandError;
            } else {
                response = serializeScriptValue(result);
                exitCode = CommandFinished;
            }
        }
    }

    if (exitCode == CommandFinished && hasData)
        Action::setData(id, scriptable.data());

    scriptable.sendMessageToClient(response, exitCode);

    SCRIPT_LOG("DONE");
}