mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-03 00:15:21 +00:00

配置项规范化 Log: Influence: 无 Task: https://pms.uniontech.com/task-view-104239.html Change-Id: I92646d1d17cdb8678a02057a0e3729d828f2e46a
432 lines
19 KiB
C++
432 lines
19 KiB
C++
/*
|
||
* Copyright (C) 2011 ~ 2021 Uniontech Technology Co., Ltd.
|
||
*
|
||
* Author: fanpengcheng <fanpengcheng@uniontech.com>
|
||
*
|
||
* Maintainer: fanpengcheng <fanpengcheng@uniontech.com>
|
||
*
|
||
* 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
|
||
* 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 <http://www.gnu.org/licenses/>.
|
||
*/
|
||
#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(10);
|
||
|
||
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->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->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->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->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"}};
|
||
if (plugins.size() != 0) {
|
||
layout->addSpacing(10);
|
||
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, 5, 10, 5);
|
||
m_pluginTips->setAlignment(Qt::AlignLeft);
|
||
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->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);
|
||
leftAction->setIcon(QIcon::fromTheme(pluginIconMap.value(m_dockInter->getPluginKey(name), "dcc_dock_plug_in")));
|
||
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->window(), 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;
|
||
}
|
||
}
|