Skip to content

Commit

Permalink
feat: [sidebar/settings] custom settings can be added.
Browse files Browse the repository at this point in the history
as title.
now you can add your custom setting item into setting pane, and you can
customize it's order.

Log: custom setting pane.

Task: https://pms.uniontech.com/task-view-286565.html?onlybody=yes
  • Loading branch information
itsXuSt committed Aug 24, 2023
1 parent a6f57f5 commit d9f4fa7
Show file tree
Hide file tree
Showing 21 changed files with 750 additions and 88 deletions.
30 changes: 30 additions & 0 deletions include/dfm-base/settingdialog/customsettingitemregister.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef CUSTOMSETTINGITEMREGISTER_H
#define CUSTOMSETTINGITEMREGISTER_H

#include <QMap>
#include <QPair>

class QWidget;
class QObject;

typedef QPair<QWidget *, QWidget *> (*CustomSettingItemCreator)(QObject *);

namespace dfmbase {
class CustomSettingItemRegister
{
public:
static CustomSettingItemRegister *instance();
bool registCustomSettingItemType(const QString &type, const CustomSettingItemCreator &creator);
const QMap<QString, CustomSettingItemCreator> &getCreators() const;

private:
CustomSettingItemRegister();
QMap<QString, CustomSettingItemCreator> creators;
};
}

#endif // CUSTOMSETTINGITEMREGISTER_H
72 changes: 72 additions & 0 deletions include/dfm-base/settingdialog/settingjsongenerator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef SETTINGJSONGENERATOR_H
#define SETTINGJSONGENERATOR_H

#include <QVariantMap>

/*
* the root group:
* {
* "groups": [(top level group)]
* }
*
* a top level group:
* {
* "key": (string),
* "name": (string),
* "groups": [(config group)]
* }
*
* a config group:
* {
* "key": (string),
* "name": (string),
* "options": [(config item)]
* }
*
* config item: // option item
* {
* "key": (string),
* "text": (string),
* "type": (string),
* "default": (variant),
* "hide": (bool),
* "custom_info": (variant)
* }
* */

namespace dfmbase {

class SettingJsonGenerator
{
public:
static SettingJsonGenerator *instance();

QByteArray genSettingJson();
bool addGroup(const QString &key, const QString &name);
bool addConfig(const QString &key, const QVariantMap &config);
bool addCheckBoxConfig(const QString &key, const QString &text, bool defaultVal = true);
bool addComboboxConfig(const QString &key, const QString &name, const QStringList &options, int defaultVal = 0);
bool addComboboxConfig(const QString &key, const QString &name, const QVariantMap &options, QVariant defaultVal = QVariant());

protected:
SettingJsonGenerator();

void mergeGroups();
QJsonObject constructTopGroup(const QString &key);
QJsonObject constructConfigGroup(const QString &key);
QJsonObject constructConfig(const QString &key);

private:
QMap<QString, QString> topGroups;
QMap<QString, QString> tmpTopGroups;
QMap<QString, QString> configGroups;
QMap<QString, QString> tmpConfigGroups;
QMap<QString, QVariantMap> configs;
};

}
#endif // SETTINGJSONGENERATOR_H
34 changes: 34 additions & 0 deletions src/dfm-base/base/configs/customsettingitemregister.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "dfm-base/settingdialog/customsettingitemregister.h"

#include <QDebug>

using namespace dfmbase;

CustomSettingItemRegister::CustomSettingItemRegister()
{
}

const QMap<QString, CustomSettingItemCreator> &CustomSettingItemRegister::getCreators() const
{
return creators;
}

CustomSettingItemRegister *CustomSettingItemRegister::instance()
{
static CustomSettingItemRegister ins;
return &ins;
}

bool CustomSettingItemRegister::registCustomSettingItemType(const QString &type, const CustomSettingItemCreator &creator)
{
if (creators.contains(type)) {
qWarning() << type << "is already registered...";
return false;
}
creators.insert(type, creator);
return true;
}
233 changes: 198 additions & 35 deletions src/dfm-base/base/configs/settingbackend.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/dfm-base/base/configs/settingbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class SettingBackend : public DSettingsBackend
void doSetOption(const QString &key, const QVariant &value);
void onValueChanged(int attribute, const QVariant &value);

void initPresetSettingConfig();

private:
explicit SettingBackend(QObject *parent = nullptr);
~SettingBackend();
Expand Down
208 changes: 208 additions & 0 deletions src/dfm-base/base/configs/settingjsongenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "dfm-base/settingdialog/settingjsongenerator.h"

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

#include <QDebug>

using namespace dfmbase;

SettingJsonGenerator::SettingJsonGenerator()
{
}

SettingJsonGenerator *SettingJsonGenerator::instance()
{
static SettingJsonGenerator gen;
return &gen;
}

