예제 #1
0
ScriptableWorker::ScriptableWorker(MainWindow *mainWindow,
                                   const Arguments &args, ClientSocket *socket)
    : QRunnable()
    , m_wnd(mainWindow)
    , m_args(args)
    , m_socket(socket)
    , m_pluginScript(ConfigurationManager::instance()->itemFactory()->scripts())
{
    if ( hasLogLevel(LogDebug) )
        m_id = m_socket->property("id").toString();
}
예제 #2
0
ScriptableWorker::ScriptableWorker(
        MainWindow *mainWindow, const Arguments &args, ClientSocket *socket,
        const QString &pluginScript)
    : QRunnable()
    , m_wnd(mainWindow)
    , m_args(args)
    , m_socket(socket)
    , m_pluginScript(pluginScript)
{
    if ( hasLogLevel(LogDebug) )
        m_id = m_socket->property("id").toString();
}
예제 #3
0
파일: log.cpp 프로젝트: DINKIN/CopyQ
void log(const QString &text, const LogLevel level)
{
    if ( !hasLogLevel(level) )
        return;

    SystemMutexLocker lock(getSessionMutex());

    const QByteArray msg = createLogMessage(text, level).toUtf8();

    QFile f( logFileName() );
    const bool writtenToLogFile = f.open(QIODevice::Append) && f.write(msg);
    if (writtenToLogFile)
        f.close();

    // Log to file and if needed to stderr.
    if ( !writtenToLogFile || level <= LogWarning ) {
        QFile ferr;
        ferr.open(stderr, QIODevice::WriteOnly);
        ferr.write(msg);
    }

    if ( writtenToLogFile && f.size() > logFileSize )
        rotateLogFiles();
}
예제 #4
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) {
            const QString indent = isEval
                    ? QString("EVAL:")
                    : (QString::number(i - Arguments::Rest + 1) + " ");
            SCRIPT_LOG( indent + getTextData(m_args.at(i)) );
        }
    }

    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;
        }

        QMetaObject::invokeMethod(m_socket, "start", Qt::QueuedConnection);
    }

    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");
}
예제 #5
0
파일: common.cpp 프로젝트: amosbird/CopyQ
QVariantMap cloneData(const QMimeData &rawData, QStringList formats)
{
    ClipboardDataGuard data(rawData);

    const auto internalMimeTypes = {mimeOwner, mimeWindowTitle, mimeItemNotes, mimeHidden};

    QVariantMap newdata;

    /*
     Some apps provide images even when copying huge spreadsheet, this can
     block those apps while generating and providing the data.

     This code removes ignores any image data if text is available.

     Images in SVG and other XML formats are expected to be relatively small
     so these doesn't have to be ignored.
     */
    if ( formats.contains(mimeText) && data.hasFormat(mimeText) ) {
        const QString mimeImagePrefix = "image/";
        const auto first = std::remove_if(
                    std::begin(formats), std::end(formats),
                    [&mimeImagePrefix](const QString &format) {
                        return format.startsWith(mimeImagePrefix)
                            && !format.contains("xml")
                            && !format.contains("svg");
                    });
        formats.erase(first, std::end(formats));
    }

    QStringList imageFormats;
    for (const auto &mime : formats) {
        const QByteArray bytes = data.getUtf8Data(mime);
        if ( bytes.isEmpty() )
            imageFormats.append(mime);
        else
            newdata.insert(mime, bytes);
    }

    for (const auto &internalMime : internalMimeTypes) {
        if ( data.hasFormat(internalMime) )
            newdata.insert( internalMime, data.data(internalMime) );
    }

    // Retrieve images last since this can take a while.
    if ( !imageFormats.isEmpty() ) {
        const QImage image = data.getImageData();
        if ( !image.isNull() ) {
            for (const auto &mime : imageFormats) {
                const QString format = getImageFormatFromMime(mime);
                if ( !format.isEmpty() )
                    cloneImageData(image, format, mime, &newdata);
            }
        }
    }

    if ( hasLogLevel(LogTrace) ) {
        for (const auto &format : data.formats()) {
            if ( !formats.contains(format) )
                COPYQ_LOG_VERBOSE(QString("Skipping format: %1").arg(format));
        }
    }

    return newdata;
}
예제 #6
0
void ScriptableWorker::run()
{
    MONITOR_LOG("starting");

    QScriptEngine engine;
    ScriptableProxy proxy(m_wnd);
    Scriptable scriptable(&proxy);
    scriptable.initEngine( &engine, QString::fromUtf8(m_args.at(Arguments::CurrentPath)),
                           m_args.at(Arguments::ActionId) );

    if (m_socket) {
        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() ) {
            MONITOR_LOG("terminated");
            return;
        }

        m_socket->start();
    }

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

    QByteArray response;
    int exitCode;

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

        if ( hasLogLevel(LogDebug) ) {
            MONITOR_LOG("Client arguments:");
            for (int i = Arguments::Rest; i < m_args.length(); ++i)
                MONITOR_LOG( "    " + QString::fromUtf8(m_args.at(i)) );
        }

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

        QScriptValue fn = engine.globalObject().property(cmd);
        if ( !fn.isFunction() ) {
            MONITOR_LOG("Error: unknown command");
            response = createLogMessage("CopyQ client",
                                        Scriptable::tr("Name \"%1\" doesn't refer to a function.")
                                        .arg(cmd),
                                        LogError).toUtf8();
            exitCode = CommandError;
        } else {
            QScriptValueList fnArgs;
            for ( int i = Arguments::Rest + 1; i < m_args.length(); ++i )
                fnArgs.append( scriptable.newByteArray(m_args.at(i)) );

            QScriptValue result = fn.call(QScriptValue(), fnArgs);

            if ( engine.hasUncaughtException() ) {
                const QString exceptionText = engine.uncaughtException().toString();
                MONITOR_LOG( QString("Error: exception in command \"%1\": %2")
                             .arg(cmd).arg(exceptionText) );
                response = createLogMessage("CopyQ client", exceptionText, LogError).toUtf8();
                exitCode = CommandError;
            } else {
                response = serializeScriptValue(result);
                exitCode = CommandFinished;
            }
        }
    }

    scriptable.sendMessageToClient(response, exitCode);

    MONITOR_LOG("finished");
}