feat: 增加display插件

将原来在dde-dock中的显示相关的代码部分移动到display插件中,生成新的插件

Log:
Influence: 展开任务栏快捷面板,观察是否有亮度设置相关的功能
Task: https://pms.uniontech.com/task-view-220489.html
Change-Id: Ifc1bb2395c3f9ff449513078aba0e3c56ad66881
This commit is contained in:
donghualin 2022-11-28 14:37:54 +08:00
parent 4f3f7a0aed
commit 4aed03f62b
27 changed files with 1984 additions and 0 deletions

View File

@ -0,0 +1,51 @@
set(PLUGIN_NAME "display")
project(${PLUGIN_NAME})
generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface)
# Sources files
file(GLOB_RECURSE SRCS "*.h" "*.cpp"
"../../widgets/*.h"
"../../widgets/*.cpp"
"../../frame/util/imageutil.h"
"../../frame/util/imageutil.cpp"
"../../frame/util/statebutton.h"
"../../frame/util/statebutton.cpp"
"../../frame/util/horizontalseperator.h"
"../../frame/util/horizontalseperator.cpp"
"../../frame/qtdbusextended/*.h"
"../../frame/qtdbusextended/*.cpp")
find_package(PkgConfig REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Svg REQUIRED)
find_package(Qt5DBus REQUIRED)
find_package(DtkWidget REQUIRED)
pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor)
pkg_check_modules(QGSettings REQUIRED gsettings-qt)
add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN")
add_library(${PLUGIN_NAME} SHARED ${SRCS} ./resource/display.qrc)
set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../quick-trays)
target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS}
${QGSettings_INCLUDE_DIRS}
../../interfaces
../../widgets
../../frame
../../frame/qtdbusextended
./dbusinterface/generation_dbus_interface
componments)
target_link_libraries(${PLUGIN_NAME} PRIVATE
${XCB_EWMH_LIBRARIES}
${DtkWidget_LIBRARIES}
${QGSettings_LIBRARIES}
${Qt5DBus_LIBRARIES}
${Qt5Widgets_LIBRARIES}
${Qt5Svg_LIBRARIES}
)
install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/quick-trays)

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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 "brightnessadjwidget.h"
#include "brightnessmodel.h"
#include "slidercontainer.h"
#include "imageutil.h"
#include <QVBoxLayout>
const int ItemSpacing = 5;
BrightnessAdjWidget::BrightnessAdjWidget(QWidget *parent)
: QWidget(parent)
, m_mainLayout(new QVBoxLayout(this))
, m_brightnessModel(new BrightnessModel(this))
{
m_mainLayout->setMargin(0);
m_mainLayout->setSpacing(ItemSpacing);
loadBrightnessItem();
}
void BrightnessAdjWidget::loadBrightnessItem()
{
QList<BrightMonitor *> monitors = m_brightnessModel->monitors();
int itemHeight = monitors.count() > 1 ? 56 : 30;
for (BrightMonitor *monitor : monitors) {
SliderContainer *sliderContainer = new SliderContainer(this);
if (monitors.count() > 1)
sliderContainer->setTitle(monitor->name());
QPixmap leftPixmap = ImageUtil::loadSvg(":/icons/resources/brightnesslow", QSize(20, 20));
QPixmap rightPixmap = ImageUtil::loadSvg(":/icons/resources/brightnesshigh", QSize(20, 20));
sliderContainer->setIcon(SliderContainer::IconPosition::LeftIcon,leftPixmap, QSize(), 12);
sliderContainer->setIcon(SliderContainer::IconPosition::RightIcon, rightPixmap, QSize(), 12);
sliderContainer->setFixedWidth(310);
sliderContainer->setFixedHeight(itemHeight);
sliderContainer->updateSliderValue(monitor->brightness());
SliderProxyStyle *proxy = new SliderProxyStyle(SliderProxyStyle::Normal);
sliderContainer->setSliderProxyStyle(proxy);
m_mainLayout->addWidget(sliderContainer);
connect(monitor, &BrightMonitor::brightnessChanged, sliderContainer, &SliderContainer::updateSliderValue);
connect(sliderContainer, &SliderContainer::sliderValueChanged, monitor, &BrightMonitor::setBrightness);
}
QMargins margins = this->contentsMargins();
setFixedHeight(margins.top() + margins.bottom() + monitors.count() * itemHeight + monitors.count() * ItemSpacing);
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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/>.
*/
#ifndef BRIGHTNESS_ADJUSTMENT_WIDGET_H
#define BRIGHTNESS_ADJUSTMENT_WIDGET_H
#include <QWidget>
class QVBoxLayout;
class BrightnessModel;
/*!
* \brief The BrightnessAdjWidget class
*
*/
class BrightnessAdjWidget : public QWidget
{
Q_OBJECT
public:
explicit BrightnessAdjWidget(QWidget *parent = nullptr);
private:
void loadBrightnessItem();
private:
QVBoxLayout *m_mainLayout;
BrightnessModel *m_brightnessModel;
};
#endif // BRIGHTNESS_ADJUSTMENT_WIDGET_H

View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
* kirigaya <kirigaya@mkacg.com>
* Hualet <mr.asianwang@gmail.com>
*
* Maintainer: sbw <sbw@sbw.so>
* kirigaya <kirigaya@mkacg.com>
* Hualet <mr.asianwang@gmail.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 "brightnessmodel.h"
#include <QDBusArgument>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <QDebug>
#include <QApplication>
#include <QScreen>
static const QString serviceName("com.deepin.daemon.Display");
static const QString servicePath("/com/deepin/daemon/Display");
static const QString serviceInterface("com.deepin.daemon.Display");
static const QString propertiesInterface("org.freedesktop.DBus.Properties");
BrightnessModel::BrightnessModel(QObject *parent)
: QObject(parent)
{
QDBusInterface dbusInter(serviceName, servicePath, serviceInterface, QDBusConnection::sessionBus());
if (dbusInter.isValid()) {
// 读取所有的屏幕的信息
QString primaryScreenName = dbusInter.property("Primary").value<QString>();
QList<QDBusObjectPath> paths = dbusInter.property("Monitors").value<QList<QDBusObjectPath>>();
for (QDBusObjectPath path : paths) {
BrightMonitor *monitor = new BrightMonitor(path.path(), this);
monitor->setPrimary(primaryScreenName == monitor->name());
m_monitor << monitor;
}
}
connect(qApp, &QApplication::primaryScreenChanged, this, &BrightnessModel::primaryScreenChanged);
}
BrightnessModel::~BrightnessModel()
{
}
QList<BrightMonitor *> BrightnessModel::monitors()
{
return m_monitor;
}
BrightMonitor *BrightnessModel::primaryMonitor() const
{
for (BrightMonitor *monitor : m_monitor) {
if (monitor->isPrimary())
return monitor;
}
return nullptr;
}
void BrightnessModel::primaryScreenChanged(QScreen *screen)
{
BrightMonitor *defaultMonitor = nullptr;
for (BrightMonitor *monitor : m_monitor) {
monitor->setPrimary(monitor->name() == screen->name());
if (monitor->isPrimary())
defaultMonitor = monitor;
}
if (defaultMonitor)
Q_EMIT primaryChanged(defaultMonitor);
}
/**
* @brief monitor
*/
BrightMonitor::BrightMonitor(QString path, QObject *parent)
: QObject(parent)
, m_path(path)
, m_brightness(100)
, m_enabled(false)
, m_isPrimary(false)
{
QDBusInterface dbusInter(serviceName, path, serviceInterface + QString(".Monitor"), QDBusConnection::sessionBus());
if (dbusInter.isValid()) {
// 读取所有的屏幕的信息
m_name = dbusInter.property("Name").toString();
m_brightness = static_cast<int>(dbusInter.property("Brightness").toDouble() * 100);
m_enabled = dbusInter.property("Enabled").toBool();
}
QDBusConnection::sessionBus().connect(serviceName, path, propertiesInterface,
"PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &)));
}
BrightMonitor::~BrightMonitor()
{
}
void BrightMonitor::setPrimary(bool primary)
{
m_isPrimary = primary;
}
int BrightMonitor::brightness()
{
return m_brightness;
}
bool BrightMonitor::enabled()
{
return m_enabled;
}
QString BrightMonitor::name()
{
return m_name;
}
bool BrightMonitor::isPrimary()
{
return m_isPrimary;
}
void BrightMonitor::setBrightness(int value)
{
callMethod("SetBrightness", { m_name, static_cast<double>(value * 0.01) });
}
void BrightMonitor::onPropertyChanged(const QDBusMessage &msg)
{
QList<QVariant> arguments = msg.arguments();
if (3 != arguments.count())
return;
QString interfaceName = msg.arguments().at(0).toString();
if (interfaceName != QString("%1.Monitor").arg(serviceInterface))
return;
QVariantMap changedProps = qdbus_cast<QVariantMap>(arguments.at(1).value<QDBusArgument>());
if (changedProps.contains("Brightness")) {
int brightness = static_cast<int>(changedProps.value("Brightness").value<double>() * 100);
if (brightness != m_brightness) {
m_brightness = brightness;
Q_EMIT brightnessChanged(brightness);
}
}
if (changedProps.contains("Name")) {
QString name = changedProps.value("Name").value<QString>();
if (name != m_name) {
m_name = name;
Q_EMIT nameChanged(name);
}
}
if (changedProps.contains("Enabled")) {
bool enabled = changedProps.value("Enabled").value<bool>();
if (enabled != m_enabled) {
m_enabled = enabled;
Q_EMIT enabledChanged(enabled);
}
}
}
QDBusMessage BrightMonitor::callMethod(const QString &methodName, const QList<QVariant> &argument)
{
QDBusInterface dbusInter(serviceName, servicePath, serviceInterface, QDBusConnection::sessionBus());
if (dbusInter.isValid()) {
QDBusPendingCall reply = dbusInter.asyncCallWithArgumentList(methodName, argument);
reply.waitForFinished();
return reply.reply();
}
return QDBusMessage();
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2011 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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/>.
*/
#ifndef BRIGHTNESSMODEL_H
#define BRIGHTNESSMODEL_H
#include <QObject>
class BrightMonitor;
class QDBusMessage;
class QScreen;
class BrightnessModel : public QObject
{
Q_OBJECT
public:
explicit BrightnessModel(QObject *parent = nullptr);
~BrightnessModel();
QList<BrightMonitor *> monitors();
BrightMonitor *primaryMonitor() const;
Q_SIGNALS:
void primaryChanged(BrightMonitor *);
protected Q_SLOTS:
void primaryScreenChanged(QScreen *screen);
private:
QList<BrightMonitor *> m_monitor;
};
class BrightMonitor : public QObject
{
Q_OBJECT
public:
explicit BrightMonitor(QString path, QObject *parent);
~BrightMonitor();
Q_SIGNALS:
void brightnessChanged(int);
void nameChanged(QString);
void enabledChanged(bool);
public:
void setPrimary(bool primary);
int brightness();
bool enabled();
QString name();
bool isPrimary();
public slots:
void setBrightness(int value);
void onPropertyChanged(const QDBusMessage &msg);
private:
QDBusMessage callMethod(const QString &methodName, const QList<QVariant> &argument);
private:
QString m_path;
QString m_name;
int m_brightness;
bool m_enabled;
bool m_isPrimary;
};
#endif // DISPLAYMODEL_H

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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 "brightnesswidget.h"
#include "brightnessmodel.h"
#include "imageutil.h"
#include "slidercontainer.h"
#include <QHBoxLayout>
#include <QDebug>
#define BACKSIZE 36
#define IMAGESIZE 18
BrightnessWidget::BrightnessWidget(BrightnessModel *model, QWidget *parent)
: QWidget(parent)
, m_sliderContainer(new SliderContainer(this))
, m_model(model)
{
initUi();
initConnection();
}
BrightnessWidget::~BrightnessWidget()
{
}
void BrightnessWidget::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
// 显示的时候更新一下slider的主屏幕亮度值
updateSliderValue();
Q_EMIT visibleChanged(true);
}
void BrightnessWidget::hideEvent(QHideEvent *event)
{
QWidget::hideEvent(event);
Q_EMIT visibleChanged(true);
}
void BrightnessWidget::initUi()
{
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(15, 0, 12, 0);
QPixmap leftPixmap = ImageUtil::loadSvg(":/brightness.svg", QSize(IMAGESIZE, IMAGESIZE));
QPixmap rightPixmap = ImageUtil::loadSvg(":/ICON_Device_Laptop.svg", QSize(IMAGESIZE, IMAGESIZE));
m_sliderContainer->setIcon(SliderContainer::IconPosition::LeftIcon, leftPixmap, QSize(), 10);
m_sliderContainer->setIcon(SliderContainer::IconPosition::RightIcon, rightPixmap, QSize(BACKSIZE, BACKSIZE), 12);
// 需求要求调节范围是10%-100%,且调节幅度为1%
m_sliderContainer->setRange(10, 100);
m_sliderContainer->setPageStep(1);
SliderProxyStyle *style = new SliderProxyStyle;
m_sliderContainer->setSliderProxyStyle(style);
mainLayout->addWidget(m_sliderContainer);
}
void BrightnessWidget::initConnection()
{
connect(m_sliderContainer, &SliderContainer::sliderValueChanged, this, [ this ](int value) {
BrightMonitor *monitor = m_model->primaryMonitor();
if (monitor)
monitor->setBrightness(value);
});
connect(m_sliderContainer, &SliderContainer::iconClicked, this, [ this ](const SliderContainer::IconPosition &position) {
if (position == SliderContainer::IconPosition::RightIcon)
Q_EMIT brightClicked();
});
updateSliderValue();
}
void BrightnessWidget::updateSliderValue()
{
BrightMonitor *monitor = m_model->primaryMonitor();
if (monitor) {
m_sliderContainer->updateSliderValue(monitor->brightness());
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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/>.
*/
#ifndef BRIGHTNESSWIDGET_H
#define BRIGHTNESSWIDGET_H
#include <DBlurEffectWidget>
DWIDGET_USE_NAMESPACE
class SliderContainer;
class BrightnessModel;
class BrightMonitor;
class BrightnessWidget : public QWidget
{
Q_OBJECT
public:
explicit BrightnessWidget(BrightnessModel *model, QWidget *parent = nullptr);
~BrightnessWidget() override;
Q_SIGNALS:
void visibleChanged(bool);
void brightClicked();
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
private:
void initUi();
void initConnection();
void updateSliderValue();
private:
SliderContainer *m_sliderContainer;
BrightnessModel *m_model;
};
#endif // LIGHTSETTINGWIDGET_H

View File

@ -0,0 +1,267 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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 "collaborationdevmodel.h"
#include <QIcon>
#include <QTimer>
#include <QDebug>
#include <QDBusArgument>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <DGuiApplicationHelper>
DGUI_USE_NAMESPACE
DCORE_USE_NAMESPACE
static const QString CollaborationService = "com.deepin.Cooperation";
static const QString CollaborationPath = "/com/deepin/Cooperation";
static const QString CollaborationInterface = "com.deepin.Cooperation";
static const QString ColPropertiesInterface = "org.freedesktop.DBus.Properties";
CollaborationDevModel::CollaborationDevModel(QObject *parent)
: QObject(parent)
, m_colDbusInter(new QDBusInterface(CollaborationService, CollaborationPath, CollaborationInterface, QDBusConnection::sessionBus(), this))
{
if (m_colDbusInter->isValid()) {
QList<QDBusObjectPath> paths = m_colDbusInter->property("Machines").value<QList<QDBusObjectPath>>();
for (const QDBusObjectPath& path : paths) {
CollaborationDevice *device = new CollaborationDevice(path.path(), this);
if (device->isValid())
m_devices[path.path()] = device;
else
device->deleteLater();
}
} else {
qWarning() << CollaborationService << " is invalid";
}
m_colDbusInter->connection().connect(CollaborationService, CollaborationPath, ColPropertiesInterface,
"PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(QDBusMessage)));
}
void CollaborationDevModel::checkServiceValid()
{
if (!m_colDbusInter->isValid()) {
for (CollaborationDevice *device : m_devices) {
device->deleteLater();
}
m_devices.clear();
Q_EMIT devicesChanged();
}
}
QList<CollaborationDevice *> CollaborationDevModel::devices() const
{
return m_devices.values();
}
void CollaborationDevModel::onPropertyChanged(const QDBusMessage &msg)
{
QList<QVariant> arguments = msg.arguments();
if (3 != arguments.count())
return;
QString interfaceName = msg.arguments().at(0).toString();
if (interfaceName != CollaborationInterface)
return;
QVariantMap changedProps = qdbus_cast<QVariantMap>(arguments.at(1).value<QDBusArgument>());
if (changedProps.contains("Machines")) {
QList<QDBusObjectPath> paths = m_colDbusInter->property("Machines").value<QList<QDBusObjectPath>>();
QStringList devPaths;
for (const QDBusObjectPath& path : paths) {
devPaths << path.path();
}
updateDevice(devPaths);
}
}
void CollaborationDevModel::updateDevice(const QStringList &devPaths)
{
if (devPaths.isEmpty()) {
qDeleteAll(m_devices);
m_devices.clear();
} else {
// 清除已不存在的设备
QMapIterator<QString, CollaborationDevice *> it(m_devices);
while (it.hasNext()) {
it.next();
if (!devPaths.contains(it.key())) {
it.value()->deleteLater();
m_devices.remove(it.key());
}
}
// 添加新增设备
for (const QString &path : devPaths) {
if (!m_devices.contains(path)) {
CollaborationDevice *device = new CollaborationDevice(path, this);
if (device->isValid())
m_devices[path] = device;
else
device->deleteLater();
}
}
}
emit devicesChanged();
}
CollaborationDevice *CollaborationDevModel::getDevice(const QString &machinePath)
{
return m_devices.value(machinePath, nullptr);
}
CollaborationDevice::CollaborationDevice(const QString &devPath, QObject *parent)
: QObject(parent)
, m_path(devPath)
, m_OS(-1)
, m_isPaired(false)
, m_isCooperated(false)
, m_isValid(false)
, m_isCooperating(false)
, m_devDbusInter(new QDBusInterface(CollaborationService, devPath, CollaborationInterface + QString(".Machine"),
QDBusConnection::sessionBus(), this))
{
if (m_devDbusInter->isValid()) {
m_name = m_devDbusInter->property("Name").toString();
m_OS = m_devDbusInter->property("OS").toInt();
m_isPaired = m_devDbusInter->property("Paired").toBool();
m_isCooperated = m_devDbusInter->property("Cooperating").toBool();
m_uuid = m_devDbusInter->property("UUID").toString();
m_isValid = true;
} else {
qWarning() << "CollaborationDevice devPath:" << devPath << " is invalid and get properties failed";
}
m_devDbusInter->connection().connect(CollaborationService, m_path, ColPropertiesInterface, "PropertiesChanged",
this, SLOT(onPropertyChanged(QDBusMessage)));
}
bool CollaborationDevice::isValid() const
{
return m_isValid;
}
QString CollaborationDevice::name() const
{
return m_name;
}
QString CollaborationDevice::uuid() const
{
return m_uuid;
}
QString CollaborationDevice::machinePath() const
{
return m_path;
}
QString CollaborationDevice::deviceIcon() const
{
switch (m_OS) {
case DeviceType::Android: {
if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType)
return QString(":/icons/resources/ICON_Device_Headphone_dark.svg");
return QString(":/icons/resources/ICON_Device_Headphone.svg");
}
default: {
if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType)
return QString(":/icons/resources/ICON_Device_Laptop_dark.svg");
return QString(":/icons/resources/ICON_Device_Laptop.svg");
}
}
}
bool CollaborationDevice::isPaired() const
{
return m_isPaired;
}
bool CollaborationDevice::isCooperated() const
{
return m_isCooperated;
}
void CollaborationDevice::setDeviceIsCooperating(bool isCooperating)
{
m_isCooperating = isCooperating;
}
void CollaborationDevice::onPropertyChanged(const QDBusMessage &msg)
{
QList<QVariant> arguments = msg.arguments();
if (3 != arguments.count())
return;
QString interfaceName = msg.arguments().at(0).toString();
if (interfaceName != QString("%1.Machine").arg(CollaborationInterface))
return;
QVariantMap changedProps = qdbus_cast<QVariantMap>(arguments.at(1).value<QDBusArgument>());
if (changedProps.contains("Paired")) {
bool isPaired = changedProps.value("Paired").value<bool>();
m_isPaired = isPaired;
if (isPaired && m_isCooperating) {
// paired 成功之后再去请求cooperate
requestCooperate();
}
if (!isPaired){
Q_EMIT pairedStateChanged(false);
}
} else if (changedProps.contains("Cooperating")) {
m_isCooperated = changedProps.value("Cooperating").value<bool>();
Q_EMIT pairedStateChanged(m_isCooperated);
}
}
void CollaborationDevice::requestCooperate() const
{
callMethod("RequestCooperate");
}
void CollaborationDevice::disconnectDevice() const
{
callMethod("Disconnect");
}
void CollaborationDevice::pair() const
{
callMethod("Pair");
}
QDBusMessage CollaborationDevice::callMethod(const QString &methodName) const
{
if (m_devDbusInter->isValid()) {
QDBusMessage msg = m_devDbusInter->call(methodName);
qInfo() << "CollaborationDevice callMethod:" << methodName << " " << msg.errorMessage();
return msg;
}
qWarning() << "CollaborationDevice callMethod: " << methodName << " failed";
return QDBusMessage();
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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/>.
*/
#ifndef COLLABORATION_DEV_MODEL_H
#define COLLABORATION_DEV_MODEL_H
#include <QMap>
#include <QObject>
class QTimer;
class QDBusInterface;
class QDBusMessage;
class CollaborationDevice;
/*!
* \brief The CollaborationDevModel class
* model
*/
class CollaborationDevModel : public QObject
{
Q_OBJECT
public:
explicit CollaborationDevModel(QObject *parent = nullptr);
signals:
void devicesChanged();
public:
void checkServiceValid();
QList<CollaborationDevice *> devices() const;
CollaborationDevice *getDevice(const QString &machinePath);
private slots:
void onPropertyChanged(const QDBusMessage &msg);
private:
void updateDevice(const QStringList &devPaths);
private:
QDBusInterface *m_colDbusInter;
// machine path : device object
QMap<QString, CollaborationDevice *> m_devices;
};
/*!
* \brief The CollaborationDevice class
*
*/
class CollaborationDevice : public QObject
{
Q_OBJECT
public:
explicit CollaborationDevice(const QString &devPath, QObject *parent = nullptr);
signals:
void pairedStateChanged(bool);
public:
bool isValid() const;
void pair() const;
void requestCooperate() const;
void disconnectDevice() const;
QString name() const;
QString uuid() const;
QString machinePath() const;
QString deviceIcon() const;
bool isPaired() const;
bool isCooperated() const;
void setDeviceIsCooperating(bool isCooperating);
private slots:
void onPropertyChanged(const QDBusMessage &msg);
private:
QDBusMessage callMethod(const QString &methodName) const;
private:
enum DeviceType {
Other = 0,
UOS,
Linux,
Windows,
MacOS,
Android
};
QString m_path;
QString m_name;
QString m_uuid;
int m_OS;
bool m_isPaired;
bool m_isCooperated;
bool m_isValid;
// 标记任务栏点击触发协同连接
bool m_isCooperating;
QDBusInterface *m_devDbusInter;
};
#endif // COLLABORATION_DEV_MODEL_H

View File

@ -0,0 +1,256 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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 "devcollaborationwidget.h"
#include "collaborationdevmodel.h"
#include "devitemdelegate.h"
#include <DStyle>
#include <QMap>
#include <QTimer>
#include <QLabel>
#include <QVBoxLayout>
#include <QStandardItemModel>
#define TITLE_HEIGHT 16
#define ITEM_WIDTH 310
#define ITEM_HEIGHT 36
#define LISTVIEW_ITEM_SPACE 5
#define PER_DEGREE 14
DevCollaborationWidget::DevCollaborationWidget(QWidget *parent)
: QWidget(parent)
, m_deviceModel(new CollaborationDevModel(this))
, m_deviceListView(new DListView(this))
, m_viewItemModel(new QStandardItemModel(m_deviceListView))
, m_refreshTimer(new QTimer(this))
{
initUI();
loadDevice();
connect(m_deviceModel, &CollaborationDevModel::devicesChanged, this, &DevCollaborationWidget::loadDevice);
connect(m_deviceListView, &DListView::clicked, this, &DevCollaborationWidget::itemClicked);
connect(m_refreshTimer, &QTimer::timeout, this, &DevCollaborationWidget::refreshViewItem);
}
void DevCollaborationWidget::showEvent(QShowEvent *event)
{
m_deviceModel->checkServiceValid();
QWidget::showEvent(event);
}
void DevCollaborationWidget::resizeEvent(QResizeEvent *event)
{
Q_EMIT sizeChanged();
QWidget::resizeEvent(event);
}
void DevCollaborationWidget::initUI()
{
m_deviceListView->setModel(m_viewItemModel);
QLabel *title = new QLabel(tr("Cross-end Collaboration"), this);
title->setFixedHeight(TITLE_HEIGHT);
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->setContentsMargins(10, 0, 0, 0);
hLayout->addWidget(title);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->setMargin(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
mainLayout->addLayout(hLayout);
mainLayout->addWidget(m_deviceListView);
setLayout(mainLayout);
m_deviceListView->setContentsMargins(0, 0, 0, 0);
m_deviceListView->setFrameShape(QFrame::NoFrame);
m_deviceListView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_deviceListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_deviceListView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_deviceListView->setResizeMode(QListView::Adjust);
m_deviceListView->setViewportMargins(0, 0, 0, 0);
m_deviceListView->setSpacing(LISTVIEW_ITEM_SPACE);
m_deviceListView->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_deviceListView->setItemDelegate(new DevItemDelegate(this));
}
void DevCollaborationWidget::loadDevice()
{
if (!m_deviceListView->count()) {
for (CollaborationDevice *device : m_deviceModel->devices()) {
addItem(device);
}
} else {
updateDeviceListView();
}
if(!m_deviceListView->count()) {
m_deviceListView->hide();
} else {
if (!m_deviceListView->isVisible())
m_deviceListView->setVisible(true);
m_deviceListView->setFixedSize(ITEM_WIDTH, m_deviceListView->count() * ITEM_HEIGHT + LISTVIEW_ITEM_SPACE * (m_deviceListView->count() * 2));
}
resetWidgetSize();
}
void DevCollaborationWidget::addItem(const CollaborationDevice *device)
{
if (!device)
return;
QStandardItem *item = new QStandardItem();
DevItemDelegate::DevItemData data;
data.checkedIconPath = device->deviceIcon(); // TODO
data.text = device->name();
data.iconPath = device->deviceIcon();
int resultState = device->isCooperated() ? DevItemDelegate::Connected : DevItemDelegate::None;
item->setData(QVariant::fromValue(data), DevItemDelegate::StaticDataRole);
item->setData(device->machinePath(), DevItemDelegate::MachinePathDataRole);
item->setData(0, DevItemDelegate::DegreeDataRole);
item->setData(resultState, DevItemDelegate::ResultDataRole);
m_viewItemModel->appendRow(item);
m_deviceItemMap[device->machinePath()] = item;
connect(device, &CollaborationDevice::pairedStateChanged, this, &DevCollaborationWidget::itemStatusChanged);
}
void DevCollaborationWidget::updateDeviceListView()
{
QList<CollaborationDevice *> devices = m_deviceModel->devices();
if (devices.isEmpty()) {
m_deviceListView->removeItems(0, m_deviceListView->count());
m_deviceItemMap.clear();
m_connectingDevices.clear();
return;
}
// 删除不存在设备
for (int row = 0; row < m_deviceListView->count(); row++) {
QStandardItem *item = m_viewItemModel->item(row);
if (!item)
continue;
QString machinePath = item->data(DevItemDelegate::MachinePathDataRole).toString();
if (m_deviceModel->getDevice(machinePath))
continue;
m_deviceListView->removeItem(row);
if (m_deviceItemMap.contains(machinePath)) {
m_deviceItemMap.remove(machinePath);
}
if (m_connectingDevices.contains(machinePath)) {
m_connectingDevices.removeAll(machinePath);
}
}
// 处理新增
for (CollaborationDevice *device : devices) {
if (!m_deviceItemMap.contains(device->machinePath())) {
addItem(device);
}
}
}
void DevCollaborationWidget::resetWidgetSize()
{
int height = TITLE_HEIGHT + (m_deviceListView->count() ? m_deviceListView->height() : 0);
setFixedSize(ITEM_WIDTH, height);
}
void DevCollaborationWidget::itemClicked(const QModelIndex &index)
{
QString machinePath = index.data(DevItemDelegate::MachinePathDataRole).toString();
CollaborationDevice *device = m_deviceModel->getDevice(machinePath);
if (!device)
return;
if (!device->isPaired()) {
device->setDeviceIsCooperating(true);
device->pair();
if (!m_connectingDevices.contains(machinePath))
m_connectingDevices.append(machinePath);
} else if (!device->isCooperated()) {
device->requestCooperate();
if (!m_connectingDevices.contains(machinePath))
m_connectingDevices.append(machinePath);
} else if (device->isCooperated()) {
device->disconnectDevice();
if (m_connectingDevices.contains(machinePath))
m_connectingDevices.removeOne(machinePath);
}
if (!m_connectingDevices.isEmpty() && !m_refreshTimer->isActive())
m_refreshTimer->start(80);
}
void DevCollaborationWidget::itemStatusChanged()
{
CollaborationDevice *device = qobject_cast<CollaborationDevice *>(sender());
if (!device)
return;
device->setDeviceIsCooperating(false);
QString machinePath = device->machinePath();
if (m_deviceItemMap.contains(machinePath) && m_deviceItemMap[machinePath]) {
// 更新item的连接状态
int resultState = device->isCooperated() ? DevItemDelegate::Connected : DevItemDelegate::None;
m_deviceItemMap[machinePath]->setData(resultState, DevItemDelegate::ResultDataRole);
if (device->isCooperated() || !device->isPaired())
m_deviceItemMap[machinePath]->setData(0, DevItemDelegate::DegreeDataRole);
m_deviceListView->update(m_deviceItemMap[machinePath]->index());
if ((resultState == DevItemDelegate::Connected || !device->isPaired()) && m_connectingDevices.contains(machinePath)) {
m_connectingDevices.removeAll(machinePath);
}
}
}
void DevCollaborationWidget::refreshViewItem()
{
if (m_connectingDevices.isEmpty()) {
m_refreshTimer->stop();
return;
}
for (const QString &machinePath : m_connectingDevices) {
if (m_deviceItemMap.contains(machinePath) && m_deviceItemMap[machinePath]) {
int degree = m_deviceItemMap[machinePath]->data(DevItemDelegate::DegreeDataRole).toInt();
degree += PER_DEGREE; // 递进值
m_deviceItemMap[machinePath]->setData(DevItemDelegate::Connecting, DevItemDelegate::ResultDataRole);
m_deviceItemMap[machinePath]->setData(degree, DevItemDelegate::DegreeDataRole);
m_deviceListView->update(m_deviceItemMap[machinePath]->index());
}
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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/>.
*/
#ifndef DEVICE_COLLABORATION_WIDGET_H
#define DEVICE_COLLABORATION_WIDGET_H
#include <QWidget>
#include <DListView>
DWIDGET_USE_NAMESPACE
class CollaborationDevice;
class CollaborationDevModel;
/*!
* \brief The DevCollaborationWidget class
*
*/
class DevCollaborationWidget : public QWidget
{
Q_OBJECT
public:
explicit DevCollaborationWidget(QWidget *parent = nullptr);
signals:
void sizeChanged();
protected:
void showEvent(QShowEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private slots:
void loadDevice();
void itemClicked(const QModelIndex &index);
void itemStatusChanged();
void refreshViewItem();
private:
void initUI();
void updateDeviceListView();
void addItem(const CollaborationDevice *device);
void resetWidgetSize();
private:
CollaborationDevModel *m_deviceModel;
DListView *m_deviceListView;
QStandardItemModel *m_viewItemModel;
QMap<QString, QStandardItem *> m_deviceItemMap;
QStringList m_connectingDevices;
QTimer *m_refreshTimer;
};
#endif // DEVICE_COLLABORATION_WIDGET_H

View File

@ -0,0 +1,179 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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 "devitemdelegate.h"
#include <QtMath>
#include <QPainter>
#include <QPainterPath>
#include <DFontSizeManager>
#define RADIUS_VALUE 10
#define ITEM_SPACE 20
#define ICON_WIDTH 16
#define ICON_HEIGHT 16
#define TEXT_RECT_HEIGHT 20
#define ITEM_HEIGHT 36
#define INDICATOR_SHADOW_OFFSET 10
DevItemDelegate::DevItemDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
void DevItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (!index.isValid())
return;
painter->setRenderHint(QPainter::Antialiasing);
QVariant var = index.data(StaticDataRole);
DevItemData itemData = var.value<DevItemData>();
QRect rect = option.rect;
QPen pen;
pen.setWidth(2);
// 鼠标悬停
if (option.state.testFlag(QStyle::State_MouseOver)) {
pen.setColor(QColor("#EBECED"));
painter->setPen(pen);
painter->setBrush(QColor("#EBECED"));
painter->drawRoundedRect(rect, RADIUS_VALUE, RADIUS_VALUE);
}
// 选中背景(连接上和选中)
int result = index.data(ResultDataRole).toInt();
if (option.state.testFlag(QStyle::State_Selected) && result == Connected) {
pen.setColor(QColor("#0081FF"));
painter->setPen(pen);
painter->setBrush(QColor("#0081FF"));
painter->drawRoundedRect(rect, RADIUS_VALUE, RADIUS_VALUE);
} else {
// 绘制默认背景
pen.setColor(QColor("#EBECED"));
painter->setPen(pen);
painter->setBrush(QColor("#EBECED"));
painter->drawRoundedRect(rect, RADIUS_VALUE, RADIUS_VALUE);
}
bool selected = (option.state.testFlag(QStyle::State_Selected) && result == Connected);
// 绘制Icon
QString imagePath = selected ? itemData.checkedIconPath : itemData.iconPath;
QRect iconRect = QRect(rect.left() + ITEM_SPACE, rect.top() + rect.height() / 2 - ICON_HEIGHT / 2,
ICON_WIDTH, ICON_HEIGHT);
painter->drawImage(iconRect, QImage(imagePath));
// 绘制text
QFont font = Dtk::Widget::DFontSizeManager::instance()->t4();
painter->setFont(font);
pen.setColor(selected ? Qt::white : Qt::black);
painter->setPen(pen);
int textRectWidth = rect.width() - ITEM_SPACE - iconRect.width() - iconRect.width() - ITEM_SPACE;
QRect textRect = QRect(iconRect.right() + ITEM_SPACE, rect.top() + 2,
textRectWidth, rect.height());
QFontMetrics fm(font);
QString itemText = fm.elidedText(itemData.text, Qt::ElideRight, textRectWidth);
painter->drawText(textRect, itemText);
switch (result) {
case ResultState::Connected:
drawResultState(painter, rect);
break;
case ResultState::Connecting:
drawWaitingState(painter, rect, index.data(DegreeDataRole).toInt());
break;
default:
break;
}
}
QSize DevItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index)
return QSize(option.rect.width(), ITEM_HEIGHT);
}
void DevItemDelegate::drawWaitingState(QPainter *painter, const QRect &rect, int degree) const
{
int left = rect.width() - ITEM_SPACE;
int top = rect.top() + rect.height() / 2 - ICON_HEIGHT / 2;
QRect newRect(left, top, ICON_WIDTH, ICON_HEIGHT);
painter->setRenderHint(QPainter::Antialiasing, true);
QList<QList<QColor>> indicatorColors;
for (int i = 0; i < 3; i++)
indicatorColors << createDefaultIndicatorColorList(QColor("#0081FF"));
double radius = 16 * 0.66;
auto center = QRectF(newRect).center();
auto indicatorRadius = radius / 2 / 2 * 1.1;
auto indicatorDegreeDelta = 360 / indicatorColors.count();
for (int i = 0; i < indicatorColors.count(); ++i) {
QList<QColor> colors = indicatorColors.value(i);
for (int j = 0; j < colors.count(); ++j) {
double degreeCurrent = degree - j * INDICATOR_SHADOW_OFFSET + indicatorDegreeDelta * i;
auto x = (radius - indicatorRadius) * qCos(qDegreesToRadians(degreeCurrent));
auto y = (radius - indicatorRadius) * qSin(qDegreesToRadians(degreeCurrent));
x = center.x() + x;
y = center.y() + y;
auto tl = QPointF(x - 1 * indicatorRadius, y - 1 * indicatorRadius);
QRectF rf(tl.x(), tl.y(), indicatorRadius * 2, indicatorRadius * 2);
QPainterPath path;
path.addEllipse(rf);
painter->fillPath(path, colors.value(j));
}
}
}
void DevItemDelegate::drawResultState(QPainter *painter, const QRect &rect) const
{
// 绘制对勾,14x12
int left = rect.width() - ITEM_SPACE;
int top = rect.top() + rect.height() / 2 - 6;
QPainterPath path;
path.moveTo(left, top + 6);
path.lineTo(left + 4, top + 11);
path.lineTo(left + 12, top + 1);
painter->drawPath(path);
}
QList<QColor> DevItemDelegate::createDefaultIndicatorColorList(QColor color) const
{
QList<QColor> colors;
QList<int> opacitys;
opacitys << 100 << 30 << 15 << 10 << 5 << 4 << 3 << 2 << 1;
for (int i = 0; i < opacitys.count(); ++i) {
color.setAlpha(255 * opacitys.value(i) / 100);
colors << color;
}
return colors;
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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/>.
*/
#ifndef DEVITEMDELEGATE_H
#define DEVITEMDELEGATE_H
#include <DStyledItemDelegate>
/*!
* \brief The DevItemDelegate class
*/
class DevItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
enum DevItemDataRole {
StaticDataRole = Qt::UserRole + 1, // 静态信息
MachinePathDataRole = Qt::UserRole + 2, // machinePath, 可唯一代表一个设备
DegreeDataRole = Qt::UserRole + 3, // degree 绘制waiting使用的参数
ResultDataRole = Qt::UserRole + 4 // 连接结果
};
enum ResultState {
None,
Connecting,
Connected
};
struct DevItemData {
QString checkedIconPath;
QString iconPath;
QString text;
};
public:
explicit DevItemDelegate(QObject *parent = nullptr);
protected:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
private:
void drawWaitingState(QPainter *painter, const QRect &rect, int degree) const;
void drawResultState(QPainter *painter, const QRect &rect) const;
QList<QColor> createDefaultIndicatorColorList(QColor color) const;
};
Q_DECLARE_METATYPE(DevItemDelegate::DevItemData)
#endif // DEVITEMDELEGATE_H

View File

@ -0,0 +1,3 @@
{
"api": "2.0.0"
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* 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 "displayplugin.h"
#include "brightnesswidget.h"
#include "displaysettingwidget.h"
#include "brightnesswidget.h"
#include "brightnessmodel.h"
#include "../../widgets/tipswidget.h"
#include "../../frame/util/utils.h"
#include <DDBusSender>
#include <QDebug>
#include <QDBusConnectionInterface>
#include <unistd.h>
#define PLUGIN_STATE_KEY "enable"
#define TIME_FORMAT_KEY "Use24HourFormat"
using namespace Dock;
DisplayPlugin::DisplayPlugin(QObject *parent)
: QObject(parent)
, m_displayWidget(nullptr)
, m_displaySettingWidget(nullptr)
, m_displayTips(nullptr)
, m_model(new BrightnessModel(this))
{
}
const QString DisplayPlugin::pluginName() const
{
return "display";
}
const QString DisplayPlugin::pluginDisplayName() const
{
return tr("brightness");
}
void DisplayPlugin::init(PluginProxyInterface *proxyInter)
{
if (m_proxyInter == proxyInter)
return;
m_proxyInter = proxyInter;
m_displayTips.reset(new TipsWidget);
m_displayWidget.reset(new BrightnessWidget(m_model));
m_displayWidget->setFixedHeight(60);
m_displaySettingWidget.reset(new DisplaySettingWidget);
m_proxyInter->itemAdded(this, pluginName());
connect(m_displayWidget.data(), &BrightnessWidget::brightClicked, this, [ this ] {
m_proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, true);
});
}
QWidget *DisplayPlugin::itemWidget(const QString &itemKey)
{
if (itemKey == QUICK_ITEM_KEY) {
return m_displayWidget.data();
}
return nullptr;
}
QWidget *DisplayPlugin::itemTipsWidget(const QString &itemKey)
{
Q_UNUSED(itemKey);
return m_displayTips.data();
}
QWidget *DisplayPlugin::itemPopupApplet(const QString &itemKey)
{
if (itemKey == QUICK_ITEM_KEY)
return m_displaySettingWidget.data();
return nullptr;
}
PluginFlags DisplayPlugin::flags() const
{
return PluginFlag::Type_Common | PluginFlag::Quick_Full;
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* 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/>.
*/
#ifndef DISPLAYPLUGIN_H
#define DISPLAYPLUGIN_H
#include "pluginsiteminterface.h"
#include <QTimer>
#include <QLabel>
#include <QSettings>
namespace Dock{
class TipsWidget;
}
class BrightnessWidget;
class BrightnessModel;
class DisplaySettingWidget;
class DisplayPlugin : public QObject, PluginsItemInterface
{
Q_OBJECT
Q_INTERFACES(PluginsItemInterface)
Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "display.json")
public:
explicit DisplayPlugin(QObject *parent = nullptr);
const QString pluginName() const override;
const QString pluginDisplayName() const override;
void init(PluginProxyInterface *proxyInter) override;
QWidget *itemWidget(const QString &itemKey) override;
QWidget *itemTipsWidget(const QString &itemKey) override;
QWidget *itemPopupApplet(const QString &itemKey) override;
PluginFlags flags() const override;
private:
QScopedPointer<BrightnessWidget> m_displayWidget;
QScopedPointer<DisplaySettingWidget> m_displaySettingWidget;
QScopedPointer<Dock::TipsWidget> m_displayTips;
BrightnessModel *m_model;
};
#endif // DATETIMEPLUGIN_H

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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 "displaysettingwidget.h"
#include "brightnessadjwidget.h"
#include "devcollaborationwidget.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <DDBusSender>
const int ItemSpacing = 10;
DisplaySettingWidget::DisplaySettingWidget(QWidget *parent)
: QWidget(parent)
, m_brightnessAdjWidget(new BrightnessAdjWidget(this))
, m_collaborationWidget(new DevCollaborationWidget(this))
, m_settingBtn(new QPushButton(tr("Display setting"), this))
{
initUI();
connect(m_settingBtn, &QPushButton::clicked, this, [ this ](){
DDBusSender().service("org.deepin.dde.ControlCenter1")
.path("/org/deepin/dde/ControlCenter1")
.interface("org.deepin.dde.ControlCenter1")
.method("ShowPage").arg(QString("display")).call();
hide();
});
}
void DisplaySettingWidget::initUI()
{
setContentsMargins(0, 10, 0, 30);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->setMargin(0);
mainLayout->setSpacing(ItemSpacing);
mainLayout->addWidget(m_brightnessAdjWidget);
mainLayout->addWidget(m_collaborationWidget);
mainLayout->addWidget(m_settingBtn);
mainLayout->addStretch();
setLayout(mainLayout);
resizeWidgetHeight();
connect(m_collaborationWidget, &DevCollaborationWidget::sizeChanged,
this, &DisplaySettingWidget::resizeWidgetHeight);
}
void DisplaySettingWidget::resizeWidgetHeight()
{
QMargins margins = this->contentsMargins();
setFixedHeight(margins.top() + margins.bottom() + m_brightnessAdjWidget->height() +
m_collaborationWidget->height() + m_settingBtn->height() + ItemSpacing * 2);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author: zhaoyingzhen <zhaoyingzhen@uniontech.com>
*
* Maintainer: zhaoyingzhen <zhaoyingzhen@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/>.
*/
#ifndef DISPLAY_SETTING_WIDGET_H
#define DISPLAY_SETTING_WIDGET_H
#include <QWidget>
class QPushButton;
class BrightnessAdjWidget;
class DevCollaborationWidget;
/*!
* \brief The DisplaySettingWidget class
* -->-->
*/
class DisplaySettingWidget : public QWidget
{
Q_OBJECT
public:
explicit DisplaySettingWidget(QWidget *parent = nullptr);
private:
void initUI();
void resizeWidgetHeight();
private:
BrightnessAdjWidget *m_brightnessAdjWidget; // 亮度调整
DevCollaborationWidget *m_collaborationWidget; // 跨端协同
QPushButton *m_settingBtn; // 设置按钮
};
#endif // DISPLAY_SETTING_WIDGET_H

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>-mockplus-</title>
<g id="任务栏" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务栏-其他插件" transform="translate(-43.000000, -222.000000)" fill="#FFFFFF" fill-rule="nonzero">
<g id="声音" transform="translate(23.000000, 50.000000)">
<g id="-mockplus-" transform="translate(10.000000, 162.000000)">
<g id="-mockplus-" transform="translate(10.000000, 10.000000)">
<g id="ICON" transform="translate(1.000000, 1.500000)">
<path d="M7,0 C10.7854517,0 13.8690987,3.00478338 13.995941,6.75935025 L14,7 L14,9.5 C14,9.77614237 13.7761424,10 13.5,10 C13.2545401,10 13.0503916,9.82312484 13.0080557,9.58987563 L13,9.5 L13,7 C13,3.6862915 10.3137085,1 7,1 C3.76160306,1 1.12242824,3.56557489 1.00413847,6.77506174 L1,7 L1,9.5 C1,9.77614237 0.776142375,10 0.5,10 C0.254540111,10 0.0503916296,9.82312484 0.00805566941,9.58987563 L0,9.5 L0,7 C0,3.13400675 3.13400675,0 7,0 Z M3.5,7 C4.32842712,7 5,7.67157288 5,8.5 L5,11.5 C5,12.3284271 4.32842712,13 3.5,13 C2.67157288,13 2,12.3284271 2,11.5 L2,8.5 C2,7.67157288 2.67157288,7 3.5,7 Z M10.5,7 C11.3284271,7 12,7.67157288 12,8.5 L12,11.5 C12,12.3284271 11.3284271,13 10.5,13 C9.67157288,13 9,12.3284271 9,11.5 L9,8.5 C9,7.67157288 9.67157288,7 10.5,7 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>-mockplus-</title>
<g id="任务栏" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务栏-其他插件" transform="translate(-34.000000, -680.000000)" fill="#000000" fill-rule="nonzero">
<g id="蓝牙" transform="translate(14.000000, 580.000000)">
<g id="-mockplus-" transform="translate(10.000000, 90.000000)">
<g id="-mockplus-" transform="translate(10.000000, 10.000000)">
<g id="ICON" transform="translate(1.000000, 1.500000)">
<path d="M7,0 C10.7854517,0 13.8690987,3.00478338 13.995941,6.75935025 L14,7 L14,9.5 C14,9.77614237 13.7761424,10 13.5,10 C13.2545401,10 13.0503916,9.82312484 13.0080557,9.58987563 L13,9.5 L13,7 C13,3.6862915 10.3137085,1 7,1 C3.76160306,1 1.12242824,3.56557489 1.00413847,6.77506174 L1,7 L1,9.5 C1,9.77614237 0.776142375,10 0.5,10 C0.254540111,10 0.0503916296,9.82312484 0.00805566941,9.58987563 L0,9.5 L0,7 C0,3.13400675 3.13400675,0 7,0 Z M3.5,7 C4.32842712,7 5,7.67157288 5,8.5 L5,11.5 C5,12.3284271 4.32842712,13 3.5,13 C2.67157288,13 2,12.3284271 2,11.5 L2,8.5 C2,7.67157288 2.67157288,7 3.5,7 Z M10.5,7 C11.3284271,7 12,7.67157288 12,8.5 L12,11.5 C12,12.3284271 11.3284271,13 10.5,13 C9.67157288,13 9,12.3284271 9,11.5 L9,8.5 C9,7.67157288 9.67157288,7 10.5,7 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>-mockplus-</title>
<g id="任务栏" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务栏-其他插件" transform="translate(-393.000000, -176.000000)" fill="#000000" fill-rule="nonzero">
<g id="声音" transform="translate(373.000000, 50.000000)">
<g id="-mockplus-" transform="translate(10.000000, 116.000000)">
<g id="-mockplus-" transform="translate(10.000000, 10.000000)">
<g id="ICON" transform="translate(0.000000, 2.000000)">
<path d="M13,0 C14.1045695,-2.02906125e-16 15,0.8954305 15,2 L15,10 L15.5,10 C15.7761424,10 16,10.2238576 16,10.5 C16,10.7761424 15.7761424,11 15.5,11 L0.5,11 C0.223857625,11 3.38176876e-17,10.7761424 0,10.5 C-3.38176876e-17,10.2238576 0.223857625,10 0.5,10 L1,10 L1,2 C1,0.8954305 1.8954305,2.02906125e-16 3,0 L13,0 Z M13,0.999999998 L3,0.999999998 C2.44771525,0.999999998 2,1.44771525 2,2 L2,2 L2,8 C2,8.55228475 2.44771525,9 3,9 L3,9 L13,9 C13.5522847,9 14,8.55228475 14,8 L14,8 L14,2 C14,1.44771525 13.5522847,0.999999998 13,0.999999998 L13,0.999999998 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>-mockplus-</title>
<g id="任务栏" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务栏-其他插件" transform="translate(-43.000000, -176.000000)" fill="#000000" fill-rule="nonzero">
<g id="声音" transform="translate(23.000000, 50.000000)">
<g id="-mockplus-" transform="translate(10.000000, 116.000000)">
<g id="-mockplus-" transform="translate(10.000000, 10.000000)">
<g id="ICON" transform="translate(0.000000, 2.000000)">
<path d="M13,0 C14.1045695,-2.02906125e-16 15,0.8954305 15,2 L15,10 L15.5,10 C15.7761424,10 16,10.2238576 16,10.5 C16,10.7761424 15.7761424,11 15.5,11 L0.5,11 C0.223857625,11 3.38176876e-17,10.7761424 0,10.5 C-3.38176876e-17,10.2238576 0.223857625,10 0.5,10 L1,10 L1,2 C1,0.8954305 1.8954305,2.02906125e-16 3,0 L13,0 Z M13,0.999999998 L3,0.999999998 C2.44771525,0.999999998 2,1.44771525 2,2 L2,2 L2,8 C2,8.55228475 2.44771525,9 3,9 L3,9 L13,9 C13.5522847,9 14,8.55228475 14,8 L14,8 L14,2 C14,1.44771525 13.5522847,0.999999998 13,0.999999998 L13,0.999999998 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ICON / MenuItem / Brightness+</title>
<g id="任务栏" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务栏-时尚" transform="translate(-738.000000, -914.000000)" fill="#000000" fill-rule="nonzero">
<g id="UDE-/-ControlPanel" transform="translate(712.000000, 534.000000)">
<g id="编组-5" transform="translate(10.000000, 360.000000)">
<g id="ICON-/-MenuItem-/-Brightness+" transform="translate(16.000000, 20.000000)">
<path d="M10.125,15.625 C10.4011424,15.625 10.625,15.8488576 10.625,16.125 L10.625,18.875 C10.625,19.1511424 10.4011424,19.375 10.125,19.375 L9.875,19.375 C9.59885763,19.375 9.375,19.1511424 9.375,18.875 L9.375,16.125 C9.375,15.8488576 9.59885763,15.625 9.875,15.625 L10.125,15.625 Z M14.7729708,13.8890873 L16.7175144,15.8336309 C16.9127766,16.0288931 16.9127766,16.3454756 16.7175144,16.5407377 L16.5407377,16.7175144 C16.3454756,16.9127766 16.0288931,16.9127766 15.8336309,16.7175144 L13.8890873,14.7729708 C13.6938252,14.5777086 13.6938252,14.2611261 13.8890873,14.065864 L14.065864,13.8890873 C14.2611261,13.6938252 14.5777086,13.6938252 14.7729708,13.8890873 Z M5.93413601,13.8890873 L6.1109127,14.065864 C6.30617485,14.2611261 6.30617485,14.5777086 6.1109127,14.7729708 L4.16636906,16.7175144 C3.97110691,16.9127766 3.65452442,16.9127766 3.45926227,16.7175144 L3.28248558,16.5407377 C3.08722343,16.3454756 3.08722343,16.0288931 3.28248558,15.8336309 L5.22702923,13.8890873 C5.42229137,13.6938252 5.73887386,13.6938252 5.93413601,13.8890873 Z M10,5.625 C12.4162458,5.625 14.375,7.58375422 14.375,10 C14.375,12.4162458 12.4162458,14.375 10,14.375 C7.58375422,14.375 5.625,12.4162458 5.625,10 C5.625,7.58375422 7.58375422,5.625 10,5.625 Z M18.875,9.375 C19.1511424,9.375 19.375,9.59885763 19.375,9.875 L19.375,10.125 C19.375,10.4011424 19.1511424,10.625 18.875,10.625 L16.125,10.625 C15.8488576,10.625 15.625,10.4011424 15.625,10.125 L15.625,9.875 C15.625,9.59885763 15.8488576,9.375 16.125,9.375 L18.875,9.375 Z M3.875,9.375 C4.15114237,9.375 4.375,9.59885763 4.375,9.875 L4.375,10.125 C4.375,10.4011424 4.15114237,10.625 3.875,10.625 L1.125,10.625 C0.848857625,10.625 0.625,10.4011424 0.625,10.125 L0.625,9.875 C0.625,9.59885763 0.848857625,9.375 1.125,9.375 L3.875,9.375 Z M16.5407377,3.28248558 L16.7175144,3.45926227 C16.9127766,3.65452442 16.9127766,3.97110691 16.7175144,4.16636906 L14.7729708,6.1109127 C14.5777086,6.30617485 14.2611261,6.30617485 14.065864,6.1109127 L13.8890873,5.93413601 C13.6938252,5.73887386 13.6938252,5.42229137 13.8890873,5.22702923 L15.8336309,3.28248558 C16.0288931,3.08722343 16.3454756,3.08722343 16.5407377,3.28248558 Z M4.16636906,3.28248558 L6.1109127,5.22702923 C6.30617485,5.42229137 6.30617485,5.73887386 6.1109127,5.93413601 L5.93413601,6.1109127 C5.73887386,6.30617485 5.42229137,6.30617485 5.22702923,6.1109127 L3.28248558,4.16636906 C3.08722343,3.97110691 3.08722343,3.65452442 3.28248558,3.45926227 L3.45926227,3.28248558 C3.65452442,3.08722343 3.97110691,3.08722343 4.16636906,3.28248558 Z M10.125,0.625 C10.4011424,0.625 10.625,0.848857625 10.625,1.125 L10.625,3.875 C10.625,4.15114237 10.4011424,4.375 10.125,4.375 L9.875,4.375 C9.59885763,4.375 9.375,4.15114237 9.375,3.875 L9.375,1.125 C9.375,0.848857625 9.59885763,0.625 9.875,0.625 L10.125,0.625 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="#536076" fill-rule="evenodd" d="M11.5,18 C11.7761424,18 12,18.2238576 12,18.5 L12,20.5 C12,20.7761424 11.7761424,21 11.5,21 C11.2238576,21 11,20.7761424 11,20.5 L11,18.5 C11,18.2238576 11.2238576,18 11.5,18 Z M17.8121778,14.5669873 L19.5442286,15.5669873 C19.7833749,15.7050585 19.8653125,16.0108537 19.7272413,16.25 C19.5891701,16.4891463 19.2833749,16.5710839 19.0442286,16.4330127 L17.3121778,15.4330127 C17.0730315,15.2949415 16.9910939,14.9891463 17.1291651,14.75 C17.2672363,14.5108537 17.5730315,14.4289161 17.8121778,14.5669873 Z M5.87083488,14.75 C6.00890606,14.9891463 5.92696849,15.2949415 5.68782217,15.4330127 L3.95577137,16.4330127 C3.71662505,16.5710839 3.41082985,16.4891463 3.27275866,16.25 C3.13468748,16.0108537 3.21662505,15.7050585 3.45577137,15.5669873 L5.18782217,14.5669873 C5.42696849,14.4289161 5.73276369,14.5108537 5.87083488,14.75 Z M11.5,7 C13.9852814,7 16,9.01471863 16,11.5 C16,13.9852814 13.9852814,16 11.5,16 C9.01471863,16 7,13.9852814 7,11.5 C7,9.01471863 9.01471863,7 11.5,7 Z M19.7272413,6.75 C19.8653125,6.98914631 19.7833749,7.29494151 19.5442286,7.4330127 L17.8121778,8.4330127 C17.5730315,8.57108389 17.2672363,8.48914631 17.1291651,8.25 C16.9910939,8.01085369 17.0730315,7.70505849 17.3121778,7.5669873 L19.0442286,6.5669873 C19.2833749,6.42891611 19.5891701,6.51085369 19.7272413,6.75 Z M3.95577137,6.5669873 L5.68782217,7.5669873 C5.92696849,7.70505849 6.00890606,8.01085369 5.87083488,8.25 C5.73276369,8.48914631 5.42696849,8.57108389 5.18782217,8.4330127 L3.45577137,7.4330127 C3.21662505,7.29494151 3.13468748,6.98914631 3.27275866,6.75 C3.41082985,6.51085369 3.71662505,6.42891611 3.95577137,6.5669873 Z M11.5,2 C11.7761424,2 12,2.22385763 12,2.5 L12,4.5 C12,4.77614237 11.7761424,5 11.5,5 C11.2238576,5 11,4.77614237 11,4.5 L11,2.5 C11,2.22385763 11.2238576,2 11.5,2 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="24" viewBox="0 0 25 24">
<path fill="#536076" fill-rule="evenodd" d="M11.5,17 C11.7761424,17 12,17.2238576 12,17.5 L12,18.5 C12,18.7761424 11.7761424,19 11.5,19 C11.2238576,19 11,18.7761424 11,18.5 L11,17.5 C11,17.2238576 11.2238576,17 11.5,17 Z M16.9461524,14.0669873 L17.8121778,14.5669873 C18.0513241,14.7050585 18.1332617,15.0108537 17.9951905,15.25 C17.8571193,15.4891463 17.5513241,15.5710839 17.3121778,15.4330127 L16.4461524,14.9330127 C16.2070061,14.7949415 16.1250685,14.4891463 16.2631397,14.25 C16.4012109,14.0108537 16.7070061,13.9289161 16.9461524,14.0669873 Z M6.73686028,14.25 C6.87493147,14.4891463 6.79299389,14.7949415 6.55384758,14.9330127 L5.68782217,15.4330127 C5.44867586,15.5710839 5.14288066,15.4891463 5.00480947,15.25 C4.86673828,15.0108537 4.94867586,14.7050585 5.18782217,14.5669873 L6.05384758,14.0669873 C6.29299389,13.9289161 6.59878909,14.0108537 6.73686028,14.25 Z M11.5,8 C13.4329966,8 15,9.56700338 15,11.5 C15,13.4329966 13.4329966,15 11.5,15 C9.56700338,15 8,13.4329966 8,11.5 C8,9.56700338 9.56700338,8 11.5,8 Z M17.9951905,7.75 C18.1332617,7.98914631 18.0513241,8.29494151 17.8121778,8.4330127 L16.9461524,8.9330127 C16.7070061,9.07108389 16.4012109,8.98914631 16.2631397,8.75 C16.1250685,8.51085369 16.2070061,8.20505849 16.4461524,8.0669873 L17.3121778,7.5669873 C17.5513241,7.42891611 17.8571193,7.51085369 17.9951905,7.75 Z M5.68782217,7.5669873 L6.55384758,8.0669873 C6.79299389,8.20505849 6.87493147,8.51085369 6.73686028,8.75 C6.59878909,8.98914631 6.29299389,9.07108389 6.05384758,8.9330127 L5.18782217,8.4330127 C4.94867586,8.29494151 4.86673828,7.98914631 5.00480947,7.75 C5.14288066,7.51085369 5.44867586,7.42891611 5.68782217,7.5669873 Z M11.5,4 C11.7761424,4 12,4.22385763 12,4.5 L12,5.5 C12,5.77614237 11.7761424,6 11.5,6 C11.2238576,6 11,5.77614237 11,5.5 L11,4.5 C11,4.22385763 11.2238576,4 11.5,4 Z" transform="translate(1)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="20px" viewBox="0 0 18 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ICON / MenuItem / Broadcast</title>
<g id="任务栏" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务栏-时尚" transform="translate(-993.000000, -844.000000)" fill="#000000" fill-rule="nonzero">
<g id="UDE-/-ControlPanel" transform="translate(712.000000, 534.000000)">
<g id="编组-4" transform="translate(10.000000, 290.000000)">
<g id="形状结合" transform="translate(268.000000, 18.000000)">
<path d="M12,14 L20,22 L4,22 L12,14 Z M12,2 C16.9705627,2 21,6.02943725 21,11 C21,13.8342485 19.6898859,16.3625035 17.642214,18.0122085 L16.8031599,17.146139 C18.6274776,15.7184347 19.8,13.496146 19.8,11 C19.8,6.69217895 16.307821,3.2 12,3.2 C7.69217895,3.2 4.2,6.69217895 4.2,11 C4.2,13.4965987 5.37294772,15.7192407 7.19783267,17.1469157 L6.35879863,18.0130242 C4.31054605,16.3633369 3,13.8347157 3,11 C3,6.02943725 7.02943725,2 12,2 Z M12,5 C15.3137085,5 18,7.6862915 18,11 C18,12.9892946 17.0318944,14.752476 15.541118,15.8441093 L14.6955445,14.9722251 C15.9657118,14.1086147 16.8,12.6517366 16.8,11 C16.8,8.3490332 14.6509668,6.2 12,6.2 C9.3490332,6.2 7.2,8.3490332 7.2,11 C7.2,12.652163 8.03471909,14.109367 9.30543941,14.9728939 L8.4598839,15.8448429 C6.96853942,14.753266 6,12.9897402 6,11 C6,7.6862915 8.6862915,5 12,5 Z M12,8 C13.6568542,8 15,9.34314575 15,11 C15,12.1468362 14.356487,13.1433719 13.4108513,13.6482168 L12,12.1937608 L10.5901445,13.6487482 C9.6439648,13.1440714 9,12.1472387 9,11 C9,9.34314575 10.3431458,8 12,8 Z"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,12 @@
<RCC>
<qresource prefix="/">
<file>brightness.svg</file>
<file>brightnesshigh.svg</file>
<file>brightnesslow.svg</file>
<file>broadcast.svg</file>
<file>ICON_Device_Headphone_dark.svg</file>
<file>ICON_Device_Headphone.svg</file>
<file>ICON_Device_Laptop_dark.svg</file>
<file>ICON_Device_Laptop.svg</file>
</qresource>
</RCC>