1 /*
2 * SPDX-FileCopyrightText: 2017~2017 CSSlayer <wengxt@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 *
6 */
7 #include "varianthelper.h"
8 #include <QDBusArgument>
9
10 namespace fcitx {
11 namespace kcm {
12
toMap(const QVariant & variant)13 QVariantMap toMap(const QVariant &variant) {
14 QVariantMap map;
15 if (variant.canConvert<QDBusArgument>()) {
16 auto argument = qvariant_cast<QDBusArgument>(variant);
17 argument >> map;
18 }
19 if (variant.canConvert<QVariantMap>()) {
20 map = variant.toMap();
21 }
22 return map;
23 }
24
valueFromVariantMapByPath(const QVariantMap & map,const QStringList & path,int depth)25 QString valueFromVariantMapByPath(const QVariantMap &map,
26 const QStringList &path, int depth) {
27 auto iter = map.find(path[depth]);
28 if (iter == map.end()) {
29 return QString();
30 }
31 if (depth + 1 == path.size()) {
32 if (iter->canConvert<QString>()) {
33 return iter->toString();
34 }
35 } else {
36 QVariantMap map = toMap(*iter);
37
38 if (!map.isEmpty()) {
39 return valueFromVariantMapByPath(map, path, depth + 1);
40 }
41 }
42 return QString();
43 }
44
valueFromVariantHelper(const QVariant & value,const QStringList & pathList,int depth)45 QVariant valueFromVariantHelper(const QVariant &value,
46 const QStringList &pathList, int depth) {
47 if (depth == pathList.size()) {
48 return value;
49 }
50 auto map = toMap(value);
51 // Make it finishes faster.
52 if (map.isEmpty() || !map.contains(pathList[depth])) {
53 return {};
54 }
55 return valueFromVariantHelper(map[pathList[depth]], pathList, depth + 1);
56 }
57
readVariant(const QVariant & value,const QString & path)58 QVariant readVariant(const QVariant &value, const QString &path) {
59 auto pathList = path.split("/");
60 return valueFromVariantHelper(toMap(value), pathList, 0);
61 }
62
readString(const QVariantMap & map,const QString & path)63 QString readString(const QVariantMap &map, const QString &path) {
64 auto pathList = path.split("/");
65 if (pathList.empty()) {
66 return QString();
67 }
68 return valueFromVariantMapByPath(map, pathList, 0);
69 }
70
readBool(const QVariantMap & map,const QString & path)71 bool readBool(const QVariantMap &map, const QString &path) {
72 return readString(map, path) == "True";
73 }
74
writeVariantHelper(QVariantMap & map,const QStringList & path,const QVariant & value,int depth)75 void writeVariantHelper(QVariantMap &map, const QStringList &path,
76 const QVariant &value, int depth) {
77 if (depth + 1 == path.size()) {
78 map[path[depth]] = value;
79 } else {
80 auto iter = map.find(path[depth]);
81 if (iter == map.end()) {
82 iter = map.insert(path[depth], QVariantMap());
83 }
84
85 if (iter->type() != QVariant::Map) {
86 auto oldValue = *iter;
87 *iter = QVariantMap({{"", oldValue}});
88 }
89
90 auto &nextMap = *static_cast<QVariantMap *>(iter->data());
91 writeVariantHelper(nextMap, path, value, depth + 1);
92 }
93 }
94
writeVariant(QVariantMap & map,const QString & path,const QVariant & value)95 void writeVariant(QVariantMap &map, const QString &path,
96 const QVariant &value) {
97 auto pathList = path.split("/");
98 if (pathList.empty()) {
99 return;
100 }
101 writeVariantHelper(map, pathList, value, 0);
102 }
103
104 } // namespace kcm
105 } // namespace fcitx
106