diff --git a/src/tools/sdktool/CMakeLists.txt b/src/tools/sdktool/CMakeLists.txt index b238ab2af8e..22b1c37af78 100644 --- a/src/tools/sdktool/CMakeLists.txt +++ b/src/tools/sdktool/CMakeLists.txt @@ -13,6 +13,7 @@ add_qtc_executable(sdktool addkitoperation.cpp addkitoperation.h addqtoperation.cpp addqtoperation.h addtoolchainoperation.cpp addtoolchainoperation.h + addvalueoperation.cpp addvalueoperation.h findkeyoperation.cpp findkeyoperation.h findvalueoperation.cpp findvalueoperation.h getoperation.cpp getoperation.h diff --git a/src/tools/sdktool/addvalueoperation.cpp b/src/tools/sdktool/addvalueoperation.cpp new file mode 100644 index 00000000000..017c17fb994 --- /dev/null +++ b/src/tools/sdktool/addvalueoperation.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Christoph Schlosser, B/S/H/ +** +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "addvalueoperation.h" +#include "addkeysoperation.h" +#include "getoperation.h" +#include "rmkeysoperation.h" + +#include +#include + +namespace { +constexpr auto SUCCESS = 0; +constexpr auto FAILURE = not SUCCESS; +} // namespace + +QString AddValueOperation::name() const +{ + return QLatin1String("addValue"); +} + +QString AddValueOperation::helpText() const +{ + return QLatin1String("add a value to an existing list"); +} + +QString AddValueOperation::argumentsHelpText() const +{ + return QLatin1String( + "A file (relative to top-level settings directory and without .xml extension)\n" + "followed by the key of the list followed by one or more type:values to append to the " + "list.\n"); +} + +bool AddValueOperation::setArguments(const QStringList &args) +{ + if (args.size() < 3) { + std::cerr << "Error: No"; + switch (args.size()) { + case 0: + std::cerr << " file,"; + case 1: + std::cerr << " key and"; + case 2: + std::cerr << " values"; + break; + } + std::cerr << " given.\n" << std::endl; + return false; + } + + auto tempArgs = args; + m_file = tempArgs.takeFirst(); + m_key = tempArgs.takeFirst(); + for (const auto &arg : tempArgs) { + const auto val = Operation::valueFromString(arg); + if (not val.isValid() or val.isNull()) { + std::cerr << "Error: " << std::quoted(arg.toStdString()) + << " is not a valid QVariant like string Type:Value.\n" + << std::endl; + return false; + } + m_values.append(val); + } + + return true; +} + +int AddValueOperation::execute() const +{ + auto map = load(m_file); + + if (map.empty()) { + std::cerr << "Error: Could not load " << m_file.toStdString() << std::endl; + return FAILURE; + } + + auto status = appendListToMap(map, m_key, m_values); + + if (status) { + status = save(map, m_file); + } + + return status ? SUCCESS : FAILURE; +} + +#ifdef WITH_TESTS +bool AddValueOperation::test() const +{ + QVariantList testDataList; + testDataList.append(QLatin1String("Some String")); + testDataList.append(int(1860)); + + KeyValuePairList testKvpList; + testKvpList.append(KeyValuePair(QLatin1String("test/foo"), QString::fromLatin1("QString:Foo"))); + testKvpList.append(KeyValuePair(QLatin1String("test/foobar"), QString::fromLatin1("int:42"))); + testKvpList.append(KeyValuePair(QLatin1String("test/bar"), testDataList)); + + const auto valueList = QVariantList( + {Operation::valueFromString("QString:ELIL"), Operation::valueFromString("int:-1")}); + + QVariantMap testMap; + + // add to empty map + auto result = appendListToMap(testMap, "some key", valueList); + + if (result) + return false; + + testMap.insert(QLatin1String("someEmptyThing"), QVariantMap()); + testMap.insert(QLatin1String("aKey"), "withAString"); + + // append to a value + result = appendListToMap(testMap, "aKey", valueList); + + if (result) + return false; + + testMap = AddKeysOperation::addKeys(testMap, testKvpList); + + // quick sanity check + if (testMap.count() != 3 and testDataList.count() != 2 and testKvpList.count() != 3) + return false; + + // successful adding of values + result = appendListToMap(testMap, "test/bar", valueList); + if (not result) + return false; + + const auto newList = qvariant_cast(GetOperation::get(testMap, "test/bar")); + if (newList.count() != (testDataList.count() + valueList.count())) + return false; + + if (not newList.contains(1860) or not newList.contains(QString("Some String")) + or not newList.contains("ELIL") or not newList.contains(-1)) + return false; + + return true; +} +#endif + +bool AddValueOperation::appendListToMap(QVariantMap &map, + const QString &key, + const QVariantList &values) +{ + const auto data = GetOperation::get(map, key); + + if (not data.isValid() or data.isNull()) { + std::cerr << "Error: Could not retrieve value for key " << std::quoted(key.toStdString()) + << std::endl; + return false; + } + + if (not data.canConvert()) { + std::cerr << "Error: Data stored in " << std::quoted(key.toStdString()) + << " can not be converted into QVariantList." << std::endl; + return false; + } + + auto newList = qvariant_cast(data); + + newList.append(values); + + map = RmKeysOperation::rmKeys(map, {key}); + map = AddKeysOperation::addKeys(map, {Operation::KeyValuePair(key, newList)}); + + return true; +} diff --git a/src/tools/sdktool/addvalueoperation.h b/src/tools/sdktool/addvalueoperation.h new file mode 100644 index 00000000000..fe1910a2272 --- /dev/null +++ b/src/tools/sdktool/addvalueoperation.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Christoph Schlosser, B/S/H/ +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "operation.h" + +class AddValueOperation : public Operation +{ +public: + QString name() const override; + QString helpText() const override; + QString argumentsHelpText() const override; + + bool setArguments(const QStringList &args) override; + + int execute() const override; + +#ifdef WITH_TESTS + bool test() const override; +#endif + + static bool appendListToMap(QVariantMap &map, const QString &key, const QVariantList &values); + +private: + QString m_file; + QString m_key; + QVariantList m_values; +}; diff --git a/src/tools/sdktool/main.cpp b/src/tools/sdktool/main.cpp index 808a2652fa4..c1ecb287461 100644 --- a/src/tools/sdktool/main.cpp +++ b/src/tools/sdktool/main.cpp @@ -35,6 +35,7 @@ #include "addkitoperation.h" #include "addqtoperation.h" #include "addtoolchainoperation.h" +#include "addvalueoperation.h" #include "findkeyoperation.h" #include "findvalueoperation.h" #include "getoperation.h" @@ -187,6 +188,7 @@ int main(int argc, char *argv[]) operations.emplace_back(std::make_unique()); operations.emplace_back(std::make_unique()); operations.emplace_back(std::make_unique()); + operations.emplace_back(std::make_unique()); operations.emplace_back(std::make_unique()); diff --git a/src/tools/sdktool/sdktool.pro b/src/tools/sdktool/sdktool.pro index 379a1b10cac..1e6a6769595 100644 --- a/src/tools/sdktool/sdktool.pro +++ b/src/tools/sdktool/sdktool.pro @@ -18,6 +18,7 @@ SOURCES += \ addkitoperation.cpp \ addqtoperation.cpp \ addtoolchainoperation.cpp \ + addvalueoperation.cpp \ findkeyoperation.cpp \ findvalueoperation.cpp \ getoperation.cpp \ @@ -50,6 +51,7 @@ HEADERS += \ addkitoperation.h \ addqtoperation.h \ addtoolchainoperation.h \ + addvalueoperation.h \ findkeyoperation.h \ findvalueoperation.h \ getoperation.h \ diff --git a/src/tools/sdktool/sdktool.qbs b/src/tools/sdktool/sdktool.qbs index 8806af1d468..8e6408971cc 100644 --- a/src/tools/sdktool/sdktool.qbs +++ b/src/tools/sdktool/sdktool.qbs @@ -38,6 +38,8 @@ QtcTool { "addqtoperation.h", "addtoolchainoperation.cpp", "addtoolchainoperation.h", + "addvalueoperation.cpp", + "addvalueoperation.h", "findkeyoperation.cpp", "findkeyoperation.h", "findvalueoperation.cpp",