diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index 9ec5edd..41393da 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -22,17 +22,17 @@ set(PROJECT_SOURCES widget/widget-loader.cpp widget/widget-loader.h widget/widget-metadata.cpp widget/widget-metadata.h widget/widget-content.cpp widget/widget-content.h + widget/widget-container.cpp widget/widget-container.h widget-ui/widget-item.cpp widget-ui/widget-item.h - widget-ui/widget-item-engine.cpp - widget-ui/widget-item-engine.h - widget-ui/widget-item-context.cpp - widget-ui/widget-item-context.h - widget-ui/widget-item-attached.cpp - widget-ui/widget-item-attached.h + widget-ui/widget-item-engine.cpp widget-ui/widget-item-engine.h + widget-ui/widget-item-context.cpp widget-ui/widget-item-context.h + widget-ui/widget-item-attached.cpp widget-ui/widget-item-attached.h view/shared-engine-view.h view/shared-engine-view.cpp config/config.h config/config.cpp config/ini-config.h config/ini-config.cpp config/json-config.h config/json-config.cpp + config/widget-config.cpp config/widget-config.h + config/widget-config-loader.cpp config/widget-config-loader.h ) set(HEADERS widget/widget.h widget/widget-interface.h) @@ -49,7 +49,7 @@ set(PC_INSTALL_DIR "/usr/lib/pkgconfig") target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ - $) + $) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/ukui-panel-framework-config.cmake.in" diff --git a/framework/config/CMakeLists.txt b/framework/config/CMakeLists.txt index 4b55caf..72c71ed 100644 --- a/framework/config/CMakeLists.txt +++ b/framework/config/CMakeLists.txt @@ -4,6 +4,8 @@ set(PROJECT_SOURCES config.h config.cpp ini-config.h ini-config.cpp json-config.h json-config.cpp + widget-config.cpp widget-config.h + widget-config-loader.cpp widget-config-loader.h ) add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES}) diff --git a/framework/config/config.h b/framework/config/config.h index 3e694ab..2b22f81 100644 --- a/framework/config/config.h +++ b/framework/config/config.h @@ -20,13 +20,13 @@ public: }; explicit Config(const QString &filename, QObject *parent = nullptr); - QString filename() const; - virtual Config::Type type() const = 0; + Q_INVOKABLE QString filename() const; + Q_INVOKABLE virtual Config::Type type() const = 0; - virtual QVariant getValue(const QString &key) const = 0; - virtual void setValue(const QString &key, QVariant &value) = 0; + Q_INVOKABLE virtual QVariant getValue(const QString &key) const = 0; + Q_INVOKABLE virtual void setValue(const QString &key, const QVariant &value) = 0; - virtual void forceSync() const = 0; + Q_INVOKABLE virtual void forceSync() const = 0; Q_SIGNALS: void configChanged(const QString &key); diff --git a/framework/config/ini-config.cpp b/framework/config/ini-config.cpp index ca54e4d..97efdb6 100644 --- a/framework/config/ini-config.cpp +++ b/framework/config/ini-config.cpp @@ -32,13 +32,13 @@ Config::Type IniConfig::type() const QVariant IniConfig::getValue(const QString &key) const { if (d->settings) { - return {}; + return d->settings->value(key); } - return d->settings->value(key); + return {}; } -void IniConfig::setValue(const QString &key, QVariant &value) +void IniConfig::setValue(const QString &key, const QVariant &value) { if (d->settings) { d->settings->setValue(key, value); diff --git a/framework/config/ini-config.h b/framework/config/ini-config.h index 89c234d..cc93022 100644 --- a/framework/config/ini-config.h +++ b/framework/config/ini-config.h @@ -19,7 +19,7 @@ public: Type type() const override; QVariant getValue(const QString &key) const override; - void setValue(const QString &key, QVariant &value) override; + void setValue(const QString &key, const QVariant &value) override; void forceSync() const override; diff --git a/framework/config/widget-config-loader.cpp b/framework/config/widget-config-loader.cpp new file mode 100644 index 0000000..7c4b9eb --- /dev/null +++ b/framework/config/widget-config-loader.cpp @@ -0,0 +1,135 @@ + + +#include "widget-config-loader.h" +#include +#include +#include +#include +#include +#include + +namespace UkuiPanel { + +class WidgetConfigLoaderPrivate +{ +public: + WidgetConfigLoaderPrivate() = default; + + QString appid; + QString containerId; + + // var + static QMap* > globalCache; + + // func + static bool hasContainer(const QString &container); + static QString globalAppid(); + static QString globalContainerId(); + static QString constructFileName(const QString &widgetId); + static QString constructFilePath(const QString &appid, const QString &containerId); + static QString rootConfigPath(); + static QString configPath(); +}; + +QMap* > WidgetConfigLoaderPrivate::globalCache = QMap* >(); + +bool WidgetConfigLoaderPrivate::hasContainer(const QString &container) +{ + return globalCache.contains(container); +} + +QString WidgetConfigLoaderPrivate::constructFileName(const QString &widgetId) +{ + return widgetId + QStringLiteral(".conf"); +} + +QString WidgetConfigLoaderPrivate::rootConfigPath() +{ + return constructFilePath(globalAppid(), globalContainerId()); +} + +QString WidgetConfigLoaderPrivate::globalAppid() +{ + return QStringLiteral("org.ukui"); +} + +QString WidgetConfigLoaderPrivate::globalContainerId() +{ + return QStringLiteral("widget-config-global"); +} + +QString WidgetConfigLoaderPrivate::constructFilePath(const QString &appid, const QString &containerId) +{ + return QString(QDir::homePath() + QStringLiteral("/.config/%1/%2/")).arg(appid, containerId); +} + +// ====== WidgetConfigLoader ====== // +WidgetConfigLoader::WidgetConfigLoader(const QString &appid, const QString &containerId) : d(new WidgetConfigLoaderPrivate) +{ + d->appid = appid; + d->containerId = containerId; +} + +WidgetConfig *WidgetConfigLoader::getConfig(const QString &widgetId) +{ + return WidgetConfigLoader::loadConfig(widgetId, d->containerId, d->appid); +} + +WidgetConfig * +WidgetConfigLoader::loadConfig(const QString &widgetId, const QString &containerId, const QString &appid) +{ + if (widgetId.isEmpty()) { + return nullptr; + } + + QString app = appid; + QString container = containerId; + if (appid.isEmpty() || containerId.isEmpty()) { + app = WidgetConfigLoaderPrivate::globalAppid(); + container = WidgetConfigLoaderPrivate::globalContainerId(); + } + + QString cacheKey = app + "-" + container; + if (WidgetConfigLoaderPrivate::hasContainer(cacheKey)) { + const QMap *map = WidgetConfigLoaderPrivate::globalCache.value(cacheKey); + if (map->contains(widgetId)) { + return map->value(widgetId); + } + } + + QString configPath = WidgetConfigLoaderPrivate::constructFilePath(app, container); + if (!QFile::exists(configPath)) { + QDir().mkpath(configPath); + } + + // not create. + QString filename = configPath + WidgetConfigLoaderPrivate::constructFileName(widgetId); +// QFile f(filename); +// if (!f.exists()) { +// f.open(QFile::WriteOnly); +// f.close(); +// } + + auto widgetConfig = new WidgetConfig(filename); + if (WidgetConfigLoaderPrivate::hasContainer(cacheKey)) { + WidgetConfigLoaderPrivate::globalCache.value(cacheKey)->insert(widgetId, widgetConfig); + } else { + auto map = new QMap; + map->insert(widgetId, widgetConfig); + WidgetConfigLoaderPrivate::globalCache.insert(cacheKey, map); + } + + return widgetConfig; +} + +QString WidgetConfigLoader::configFileName(const QString &widgetId) +{ + return WidgetConfigLoaderPrivate::constructFileName(widgetId); +} + +QString WidgetConfigLoader::getConfigFileName(const QString &widgetId) +{ + return WidgetConfigLoaderPrivate::constructFilePath(d->appid, d->containerId) + WidgetConfigLoader::configFileName(widgetId); +} + +} // UkuiPanel diff --git a/framework/config/widget-config-loader.h b/framework/config/widget-config-loader.h new file mode 100644 index 0000000..631a68f --- /dev/null +++ b/framework/config/widget-config-loader.h @@ -0,0 +1,29 @@ + + +#ifndef UKUI_PANEL_WIDGET_CONFIG_LOADER_H +#define UKUI_PANEL_WIDGET_CONFIG_LOADER_H + +#include +#include "widget-config.h" + +namespace UkuiPanel { + +class WidgetConfigLoaderPrivate; + +class WidgetConfigLoader +{ +public: + static QString configFileName(const QString &widgetId); + static WidgetConfig *loadConfig(const QString &widgetId, const QString &containerId = QString(), const QString &appid = QString()); + + explicit WidgetConfigLoader(const QString &appid, const QString &containerId); + WidgetConfig *getConfig(const QString &widgetId); + QString getConfigFileName(const QString &widgetId); + +private: + WidgetConfigLoaderPrivate *d {nullptr}; +}; + +} // UkuiPanel + +#endif //UKUI_PANEL_WIDGET_CONFIG_LOADER_H diff --git a/framework/config/widget-config.cpp b/framework/config/widget-config.cpp new file mode 100644 index 0000000..376ee0c --- /dev/null +++ b/framework/config/widget-config.cpp @@ -0,0 +1,12 @@ + + +#include "widget-config.h" + +namespace UkuiPanel { + +WidgetConfig::WidgetConfig(const QString &widgetId, QObject *parent) : IniConfig(widgetId, parent) +{ + +} + +} // UkuiPanel diff --git a/framework/config/widget-config.h b/framework/config/widget-config.h new file mode 100644 index 0000000..477c295 --- /dev/null +++ b/framework/config/widget-config.h @@ -0,0 +1,24 @@ + +#ifndef UKUI_PANEL_WIDGET_CONFIG_H +#define UKUI_PANEL_WIDGET_CONFIG_H + +#include "ini-config.h" + +namespace UkuiPanel { + +class WidgetConfigLoader; + +class WidgetConfig : public IniConfig +{ + Q_OBJECT + friend class WidgetConfigLoader; +public: + WidgetConfig() = delete; + +private: + explicit WidgetConfig(const QString &file, QObject *parent = nullptr); +}; + +} // UkuiPanel + +#endif //UKUI_PANEL_WIDGET_CONFIG_H diff --git a/framework/test/CMakeLists.txt b/framework/test/CMakeLists.txt index 654aa0d..8b3aca7 100644 --- a/framework/test/CMakeLists.txt +++ b/framework/test/CMakeLists.txt @@ -2,6 +2,7 @@ project(framework-test VERSION 4.1 LANGUAGES CXX) include_directories(../widget-ui) include_directories(../widget) +include_directories(../config) set(QRC_FILES qml.qrc) set(PROJECT_SOURCES diff --git a/framework/test/main.cpp b/framework/test/main.cpp index a56b167..66df9e2 100644 --- a/framework/test/main.cpp +++ b/framework/test/main.cpp @@ -7,6 +7,8 @@ #include "widget.h" #include "widget-loader.h" #include "widget-item.h" +#include "widget-config-loader.h" +#include "widget-container.h" int main(int argc, char *argv[]) { @@ -16,7 +18,7 @@ int main(int argc, char *argv[]) // widgets << "org.ukui.panel.taskmanager"; // widgets << "org.ukui.panel.test"; widgets << "org.ukui.menu.starter"; - widgets << "org.ukui.panel.widget.test"; +// widgets << "org.ukui.panel.widget.test"; auto view = new QQuickView; view->setResizeMode(QQuickView::SizeRootObjectToView); @@ -24,6 +26,7 @@ int main(int argc, char *argv[]) view->setColor(QColor(Qt::transparent)); view->setSource(QUrl("qrc:///main.qml")); + UkuiPanel::WidgetContainer container("ukui-panel", "panel-0"); QList widgetList; UkuiPanel::WidgetLoader loader; for (const auto &id : widgets) { @@ -31,6 +34,7 @@ int main(int argc, char *argv[]) if (!widget) { continue; } + container.addWidget(widget); widgetList << widget; UkuiPanel::WidgetItem *widgetItem = UkuiPanel::WidgetItem::itemForWidget(widget); diff --git a/framework/widget-ui/CMakeLists.txt b/framework/widget-ui/CMakeLists.txt index 7ac19a1..acdf03a 100644 --- a/framework/widget-ui/CMakeLists.txt +++ b/framework/widget-ui/CMakeLists.txt @@ -1,7 +1,5 @@ project(framework-widget-ui VERSION 4.1 LANGUAGES CXX) -include_directories(../widget) - set(PROJECT_SOURCES widget-item.cpp widget-item.h widget-item-engine.cpp diff --git a/framework/widget/CMakeLists.txt b/framework/widget/CMakeLists.txt index 59bfe61..8f43a2c 100644 --- a/framework/widget/CMakeLists.txt +++ b/framework/widget/CMakeLists.txt @@ -5,6 +5,7 @@ set(PROJECT_SOURCES widget-loader.cpp widget-loader.h widget-metadata.cpp widget-metadata.h widget-content.cpp widget-content.h + widget-container.cpp widget-container.h ) add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES}) diff --git a/framework/widget/widget-container.cpp b/framework/widget/widget-container.cpp new file mode 100644 index 0000000..a08885d --- /dev/null +++ b/framework/widget/widget-container.cpp @@ -0,0 +1,161 @@ +// +// Created by hxf on 23-9-18. +// + +#include "widget-container.h" +#include "widget.h" +#include + +namespace UkuiPanel { + +class WidgetContainerPrivate +{ +public: + WidgetContainerPrivate() = default; + + // prop + QString appid; + QString containerId; + bool visible {false}; + QRect geometry; + QMargins margins {0, 0, 0, 0}; + + WidgetContainer::Orientation orientation {WidgetContainer::LeftToRight}; + + // widgets + QVector widgets; +}; + +WidgetContainer::WidgetContainer(const QString &appid, const QString &containerId, QObject *parent) : QObject(parent), d(new WidgetContainerPrivate) +{ + d->appid = appid; + d->containerId = containerId; + qRegisterMetaType(); + qRegisterMetaType("WidgetContainer*"); +} + +QString WidgetContainer::appid() const +{ + return d->appid; +} + +QString WidgetContainer::containerId() const +{ + return d->containerId; +} + +void WidgetContainer::addWidget(int index, Widget *widget) +{ + if (!widget) { + return; + } + + int idx; + int maxIdx = d->widgets.size(); + + if (index < 0 || index > maxIdx) { + idx = maxIdx; + } else { + idx = index; + } + + d->widgets.insert(idx, widget); + widget->setContainer(this); + Q_EMIT widgetAdded(widget->id()); +} + +void WidgetContainer::addWidget(Widget *widget) +{ + addWidget(-1, widget); +} + +void WidgetContainer::removeWidget(Widget *widget) +{ + if (!widget) { + return; + } + + int idx = -1; + for (int i = 0; i < d->widgets.size(); ++i) { + if (d->widgets.at(i) == widget) { + idx = i; + break; + } + } + + if (idx > 0) { + removeWidget(idx); + } +} + +void WidgetContainer::removeWidget(int index) +{ + if (index < 0 || index > (d->widgets.size() - 1)) { + return; + } + + Widget *widget = d->widgets.takeAt(index); + widget->setContainer(nullptr); + Q_EMIT widgetRemoved(widget->id()); +} + +WidgetContainer::Orientation WidgetContainer::orientation() const +{ + return d->orientation; +} + +void WidgetContainer::setOrientation(WidgetContainer::Orientation o) +{ + if (d->orientation == o) { + return; + } + + d->orientation = o; + Q_EMIT orientationChanged(); +} + +bool WidgetContainer::visible() const +{ + return false; +} + +void WidgetContainer::setVisible(bool visible) +{ + if (d->visible == visible) { + return; + } + + d->visible = visible; +} + +QRect WidgetContainer::geometry() const +{ + return d->geometry; +} + +void WidgetContainer::setGeometry(QRect geometry) +{ + if (d->geometry == geometry) { + return; + } + + d->geometry = geometry; + Q_EMIT geometryChanged(); +} + +QMargins WidgetContainer::margins() const +{ + return d->margins; +} + +void WidgetContainer::setMargins(QMargins margins) +{ + if (d->margins == margins) { + return; + } + + d->margins = margins; + Q_EMIT marginsChanged(); +} + +} // UkuiPanel diff --git a/framework/widget/widget-container.h b/framework/widget/widget-container.h new file mode 100644 index 0000000..d8b015a --- /dev/null +++ b/framework/widget/widget-container.h @@ -0,0 +1,75 @@ +// +// Created by hxf on 23-9-18. +// + +#ifndef UKUI_PANEL_WIDGET_CONTAINER_H +#define UKUI_PANEL_WIDGET_CONTAINER_H + +#include +#include +#include +#include + +namespace UkuiPanel { + +class Widget; +class WidgetContainerPrivate; + +class WidgetContainer : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString appid READ appid CONSTANT FINAL) + Q_PROPERTY(QString containerId READ containerId CONSTANT FINAL) + Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged FINAL) + Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged FINAL) + Q_PROPERTY(QMargins margins READ margins NOTIFY marginsChanged FINAL) + Q_PROPERTY(WidgetContainer::Orientation orientation READ orientation NOTIFY orientationChanged FINAL) +public: + enum Orientation { + LeftToRight, + TopToBottom + }; + Q_ENUM(Orientation) + + explicit WidgetContainer(const QString &appid, const QString &containerId, QObject *parent = nullptr); + + // prop + QString appid() const; + QString containerId() const; + + bool visible() const; + void setVisible(bool visible); + + QRect geometry() const; + void setGeometry(QRect geometry); + + QMargins margins() const; + void setMargins(QMargins margins); + + WidgetContainer::Orientation orientation() const; + void setOrientation(WidgetContainer::Orientation o); + + // widgets + void addWidget(Widget *widget); + void addWidget(int index, Widget *widget); + + void removeWidget(int index); + void removeWidget(Widget *widget); + +Q_SIGNALS: + void widgetAdded(const QString &id); + void widgetRemoved(const QString &id); + void visibleChanged(); + void geometryChanged(); + void marginsChanged(); + void orientationChanged(); + +private: + WidgetContainerPrivate *d {nullptr}; +}; + +} // UkuiPanel + +Q_DECLARE_METATYPE(UkuiPanel::WidgetContainer::Orientation) + +#endif //UKUI_PANEL_WIDGET_CONTAINER_H diff --git a/framework/widget/widget-metadata.cpp b/framework/widget/widget-metadata.cpp index f0049e9..cbb5f82 100644 --- a/framework/widget/widget-metadata.cpp +++ b/framework/widget/widget-metadata.cpp @@ -186,3 +186,13 @@ QVariantMap WidgetMetadata::contents() const return value.toObject().toVariantMap(); } + +QVariantMap WidgetMetadata::config() const +{ + QJsonValue value = m_object.value(QLatin1String("Config")); + if (value.type() == QJsonValue::Undefined || value.type() != QJsonValue::Object) { + return {}; + } + + return value.toObject().toVariantMap(); +} diff --git a/framework/widget/widget-metadata.h b/framework/widget/widget-metadata.h index 4d0c194..8cf7483 100644 --- a/framework/widget/widget-metadata.h +++ b/framework/widget/widget-metadata.h @@ -30,6 +30,7 @@ public: QString description() const; QVariantList authors() const; QVariantMap contents() const; + QVariantMap config() const; private: void init(); diff --git a/framework/widget/widget.cpp b/framework/widget/widget.cpp index 8f18f98..3da6ee9 100644 --- a/framework/widget/widget.cpp +++ b/framework/widget/widget.cpp @@ -1,10 +1,10 @@ #include "widget.h" - +#include "widget-container.h" +#include "widget-config-loader.h" #include -#include using namespace UkuiPanel; @@ -24,6 +24,8 @@ public: WidgetContent content; WidgetMetadata metaData; + + WidgetContainer *container {nullptr}; }; WidgetPrivate::WidgetPrivate(const WidgetMetadata &m) @@ -48,12 +50,12 @@ WidgetPrivate::WidgetPrivate(const WidgetMetadata &m) */ Widget::Widget(const WidgetMetadata& metaData, QObject *parent) : QObject(parent), d(new WidgetPrivate(metaData)) { - qDebug() << "id:" << metaData.id(); - qDebug() << "name:" << metaData.name(); - qDebug() << "authors:" << metaData.authors(); - qDebug() << "description:" << metaData.description(); +// qDebug() << "load widget, id:" << metaData.id() << "name:" << metaData.name() +// << "authors:" << metaData.authors() << "description:" << metaData.description(); + qRegisterMetaType("WidgetConfig*"); } + Widget::~Widget() { if (d) { @@ -155,3 +157,30 @@ QString Widget::uiError() const { return d->uiError; } + +// TODO: init config +WidgetConfig *Widget::config() const +{ + if (!d->container) { + return nullptr; + } + + QVariantMap m = d->metaData.config(); + if (m.isEmpty()) { + return nullptr; + } + + if (m.value("IsGlobal").toBool()) { + return WidgetConfigLoader::loadConfig(d->metaData.id()); + } + + return WidgetConfigLoader::loadConfig(d->metaData.id(), d->container->containerId(), d->container->appid()); +} + +void Widget::setContainer(WidgetContainer *container) +{ + WidgetContainer *old = d->container; + d->container = container; + + Q_EMIT containerChanged(old ? old->containerId() : "", d->container ? d->container->containerId() : ""); +} diff --git a/framework/widget/widget.h b/framework/widget/widget.h index 1534304..fb75a72 100644 --- a/framework/widget/widget.h +++ b/framework/widget/widget.h @@ -8,7 +8,9 @@ namespace UkuiPanel { +class WidgetConfig; class WidgetPrivate; +class WidgetContainer; /** * 一个"Widget"。 @@ -27,6 +29,7 @@ class Widget : public QObject Q_PROPERTY(QString bugReport READ bugReport CONSTANT FINAL) Q_PROPERTY(QString description READ description CONSTANT FINAL) Q_PROPERTY(QVariantList authors READ authors CONSTANT FINAL) + Q_PROPERTY(WidgetConfig *config READ config CONSTANT FINAL) public: explicit Widget(const WidgetMetadata& metaData, QObject *parent=nullptr); ~Widget() override; @@ -58,6 +61,11 @@ public: QString uiError() const; bool hasUiError() const; + WidgetConfig *config() const; + +private: + void setContainer(WidgetContainer *container); + Q_SIGNALS: void iconChanged(); void nameChanged(); @@ -66,9 +74,11 @@ Q_SIGNALS: // widget生命周期信号 void widgetDeleted(Widget *widget); + void containerChanged(const QString &oldId, const QString &newId); private: WidgetPrivate *d {nullptr}; + friend class WidgetContainer; }; } // UkuiPanel