QByteArray SettingJsonGenerator::genSettingJson()
{
mergeGroups();

QJsonArray groups;
auto iter = topGroups.cbegin();
while (iter != topGroups.cend()) {
groups.append(constructTopGroup(iter.key()));
iter++;
}

QJsonObject obj;
obj.insert("groups", groups);

QJsonDocument doc;
doc.setObject(obj);
return doc.toJson(QJsonDocument::Indented);
}

bool SettingJsonGenerator::addGroup(const QString &key, const QString &name)
{
if (key.count(".") > 1) {
qWarning() << "max group level is 2, inputed: " << key.count(".") << key;
return false;
}
if (key.startsWith(".") || key.endsWith(".")) {
qWarning() << "the dot must not be start or end of the key." << key;
return false;
}

if (key.contains(".")) {
if (configGroups.contains(key)) {
qWarning() << "same name key has been added:" << key << ":" << configGroups.value(key);
return false;
}
configGroups.insert(key, name);

// check if top group exist.
QString topGroup = key.split(".").first();
if (!topGroups.contains(topGroup)) {
qWarning() << "no top group exist: " << topGroup;
tmpTopGroups.insert(topGroup, topGroup);
}
} else {
if (topGroups.contains(key)) {
qWarning() << "same name key has been added: " << key << ":" << topGroups.value(key);
return false;
}
topGroups.insert(key, name);
}

return true;
}

bool SettingJsonGenerator::addConfig(const QString &key, const QVariantMap &config)
{
if (key.count(".") != 2) {
qWarning() << "config can only be inserted in level 2:" << key;
return false;
}
if (key.startsWith(".") || key.endsWith(".")) {
qWarning() << "the dot must not be start or end of the key." << key;
return false;
}
if (key.contains("..")) {
qWarning() << "cannot insert config into empty group: " << key;
return false;
}
if (configs.contains(key)) {
qWarning() << "a same name key is already added." << key << ":" << configs.value(key);
return false;
}

QStringList frags = key.split(".");
if (frags.count() != 3)
return false;
QString configKey = frags.at(2);
if (config.value("key").toString() != configKey) {
qWarning() << "config is not valid with key" << key << config;
return false;
}

frags.removeLast();
tmpConfigGroups.insert(frags.join("."), frags.last());
frags.removeLast();
tmpTopGroups.insert(frags.first(), frags.first());

configs.insert(key, config);
return true;
}

bool SettingJsonGenerator::addCheckBoxConfig(const QString &key, const QString &text, bool defaultVal)
{
QVariantMap config {
{ "key", key.mid(key.lastIndexOf(".") + 1) },
{ "text", text },
{ "type", "checkbox" },
{ "default", defaultVal }
};
return addConfig(key, config);
}

bool SettingJsonGenerator::addComboboxConfig(const QString &key, const QString &name, const QStringList &options, int defaultVal)
{
QVariantMap config {
{ "key", key.mid(key.lastIndexOf(".") + 1) },
{ "name", name },
{ "items", options },
{ "type", "combobox" },
{ "default", defaultVal }
};
return addConfig(key, config);
}

bool SettingJsonGenerator::addComboboxConfig(const QString &key, const QString &name, const QVariantMap &options, QVariant defaultVal)
{
QVariantMap config {
{ "key", key.mid(key.lastIndexOf(".") + 1) },
{ "name", name },
{ "items", options },
{ "type", "combobox" },
{ "default", defaultVal }
};
return addConfig(key, config);
}

void SettingJsonGenerator::mergeGroups()
{
auto merge = [](const QMap<QString, QString> &from, QMap<QString, QString> &into) {
auto iter = from.cbegin();
while (iter != from.cend()) {
if (!into.contains(iter.key()))
into.insert(iter.key(), iter.value());
iter++;
}
};
merge(tmpConfigGroups, configGroups);
merge(tmpTopGroups, topGroups);
}

QJsonObject SettingJsonGenerator::constructTopGroup(const QString &key)
{
qDebug() << "construct top group:" << key;
QJsonObject obj;
obj.insert("key", key);
obj.insert("name", topGroups.value(key, "Unknown"));

QJsonArray groups;
auto iter = configGroups.cbegin();
while (iter != configGroups.cend()) {
if (iter.key().startsWith(key))
groups.append(constructConfigGroup(iter.key()));
iter++;
}

obj.insert("groups", groups);
return obj;
}

QJsonObject SettingJsonGenerator::constructConfigGroup(const QString &key)
{
qDebug() << "construct config group:" << key;
QJsonObject obj;
obj.insert("key", key.mid(key.indexOf(".") + 1));
obj.insert("name", configGroups.value(key, "Unknown"));

QJsonArray options;
auto iter = configs.cbegin();
while (iter != configs.cend()) {
if (iter.key().startsWith(key))
options.append(constructConfig(iter.key()));
iter++;
}

obj.insert("options", options);
return obj;
}

QJsonObject SettingJsonGenerator::constructConfig(const QString &key)
{
qDebug() << "construct item: " << key;
QVariantMap config = configs.value(key, QVariantMap());
return QJsonObject::fromVariantMap(config);
}
Loading

0 comments on commit d9f4fa7

Please sign in to comment.