From eb574d77b0ab9a92b61e7738d089cd4ea4304e51 Mon Sep 17 00:00:00 2001 From: Karsten Heimrich Date: Tue, 23 Jun 2015 14:01:14 +0200 Subject: Use QQmlV4Function to correctly get empty parameters from script. By using QQmlV4Function to get the parameters, empty strings passed are correctly kept as empty and not null. Task-number: QTIFW-724 Change-Id: I592e2230e574ba82e765bd0079964db29452b2e9 Reviewed-by: Simon Hausmann --- doc/scripting-api/component.qdoc | 12 ---- src/libs/installer/component.cpp | 80 +++++++++++++--------- src/libs/installer/component.h | 19 ++--- src/libs/installer/installer.pro | 3 +- .../installer/scriptengine/data/addOperation.qs | 53 ++++++++++++++ tests/auto/installer/scriptengine/scriptengine.qrc | 1 + .../installer/scriptengine/tst_scriptengine.cpp | 67 ++++++++++++++++++ 7 files changed, 177 insertions(+), 58 deletions(-) create mode 100644 tests/auto/installer/scriptengine/data/addOperation.qs diff --git a/doc/scripting-api/component.qdoc b/doc/scripting-api/component.qdoc index 8e38c7e92..aa986ff38 100644 --- a/doc/scripting-api/component.qdoc +++ b/doc/scripting-api/component.qdoc @@ -324,18 +324,6 @@ The method is typically called from within \l component::createOperations(). */ -/*! - \qmlmethod boolean component::addOperation(string operation, string parameter1 = "", string parameter2 = "", ..., string parameter10 = "") - - Convenience method for calling addOperation(string, stringlist) with up to 10 arguments. -*/ - -/*! - \qmlmethod boolean component::addElevatedOperation(string operation, string parameter1 = "", string parameter2 = "", ..., string parameter10 = "") - - Convenience method for calling addElevatedOperation(string, stringlist) with up to 10 arguments. -*/ - /*! \qmlmethod boolean component::addElevatedOperation(string operation, stringlist parameters) diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp index b49bfe3a4..f3ba9c63c 100644 --- a/src/libs/installer/component.cpp +++ b/src/libs/installer/component.cpp @@ -56,6 +56,10 @@ #include +#include +#include +#include + #include using namespace QInstaller; @@ -703,11 +707,11 @@ void Component::createOperationsForPath(const QString &path) if (fi.isFile()) { static const QString copy = QString::fromLatin1("Copy"); - addOperation(copy, fi.filePath(), target); + addOperation(copy, QStringList() << fi.filePath() << target); } else if (fi.isDir()) { qApp->processEvents(); static const QString mkdir = QString::fromLatin1("Mkdir"); - addOperation(mkdir, target); + addOperation(mkdir, QStringList(target)); QDirIterator it(fi.filePath()); while (it.hasNext()) @@ -747,7 +751,7 @@ void Component::createOperationsForArchive(const QString &archive) if (isZip) { // archives get completely extracted per default (if the script isn't doing other stuff) - addOperation(QLatin1String("Extract"), archive, QLatin1String("@TargetDir@")); + addOperation(QLatin1String("Extract"), QStringList() << archive << QLatin1String("@TargetDir@")); } else { createOperationsForPath(archive); } @@ -1009,23 +1013,44 @@ Operation *Component::createOperation(const QString &operationName, const QStrin return operation; } -/*! - Convenience method for calling the operation \a operation with up to ten parameters: - \a parameter1, \a parameter2, \a parameter3, \a parameter4, \a parameter5, \a parameter6, - \a parameter7, \a parameter8, \a parameter9, and \a parameter10. +namespace { - \sa {component::addOperation}{component.addOperation} -*/ -bool Component::addOperation(const QString &operation, const QString ¶meter1, const QString ¶meter2, - const QString ¶meter3, const QString ¶meter4, const QString ¶meter5, const QString ¶meter6, - const QString ¶meter7, const QString ¶meter8, const QString ¶meter9, const QString ¶meter10) +inline bool convert(QQmlV4Function *func, QStringList *toArgs) { - if (Operation *op = createOperation(operation, parameter1, parameter2, parameter3, parameter4, parameter5, - parameter6, parameter7, parameter8, parameter9, parameter10)) { - addOperation(op); - return true; + if (func->length() < 2) + return false; + + QV4::Scope scope(func->v4engine()); + QV4::ScopedValue val(scope); + val = (*func)[0]; + + *toArgs << val->toQString(); + for (int i = 1; i < func->length(); i++) { + val = (*func)[i]; + if (val->isObject() && val->asObject()->isArrayObject()) { + QV4::ScopedValue valtmp(scope); + QV4::Object *array = val->asObject(); + uint length = array->getLength(); + for (uint ii = 0; ii < length; ++ii) { + valtmp = array->getIndexed(ii); + *toArgs << valtmp->toQStringNoThrow(); + } + } else { + *toArgs << val->toQString(); + } } + return true; +} +} +/*! + \internal +*/ +bool Component::addOperation(QQmlV4Function *func) +{ + QStringList args; + if (convert(func, &args)) + return addOperation(args[0], args.mid(1)); return false; } @@ -1033,6 +1058,8 @@ bool Component::addOperation(const QString &operation, const QString ¶meter1 Creates and adds an installation operation for \a operation. Add any number of \a parameters. The variables that the parameters contain, such as \c @TargetDir@, are replaced with their values. + + \sa {component::addOperation}{component.addOperation} */ bool Component::addOperation(const QString &operation, const QStringList ¶meters) { @@ -1045,23 +1072,13 @@ bool Component::addOperation(const QString &operation, const QStringList ¶me } /*! - Convenience method for calling the elevated operation \a operation with up to ten parameters: - \a parameter1, \a parameter2, \a parameter3, \a parameter4, \a parameter5, \a parameter6, - \a parameter7, \a parameter8, \a parameter9, and \a parameter10. - - \sa {component::addElevatedOperation}{component.addElevatedOperation} + \internal */ -bool Component::addElevatedOperation(const QString &operation, const QString ¶meter1, - const QString ¶meter2, const QString ¶meter3, const QString ¶meter4, const QString ¶meter5, - const QString ¶meter6, const QString ¶meter7, const QString ¶meter8, const QString ¶meter9, - const QString ¶meter10) +bool Component::addElevatedOperation(QQmlV4Function *func) { - if (Operation *op = createOperation(operation, parameter1, parameter2, parameter3, parameter4, parameter5, - parameter6, parameter7, parameter8, parameter9, parameter10)) { - addElevatedOperation(op); - return true; - } - + QStringList args; + if (convert(func, &args)) + return addElevatedOperation(args[0], args.mid(1)); return false; } @@ -1070,6 +1087,7 @@ bool Component::addElevatedOperation(const QString &operation, const QString &pa The variables that the parameters contain, such as \c @TargetDir@, are replaced with their values. The operation is executed with elevated rights. + \sa {component::addElevatedOperation}{component.addElevatedOperation} */ bool Component::addElevatedOperation(const QString &operation, const QStringList ¶meters) { diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h index b184d27d2..e679be593 100644 --- a/src/libs/installer/component.h +++ b/src/libs/installer/component.h @@ -45,6 +45,7 @@ #include QT_FORWARD_DECLARE_CLASS(QDebug) +QT_FORWARD_DECLARE_CLASS(QQmlV4Function) namespace KDUpdater { class Update; @@ -131,22 +132,12 @@ public: OperationList operations() const; void addOperation(Operation *operation); - Q_INVOKABLE bool addOperation(const QString &operation, const QString ¶meter1 = QString(), - const QString ¶meter2 = QString(), const QString ¶meter3 = QString(), - const QString ¶meter4 = QString(), const QString ¶meter5 = QString(), - const QString ¶meter6 = QString(), const QString ¶meter7 = QString(), - const QString ¶meter8 = QString(), const QString ¶meter9 = QString(), - const QString ¶meter10 = QString()); - Q_INVOKABLE bool addOperation(const QString &operation, const QStringList ¶meters); + Q_INVOKABLE bool addOperation(QQmlV4Function *args); + bool addOperation(const QString &operation, const QStringList ¶meters); void addElevatedOperation(Operation *operation); - Q_INVOKABLE bool addElevatedOperation(const QString &operation, - const QString ¶meter1 = QString(), const QString ¶meter2 = QString(), - const QString ¶meter3 = QString(), const QString ¶meter4 = QString(), - const QString ¶meter5 = QString(), const QString ¶meter6 = QString(), - const QString ¶meter7 = QString(), const QString ¶meter8 = QString(), - const QString ¶meter9 = QString(), const QString ¶meter10 = QString()); - Q_INVOKABLE bool addElevatedOperation(const QString &operation, const QStringList ¶meters); + Q_INVOKABLE bool addElevatedOperation(QQmlV4Function *args); + bool addElevatedOperation(const QString &operation, const QStringList ¶meters); QStringList downloadableArchives() const; Q_INVOKABLE void addDownloadableArchive(const QString &path); diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index 87af31f3c..cfa83d08d 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -34,7 +34,8 @@ QT += \ xml \ concurrent \ widgets \ - core-private + core-private \ + qml-private win32:QT += winextras HEADERS += packagemanagercore.h \ diff --git a/tests/auto/installer/scriptengine/data/addOperation.qs b/tests/auto/installer/scriptengine/data/addOperation.qs new file mode 100644 index 000000000..9be112aaf --- /dev/null +++ b/tests/auto/installer/scriptengine/data/addOperation.qs @@ -0,0 +1,53 @@ +/************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +function Component() +{ +} + +Component.prototype.createOperations = function () +{ + console.log("Component::createOperations()"); + component.createOperations(); + + component.addOperation("EmptyArg", "Arg", "Arg2", ""); + component.addOperation("EmptyArg", "Arg", "", "Arg3"); + component.addOperation("EmptyArg", "", "Arg2", "Arg3"); + component.addOperation("EmptyArg", ["Arg", "Arg2", ""]); + + component.addElevatedOperation("EmptyArg", "eArg", "eArg2", ""); + component.addElevatedOperation("EmptyArg", "eArg", "", "eArg3"); + component.addElevatedOperation("EmptyArg", "", "eArg2", "eArg3"); + component.addElevatedOperation("EmptyArg", ["eArg", "eArg2", ""]); +} diff --git a/tests/auto/installer/scriptengine/scriptengine.qrc b/tests/auto/installer/scriptengine/scriptengine.qrc index d630f3196..9c72e686f 100644 --- a/tests/auto/installer/scriptengine/scriptengine.qrc +++ b/tests/auto/installer/scriptengine/scriptengine.qrc @@ -8,5 +8,6 @@ data/enteringpage.qs data/form.ui data/userinterface.qs + data/addOperation.qs diff --git a/tests/auto/installer/scriptengine/tst_scriptengine.cpp b/tests/auto/installer/scriptengine/tst_scriptengine.cpp index 0bbb79060..04a5e0b63 100644 --- a/tests/auto/installer/scriptengine/tst_scriptengine.cpp +++ b/tests/auto/installer/scriptengine/tst_scriptengine.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -157,6 +158,30 @@ signals: void emitted(); }; +class EmptyArgOperation : public KDUpdater::UpdateOperation +{ +public: + EmptyArgOperation() { + setName("EmptyArg"); + } + + void backup() {} + bool performOperation() { + return true; + } + bool undoOperation() { + return true; + } + bool testOperation() { + return true; + } + UpdateOperation *clone() const { + return 0; + } +}; + + +// -- tst_ScriptEngine class tst_ScriptEngine : public QObject { @@ -173,6 +198,10 @@ private slots: m_component->setValue("Default", "Script"); m_component->setValue(scName, "component.test.name"); + Component *component = new Component(&m_core); + component->setValue(scName, "component.test.addOperation"); + m_core.appendRootComponent(component); + m_scriptEngine = m_core.componentScriptEngine(); } @@ -460,6 +489,44 @@ private slots: QCOMPARE(enteringPage->invocationOrder(), expectedOrder); } + void testAddOperation_AddElevatedOperation() + { + using namespace KDUpdater; + UpdateOperationFactory &factory = UpdateOperationFactory::instance(); + factory.registerUpdateOperation(QLatin1String("EmptyArg")); + + try { + m_core.setPackageManager(); + Component *component = m_core.componentByName("component.test.addOperation"); + component->loadComponentScript(":///data/addOperation.qs"); + + setExpectedScriptOutput("\"Component::createOperations()\""); + component->createOperations(); + + const OperationList operations = component->operations(); + QCOMPARE(operations.count(), 8); + + struct { + const char* args[3]; + const char* operator[](int i) const { + return args[i]; + } + } expectedArgs[] = { + { "Arg", "Arg2", "" }, { "Arg", "", "Arg3" }, { "", "Arg2", "Arg3" }, { "Arg", "Arg2", "" }, + { "eArg", "eArg2", "" }, { "eArg", "", "eArg3" }, { "", "eArg2", "eArg3" }, { "eArg", "eArg2", "" } + }; + + for (int i = 0; i < operations.count(); ++i) { + const QStringList arguments = operations[i]->arguments(); + QCOMPARE(arguments.count(), 3); + for (int j = 0; j < 3; ++j) + QCOMPARE(arguments[j], QString(expectedArgs[i][j])); + } + } catch (const QInstaller::Error &error) { + QFAIL(qPrintable(error.message())); + } + } + private: void setExpectedScriptOutput(const char *message) { -- cgit v1.2.3