dde-dock/plugins/dcc-dock-plugin/module_widget.cpp
chenjun a20006aa2b
fix: 按UI设计要求调整插件管理标题与说明文字间距 (#728)
按UI设计要求调整插件管理标题与说明文字间距

Log: 按UI设计要求调整插件管理标题与说明文字间距
Bug: https://pms.uniontech.com/bug-view-173635.html
Influence: 按UI设计要求调整插件管理标题与说明文字间距
2022-11-29 10:05:25 +08:00

438 lines
19 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "module_widget.h"
#include "utils.h"
#include <widgets/comboxwidget.h>
#include <widgets/titledslideritem.h>
#include <widgets/dccslider.h>
#include <widgets/titlelabel.h>
#include <DSlider>
#include <DListView>
#include <DTipLabel>
#include <QApplication>
#include <QScreen>
#include <QLabel>
#include <QVBoxLayout>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusError>
#include <QMap>
#include <QScrollArea>
#include <QScroller>
#include <QComboBox>
#include <QTimer>
DWIDGET_USE_NAMESPACE
enum DisplayMode {
Fashion = 0,
Efficient = 1,
};
enum HideMode {
KeepShowing = 0,
KeepHidden = 1,
SmartHide = 3,
};
enum Position {
Top = 0,
Right = 1,
Bottom = 2,
Left = 3,
};
ModuleWidget::ModuleWidget(QWidget *parent)
: QScrollArea(parent)
, m_modeComboxWidget(new ComboxWidget(this))
, m_positionComboxWidget(new ComboxWidget(this))
, m_stateComboxWidget(new ComboxWidget(this))
, m_screenSettingComboxWidget(new ComboxWidget(this))
, m_pluginTips(new DTipLabel(tr("Select which icons appear in the Dock"), this))
, m_pluginView(new DListView(this))
, m_pluginModel(new QStandardItemModel(this))
, m_daemonDockInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this))
, m_dockInter(new DBusInter("com.deepin.dde.Dock", "/com/deepin/dde/Dock", QDBusConnection::sessionBus(), this))
, m_dconfigWatcher(new ConfigWatcher("org.deepin.dde.control-center", "org.deepin.dde.dock.plugin", this))
, m_sliderPressed(false)
{
//~ contents_path /personalization/Dock
//~ child_page Dock
m_pluginAreaTitle = new TitleLabel(tr("Plugin Area"), this);
//~ contents_path /personalization/Dock
//~ child_page Dock
m_sizeSlider = new TitledSliderItem(tr("Size"), this);
//~ contents_path /personalization/Dock
//~ child_page Dock
m_screenSettingTitle = new TitleLabel(tr("Multiple Displays"), this);
// 异步,否则频繁调用可能会导致卡顿
m_daemonDockInter->setSync(false);
initUI();
connect(m_dockInter, &DBusInter::pluginVisibleChanged, this, &ModuleWidget::updateItemCheckStatus);
}
ModuleWidget::~ModuleWidget()
{
}
void ModuleWidget::initUI()
{
setBackgroundRole(QPalette::Base);
setFrameShape(QFrame::NoFrame);
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins(10, 10, 10, 10);
layout->setSpacing(0);
static QMap<QString, int> g_modeMap = {{tr("Fashion mode"), Fashion}
, {tr("Efficient mode"), Efficient}};
// 模式
if (Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "modeVisible", true).toBool()) {
//~ contents_path /personalization/Dock
//~ child_page Dock
m_modeComboxWidget->setTitle(tr("Mode"));
m_modeComboxWidget->addBackground();
m_modeComboxWidget->setComboxOption(QStringList() << tr("Fashion mode") << tr("Efficient mode"));
m_modeComboxWidget->setCurrentText(g_modeMap.key(m_daemonDockInter->displayMode()));
connect(m_modeComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) {
m_daemonDockInter->setDisplayMode(g_modeMap.value(text));
});
connect(m_daemonDockInter, &DBusDock::DisplayModeChanged, this, [ = ] (int value) {
DisplayMode mode = static_cast<DisplayMode>(value);
if (g_modeMap.key(mode) == m_modeComboxWidget->comboBox()->currentText())
return;
m_modeComboxWidget->setCurrentText(g_modeMap.key(mode));
});
layout->addWidget(m_modeComboxWidget);
m_dconfigWatcher->bind("dockModel", m_modeComboxWidget);
} else {
m_modeComboxWidget->setVisible(false);
}
if (Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "locationVisible", true).toBool()) {
// 位置
static QMap<QString, int> g_positionMap = {{tr("Top"), Top}
, {tr("Bottom"), Bottom}
, {tr("Left"), Left}
, {tr("Right"), Right}};
//~ contents_path /personalization/Dock
//~ child_page Dock
m_positionComboxWidget->setTitle(tr("Location"));
m_positionComboxWidget->addBackground();
m_positionComboxWidget->setComboxOption(QStringList() << tr("Top") << tr("Bottom") << tr("Left") << tr("Right"));
m_positionComboxWidget->setCurrentText(g_positionMap.key(m_daemonDockInter->position()));
connect(m_positionComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) {
m_daemonDockInter->setPosition(g_positionMap.value(text));
});
connect(m_daemonDockInter, &DBusDock::PositionChanged, this, [ = ] (int position) {
Position pos = static_cast<Position>(position);
if (g_positionMap.key(pos) == m_positionComboxWidget->comboBox()->currentText())
return;
m_positionComboxWidget->setCurrentText(g_positionMap.key(pos));
});
layout->addSpacing(10);
layout->addWidget(m_positionComboxWidget);
m_dconfigWatcher->bind("dockLocation", m_positionComboxWidget);
} else {
m_positionComboxWidget->setVisible(false);
}
// 状态
if (Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "statusVisible", true).toBool()) {
static QMap<QString, int> g_stateMap = {{tr("Keep shown"), KeepShowing}
, {tr("Keep hidden"), KeepHidden}
, {tr("Smart hide"), SmartHide}};
//~ contents_path /personalization/Dock
//~ child_page Dock
m_stateComboxWidget->setTitle(tr("Status"));
m_stateComboxWidget->addBackground();
m_stateComboxWidget->setComboxOption(QStringList() << tr("Keep shown") << tr("Keep hidden") << tr("Smart hide"));
m_stateComboxWidget->setCurrentText(g_stateMap.key(m_daemonDockInter->hideMode()));
connect(m_stateComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) {
m_daemonDockInter->setHideMode(g_stateMap.value(text));
});
connect(m_daemonDockInter, &DBusDock::HideModeChanged, this, [ = ] (int value) {
HideMode mode = static_cast<HideMode>(value);
if (g_stateMap.key(mode) == m_stateComboxWidget->comboBox()->currentText())
return;
m_stateComboxWidget->setCurrentText(g_stateMap.key(mode));
});
layout->addSpacing(10);
layout->addWidget(m_stateComboxWidget);
m_dconfigWatcher->bind("dockState", m_stateComboxWidget);
} else {
m_stateComboxWidget->setVisible(false);
}
// 高度调整控件
m_sizeSlider->addBackground();
m_sizeSlider->slider()->setRange(40, 100);
QStringList ranges;
ranges << tr("Small") << "" << tr("Large");
m_sizeSlider->setAnnotations(ranges);
connect(m_daemonDockInter, &DBusDock::DisplayModeChanged, this, &ModuleWidget::updateSliderValue);
connect(m_daemonDockInter, &DBusDock::WindowSizeFashionChanged, this, &ModuleWidget::updateSliderValue);
connect(m_daemonDockInter, &DBusDock::WindowSizeEfficientChanged, this, &ModuleWidget::updateSliderValue);
connect(m_sizeSlider->slider(), &DSlider::sliderMoved, m_sizeSlider->slider(), &DSlider::valueChanged);
connect(m_sizeSlider->slider(), &DSlider::valueChanged, this, [ = ] (int value) {
m_dockInter->resizeDock(value, true);
});
connect(m_sizeSlider->slider(), &DSlider::sliderPressed, m_dockInter, [ = ] {
m_daemonDockInter->blockSignals(true);
m_sliderPressed = true;
});
connect(m_sizeSlider->slider(), &DSlider::sliderReleased, m_dockInter, [ = ] {
m_daemonDockInter->blockSignals(false);
m_sliderPressed = false;
// 松开手后通知dock拖拽状态接触
QTimer::singleShot(0, this, [ = ] {
int offset = m_sizeSlider->slider()->value();
m_dockInter->resizeDock(offset, false);
});
});
updateSliderValue();
m_dconfigWatcher->bind("dockSize", m_sizeSlider);
layout->addSpacing(10);
layout->addWidget(m_sizeSlider);
// 多屏显示设置
if (QDBusConnection::sessionBus().interface()->isServiceRegistered("com.deepin.dde.Dock")
&& QApplication::screens().size() > 1
&& !isCopyMode()
&& Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "multiscreenVisible", true).toBool()) {
static QMap<QString, bool> g_screenSettingMap = {{tr("On screen where the cursor is"), false}
, {tr("Only on main screen"), true}};
layout->addSpacing(10);
layout->addWidget(m_screenSettingTitle);
m_screenSettingComboxWidget->setTitle(tr("Show Dock"));
m_screenSettingComboxWidget->addBackground();
m_screenSettingComboxWidget->setComboxOption(QStringList() << tr("On screen where the cursor is") << tr("Only on main screen"));
m_screenSettingComboxWidget->setCurrentText(g_screenSettingMap.key(m_dockInter->showInPrimary()));
connect(m_screenSettingComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) {
m_dockInter->setShowInPrimary(g_screenSettingMap.value(text));
});
connect(qApp, &QApplication::screenAdded, this, [ = ] {
m_screenSettingTitle->setVisible(qApp->screens().count() > 1);
m_screenSettingComboxWidget->setVisible(qApp->screens().count() > 1);
});
connect(qApp, &QApplication::screenRemoved, this, [ = ] {
m_screenSettingTitle->setVisible(qApp->screens().count() > 1);
m_screenSettingComboxWidget->setVisible(qApp->screens().count() > 1);
});
// 这里不会生效,但实际场景中也不存在有其他可配置的地方,可以不用处理
connect(m_dockInter, &DBusInter::ShowInPrimaryChanged, this, [ = ] (bool showInPrimary) {
if (m_screenSettingComboxWidget->comboBox()->currentText() == g_screenSettingMap.key(showInPrimary))
return;
m_screenSettingComboxWidget->blockSignals(true);
m_screenSettingComboxWidget->setCurrentText(g_screenSettingMap.key(showInPrimary));
m_screenSettingComboxWidget->blockSignals(false);
});
layout->addSpacing(10);
layout->addWidget(m_screenSettingComboxWidget);
m_dconfigWatcher->bind("multiscreen", m_screenSettingTitle);
m_dconfigWatcher->bind("multiscreen", m_screenSettingComboxWidget);
} else {
m_screenSettingTitle->setVisible(false);
m_screenSettingComboxWidget->setVisible(false);
}
// 插件区域
QDBusPendingReply<QStringList> reply = m_dockInter->GetLoadedPlugins();
QStringList plugins = reply.value();
if (reply.error().type() != QDBusError::ErrorType::NoError
|| !Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "hideVisible", true).toBool()) {
m_pluginAreaTitle->setVisible(false);
m_pluginTips->setVisible(false);
m_pluginView->setVisible(false);
qWarning() << "dbus call failed, method: 'GetLoadedPlugins()'";
} else {
const QMap<QString, QString> &pluginIconMap = {{"AiAssistant", "dcc_dock_assistant"}
, {"show-desktop", "dcc_dock_desktop"}
, {"onboard", "dcc_dock_keyboard"}
, {"notifications", "dcc_dock_notify"}
, {"shutdown", "dcc_dock_power"}
, {"multitasking", "dcc_dock_task"}
, {"datetime", "dcc_dock_time"}
, {"system-monitor", "dcc_dock_systemmonitor"}
, {"grand-search", "dcc_dock_grandsearch"}
, {"trash", "dcc_dock_trash"}
, {"shot-start-plugin", "shot-start-plugin"}};
if (plugins.size() != 0) {
layout->addSpacing(20);
layout->addWidget(m_pluginAreaTitle);
m_dconfigWatcher->bind("dockPlugins", m_pluginAreaTitle);
DFontSizeManager::instance()->bind(m_pluginTips, DFontSizeManager::T8);
m_pluginTips->adjustSize();
m_pluginTips->setWordWrap(true);
m_pluginTips->setContentsMargins(10, 0, 10, 0);
m_pluginTips->setAlignment(Qt::AlignLeft);
layout->addSpacing(2);
layout->addWidget(m_pluginTips);
m_dconfigWatcher->bind("dockPlugins", m_pluginTips);
m_pluginView->setAccessibleName("pluginList");
m_pluginView->setBackgroundType(DStyledItemDelegate::BackgroundType::ClipCornerBackground);
m_pluginView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_pluginView->setSelectionMode(QListView::SelectionMode::NoSelection);
m_pluginView->setEditTriggers(DListView::NoEditTriggers);
m_pluginView->setFrameShape(DListView::NoFrame);
m_pluginView->setViewportMargins(0, 0, 0, 0);
m_pluginView->setItemSpacing(1);
QMargins itemMargins(m_pluginView->itemMargins());
itemMargins.setLeft(14);
m_pluginView->setItemMargins(itemMargins);
m_pluginView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QScroller *scroller = QScroller::scroller(m_pluginView->viewport());
QScrollerProperties sp;
sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
scroller->setScrollerProperties(sp);
m_pluginView->setModel(m_pluginModel);
layout->addSpacing(10);
layout->addWidget(m_pluginView);
m_dconfigWatcher->bind("dockPlugins", m_pluginView);
for (auto name : plugins) {
DStandardItem *item = new DStandardItem(name);
item->setFontSize(DFontSizeManager::T8);
QSize size(16, 16);
// 插件图标
auto leftAction = new DViewItemAction(Qt::AlignVCenter, size, size, true);
const QString pluginKey = m_dockInter->getPluginKey(name);
QIcon pluginIcon;
// 第三方插件通过pluginKey从系统中读取图标
if (pluginIconMap.contains(pluginKey)) {
pluginIcon = QIcon::fromTheme(pluginIconMap.value(m_dockInter->getPluginKey(name)));
} else {
pluginIcon = QIcon::fromTheme(pluginKey);
}
// 如果获取不到图标则使用默认图标
if (pluginIcon.isNull()) {
pluginIcon = QIcon::fromTheme("dcc_dock_plug_in");
}
leftAction->setIcon(pluginIcon);
item->setActionList(Qt::Edge::LeftEdge, {leftAction});
auto rightAction = new DViewItemAction(Qt::AlignVCenter, size, size, true);
bool visible = m_dockInter->getPluginVisible(name);
auto checkstatus = visible ? DStyle::SP_IndicatorChecked : DStyle::SP_IndicatorUnchecked ;
auto checkIcon = qobject_cast<DStyle *>(style())->standardIcon(checkstatus);
rightAction->setIcon(checkIcon);
item->setActionList(Qt::Edge::RightEdge, {rightAction});
m_pluginModel->appendRow(item);
connect(rightAction, &DViewItemAction::triggered, this, [ = ] {
bool checked = m_dockInter->getPluginVisible(name);
m_dockInter->setPluginVisible(name, !checked);
updateItemCheckStatus(name, !checked);
});
}
// 固定大小,防止滚动
int lineHeight = m_pluginView->visualRect(m_pluginView->indexAt(QPoint(0, 0))).height();
m_pluginView->setMinimumHeight(lineHeight * plugins.size() + 10);
} else {
m_pluginAreaTitle->setVisible(false);
m_pluginTips->setVisible(false);
m_pluginView->setVisible(false);
}
}
// 支持在触摸屏上滚动
QScroller::grabGesture(this->viewport(), QScroller::LeftMouseButtonGesture);
QScroller *scroller = QScroller::scroller(this->window());
QScrollerProperties sp;
sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
scroller->setScrollerProperties(sp);
// 保持内容正常铺满
layout->addStretch();
// 界面内容过多时可滚动查看
QWidget *widget = new QWidget;
widget->setLayout(layout);
setWidget(widget);
}
/**判断屏幕是否为复制模式的依据第一个屏幕的X和Y值是否和其他的屏幕的X和Y值相等
* 对于复制模式,这两个值肯定是相等的,如果不是复制模式,这两个值肯定不等,目前支持双屏
* @brief DisplayManager::isCopyMode
* @return
*/
bool ModuleWidget::isCopyMode()
{
QList<QScreen *> screens = qApp->screens();
if (screens.size() < 2)
return false;
// 在多个屏幕的情况下如果所有屏幕的位置的X和Y值都相等则认为是复制模式
QRect screenRect = screens[0]->availableGeometry();
for (int i = 1; i < screens.size(); i++) {
QRect rect = screens[i]->availableGeometry();
if (screenRect.x() != rect.x() || screenRect.y() != rect.y())
return false;
}
return true;
}
void ModuleWidget::updateSliderValue()
{
auto displayMode = m_daemonDockInter->displayMode();
m_sizeSlider->slider()->blockSignals(true);
if (displayMode == DisplayMode::Fashion) {
if (int(m_daemonDockInter->windowSizeFashion()) != m_sizeSlider->slider()->value())
m_sizeSlider->slider()->setValue(int(m_daemonDockInter->windowSizeFashion()));
} else if (displayMode == DisplayMode::Efficient) {
if (int(m_daemonDockInter->windowSizeEfficient()) != m_sizeSlider->slider()->value())
m_sizeSlider->slider()->setValue(int(m_daemonDockInter->windowSizeEfficient()));
}
m_sizeSlider->slider()->blockSignals(false);
}
void ModuleWidget::updateItemCheckStatus(const QString &name, bool visible)
{
for (int i = 0; i < m_pluginModel->rowCount(); ++i) {
auto item = static_cast<DStandardItem *>(m_pluginModel->item(i));
if (item->text() != name || item->actionList(Qt::Edge::RightEdge).size() < 1)
continue;
auto action = item->actionList(Qt::Edge::RightEdge).first();
auto checkstatus = visible ? DStyle::SP_IndicatorChecked : DStyle::SP_IndicatorUnchecked ;
auto icon = qobject_cast<DStyle *>(style())->standardIcon(checkstatus);
action->setIcon(icon);
m_pluginView->update(item->index());
break;
}
}