forked from openkylin/ukui-panel
feat(panel): 增加插件排序和动态卸载功能
This commit is contained in:
parent
58b9baeaef
commit
08d3d9429f
|
@ -48,6 +48,8 @@ set(PROJECT_SOURCES
|
|||
src/general-config-define.h
|
||||
src/screens-manager.cpp
|
||||
src/screens-manager.h
|
||||
src/view/widget-model.cpp
|
||||
src/view/widget-model.h
|
||||
)
|
||||
qt5_generate_repc(PROJECT_SOURCES src/remote-config.rep SOURCE)
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.ukui.quick.widgets 1.0
|
|||
import org.ukui.quick.container 1.0
|
||||
import org.ukui.quick.items 1.0
|
||||
import org.ukui.quick.platform 1.0
|
||||
import org.ukui.panel.impl 1.0 as Panel
|
||||
|
||||
WidgetContainerItem {
|
||||
id: containerItem
|
||||
|
@ -40,7 +41,11 @@ WidgetContainerItem {
|
|||
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: containerItem.widgetItemModel
|
||||
model: Panel.WidgetSortModel {
|
||||
// TODO: use config
|
||||
widgetOrder: widgetsOrder
|
||||
sourceModel: containerItem.widgetItemModel
|
||||
}
|
||||
delegate: widgetLoaderComponent
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <config-loader.h>
|
||||
#include <widget-container-item.h>
|
||||
#include "general-config-define.h"
|
||||
#include "widget-model.h"
|
||||
|
||||
#define DEFAULT_PANEL_SIZE 48
|
||||
static const QString WIDGETS_KEY = QStringLiteral("widgets");
|
||||
|
@ -46,6 +47,9 @@ Panel::Panel(Screen *screen, const QString &id, QWindow *parent)
|
|||
m_id(id),
|
||||
m_container(new UkuiQuick::WidgetContainer(QStringLiteral("ukui-panel"), id, this))
|
||||
{
|
||||
qRegisterMetaType<QList<int>>();
|
||||
qmlRegisterType<UkuiPanel::WidgetSortModel>("org.ukui.panel.impl", 1, 0, "WidgetSortModel");
|
||||
|
||||
setColor(Qt::transparent);
|
||||
setFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
|
||||
|
||||
|
@ -61,6 +65,7 @@ Panel::Panel(Screen *screen, const QString &id, QWindow *parent)
|
|||
// items
|
||||
loadContainerItem();
|
||||
initWidgets();
|
||||
loadActions();
|
||||
|
||||
KWindowEffects::enableBlurBehind(this);
|
||||
kdk::WindowManager::setSkipSwitcher(this, true);
|
||||
|
@ -147,8 +152,6 @@ void Panel::initContainer()
|
|||
|
||||
// position
|
||||
setPosition(UkuiQuick::Types::Pos(map.value(QStringLiteral("position"))));
|
||||
|
||||
loadActions();
|
||||
}
|
||||
|
||||
void Panel::setPosition(UkuiQuick::Types::Pos position)
|
||||
|
@ -199,18 +202,101 @@ void Panel::loadContainerItem()
|
|||
setSource(QUrl("qrc:///Container.qml"));
|
||||
}
|
||||
|
||||
void Panel::initWidgets()
|
||||
void Panel::loadWidgetsConfig()
|
||||
{
|
||||
QStringList loadingWidgets = DEFAULT_LOADING_WIDGETS;
|
||||
QVariant widgets = m_config->getValue(WIDGETS_KEY);
|
||||
if(widgets.isNull()) {
|
||||
m_config->setValue(WIDGETS_KEY, DEFAULT_LOADING_WIDGETS);
|
||||
QVariant widgets = m_config->getValue(QStringLiteral("widgets"));
|
||||
QStringList widgetList, widgetsOrder;
|
||||
|
||||
if (widgets.isNull()) {
|
||||
for (const auto &widget : DEFAULT_LOADING_WIDGETS) {
|
||||
int instanceId = widgetList.size();
|
||||
widgetsOrder.append(QString::number(instanceId));
|
||||
widgetList.append(widget + QStringLiteral(":") + widgetsOrder.last());
|
||||
|
||||
m_widgetMap.insert(instanceId, widget);
|
||||
m_widgetsOrder.append(instanceId);
|
||||
}
|
||||
|
||||
m_config->setValue(QStringLiteral("widgets"), widgetList);
|
||||
m_config->setValue(QStringLiteral("widgetsOrder"), widgetsOrder);
|
||||
|
||||
} else {
|
||||
loadingWidgets = widgets.toStringList();
|
||||
widgetList = widgets.toStringList();
|
||||
widgetsOrder = m_config->getValue(QStringLiteral("widgetsOrder")).toStringList();
|
||||
|
||||
bool ok = false;
|
||||
for (const auto &item : widgetList) {
|
||||
QStringList tmp = item.split(QStringLiteral(":"));
|
||||
if (tmp.size() != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int instanceId = tmp.last().toInt(&ok);
|
||||
if (ok) {
|
||||
m_widgetMap.insert(instanceId, tmp.first());
|
||||
if (!widgetsOrder.contains(tmp.last())) {
|
||||
widgetsOrder << tmp.last();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : widgetsOrder) {
|
||||
int instanceId = item.toInt(&ok);
|
||||
if (ok) {
|
||||
m_widgetsOrder << instanceId;
|
||||
}
|
||||
}
|
||||
|
||||
m_config->setValue(QStringLiteral("widgetsOrder"), widgetsOrder);
|
||||
}
|
||||
|
||||
for (const auto &id : loadingWidgets) {
|
||||
m_container->addWidget(id);
|
||||
// 禁用列表
|
||||
m_disabledWidgets = m_config->getValue(QStringLiteral("disabledWidgets")).toStringList();
|
||||
|
||||
// widgetsOrder
|
||||
rootContext()->setContextProperty("widgetsOrder", QVariant::fromValue(m_widgetsOrder));
|
||||
}
|
||||
|
||||
void Panel::initWidgets()
|
||||
{
|
||||
loadWidgetsConfig();
|
||||
|
||||
// 加载Widget
|
||||
QMapIterator<int, QString> iterator(m_widgetMap);
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
if (m_disabledWidgets.contains(iterator.value())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_container->addWidget(iterator.value(), iterator.key());
|
||||
}
|
||||
|
||||
|
||||
// 卸载插件选项
|
||||
QStringList canRemove;
|
||||
canRemove << QStringLiteral("org.ukui.panel.search");
|
||||
canRemove << QStringLiteral("org.ukui.panel.taskView");
|
||||
|
||||
QStringList widgets = m_widgetMap.values();
|
||||
widgets.removeDuplicates();
|
||||
for (const auto &wid : widgets) {
|
||||
if (canRemove.contains(wid)) {
|
||||
UkuiQuick::WidgetMetadata metadata = UkuiQuick::WidgetContainer::widgetLoader().loadMetadata(wid);
|
||||
if (!metadata.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto action = new QAction(metadata.name());
|
||||
action->setProperty("widget", wid);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(!m_disabledWidgets.contains(wid));
|
||||
|
||||
m_widgetActions << action;
|
||||
connect(action, &QAction::triggered, this, [this, action] {
|
||||
widgetActionTriggered(action);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,18 +416,56 @@ void Panel::setPanelPolicy(GeneralConfigDefine::PanelSizePolicy sizePolicy)
|
|||
}
|
||||
}
|
||||
|
||||
void Panel::widgetActionTriggered(const QAction *action)
|
||||
{
|
||||
QString id = action->property("widget").toString();
|
||||
if (id.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (action->isChecked()) {
|
||||
// 启用
|
||||
m_disabledWidgets.removeAll(id);
|
||||
|
||||
// 重新激活全部widget
|
||||
QMapIterator<int, QString> iterator(m_widgetMap);
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
if (iterator.value() == id) {
|
||||
container()->addWidget(iterator.value(), iterator.key());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 禁用
|
||||
m_disabledWidgets.append(id);
|
||||
|
||||
// 卸载全部widget
|
||||
QVector<UkuiQuick::Widget *> widgets = m_container->widgets();
|
||||
for (const auto &item : widgets) {
|
||||
if (item->id() == id) {
|
||||
m_container->removeWidget(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_config->setValue(QStringLiteral("disabledWidgets"), m_disabledWidgets);
|
||||
}
|
||||
|
||||
void Panel::loadActions()
|
||||
{
|
||||
QList<QAction *> actions;
|
||||
// widget操作
|
||||
actions << m_widgetActions;
|
||||
|
||||
// 分割线
|
||||
auto *separator = new QAction(this);
|
||||
separator->setSeparator(true);
|
||||
actions << separator;
|
||||
|
||||
// actions
|
||||
initSizeAction();
|
||||
initPositionAction();
|
||||
|
||||
// auto *separator = new QAction(this);
|
||||
// separator->setSeparator(true);
|
||||
// actions << separator;
|
||||
|
||||
// 调整大小
|
||||
actions << m_sizeAction;
|
||||
// 调整位置
|
||||
|
|
|
@ -30,9 +30,13 @@ private Q_SLOTS:
|
|||
void setPanelSize(int size);
|
||||
void setPanelPolicy(GeneralConfigDefine::PanelSizePolicy sizePolicy);
|
||||
|
||||
// widget opt
|
||||
void widgetActionTriggered(const QAction *);
|
||||
|
||||
private:
|
||||
void initContainer();
|
||||
void loadContainerItem();
|
||||
void loadWidgetsConfig();
|
||||
void initWidgets();
|
||||
void updateGeometry();
|
||||
void refreshRect();
|
||||
|
@ -52,8 +56,14 @@ private:
|
|||
|
||||
QAction *m_sizeAction {nullptr};
|
||||
QAction *m_positionAction {nullptr};
|
||||
QList<QAction*> m_widgetActions;
|
||||
QMap<int, QString> m_widgetMap;
|
||||
QStringList m_disabledWidgets;
|
||||
QList<int> m_widgetsOrder;
|
||||
};
|
||||
|
||||
} // UkuiPanel
|
||||
|
||||
Q_DECLARE_METATYPE(QList<int>)
|
||||
|
||||
#endif //UKUI_PANEL_PANEL_H
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2024, KylinSoft Co., Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: hxf <hewenfei@kylinos.cn>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "widget-model.h"
|
||||
|
||||
#include <widget.h>
|
||||
#include <widget-item.h>
|
||||
#include <widget-container-item.h>
|
||||
|
||||
namespace UkuiPanel {
|
||||
|
||||
WidgetSortModel::WidgetSortModel(QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool WidgetSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
{
|
||||
auto leftItem = source_left.data(UkuiQuick::WidgetItemModel::WidgetItemRole).value<UkuiQuick::WidgetItem *>();
|
||||
auto rightItem = source_right.data(UkuiQuick::WidgetItemModel::WidgetItemRole).value<UkuiQuick::WidgetItem *>();
|
||||
|
||||
int lIdx = m_widgetOrder.indexOf(leftItem->widget()->instanceId());
|
||||
int rIdx = m_widgetOrder.indexOf(rightItem->widget()->instanceId());
|
||||
|
||||
if (lIdx < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lIdx < rIdx;
|
||||
}
|
||||
|
||||
bool WidgetSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
void WidgetSortModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
QSortFilterProxyModel::setSourceModel(sourceModel);
|
||||
QSortFilterProxyModel::sort(0);
|
||||
}
|
||||
|
||||
QList<int> WidgetSortModel::widgetOrder() const
|
||||
{
|
||||
return m_widgetOrder;
|
||||
}
|
||||
|
||||
void WidgetSortModel::setWidgetOrder(const QList<int> &order)
|
||||
{
|
||||
m_widgetOrder = order;
|
||||
invalidate();
|
||||
|
||||
Q_EMIT widgetOrderChanged();
|
||||
}
|
||||
|
||||
} // UkuiPanel
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2024, KylinSoft Co., Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: hxf <hewenfei@kylinos.cn>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UKUI_PANEL_WIDGET_MODEL_H
|
||||
#define UKUI_PANEL_WIDGET_MODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStringList>
|
||||
#include <QPair>
|
||||
#include <QPersistentModelIndex>
|
||||
|
||||
namespace UkuiQuick{
|
||||
class WidgetItem;
|
||||
}
|
||||
|
||||
namespace UkuiPanel {
|
||||
|
||||
class WidgetSortModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QList<int> widgetOrder READ widgetOrder WRITE setWidgetOrder NOTIFY widgetOrderChanged)
|
||||
public:
|
||||
explicit WidgetSortModel(QObject *parent = nullptr);
|
||||
|
||||
QList<int> widgetOrder() const;
|
||||
void setWidgetOrder(const QList<int> &order);
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
protected:
|
||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void widgetOrderChanged();
|
||||
|
||||
private:
|
||||
QList<int> m_widgetOrder;
|
||||
};
|
||||
|
||||
} // UkuiPanel
|
||||
|
||||
#endif //UKUI_PANEL_WIDGET_MODEL_H
|
Loading…
Reference in New Issue