From 6d209d8ddb87d0a42a260a44b337b8c67ea3c482 Mon Sep 17 00:00:00 2001 From: donghualin Date: Tue, 17 May 2022 20:57:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=A0=8Fbug=EF=BC=8C=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.增加license 2.修复bug 3.UI调整 Log: 优化任务栏代码 Influence: v23任务栏 Task: https://pms.uniontech.com/task-view-112073.html Change-Id: Ic66428699f6060d8b0baefa3dbc2d3603d320242 --- frame/controller/quicksettingcontroller.cpp | 24 +- frame/controller/quicksettingcontroller.h | 26 +- frame/item/pluginsitem.cpp | 5 + frame/item/quicksettingitem.cpp | 22 +- frame/item/quicksettingitem.h | 20 + frame/model/brightnessmodel.cpp | 47 +- frame/model/brightnessmodel.h | 16 +- frame/model/mediaplayermodel.h | 10 +- frame/model/volumemodel.cpp | 313 +++---------- frame/model/volumemodel.h | 54 +-- frame/util/abstractpluginscontroller.cpp | 11 + frame/util/abstractpluginscontroller.h | 3 + .../components/brightnessmonitorwidget.cpp | 42 +- .../components/brightnessmonitorwidget.h | 20 + frame/window/components/brightnesswidget.cpp | 37 +- frame/window/components/brightnesswidget.h | 22 +- frame/window/components/datetimedisplayer.cpp | 164 ++++--- frame/window/components/datetimedisplayer.h | 52 ++- frame/window/components/mediawidget.cpp | 20 + frame/window/components/mediawidget.h | 20 + frame/window/components/settingdelegate.cpp | 20 + frame/window/components/settingdelegate.h | 26 +- .../window/components/volumedeviceswidget.cpp | 30 +- frame/window/components/volumedeviceswidget.h | 20 + frame/window/components/volumewidget.cpp | 20 + frame/window/components/volumewidget.h | 20 + frame/window/mainpanelcontrol.cpp | 4 +- frame/window/pluginchildpage.cpp | 116 +++++ frame/window/pluginchildpage.h | 61 +++ frame/window/quickpluginwindow.cpp | 411 +++++++++--------- frame/window/quickpluginwindow.h | 47 +- frame/window/quicksettingcontainer.cpp | 240 +++++----- frame/window/quicksettingcontainer.h | 72 ++- frame/window/systempluginwindow.cpp | 34 +- frame/window/systempluginwindow.h | 30 +- frame/window/tray/tray_delegate.cpp | 125 +++++- frame/window/tray/tray_delegate.h | 19 +- frame/window/tray/tray_gridview.cpp | 163 ++++++- frame/window/tray/tray_gridview.h | 28 +- frame/window/tray/tray_model.cpp | 74 +++- frame/window/tray/tray_model.h | 45 +- frame/window/tray/tray_monitor.cpp | 20 + frame/window/tray/tray_monitor.h | 32 +- frame/window/tray/widgets/basetraywidget.cpp | 9 +- frame/window/tray/widgets/basetraywidget.h | 7 +- .../window/tray/widgets/expandiconwidget.cpp | 190 +++++--- frame/window/tray/widgets/expandiconwidget.h | 59 ++- frame/window/tray/widgets/indicatorplugin.cpp | 43 +- frame/window/tray/widgets/indicatorplugin.h | 20 + .../window/tray/widgets/indicatortrayitem.cpp | 146 +------ frame/window/tray/widgets/indicatortrayitem.h | 17 +- frame/window/traymanagerwindow.cpp | 165 ++++--- frame/window/traymanagerwindow.h | 23 + 53 files changed, 2077 insertions(+), 1187 deletions(-) create mode 100644 frame/window/pluginchildpage.cpp create mode 100644 frame/window/pluginchildpage.h diff --git a/frame/controller/quicksettingcontroller.cpp b/frame/controller/quicksettingcontroller.cpp index dfb444423..71150e1fa 100644 --- a/frame/controller/quicksettingcontroller.cpp +++ b/frame/controller/quicksettingcontroller.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "quicksettingcontroller.h" #include "quicksettingitem.h" @@ -26,7 +46,7 @@ void QuickSettingController::itemAdded(PluginsItemInterface * const itemInter, c m_quickSettingItems << quickItem; - emit pluginInsert(quickItem); + emit pluginInserted(quickItem); } void QuickSettingController::itemUpdate(PluginsItemInterface * const itemInter, const QString &) @@ -51,7 +71,7 @@ void QuickSettingController::itemRemoved(PluginsItemInterface * const itemInter, if (findItemIterator != m_quickSettingItems.end()) { QuickSettingItem *quickItem = *findItemIterator; m_quickSettingItems.removeOne(quickItem); - Q_EMIT pluginRemove(quickItem); + Q_EMIT pluginRemoved(quickItem); quickItem->deleteLater(); } } diff --git a/frame/controller/quicksettingcontroller.h b/frame/controller/quicksettingcontroller.h index aaafa91cc..10bc312b1 100644 --- a/frame/controller/quicksettingcontroller.h +++ b/frame/controller/quicksettingcontroller.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef QUICKSETTINGCONTROLLER_H #define QUICKSETTINGCONTROLLER_H @@ -14,12 +34,12 @@ public: const QList &settingItems() const { return m_quickSettingItems; } Q_SIGNALS: - void pluginInsert(QuickSettingItem *); - void pluginRemove(QuickSettingItem *); + void pluginInserted(QuickSettingItem *); + void pluginRemoved(QuickSettingItem *); protected: void startLoader(); - QuickSettingController(QObject *parent = Q_NULLPTR); + explicit QuickSettingController(QObject *parent = Q_NULLPTR); ~QuickSettingController() override; protected: diff --git a/frame/item/pluginsitem.cpp b/frame/item/pluginsitem.cpp index 9ff61e1f9..43ec245b3 100644 --- a/frame/item/pluginsitem.cpp +++ b/frame/item/pluginsitem.cpp @@ -24,6 +24,8 @@ #include "pluginsiteminterface.h" #include "utils.h" +#include + #include #include #include @@ -328,10 +330,13 @@ StretchPluginsItem::StretchPluginsItem(PluginsItemInterface * const pluginInter, : PluginsItem (pluginInter, itemKey, plginApi, parent) , m_nameLabel(new QLabel(this)) { + m_nameLabel->setFont(DFontSizeManager::instance()->t10()); m_nameLabel->setText(pluginInter->pluginDisplayName()); m_nameLabel->setAlignment(Qt::AlignCenter); QBoxLayout *mainLayout = static_cast(layout()); + mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); + mainLayout->addSpacing(10); mainLayout->addWidget(m_nameLabel); } diff --git a/frame/item/quicksettingitem.cpp b/frame/item/quicksettingitem.cpp index 0d2da9967..7cf401bb5 100644 --- a/frame/item/quicksettingitem.cpp +++ b/frame/item/quicksettingitem.cpp @@ -1,4 +1,24 @@ -#include "quicksettingitem.h" +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ +#include "quicksettingitem.h" #include "pluginsiteminterface.h" #include diff --git a/frame/item/quicksettingitem.h b/frame/item/quicksettingitem.h index 185000415..1d1eb47c4 100644 --- a/frame/item/quicksettingitem.h +++ b/frame/item/quicksettingitem.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef QUICKSETTINGITEM_H #define QUICKSETTINGITEM_H diff --git a/frame/model/brightnessmodel.cpp b/frame/model/brightnessmodel.cpp index 8bc884c42..33efb327d 100644 --- a/frame/model/brightnessmodel.cpp +++ b/frame/model/brightnessmodel.cpp @@ -43,10 +43,11 @@ BrightnessModel::BrightnessModel(QObject *parent) QDBusInterface dbusInter(serviceName, servicePath, serviceInterface, QDBusConnection::sessionBus()); if (dbusInter.isValid()) { // 读取所有的屏幕的信息 - QString primaryScreenName = qApp->primaryScreen() ? qApp->primaryScreen()->name() : QString(); + QString primaryScreenName = dbusInter.property("Primary").value(); QList paths = dbusInter.property("Monitors").value>(); for (QDBusObjectPath path : paths) { BrightMonitor *monitor = new BrightMonitor(path.path(), this); + monitor->setPrimary(primaryScreenName == monitor->name()); m_monitor << monitor; connect(monitor, &BrightMonitor::brightnessChanged, this, [ = ] { Q_EMIT brightnessChanged(monitor); @@ -54,8 +55,7 @@ BrightnessModel::BrightnessModel(QObject *parent) } } - QDBusConnection::sessionBus().connect(serviceName, servicePath, propertiesInterface, - "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); + connect(qApp, &QApplication::primaryScreenChanged, this, &BrightnessModel::primaryScreenChanged); } BrightnessModel::~BrightnessModel() @@ -67,6 +67,16 @@ QList BrightnessModel::monitors() return m_monitor; } +BrightMonitor *BrightnessModel::primaryMonitor() const +{ + for (BrightMonitor *monitor : m_monitor) { + if (monitor->isPrimary()) + return monitor; + } + + return nullptr; +} + void BrightnessModel::setBrightness(BrightMonitor *monitor, int brightness) { setBrightness(monitor->name(), brightness); @@ -88,19 +98,17 @@ QDBusMessage BrightnessModel::callMethod(const QString &methodName, const QList< return QDBusMessage(); } -void BrightnessModel::onPropertyChanged(const QDBusMessage &msg) +void BrightnessModel::primaryScreenChanged(QScreen *screen) { - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName != serviceInterface) - return; - - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - if (changedProps.contains("Brightness")) { + 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); } /** @@ -111,6 +119,7 @@ BrightMonitor::BrightMonitor(QString path, 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()) { @@ -128,6 +137,11 @@ BrightMonitor::~BrightMonitor() { } +void BrightMonitor::setPrimary(bool primary) +{ + m_isPrimary = primary; +} + int BrightMonitor::brihtness() { return m_brightness; @@ -143,6 +157,11 @@ QString BrightMonitor::name() return m_name; } +bool BrightMonitor::isPrimary() +{ + return m_isPrimary; +} + void BrightMonitor::onPropertyChanged(const QDBusMessage &msg) { QList arguments = msg.arguments(); diff --git a/frame/model/brightnessmodel.h b/frame/model/brightnessmodel.h index b220c67f2..e22549cd9 100644 --- a/frame/model/brightnessmodel.h +++ b/frame/model/brightnessmodel.h @@ -26,27 +26,30 @@ class BrightMonitor; class QDBusMessage; +class QScreen; class BrightnessModel : public QObject { Q_OBJECT -Q_SIGNALS: - void brightnessChanged(BrightMonitor *); - public: explicit BrightnessModel(QObject *parent = nullptr); ~BrightnessModel(); QList monitors(); + BrightMonitor *primaryMonitor() const; void setBrightness(BrightMonitor *monitor, int brightness); void setBrightness(QString name, int brightness); +Q_SIGNALS: + void brightnessChanged(BrightMonitor *); + void primaryChanged(BrightMonitor *); + protected: QDBusMessage callMethod(const QString &methodName, const QList &argument); protected Q_SLOTS: - void onPropertyChanged(const QDBusMessage &msg); + void primaryScreenChanged(QScreen *screen); private: QList m_monitor; @@ -67,12 +70,14 @@ public: int brihtness(); bool enabled(); QString name(); - //bool isDefault(); + bool isPrimary(); protected: explicit BrightMonitor(QString path, QObject *parent); ~BrightMonitor(); + void setPrimary(bool primary); + protected Q_SLOTS: void onPropertyChanged(const QDBusMessage &msg); @@ -81,6 +86,7 @@ private: QString m_name; int m_brightness; bool m_enabled; + bool m_isPrimary; }; #endif // DISPLAYMODEL_H diff --git a/frame/model/mediaplayermodel.h b/frame/model/mediaplayermodel.h index 9dff56df8..880ea2270 100644 --- a/frame/model/mediaplayermodel.h +++ b/frame/model/mediaplayermodel.h @@ -24,11 +24,6 @@ public: Stop }; -Q_SIGNALS: - void startStop(bool); - void statusChanged(const PlayStatus &); - void metadataChanged(); - public: static MediaPlayerModel *instance(); bool isActived(); @@ -45,6 +40,11 @@ public: void setStatus(const PlayStatus &stat); void playNext(); +Q_SIGNALS: + void startStop(bool); + void statusChanged(const PlayStatus &); + void metadataChanged(); + protected: explicit MediaPlayerModel(QObject *parent = nullptr); ~MediaPlayerModel(); diff --git a/frame/model/volumemodel.cpp b/frame/model/volumemodel.cpp index 15920020e..45f2b2074 100644 --- a/frame/model/volumemodel.cpp +++ b/frame/model/volumemodel.cpp @@ -1,17 +1,10 @@ #include "volumemodel.h" -#include -#include -#include -#include -#include -#include #include #include #include #include #include -#include /** * @brief 声音控制的类 @@ -20,13 +13,14 @@ static const QString serviceName = QString("com.deepin.daemon.Audio"); static const QString servicePath = QString("/com/deepin/daemon/Audio"); -static const QString interfaceName = QString("com.deepin.daemon.Audio"); -static const QString propertiesInterface = QString("org.freedesktop.DBus.Properties"); VolumeModel::VolumeModel(QObject *parent) : QObject(parent) + , m_audio(new DBusAudio(serviceName, servicePath, QDBusConnection::sessionBus(), this)) { - initService(); + reloadSinks(); + reloadPorts(); + connect(m_audio, &DBusAudio::DefaultSinkChanged, this, &VolumeModel::onDefaultSinkChanged); } VolumeModel::~VolumeModel() @@ -37,7 +31,7 @@ VolumeModel::~VolumeModel() void VolumeModel::setActivePort(AudioPorts *port) { - callMethod("SetPort", { port->cardId(), port->name(), port->direction() }); + m_audio->SetPort(port->cardId(), port->name(), port->direction()); } QList VolumeModel::sinks() const @@ -110,62 +104,14 @@ bool VolumeModel::existActiveOutputDevice() return false; } -void VolumeModel::onPropertyChanged(const QDBusMessage &msg) -{ - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - - QString interName = msg.arguments().at(0).toString(); - if (interName != interfaceName) - return; - - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - if (changedProps.contains("DefaultSink")) { - QVariant defaultSink = changedProps.value("DefaultSink"); - QString defaultSinkPath = defaultSink.value().path(); - for (AudioSink *audioSink : m_sinks) { - if (audioSink->m_devicePath == defaultSinkPath) { - updateDefaultSink(audioSink); - Q_EMIT defaultSinkChanged(audioSink); - break; - } - } - } -} - -void VolumeModel::initService() -{ - QDBusConnection::sessionBus().connect(serviceName, servicePath, propertiesInterface, - "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); - - reloadSinks(); - reloadPorts(); - - QDBusConnectionInterface *dbusInterface = QDBusConnection::sessionBus().interface(); - connect(dbusInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, - [ = ](const QString &name, const QString &, const QString &newOwner) { - if (name == serviceName) { - if (newOwner.isEmpty()) { - QDBusConnection::sessionBus().disconnect(serviceName, servicePath, propertiesInterface, - "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); - clearSinks(); - } else { - QDBusConnection::sessionBus().connect(serviceName, servicePath, propertiesInterface, - "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); - reloadSinks(); - reloadPorts(); - } - } - }); -} - void VolumeModel::reloadSinks() { clearSinks(); - QList sinkPaths = properties>("Sinks"); + const QString defaultSinkPath = m_audio->defaultSink().path(); + QList sinkPaths = m_audio->sinks(); for (const QDBusObjectPath &sinkPath : sinkPaths) { - AudioSink *sink = new AudioSink(sinkPath.path(), this); + const QString path = sinkPath.path(); + AudioSink *sink = new AudioSink(path, (path == defaultSinkPath), this); connect(sink, &AudioSink::volumeChanged, this, [ = ](int volume) { if (sink->isDefault()) Q_EMIT volumeChanged(volume); @@ -182,13 +128,13 @@ void VolumeModel::reloadSinks() void VolumeModel::reloadPorts() { clearPorts(); - QString cards = properties("CardsWithoutUnavailable"); + QString cards = m_audio->cardsWithoutUnavailable(); QJsonParseError error; QJsonDocument json = QJsonDocument::fromJson(cards.toLocal8Bit(), &error); if (error.error != QJsonParseError::NoError) return; - int sinkCardId = -1; + uint sinkCardId = 0; QString sinkCardName; AudioSink *sink = defaultSink(); if (sink) { @@ -199,7 +145,7 @@ void VolumeModel::reloadPorts() QJsonArray array = json.array(); for (const QJsonValue value : array) { QJsonObject cardObject = value.toObject(); - int cardId = cardObject.value("Id").toInt(); + uint cardId = static_cast(cardObject.value("Id").toInt()); QString cardName = cardObject.value("Name").toString(); QJsonArray jPorts = cardObject.value("Ports").toArray(); for (const QJsonValue jPortValue : jPorts) { @@ -223,8 +169,19 @@ void VolumeModel::reloadPorts() } } -void VolumeModel::updateDefaultSink(AudioSink *audioSink) +void VolumeModel::onDefaultSinkChanged(const QDBusObjectPath &value) { + AudioSink *audioSink = nullptr; + const QString defaultPath = value.path(); + for (AudioSink *sink : m_sinks) { + sink->setDefault(defaultPath == sink->m_devicePath); + if (sink->isDefault()) + audioSink = sink; + } + + if (!audioSink) + return; + bool checkChanged = false; for (AudioPorts *port : m_ports) { bool oldChecked = port->isChecked(); @@ -237,6 +194,8 @@ void VolumeModel::updateDefaultSink(AudioSink *audioSink) if (checkChanged) Q_EMIT checkPortChanged(); + + Q_EMIT defaultSinkChanged(audioSink); } void VolumeModel::clearSinks() @@ -255,56 +214,35 @@ void VolumeModel::clearPorts() m_ports.clear(); } -QDBusMessage VolumeModel::callMethod(const QString &methodName, const QList &argument) -{ - QDBusInterface dbusInter(serviceName, servicePath, interfaceName, QDBusConnection::sessionBus()); - if (dbusInter.isValid()) { - QDBusPendingCall reply = dbusInter.asyncCallWithArgumentList(methodName, argument); - reply.waitForFinished(); - return reply.reply(); - } - return QDBusMessage(); -} - -template -T VolumeModel::properties(const QString &propName) -{ - QDBusInterface dbusInter(serviceName, servicePath, interfaceName, QDBusConnection::sessionBus()); - if (dbusInter.isValid()) { - QByteArray ba = propName.toLatin1(); - const char *prop = ba.data(); - return dbusInter.property(prop).value(); - } - - return T(); -} - /** * @brief 具体的声音设备 * @param parent */ -AudioSink::AudioSink(QString path, QObject *parent) +AudioSink::AudioSink(QString path, bool isDefault, QObject *parent) : QObject(parent) , m_devicePath(path) + , m_sink(new DBusSink(serviceName, path, QDBusConnection::sessionBus(), this)) + , m_isDefault(isDefault) { - QDBusConnection::sessionBus().connect(serviceName, path, propertiesInterface, - "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage&))); + connect(m_sink, &DBusSink::MuteChanged, this, &AudioSink::muteChanged); + connect(m_sink, &DBusSink::VolumeChanged, this, [ this ](double value) { + Q_EMIT this->volumeChanged(static_cast(value * 100)); + }); } AudioSink::~AudioSink() { } +void AudioSink::setDefault(bool isDefaultSink) +{ + m_isDefault = isDefaultSink; +} + bool AudioSink::isDefault() { - QDBusInterface dbusInter(serviceName, servicePath, interfaceName, QDBusConnection::sessionBus()); - if (dbusInter.isValid()) { - QString defaultSink = dbusInter.property("DefaultSink").value().path(); - return defaultSink == m_devicePath; - } - - return false; + return m_isDefault; } bool AudioSink::isHeadPhone() @@ -314,216 +252,83 @@ bool AudioSink::isHeadPhone() void AudioSink::setBalance(double value, bool isPlay) { - callMethod("SetBalance", { value, isPlay }); + m_sink->SetBalance(value, isPlay); } void AudioSink::setFade(double value) { - callMethod("SetFade", { value }); + m_sink->SetFade(value); } void AudioSink::setMute(bool mute) { - callMethod("SetMute", { mute }); + m_sink->SetMute(mute); } void AudioSink::setPort(QString name) { - callMethod("SetPort", { name }); + m_sink->SetPort(name); } -void AudioSink::setVolume(double value, bool isPlay) +void AudioSink::setVolume(int value, bool isPlay) { - callMethod("SetVolume", { value * 0.01, isPlay }); + m_sink->SetVolume((value * 0.01), isPlay); } bool AudioSink::isMute() { - return getProperties("Mute"); + return m_sink->mute(); } bool AudioSink::supportBalance() { - return getProperties("SupportBalance"); + return m_sink->supportBalance(); } bool AudioSink::suoportFade() { - return getProperties("SupportFade"); + return m_sink->supportFade(); } double AudioSink::balance() { - return getProperties("Balance"); + return m_sink->balance(); } double AudioSink::baseVolume() { - return getProperties("BaseVolume"); + return m_sink->baseVolume(); } double AudioSink::fade() { - return getProperties("Fade"); + return m_sink->fade(); } int AudioSink::volume() { - return static_cast(getProperties("Volume") * 100); + return static_cast(m_sink->volume() * 100); } QString AudioSink::description() { - QVariantList value = getPropertiesByFreeDesktop("ActivePort"); - if (value.size() >= 2) - return value[1].toString(); - - return getProperties("Description"); + return m_sink->activePort().description; } QString AudioSink::name() { - QVariantList value = getPropertiesByFreeDesktop("ActivePort"); - if (value.size() >= 2) - return value[0].toString(); - - return getProperties("Name"); + return m_sink->activePort().name; } -int AudioSink::cardId() +uint AudioSink::cardId() { - return getProperties("Card"); + return m_sink->card(); } -void AudioSink::onPropertyChanged(const QDBusMessage &msg) -{ - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName != propertiesInterface) - return; - - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - if (changedProps.contains("Volume")) - Q_EMIT volumeChanged(static_cast(changedProps.value("Volume").toDouble() * 100)); - - if (changedProps.contains("Mute")) - Q_EMIT muteChanged(changedProps.value("Mute").toBool()); -} - -template -T AudioSink::getProperties(const QString &propName) -{ - QDBusInterface dbusInter(serviceName, m_devicePath, interfaceName + QString(".Sink"), QDBusConnection::sessionBus()); - if (dbusInter.isValid()) { - QByteArray ba = propName.toLatin1(); - const char *prop = ba.data(); - return dbusInter.property(prop).value(); - } - - return T(); -} - -QDBusMessage AudioSink::callMethod(const QString &methodName, const QList &argument) -{ - QDBusInterface dbusInter(serviceName, m_devicePath, interfaceName + QString(".Sink"), QDBusConnection::sessionBus()); - if (dbusInter.isValid()) { - QDBusPendingCall reply = dbusInter.asyncCallWithArgumentList(methodName, argument); - reply.waitForFinished(); - return reply.reply(); - } - - return QDBusMessage(); -} - -static QVariantList argToString(const QDBusArgument &busArg) -{ - QVariantList out; - QString busSig = busArg.currentSignature(); - bool doIterate = false; - QDBusArgument::ElementType elementType = busArg.currentType(); - - switch (elementType) { - case QDBusArgument::BasicType: - case QDBusArgument::VariantType: { - QVariant value = busArg.asVariant(); - switch (value.type()) { - case QVariant::Bool: - out << value.toBool(); - break; - case QVariant::Int: - out << value.toInt(); - break; - case QVariant::String: - out << value.toString(); - break; - case QVariant::UInt: - out << value.toUInt(); - break; - case QVariant::ULongLong: - out << value.toULongLong(); - break; - case QMetaType::UChar: - out << value.toUInt(); - break; - default: - out << QVariant(); - break; - } - out += busArg.asVariant().toString(); - break; - } - case QDBusArgument::StructureType: - busArg.beginStructure(); - doIterate = true; - break; - case QDBusArgument::ArrayType: - busArg.beginArray(); - doIterate = true; - break; - case QDBusArgument::MapType: - busArg.beginMap(); - doIterate = true; - break; - case QDBusArgument::UnknownType: - default: - out << QVariant(); - return out; - } - - if (doIterate && !busArg.atEnd()) { - while (!busArg.atEnd()) { - out << argToString(busArg); - if (out.isEmpty()) - break; - } - } - - return out; -} - -QVariantList AudioSink::getPropertiesByFreeDesktop(const QString &propName) -{ - QDBusInterface dbusInter(serviceName, m_devicePath, "org.freedesktop.DBus.Properties", QDBusConnection::sessionBus()); - if (dbusInter.isValid()) { - QDBusPendingCall reply = dbusInter.asyncCallWithArgumentList("Get", { interfaceName + ".Sink", propName }); - reply.waitForFinished(); - QVariantList lists = reply.reply().arguments(); - for (QVariantList::ConstIterator it = lists.begin(); it != lists.end(); ++it) { - QVariant arg = (*it); - const QVariant v = qvariant_cast(arg).variant(); - return argToString(v.value()); - } - } - - return QVariantList(); -} - -AudioPorts::AudioPorts(int cardId, QString cardName) +AudioPorts::AudioPorts(uint cardId, QString cardName) : m_cardId(cardId) , m_cardName(cardName) + , m_direction(0) , m_isCheck(false) , m_isHeadPhone(false) { @@ -533,7 +338,7 @@ AudioPorts::~AudioPorts() { } -int AudioPorts::cardId() const +uint AudioPorts::cardId() const { return m_cardId; } diff --git a/frame/model/volumemodel.h b/frame/model/volumemodel.h index e698c59fc..8903cea23 100644 --- a/frame/model/volumemodel.h +++ b/frame/model/volumemodel.h @@ -3,6 +3,12 @@ #include +#include +#include + +using DBusAudio = com::deepin::daemon::Audio; +using DBusSink = com::deepin::daemon::audio::Sink; + class QDBusMessage; class AudioSink; class AudioPorts; @@ -11,12 +17,6 @@ class VolumeModel : public QObject { Q_OBJECT -Q_SIGNALS: - void defaultSinkChanged(AudioSink *); - void volumeChanged(int); - void muteChanged(bool); - void checkPortChanged(); - public: explicit VolumeModel(QObject *parent); ~VolumeModel(); @@ -35,25 +35,26 @@ public: bool isMute(); bool existActiveOutputDevice(); +Q_SIGNALS: + void defaultSinkChanged(AudioSink *); + void volumeChanged(int); + void muteChanged(bool); + void checkPortChanged(); + private Q_SLOTS: - void onPropertyChanged(const QDBusMessage& msg); + void onDefaultSinkChanged(const QDBusObjectPath & value); private: - void initService(); void reloadSinks(); void reloadPorts(); void clearSinks(); void clearPorts(); - void updateDefaultSink(AudioSink *audioSink); - -private: - QDBusMessage callMethod(const QString &methodName, const QList &argument); - template - T properties(const QString &propName); private: QList m_sinks; QList m_ports; + + DBusAudio *m_audio; }; class AudioSink : public QObject @@ -74,7 +75,7 @@ public: void setFade(double value); void setMute(bool mute); void setPort(QString name); - void setVolume(double value, bool isPlay); + void setVolume(int value, bool isPlay); bool isMute(); bool supportBalance(); @@ -85,24 +86,17 @@ public: int volume(); QString description(); QString name(); - int cardId(); - -private Q_SLOTS: - void onPropertyChanged(const QDBusMessage& msg); + uint cardId(); protected: - explicit AudioSink(QString path, QObject *parent = nullptr); + explicit AudioSink(QString path, bool isDefault, QObject *parent = nullptr); ~AudioSink(); - -private: - QDBusMessage callMethod(const QString &methodName, const QList &argument); - template - T getProperties(const QString &propName); - - QList getPropertiesByFreeDesktop(const QString &propName); + void setDefault(bool isDefaultSink); private: QString m_devicePath; + DBusSink *m_sink; + bool m_isDefault; }; class AudioPorts : public QObject @@ -112,7 +106,7 @@ class AudioPorts : public QObject friend class VolumeModel; public: - int cardId() const; + uint cardId() const; QString cardName() const; QString name() const; QString description() const; @@ -121,7 +115,7 @@ public: bool isHeadPhone() const; protected: - AudioPorts(int cardId, QString cardName); + AudioPorts(uint cardId, QString cardName); ~AudioPorts(); void setName(const QString &name); void setDescription(const QString &desc); @@ -129,7 +123,7 @@ protected: void setIsChecked(bool isChecked); private: - int m_cardId; + uint m_cardId; QString m_cardName; QString m_portName; QString m_description; diff --git a/frame/util/abstractpluginscontroller.cpp b/frame/util/abstractpluginscontroller.cpp index f8b719ef7..c406a2c4d 100644 --- a/frame/util/abstractpluginscontroller.cpp +++ b/frame/util/abstractpluginscontroller.cpp @@ -234,6 +234,17 @@ void AbstractPluginsController::loadPlugin(const QString &pluginFile) return; } + if (!needLoad(interface)) { + // 对于一些固定的插件是不需要加载的,例如在特效模式下,只需要加载电源插件,其他的是无需加载的 + for (const QPair &pair : m_pluginLoadMap.keys()) { + if (pair.first == pluginFile) + m_pluginLoadMap.remove(pair); + } + pluginLoader->unload(); + pluginLoader->deleteLater(); + return; + } + if (interface->pluginName() == "multitasking") { if (Utils::IS_WAYLAND_DISPLAY || Dtk::Core::DSysInfo::deepinType() == Dtk::Core::DSysInfo::DeepinServer) { for (auto &pair : m_pluginLoadMap.keys()) { diff --git a/frame/util/abstractpluginscontroller.h b/frame/util/abstractpluginscontroller.h index 66e8cd9c8..80e39a745 100644 --- a/frame/util/abstractpluginscontroller.h +++ b/frame/util/abstractpluginscontroller.h @@ -51,6 +51,9 @@ public: signals: void pluginLoaderFinished(); +protected: + virtual bool needLoad(PluginsItemInterface *) { return true; } + protected: QMap> &pluginsMap(); QObject *pluginItemAt(PluginsItemInterface * const itemInter, const QString &itemKey) const; diff --git a/frame/window/components/brightnessmonitorwidget.cpp b/frame/window/components/brightnessmonitorwidget.cpp index ee0358876..ac707795a 100644 --- a/frame/window/components/brightnessmonitorwidget.cpp +++ b/frame/window/components/brightnessmonitorwidget.cpp @@ -1,9 +1,30 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "brightnessmonitorwidget.h" #include "brightnessmodel.h" #include "customslider.h" #include "settingdelegate.h" #include +#include #include #include @@ -21,7 +42,7 @@ BrightnessMonitorWidget::BrightnessMonitorWidget(BrightnessModel *model, QWidget : QWidget(parent) , m_sliderWidget(new QWidget(this)) , m_sliderLayout(new QVBoxLayout(m_sliderWidget)) - , m_descriptionLabel(new QLabel(tr("Output Device"), this)) + , m_descriptionLabel(new QLabel(tr("Collaboration"), this)) , m_deviceList(new DListView(this)) , m_brightModel(model) , m_model(new QStandardItemModel(this)) @@ -92,15 +113,17 @@ void BrightnessMonitorWidget::initConnection() // 更新滚动条的内容 onBrightChanged(monitor); } else { - QDBusInterface controlcenter("com.deepin.dde.ControlCenter", "/com/deepin/dde/ControlCenter", - "com.deepin.dde.ControlCenter", QDBusConnection::sessionBus()); - controlcenter.call("ShowModule", "display"); + DDBusSender().service("com.deepin.dde.ControlCenter") + .path("/com/deepin/dde/ControlCenter") + .interface("com.deepin.dde.ControlCenter") + .method("ShowModule").arg(QString("display")).call(); hide(); } }); for (QPair container : m_sliderContainers) { SliderContainer *slider = container.second; + slider->slider()->setValue(container.first->brihtness()); connect(slider->slider(), &CustomSlider::valueChanged, this, [ = ](int value) { m_brightModel->setBrightness(container.first, value); }); @@ -112,16 +135,7 @@ void BrightnessMonitorWidget::initConnection() void BrightnessMonitorWidget::reloadMonitor() { m_model->clear(); - QList monitots = m_brightModel->monitors(); - for (BrightMonitor *monitor : monitots) { - DStandardItem *item = new DStandardItem; - item->setIcon(QIcon(":/icons/resources/laptop.svg")); - item->setText(monitor->name()); - item->setFlags(Qt::NoItemFlags); - item->setData(QVariant::fromValue(monitor), itemDataRole); - m_model->appendRow(item); - onBrightChanged(monitor); - } + // 跨端协同列表,后续会新增该功能 // 显示设置 DStandardItem *settingItem = new DStandardItem; settingItem->setIcon(QIcon("")); diff --git a/frame/window/components/brightnessmonitorwidget.h b/frame/window/components/brightnessmonitorwidget.h index d63c131eb..6e1c7d92b 100644 --- a/frame/window/components/brightnessmonitorwidget.h +++ b/frame/window/components/brightnessmonitorwidget.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef BRIGHTNESSMONITORWIDGET_H #define BRIGHTNESSMONITORWIDGET_H diff --git a/frame/window/components/brightnesswidget.cpp b/frame/window/components/brightnesswidget.cpp index 978f9d962..8275657a2 100644 --- a/frame/window/components/brightnesswidget.cpp +++ b/frame/window/components/brightnesswidget.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "brightnesswidget.h" #include "customslider.h" #include "brightnessmodel.h" @@ -13,7 +33,6 @@ BrightnessWidget::BrightnessWidget(QWidget *parent) { initUi(); initConenction(); - onUpdateBright(); } BrightnessWidget::~BrightnessWidget() @@ -57,14 +76,24 @@ void BrightnessWidget::initConenction() if (icon == DSlider::SliderIcons::RightIcon) Q_EMIT rightIconClicked(); }); - connect(m_slider, &CustomSlider::valueChanged, this, [ this ](int value) { + connect(m_slider, &CustomSlider::valueChanged, this, [ this ](int value) { + BrightMonitor *monitor = m_model->primaryMonitor(); + if (monitor) + m_model->setBrightness(monitor, value); }); connect(m_model, &BrightnessModel::brightnessChanged, this, &BrightnessWidget::onUpdateBright); + + BrightMonitor *monitor = m_model->primaryMonitor(); + if (monitor) + onUpdateBright(monitor); } -void BrightnessWidget::onUpdateBright() +void BrightnessWidget::onUpdateBright(BrightMonitor *monitor) { - + if (!monitor->isPrimary()) + return; + // 此处只显示主屏的亮度 + m_slider->setValue(monitor->brihtness()); } diff --git a/frame/window/components/brightnesswidget.h b/frame/window/components/brightnesswidget.h index 7988f486f..4d381acd6 100644 --- a/frame/window/components/brightnesswidget.h +++ b/frame/window/components/brightnesswidget.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef BRIGHTNESSWIDGET_H #define BRIGHTNESSWIDGET_H @@ -27,7 +47,7 @@ protected: void hideEvent(QHideEvent *event) override; private Q_SLOTS: - void onUpdateBright(); + void onUpdateBright(BrightMonitor *monitor); private: void initUi(); diff --git a/frame/window/components/datetimedisplayer.cpp b/frame/window/components/datetimedisplayer.cpp index ce95fc966..5c82eef69 100644 --- a/frame/window/components/datetimedisplayer.cpp +++ b/frame/window/components/datetimedisplayer.cpp @@ -1,6 +1,27 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "datetimedisplayer.h" #include +#include #include #include @@ -9,6 +30,11 @@ DWIDGET_USE_NAMESPACE #define DATETIMESIZE 40 +#define ITEMSPACE 8 + +static QMap dateFormat{{ 0,"yyyy/M/d" }, { 1,"yyyy-M-d" }, { 2,"yyyy.M.d" }, { 3,"yyyy/MM/dd" }, + { 4,"yyyy-MM-dd" }, { 5,"yyyy.MM.dd" }, { 6,"yy/M/d" }, { 7,"yy-M-d" }, { 8,"yy.M.d" }}; +static QMap timeFormat{{0, "h:mm"}, {1, "hh:mm"}}; DateTimeDisplayer::DateTimeDisplayer(QWidget *parent) : QWidget (parent) @@ -17,15 +43,12 @@ DateTimeDisplayer::DateTimeDisplayer(QWidget *parent) , m_timeFont(DFontSizeManager::instance()->t6()) , m_dateFont(DFontSizeManager::instance()->t10()) { - initUi(); - setShortDateFormat(m_timedateInter->shortDateFormat()); - setShortTimeFormat(m_timedateInter->shortTimeFormat()); - connect(m_timedateInter, &Timedate::ShortDateFormatChanged, this, &DateTimeDisplayer::setShortDateFormat); - connect(m_timedateInter, &Timedate::ShortTimeFormatChanged, this, &DateTimeDisplayer::setShortTimeFormat); + // 日期格式变化的时候,需要重绘 + connect(m_timedateInter, &Timedate::ShortDateFormatChanged, this, [ this ] { update(); }); + // 时间格式变化的时候,需要重绘 + connect(m_timedateInter, &Timedate::ShortTimeFormatChanged, this, [ this ] { update(); }); // 连接日期时间修改信号,更新日期时间插件的布局 - connect(m_timedateInter, &Timedate::TimeUpdate, this, [ this ] { - update(); - }); + connect(m_timedateInter, &Timedate::TimeUpdate, this, [ this ] { update(); }); } DateTimeDisplayer::~DateTimeDisplayer() @@ -39,6 +62,7 @@ void DateTimeDisplayer::setPositon(Dock::Position position) m_position = position; setCurrentPolicy(); + update(); } void DateTimeDisplayer::setCurrentPolicy() @@ -57,20 +81,25 @@ void DateTimeDisplayer::setCurrentPolicy() } } -void DateTimeDisplayer::initUi() -{ - QHBoxLayout *layout = new QHBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); -} - QSize DateTimeDisplayer::suitableSize() { DateTimeInfo info = dateTimeInfo(); - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) - return QSize(info.m_dateRect.right(), height()); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + int width = info.m_timeRect.width() + info.m_dateRect.width() + 16; + return QSize(width, height()); + } - return QSize(width(), info.m_dateRect.bottom()); + return QSize(width(), info.m_timeRect.height() + info.m_dateRect.height()); +} + +void DateTimeDisplayer::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + + DDBusSender().service("com.deepin.Calendar") + .path("/com/deepin/Calendar") + .interface("com.deepin.Calendar") + .method("RaiseWindow").call(); } DateTimeDisplayer::DateTimeInfo DateTimeDisplayer::dateTimeInfo() @@ -78,35 +107,67 @@ DateTimeDisplayer::DateTimeInfo DateTimeDisplayer::dateTimeInfo() DateTimeInfo info; const QDateTime current = QDateTime::currentDateTime(); - const Dock::Position position = qApp->property(PROP_POSITION).value(); - info.m_timeRect = rect(); info.m_dateRect = rect(); - QString format = m_shortTimeFormat; + QString format = getTimeFormat(); if (!m_timedateInter->use24HourFormat()) { - if (position == Dock::Top || position == Dock::Bottom) + if (m_position == Dock::Top || m_position == Dock::Bottom) format = format.append(" AP"); else format = format.append("\nAP"); } info.m_time = current.toString(format); - info.m_date = current.toString(m_shortDateFormat); - int timeWidth = QFontMetrics(m_timeFont).boundingRect(info.m_time).width() + 12 * 2; - int dateWidth = QFontMetrics(m_dateFont).boundingRect(info.m_date).width() + 2; + info.m_date = current.toString(getDateFormat()); - if (position == Dock::Top || position == Dock::Bottom) { - info.m_timeRect = QRect(10, 0, timeWidth, height()); - int right = rect().width() - QFontMetrics(m_dateFont).width(info.m_date) - 2; - info.m_dateRect = QRect(right, 0, dateWidth, height()); + if (m_position == Dock::Top || m_position == Dock::Bottom) { + int timeWidth = QFontMetrics(m_timeFont).boundingRect(info.m_time).width() + 10; + int dateWidth = QFontMetrics(m_dateFont).boundingRect(info.m_date).width() + 2; + info.m_timeRect = QRect(ITEMSPACE, 0, timeWidth, height()); + int dateX = rect().width() - QFontMetrics(m_dateFont).width(info.m_date) - 2 - ITEMSPACE; + // 如果时间的X坐标小于日期的X坐标,需要手动设置坐标在日期坐标的右侧 + if (dateX < info.m_timeRect.right()) + dateX = info.m_timeRect.right(); + info.m_dateRect = QRect(dateX, 0, dateWidth, height()); } else { - info.m_timeRect = QRect(0, 0, timeWidth, DATETIMESIZE / 2); - info.m_dateRect = QRect(0, DATETIMESIZE / 2 + 1, dateWidth, DATETIMESIZE / 2); + int textWidth = rect().width(); + info.m_timeRect = QRect(0, 0, textWidth, DATETIMESIZE / 2); + info.m_dateRect = QRect(0, DATETIMESIZE / 2 + 1, textWidth, DATETIMESIZE / 2); } return info; } +QString DateTimeDisplayer::getDateFormat() const +{ + int type = m_timedateInter->shortDateFormat(); + QString shortDateFormat = "yyyy-MM-dd"; + if (dateFormat.contains(type)) + shortDateFormat = dateFormat.value(type); + // 如果是左右方向,则不显示年份 + if (m_position == Dock::Position::Left || m_position == Dock::Position::Right) { + static QStringList yearStrList{"yyyy/", "yyyy-", "yyyy.", "yy/", "yy-", "yy."}; + for (int i = 0; i < yearStrList.size() ; i++) { + const QString &yearStr = yearStrList[i]; + if (shortDateFormat.contains(yearStr)) { + shortDateFormat = shortDateFormat.remove(yearStr); + break; + } + } + } + + return shortDateFormat; +} + +QString DateTimeDisplayer::getTimeFormat() const +{ + int type = m_timedateInter->shortTimeFormat(); + if (timeFormat.contains(type)) + return timeFormat[type]; + + return QString("hh:mm"); +} + void DateTimeDisplayer::paintEvent(QPaintEvent *e) { Q_UNUSED(e); @@ -117,37 +178,14 @@ void DateTimeDisplayer::paintEvent(QPaintEvent *e) painter.setRenderHint(QPainter::Antialiasing); painter.setPen(QPen(palette().brightText(), 1)); - painter.drawText(info.m_timeRect, Qt::AlignLeft | Qt::AlignVCenter, info.m_time); - + int timeTextFlag = Qt::AlignCenter; + int dateTextFlag = Qt::AlignCenter; + if (m_position == Dock::Top || m_position == Dock::Bottom) { + timeTextFlag = Qt::AlignLeft | Qt::AlignVCenter; + dateTextFlag = Qt::AlignRight | Qt::AlignVCenter; + } + painter.setFont(m_timeFont); + painter.drawText(info.m_timeRect, timeTextFlag, info.m_time); painter.setFont(m_dateFont); - painter.drawText(info.m_dateRect, Qt::AlignLeft | Qt::AlignVCenter, info.m_date); -} - -void DateTimeDisplayer::setShortDateFormat(int type) -{ - switch (type) { - case 0: m_shortDateFormat = "yyyy/M/d"; break; - case 1: m_shortDateFormat = "yyyy-M-d"; break; - case 2: m_shortDateFormat = "yyyy.M.d"; break; - case 3: m_shortDateFormat = "yyyy/MM/dd"; break; - case 4: m_shortDateFormat = "yyyy-MM-dd"; break; - case 5: m_shortDateFormat = "yyyy.MM.dd"; break; - case 6: m_shortDateFormat = "yy/M/d"; break; - case 7: m_shortDateFormat = "yy-M-d"; break; - case 8: m_shortDateFormat = "yy.M.d"; break; - default: m_shortDateFormat = "yyyy-MM-dd"; break; - } - - update(); -} - -void DateTimeDisplayer::setShortTimeFormat(int type) -{ - switch (type) { - case 0: m_shortTimeFormat = "h:mm"; break; - case 1: m_shortTimeFormat = "hh:mm"; break; - default: m_shortTimeFormat = "hh:mm"; break; - } - - update(); + painter.drawText(info.m_dateRect, dateTextFlag, info.m_date); } diff --git a/frame/window/components/datetimedisplayer.h b/frame/window/components/datetimedisplayer.h index dbb8b1a9f..9dcea0a30 100644 --- a/frame/window/components/datetimedisplayer.h +++ b/frame/window/components/datetimedisplayer.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef DATETIMEDISPLAYER_H #define DATETIMEDISPLAYER_H @@ -25,27 +45,25 @@ private: public: explicit DateTimeDisplayer(QWidget *parent = nullptr); ~DateTimeDisplayer() override; - void setPositon(Dock::Position position); - QSize suitableSize(); + void setPositon(Dock::Position position); + QSize suitableSize(); - private: - void initUi(); - void setCurrentPolicy(); - DateTimeInfo dateTimeInfo(); +protected: + void mouseReleaseEvent(QMouseEvent *event) override; + void paintEvent(QPaintEvent *e) override; - void paintEvent(QPaintEvent *e) override; +private: + void setCurrentPolicy(); + DateTimeInfo dateTimeInfo(); - private Q_SLOTS: - void setShortDateFormat(int type); - void setShortTimeFormat(int type); + QString getDateFormat() const; + QString getTimeFormat() const; - private: - Timedate *m_timedateInter; - QString m_shortDateFormat; - QString m_shortTimeFormat; - Dock::Position m_position; - mutable QFont m_timeFont; - mutable QFont m_dateFont; +private: + Timedate *m_timedateInter; + Dock::Position m_position; + mutable QFont m_timeFont; + mutable QFont m_dateFont; }; #endif // DATETIMEDISPLAYER_H diff --git a/frame/window/components/mediawidget.cpp b/frame/window/components/mediawidget.cpp index 436920f93..ae2fe112b 100644 --- a/frame/window/components/mediawidget.cpp +++ b/frame/window/components/mediawidget.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "mediawidget.h" #include diff --git a/frame/window/components/mediawidget.h b/frame/window/components/mediawidget.h index 6a727e7b4..d5d870287 100644 --- a/frame/window/components/mediawidget.h +++ b/frame/window/components/mediawidget.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef MEDIAWIDGET_H #define MEDIAWIDGET_H diff --git a/frame/window/components/settingdelegate.cpp b/frame/window/components/settingdelegate.cpp index 0827d4fab..b2c0d3511 100644 --- a/frame/window/components/settingdelegate.cpp +++ b/frame/window/components/settingdelegate.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "settingdelegate.h" #include diff --git a/frame/window/components/settingdelegate.h b/frame/window/components/settingdelegate.h index 40d70f680..b55f83371 100644 --- a/frame/window/components/settingdelegate.h +++ b/frame/window/components/settingdelegate.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef SETTINGDELEGATE_H #define SETTINGDELEGATE_H @@ -12,13 +32,13 @@ class SettingDelegate : public DStyledItemDelegate { Q_OBJECT -Q_SIGNALS: - void selectIndexChanged(const QModelIndex &); - public: explicit SettingDelegate(QAbstractItemView *parent = nullptr); ~SettingDelegate() override; +Q_SIGNALS: + void selectIndexChanged(const QModelIndex &); + protected: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; diff --git a/frame/window/components/volumedeviceswidget.cpp b/frame/window/components/volumedeviceswidget.cpp index af3d15e2b..9be4706cc 100644 --- a/frame/window/components/volumedeviceswidget.cpp +++ b/frame/window/components/volumedeviceswidget.cpp @@ -1,4 +1,24 @@ -#include "volumedeviceswidget.h" +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ +#include "volumedeviceswidget.h" #include "customslider.h" #include "volumemodel.h" #include "settingdelegate.h" @@ -7,6 +27,7 @@ #include #include #include +#include #include #include @@ -140,9 +161,10 @@ void VolumeDevicesWidget::initConnection() m_deviceList->update(); } else { // 打开控制中心的声音模块 - QDBusInterface controlcenter("com.deepin.dde.ControlCenter", "/com/deepin/dde/ControlCenter", - "com.deepin.dde.ControlCenter", QDBusConnection::sessionBus()); - controlcenter.call("ShowModule", "sound"); + DDBusSender().service("com.deepin.dde.ControlCenter") + .path("/com/deepin/dde/ControlCenter") + .interface("com.deepin.dde.ControlCenter") + .method("ShowModule").arg(QString("sound")).call(); hide(); } }); diff --git a/frame/window/components/volumedeviceswidget.h b/frame/window/components/volumedeviceswidget.h index 7ffd55474..e85ae4fe1 100644 --- a/frame/window/components/volumedeviceswidget.h +++ b/frame/window/components/volumedeviceswidget.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef VOLUMEDEVICESWIDGET_H #define VOLUMEDEVICESWIDGET_H diff --git a/frame/window/components/volumewidget.cpp b/frame/window/components/volumewidget.cpp index 4447e3a5a..c36ebe45c 100644 --- a/frame/window/components/volumewidget.cpp +++ b/frame/window/components/volumewidget.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "volumewidget.h" #include "customslider.h" #include "imageutil.h" diff --git a/frame/window/components/volumewidget.h b/frame/window/components/volumewidget.h index 5daa52665..379216efd 100644 --- a/frame/window/components/volumewidget.h +++ b/frame/window/components/volumewidget.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef VOLUMEWIDGET_H #define VOLUMEWIDGET_H diff --git a/frame/window/mainpanelcontrol.cpp b/frame/window/mainpanelcontrol.cpp index ed77791d6..6c9528dbe 100755 --- a/frame/window/mainpanelcontrol.cpp +++ b/frame/window/mainpanelcontrol.cpp @@ -976,10 +976,10 @@ QPainterPath MainPanelControl::areaPath() return QPainterPath(); QPainterPath path; - int leftWidth = m_fixedAreaWidget->width() + m_fixedSpliter->width() + m_appAreaWidget->width() + 10; + int leftWidth = m_fixedAreaWidget->width() + m_fixedSpliter->width() + m_appAreaWidget->width(); int roundHeight = height(); path.addRoundedRect(QRect(0, 0, leftWidth, roundHeight), 18, 18); - path.addRoundedRect(QRect(leftWidth + 10, 0, m_trayManagerWidget->width(), roundHeight), 18, 18); + path.addRoundedRect(QRect(m_trayManagerWidget->x(), 0, m_trayManagerWidget->width(), roundHeight), 18, 18); return path; } diff --git a/frame/window/pluginchildpage.cpp b/frame/window/pluginchildpage.cpp new file mode 100644 index 000000000..42db178c5 --- /dev/null +++ b/frame/window/pluginchildpage.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ +#include "pluginchildpage.h" + +#include +#include +#include + +PluginChildPage::PluginChildPage(QWidget *parent) + : QWidget(parent) + , m_headerWidget(new QWidget(this)) + , m_back(new QLabel(m_headerWidget)) + , m_title(new QLabel(m_headerWidget)) + , m_container(new QWidget(this)) + , m_topWidget(nullptr) + , m_containerLayout(new QVBoxLayout(m_container)) + , m_isBack(false) +{ + initUi(); + m_back->installEventFilter(this); +} + +PluginChildPage::~PluginChildPage() +{ +} + +void PluginChildPage::pushWidget(QWidget *widget) +{ + // 首先将界面其他的窗体移除 + for (int i = m_containerLayout->count() - 1; i >= 0; i--) { + QLayoutItem *item = m_containerLayout->itemAt(i); + item->widget()->removeEventFilter(this); + item->widget()->hide(); + m_containerLayout->removeItem(item); + } + m_topWidget = widget; + widget->installEventFilter(this); + m_containerLayout->addWidget(widget); + widget->show(); + m_isBack = false; + QMetaObject::invokeMethod(this, &PluginChildPage::resetHeight, Qt::QueuedConnection); +} + +void PluginChildPage::setTitle(const QString &text) +{ + m_title->setText(text); +} + +bool PluginChildPage::isBack() +{ + return m_isBack; +} + +void PluginChildPage::initUi() +{ + m_back->setFixedWidth(24); + m_title->setAlignment(Qt::AlignCenter); + QHBoxLayout *headerLayout = new QHBoxLayout(m_headerWidget); + headerLayout->setContentsMargins(11, 12, 24 + 11, 12); + headerLayout->setSpacing(0); + headerLayout->addWidget(m_back); + headerLayout->addWidget(m_title); + m_headerWidget->setFixedHeight(48); + + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + + mainLayout->addWidget(m_headerWidget); + mainLayout->addWidget(m_container); + m_containerLayout->setContentsMargins(11, 0, 11, 0); + m_containerLayout->setSpacing(0); +} + +bool PluginChildPage::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_back && event->type() == QEvent::MouseButtonRelease) { + m_isBack = true; + Q_EMIT back(); + return true; + } + if (watched == m_topWidget) { + if (event->type() == QEvent::Hide) { + Q_EMIT closeSelf(); + return true; + } + if (event->type() == QEvent::Resize) + resetHeight(); + } + return QWidget::eventFilter(watched, event); +} + +void PluginChildPage::resetHeight() +{ + QMargins m = m_containerLayout->contentsMargins(); + m_container->setFixedHeight(m.top() + m.bottom() + m_topWidget->height()); + setFixedHeight(m_headerWidget->height() + m_container->height()); +} diff --git a/frame/window/pluginchildpage.h b/frame/window/pluginchildpage.h new file mode 100644 index 000000000..b94d87d13 --- /dev/null +++ b/frame/window/pluginchildpage.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ +#ifndef PLUGINCHILDPAGE_H +#define PLUGINCHILDPAGE_H + +#include + +class QLabel; +class QVBoxLayout; + +class PluginChildPage : public QWidget +{ + Q_OBJECT + +public: + explicit PluginChildPage(QWidget *parent); + ~PluginChildPage() override; + void pushWidget(QWidget *widget); + void setTitle(const QString &text); + bool isBack(); + +Q_SIGNALS: + void back(); + void closeSelf(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + void initUi(); + void resetHeight(); + +private: + QWidget *m_headerWidget; + QLabel *m_back; + QLabel *m_title; + QWidget *m_container; + QWidget *m_topWidget; + QVBoxLayout *m_containerLayout; + bool m_isBack; +}; + +#endif // PLUGINCHILDPAGE_H diff --git a/frame/window/quickpluginwindow.cpp b/frame/window/quickpluginwindow.cpp index 139e4c541..ce26ca5c1 100644 --- a/frame/window/quickpluginwindow.cpp +++ b/frame/window/quickpluginwindow.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "quickpluginwindow.h" #include "quicksettingcontroller.h" #include "quicksettingitem.h" @@ -13,9 +33,11 @@ #include #include #include +#include #define ITEMSIZE 22 #define ITEMSPACE 6 +#define ICONSIZE 16 static QStringList fixedPluginKeys{ "network-item-key", "sound-item-key", "power" }; const int itemDataRole = Dtk::UserRole + 1; @@ -23,8 +45,7 @@ const int itemSortRole = Dtk::UserRole + 2; QuickPluginWindow::QuickPluginWindow(QWidget *parent) : QWidget(parent) - , m_listView(new DListView(this)) - , m_model(new QStandardItemModel(this)) + , m_mainLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) , m_position(Dock::Position::Bottom) { initUi(); @@ -32,8 +53,6 @@ QuickPluginWindow::QuickPluginWindow(QWidget *parent) setAcceptDrops(true); setMouseTracking(true); - - this->installEventFilter(this); } QuickPluginWindow::~QuickPluginWindow() @@ -42,28 +61,16 @@ QuickPluginWindow::~QuickPluginWindow() void QuickPluginWindow::initUi() { - m_listView->setModel(m_model); - m_listView->setViewMode(QListView::IconMode); - m_listView->setMovement(QListView::Free); - m_listView->setWordWrap(false); - m_listView->verticalScrollBar()->setVisible(false); - m_listView->horizontalScrollBar()->setVisible(false); - m_listView->setOrientation(QListView::Flow::LeftToRight, false); - m_listView->setGridSize(QSize(ITEMSIZE + 10, ITEMSIZE + 10)); - m_listView->setSpacing(ITEMSPACE); - m_listView->setContentsMargins(0,0,0,0); - m_model->setSortRole(itemSortRole); - - QHBoxLayout *layout = new QHBoxLayout(this); - layout->setContentsMargins(0,0,0,0); - layout->setSpacing(0); - layout->addWidget(m_listView); - + setAcceptDrops(true); + m_mainLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + m_mainLayout->setDirection(QBoxLayout::Direction::RightToLeft); + m_mainLayout->setContentsMargins(ITEMSPACE, 0, ITEMSPACE, 0); + m_mainLayout->setSpacing(ITEMSPACE); const QList &items = QuickSettingController::instance()->settingItems(); for (QuickSettingItem *settingItem : items) { const QString itemKey = settingItem->itemKey(); if (!fixedPluginKeys.contains(itemKey)) - return; + continue; addPlugin(settingItem); } @@ -75,228 +82,243 @@ void QuickPluginWindow::setPositon(Position position) return; m_position = position; + QuickSettingContainer::setPosition(position); if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) - m_listView->setOrientation(QListView::Flow::LeftToRight, false); + m_mainLayout->setDirection(QBoxLayout::RightToLeft); else - m_listView->setOrientation(QListView::Flow::TopToBottom, false); + m_mainLayout->setDirection(QBoxLayout::BottomToTop); +} + +int QuickPluginWindow::findActiveTargetIndex(QWidget *widget) +{ + for (int i = 0; i < m_activeSettingItems.size(); i++) { + QuickSettingItem *settingItem = m_activeSettingItems[i]; + if (settingItem->pluginItem()->itemWidget(settingItem->itemKey()) == widget) + return i; + } + return -1; +} + +void QuickPluginWindow::dragPlugin(QuickSettingItem *item) +{ + // 释放插件,一般是从快捷设置面板区域移动到这里的,固定插件不支持拖动 + if (fixedPluginKeys.contains(item->itemKey())) + return; + + QPoint itemPoint = mapFromGlobal(QCursor::pos()); + // 查找移动后的位置,如果移动后的插件找不到,就直接放到最后 + QWidget *targetWidget = childAt(itemPoint); + if (!targetWidget) { + m_activeSettingItems << item; + } else { + // 如果是拖动到固定插件区域,也放到最后 + int targetIndex = findActiveTargetIndex(targetWidget); + if (targetIndex < 0) + m_activeSettingItems << item; + else + m_activeSettingItems.insert(targetIndex, item); + } + //排序插入到当前窗体 + resetPluginDisplay(); + Q_EMIT itemCountChanged(); } void QuickPluginWindow::addPlugin(QuickSettingItem *item) { - // 判断当前的插件是否存在,如果存在,则不插入 - for (int i = 0; i < m_model->rowCount(); i++) { - QStandardItem *myItem = m_model->item(i, 0); - QuickSettingItem *settingItem = myItem->data(itemDataRole).value(); - if (settingItem == item) { - m_model->sort(0); + for (int i = 0; i < m_mainLayout->count(); i++) { + QWidget *widget = m_mainLayout->itemAt(i)->widget(); + if (item == widget) { + resetPluginDisplay(); return; } } - - DStandardItem *standItem = createStandItem(item); - if (!standItem) + QWidget *widget = item->pluginItem()->itemWidget(item->itemKey()); + if (!widget) return; - m_model->appendRow(standItem); - resetSortRole(); - m_model->sort(0); + widget->installEventFilter(this); + if (fixedPluginKeys.contains(item->itemKey())) { + // 新插入的插件如果是固定插件,则将其插入到固定插件列表中,并对其进行排序 + m_fixedSettingItems << item; + qSort(m_fixedSettingItems.begin(), m_fixedSettingItems.end(), [](QuickSettingItem *item1, QuickSettingItem *item2) { + int index1 = fixedPluginKeys.indexOf(item1->itemKey()); + int index2 = fixedPluginKeys.indexOf(item2->itemKey()); + return index1 < index2; + }); + } else { + // 如果是非固定插件,则直接插入到末尾 + m_activeSettingItems << item; + } + resetPluginDisplay(); Q_EMIT itemCountChanged(); } QSize QuickPluginWindow::suitableSize() { if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) - return QSize((ITEMSIZE + ITEMSPACE) * m_model->rowCount() + ITEMSPACE, ITEMSIZE); + return QSize((ITEMSPACE + ICONSIZE) * m_mainLayout->count() + ITEMSIZE, ITEMSIZE); - return QSize(ITEMSIZE, (ITEMSIZE + ITEMSPACE) * m_model->rowCount() + ITEMSPACE); + return QSize(ITEMSIZE, (ITEMSIZE + ITEMSPACE) * m_mainLayout->count() + ITEMSPACE); } void QuickPluginWindow::removePlugin(QuickSettingItem *item) { - for (int i = 0; i < m_model->rowCount(); i++) { - QModelIndex index = m_model->index(i, 0); - QuickSettingItem *quickItem = index.data(itemDataRole).value(); - if (quickItem == item) { - m_model->removeRow(i); - break; - } - } - m_model->sort(0); + if (m_fixedSettingItems.contains(item)) + m_fixedSettingItems.removeOne(item); + else if (m_activeSettingItems.contains(item)) + m_activeSettingItems.removeOne(item); + else + return; + resetPluginDisplay(); Q_EMIT itemCountChanged(); } -void QuickPluginWindow::resetSortRole() +QuickSettingItem *QuickPluginWindow::findQuickSettingItem(const QPoint &mousePoint, const QList &settingItems) { - QList> fixedItems; - QList activeItems; - for (int i = 0; i < m_model->rowCount(); i++) { - QModelIndex index = m_model->index(i, 0); - if (!index.data(itemDataRole).canConvert()) - continue; - - QuickSettingItem *settingItem = index.data(itemDataRole).value(); - if (fixedPluginKeys.contains(settingItem->itemKey())) - fixedItems.push_back({ m_model->item(i, 0), fixedPluginKeys.indexOf(settingItem->itemKey()) }); - else - activeItems << m_model->item(i, 0); - } - - for (int i = 0; i < activeItems.size(); i++) { - QStandardItem *item = activeItems[i]; - item->setData(i, itemSortRole); - } - - for (QPair item : fixedItems) - item.first->setData(activeItems.size() + item.second, itemSortRole); -} - -DStandardItem *QuickPluginWindow::createStandItem(QuickSettingItem *item) -{ - const QString itemKey = item->itemKey(); - QWidget *itemWidget = item->pluginItem()->itemWidget(itemKey); - if (!itemWidget) + QWidget *selectWidget = childAt(mousePoint); + if (!selectWidget) return nullptr; - itemWidget->setParent(m_listView); - DStandardItem *standItem = new DStandardItem; - standItem->setFlags(Qt::ItemIsEnabled); - standItem->setBackground(Qt::transparent); - standItem->setData(QVariant::fromValue(item), itemDataRole); - - DViewItemAction *action = new DViewItemAction(Qt::AlignCenter, QSize(ITEMSIZE, ITEMSIZE), QSize(ITEMSIZE, ITEMSIZE), true); - action->setWidget(itemWidget); - connect(action, &DViewItemAction::triggered, this, [ this ] { - QPoint ptCurrent = pos(); - QWidget *callWidget = parentWidget(); - if (callWidget) - ptCurrent = callWidget->mapToGlobal(ptCurrent); - - QuickSettingContainer::popWindow()->show(ptCurrent); - }); - connect(action, &DViewItemAction::destroyed, this, [ itemWidget ] { - itemWidget->setParent(nullptr); - itemWidget->hide(); - }); - - standItem->setActionList(Qt::LeftEdge, { action }); - return standItem; -} - -void QuickPluginWindow::mouseReleaseEvent(QMouseEvent *event) -{ - QMouseEvent *mouseEvent = static_cast(event); - QModelIndex selectedIndex = m_listView->indexAt(mouseEvent->pos()); - if (!selectedIndex.isValid()) - return; - - QuickSettingItem *moveItem = selectedIndex.data(itemDataRole).value(); - if (!moveItem) - return; - - if (fixedPluginKeys.contains(moveItem->itemKey())) { - QPoint currentPoint = pos(); - QWidget *callWidget = parentWidget(); - if (callWidget) - currentPoint = callWidget->mapToGlobal(currentPoint); - - QuickSettingContainer::popWindow()->show(currentPoint); + for (int i = 0; i < settingItems.size(); i++) { + QuickSettingItem *settingItem = settingItems[i]; + QWidget *widget = settingItem->pluginItem()->itemWidget(settingItem->itemKey()); + if (selectWidget == widget) + return settingItem; } + + return nullptr; } void QuickPluginWindow::mousePressEvent(QMouseEvent *event) { - QModelIndex selectedIndex = m_listView->indexAt(event->pos()); - if (!selectedIndex.isValid()) { - QWidget::mousePressEvent(event); + // 查找非固定的图标,然后执行拖动 + QuickSettingItem *quickItem = findQuickSettingItem(event->pos(), m_activeSettingItems); + if (!quickItem) return; + + // 如果不是固定图标,则让其拖动 + startDrag(quickItem); +} + +void QuickPluginWindow::mouseReleaseEvent(QMouseEvent *event) +{ + // 查找固定团图标,然后点击弹出快捷面板 + QuickSettingItem *quickItem = findQuickSettingItem(event->pos(), m_fixedSettingItems); + if (!quickItem) + return; + + // 如果是固定图标,则让其弹出列表 + QPoint currentPoint = pos(); + QWidget *callWidget = parentWidget(); + if (callWidget) { + currentPoint = callWidget->mapToGlobal(currentPoint); + // 如果是向上的方向,则需要减去高度 + if (m_position == Dock::Position::Top) + currentPoint.setY(currentPoint.y() + callWidget->height()); + else if (m_position == Dock::Position::Left) + currentPoint.setX(currentPoint.x() + callWidget->width()); } - QuickSettingItem *moveItem = selectedIndex.data(itemDataRole).value(); - if (!moveItem) { - QWidget::mousePressEvent(event); - return; - } - - if (fixedPluginKeys.contains(moveItem->itemKey())) { - QWidget::mousePressEvent(event); - return; - } - - startDrag(moveItem); + DockPopupWindow *popWindow = QuickSettingContainer::popWindow(); + popWindow->show(currentPoint); } void QuickPluginWindow::startDrag(QuickSettingItem *moveItem) { AppDrag *drag = new AppDrag(this, new QuickDragWidget); - CustomMimeData *mimedata = new CustomMimeData; - mimedata->setData(moveItem); + QuickPluginMimeData *mimedata = new QuickPluginMimeData(moveItem); drag->setMimeData(mimedata); drag->appDragWidget()->setDockInfo(m_position, QRect(mapToGlobal(pos()), size())); QPixmap dragPixmap = moveItem->pluginItem()->icon()->pixmap(QSize(ITEMSIZE, ITEMSIZE)); drag->setPixmap(dragPixmap); - drag->setHotSpot(QPoint(dragPixmap.width() / 2, dragPixmap.height() / 2)); + drag->setHotSpot(QPoint(0, 0)); connect(drag->appDragWidget(), &AppDragWidget::requestRemoveItem, this, [ this, moveItem ] { removePlugin(moveItem); }); - connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDropItem, this, [ this, moveItem ](){ - addPlugin(moveItem); - }); - connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDragMove, this, [ this ](QDragMoveEvent *eve){ - QPoint ptCurrent = m_listView->mapFromGlobal(QCursor::pos()); - QModelIndex index = m_listView->indexAt(ptCurrent); - if (!index.isValid()) - return; - - CustomMimeData *data = const_cast(qobject_cast(eve->mimeData())); - if (!data) - return; - - QuickSettingItem *sourceItem = static_cast(data->data()); - if (!sourceItem) - return; - - QuickSettingItem *targetItem = index.data(itemDataRole).value(); - if (!targetItem || fixedPluginKeys.contains(targetItem->itemKey()) || sourceItem == targetItem) - return; - - // recall all sortroles - QList> allItems; - for (int i = 0; i < m_model->rowCount(); i++) { - QModelIndex rowIndex = m_model->index(i, 0); - allItems.push_back({ rowIndex, rowIndex.data(itemDataRole).value() }); - } - auto findIndex = [ allItems ](QuickSettingItem *item) { - for (int i = 0; i < allItems.size(); i++) { - const QPair &rowItem = allItems[i]; - if (rowItem.second == item) - return i; - } - return -1; - }; - int sourceIndex = findIndex(sourceItem); - int targetIndex = findIndex(targetItem); - if (sourceIndex < 0 || targetIndex < 0 || sourceIndex == targetIndex) - return; - - allItems.move(sourceIndex, targetIndex); - - for (int i = 0; i < allItems.size(); i++) { - const QPair &rowItem = allItems[i]; - m_model->setData(rowItem.first, i, itemSortRole); - } - - eve->accept(); + connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDropItem, this, [ this] { + resetPluginDisplay(); + Q_EMIT itemCountChanged(); }); + connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDragMove, this, &QuickPluginWindow::onPluginDragMove); drag->exec(Qt::MoveAction | Qt::CopyAction); } +void QuickPluginWindow::onPluginDragMove(QDragMoveEvent *event) +{ + QPoint currentPoint = mapFromGlobal(QCursor::pos()); + const QuickPluginMimeData *data = qobject_cast(event->mimeData()); + if (!data) + return; + + QuickSettingItem *sourceItem = data->quickSettingItem(); + if (!sourceItem) + return; + + QWidget *sourceMoveWidget = sourceItem->pluginItem()->itemWidget(sourceItem->itemKey()); + QuickSettingItem *targetItem = findQuickSettingItem(currentPoint, m_activeSettingItems); + // 如果未找到要移动的目标位置,或者移动的目标位置是固定插件,或者原插件和目标插件是同一个插件,则不做任何操作 + if (!sourceMoveWidget || !targetItem || sourceItem == targetItem) + return; + + // 重新对所有的插件进行排序 + QMap allItems; + for (int i = 0; i < m_mainLayout->count(); i++) { + QWidget *childWidget = m_mainLayout->itemAt(i)->widget(); + allItems[childWidget] = i; + } + // 调整列表中的位置 + int sourceIndex = m_activeSettingItems.indexOf(sourceItem); + int targetIndex = m_activeSettingItems.indexOf(targetItem); + if (sourceIndex >= 0) + m_activeSettingItems.move(sourceIndex, targetIndex); + else + m_activeSettingItems.insert(targetIndex, sourceItem); + + event->accept(); +} + +QList QuickPluginWindow::settingItems() +{ + QList items; + for (int i = 0; i < m_mainLayout->count(); i++) { + qInfo() << m_mainLayout->itemAt(i)->widget(); + QuickSettingItem *item = qobject_cast(m_mainLayout->itemAt(i)->widget()); + if (item) + items << item; + } + return items; +} + +void QuickPluginWindow::resetPluginDisplay() +{ + // 先删除所有的widget + for (int i = m_mainLayout->count() - 1; i >= 0; i--) { + QLayoutItem *layoutItem = m_mainLayout->itemAt(i); + if (layoutItem) { + layoutItem->widget()->setParent(nullptr); + m_mainLayout->removeItem(layoutItem); + } + } + // 将列表中所有的控件按照顺序添加到布局上 + auto addWidget = [ this ](const QList &items) { + for (QuickSettingItem *item : items) { + QWidget *itemWidget = item->pluginItem()->itemWidget(item->itemKey()); + itemWidget->setParent(this); + m_mainLayout->addWidget(itemWidget); + } + }; + + addWidget(m_activeSettingItems); + addWidget(m_fixedSettingItems); +} + void QuickPluginWindow::initConnection() { - connect(QuickSettingController::instance(), &QuickSettingController::pluginInsert, this, [ this ](QuickSettingItem * settingItem) { + connect(QuickSettingController::instance(), &QuickSettingController::pluginInserted, this, [ this ](QuickSettingItem * settingItem) { const QString itemKey = settingItem->itemKey(); if (!fixedPluginKeys.contains(itemKey)) return; @@ -304,20 +326,5 @@ void QuickPluginWindow::initConnection() addPlugin(settingItem); }); - connect(QuickSettingController::instance(), &QuickSettingController::pluginRemove, this, [ this ](QuickSettingItem *settingItem) { - removePlugin(settingItem); - }); -} - -int QuickPluginWindow::fixedItemCount() -{ - int count = 0; - for (int i = 0; i < m_model->rowCount(); i++) { - QModelIndex index = m_model->index(i, 0); - QuickSettingItem *item = index.data(itemDataRole).value(); - if (item && fixedPluginKeys.contains(item->itemKey())) - count++; - } - - return count; + connect(QuickSettingController::instance(), &QuickSettingController::pluginRemoved, this, &QuickPluginWindow::removePlugin); } diff --git a/frame/window/quickpluginwindow.h b/frame/window/quickpluginwindow.h index dc765c02d..0a520c703 100644 --- a/frame/window/quickpluginwindow.h +++ b/frame/window/quickpluginwindow.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef QUICKPLUGINWINDOW_H #define QUICKPLUGINWINDOW_H @@ -12,6 +32,7 @@ class QuickSettingContainer; class QStandardItemModel; class QStandardItem; class QMouseEvent; +class QBoxLayout; namespace Dtk { namespace Gui { class DRegionMonitor; } namespace Widget { class DListView; class DStandardItem; } } @@ -22,35 +43,41 @@ class QuickPluginWindow : public QWidget { Q_OBJECT -Q_SIGNALS: - void itemCountChanged(); - public: explicit QuickPluginWindow(QWidget *parent = nullptr); ~QuickPluginWindow() override; void setPositon(Dock::Position position); - void addPlugin(QuickSettingItem *item); + void dragPlugin(QuickSettingItem *item); QSize suitableSize(); +Q_SIGNALS: + void itemCountChanged(); + protected: void mouseReleaseEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; +private Q_SLOTS: + void addPlugin(QuickSettingItem *item); + void removePlugin(QuickSettingItem *item); + void onPluginDragMove(QDragMoveEvent *event); + private: void initUi(); void initConnection(); - void resetSortRole(); - int fixedItemCount(); - DStandardItem *createStandItem(QuickSettingItem *item); - void removePlugin(QuickSettingItem *item); void startDrag(QuickSettingItem *moveItem); + QList settingItems(); + QuickSettingItem *findQuickSettingItem(const QPoint &mousePoint, const QList &settingItems); + int findActiveTargetIndex(QWidget *widget); + void resetPluginDisplay(); private: - DListView *m_listView; - QStandardItemModel *m_model; + QBoxLayout *m_mainLayout; Dock::Position m_position; + QList m_activeSettingItems; + QList m_fixedSettingItems; }; #endif // QUICKPLUGINWINDOW_H diff --git a/frame/window/quicksettingcontainer.cpp b/frame/window/quicksettingcontainer.cpp index ce1de0c44..dc6bc14dd 100644 --- a/frame/window/quicksettingcontainer.cpp +++ b/frame/window/quicksettingcontainer.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "quicksettingcontainer.h" #include "quicksettingcontroller.h" #include "pluginsiteminterface.h" @@ -8,6 +28,7 @@ #include "volumewidget.h" #include "volumedeviceswidget.h" #include "brightnessmonitorwidget.h" +#include "pluginchildpage.h" #include #include @@ -27,6 +48,9 @@ static const int QuickItemRole = Dtk::UserRole + 10; #define ITEMSPACE 10 #define COLUMNCOUNT 4 +DockPopupWindow *QuickSettingContainer::m_popWindow = nullptr; +Dock::Position QuickSettingContainer::m_position = Dock::Position::Bottom; + QuickSettingContainer::QuickSettingContainer(QWidget *parent) : QWidget(parent) , m_switchLayout(new QStackedLayout(this)) @@ -40,9 +64,12 @@ QuickSettingContainer::QuickSettingContainer(QWidget *parent) , m_volumeSettingWidget(new VolumeDevicesWidget(m_volumnWidget->model(), this)) , m_brightSettingWidget(new BrightnessMonitorWidget(m_brihtnessWidget->model(), this)) , m_childPage(new PluginChildPage(this)) + , m_dragPluginPosition(QPoint(0, 0)) { initUi(); initConnection(); + m_childPage->installEventFilter(this); + setMouseTracking(true); } QuickSettingContainer::~QuickSettingContainer() @@ -54,27 +81,53 @@ void QuickSettingContainer::showHomePage() m_switchLayout->setCurrentIndex(0); } -DockPopupWindow *QuickSettingContainer::popWindow() +// 根据位置获取箭头的方向 +static DArrowRectangle::ArrowDirection getDirection(const Dock::Position &position) { - static DockPopupWindow *popView = nullptr; - if (!popView) { - popView = new DockPopupWindow; - popView->setWindowFlag(Qt::Popup); - popView->setShadowBlurRadius(20); - popView->setRadius(18); - popView->setShadowYOffset(2); - popView->setShadowXOffset(0); - popView->setArrowWidth(18); - popView->setArrowHeight(10); - - QuickSettingContainer *container = new QuickSettingContainer(popView); - popView->setContent(container); - } else { - QuickSettingContainer *container = static_cast(popView->getContent()); - container->showHomePage(); + switch (position) { + case Dock::Position::Top: + return DArrowRectangle::ArrowDirection::ArrowTop; + case Dock::Position::Left: + return DArrowRectangle::ArrowDirection::ArrowLeft; + case Dock::Position::Right: + return DArrowRectangle::ArrowDirection::ArrowRight; + default: + return DArrowRectangle::ArrowDirection::ArrowBottom; } - return popView; + return DArrowRectangle::ArrowDirection::ArrowBottom; +} + +DockPopupWindow *QuickSettingContainer::popWindow() +{ + if (m_popWindow) { + QuickSettingContainer *container = static_cast(m_popWindow->getContent()); + container->showHomePage(); + return m_popWindow; + } + + m_popWindow = new DockPopupWindow; + m_popWindow->setWindowFlag(Qt::Popup); + m_popWindow->setShadowBlurRadius(20); + m_popWindow->setRadius(18); + m_popWindow->setShadowYOffset(2); + m_popWindow->setShadowXOffset(0); + m_popWindow->setArrowWidth(18); + m_popWindow->setArrowHeight(10); + m_popWindow->setContent(new QuickSettingContainer(m_popWindow)); + m_popWindow->setArrowDirection(getDirection(m_position)); + return m_popWindow; +} + +void QuickSettingContainer::setPosition(Position position) +{ + if (m_position == position) + return; + + m_position = position; + + if (m_popWindow) + m_popWindow->setArrowDirection(getDirection(m_position)); } void QuickSettingContainer::initQuickItem(QuickSettingItem *quickItem) @@ -147,21 +200,51 @@ void QuickSettingContainer::onPluginRemove(QuickSettingItem *quickItem) void QuickSettingContainer::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) - return; + return QWidget::mousePressEvent(event); QuickSettingItem *moveItem = qobject_cast(childAt(event->pos())); if (!moveItem || moveItem->pluginItem()->isPrimary()) return QWidget::mousePressEvent(event); - QDrag *drag = new QDrag(this); - CustomMimeData *mimedata = new CustomMimeData; - mimedata->setData(moveItem); - drag->setMimeData(mimedata); - QPixmap dragPixmap = moveItem->dragPixmap(); - drag->setPixmap(dragPixmap); - drag->setHotSpot(QPoint(dragPixmap.width() / 2, dragPixmap.height() / 2)); + m_dragPluginPosition = event->pos(); +} - drag->exec(Qt::MoveAction | Qt::CopyAction); +void QuickSettingContainer::clearDragPoint() +{ + m_dragPluginPosition.setX(0); + m_dragPluginPosition.setY(0); +} + +void QuickSettingContainer::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + clearDragPoint(); +} + +void QuickSettingContainer::mouseMoveEvent(QMouseEvent *event) +{ + if (m_dragPluginPosition.isNull()) + return; + + QuickSettingItem *moveItem = qobject_cast(childAt(m_dragPluginPosition)); + if (!moveItem) { + clearDragPoint(); + return; + } + + QPoint pointCurrent = event->pos(); + if (qAbs(m_dragPluginPosition.x() - pointCurrent.x()) > 5 + || qAbs(m_dragPluginPosition.y() - pointCurrent.y()) > 5) { + clearDragPoint(); + QDrag *drag = new QDrag(this); + QuickPluginMimeData *mimedata = new QuickPluginMimeData(moveItem); + drag->setMimeData(mimedata); + QPixmap dragPixmap = moveItem->dragPixmap(); + drag->setPixmap(dragPixmap); + drag->setHotSpot(QPoint(dragPixmap.width() / 2, dragPixmap.height() / 2)); + + drag->exec(Qt::MoveAction | Qt::CopyAction); + } } void QuickSettingContainer::resetItemPosition() @@ -183,9 +266,8 @@ void QuickSettingContainer::resetItemPosition() qSort(primaryQuickItems.begin(), primaryQuickItems.end(), [ = ](QuickSettingItem *item1, QuickSettingItem *item2) { int index1 = existKeys.indexOf(item1->itemKey()); int index2 = existKeys.indexOf(item2->itemKey()); - if (index1 >= 0 || index2 >= 0) { + if (index1 >= 0 || index2 >= 0) return index1 < index2; - } return true; }); int primaryColumnCount = COLUMNCOUNT / 2; @@ -265,8 +347,8 @@ void QuickSettingContainer::initUi() void QuickSettingContainer::initConnection() { - connect(m_pluginLoader, &QuickSettingController::pluginInsert, this, &QuickSettingContainer::onPluginInsert); - connect(m_pluginLoader, &QuickSettingController::pluginRemove, this, &QuickSettingContainer::onPluginRemove); + connect(m_pluginLoader, &QuickSettingController::pluginInserted, this, &QuickSettingContainer::onPluginInsert); + connect(m_pluginLoader, &QuickSettingController::pluginRemoved, this, &QuickSettingContainer::onPluginRemove); connect(m_playerWidget, &MediaWidget::visibleChanged, this, [ this ] { resizeView(); }); connect(m_volumnWidget, &VolumeWidget::visibleChanged, this, [ this ] { resizeView(); }); connect(m_volumnWidget, &VolumeWidget::rightIconClick, this, [ this ] { @@ -285,7 +367,6 @@ void QuickSettingContainer::initConnection() if (!m_childPage->isBack()) topLevelWidget()->hide(); }); - m_childPage->installEventFilter(this); } void QuickSettingContainer::resizeView() @@ -318,98 +399,3 @@ void QuickSettingContainer::resizeView() setFixedHeight(m_childPage->height()); } } - -/** - * @brief PluginChildPage::PluginChildPage - * @param parent - */ -PluginChildPage::PluginChildPage(QWidget *parent) - : QWidget(parent) - , m_headerWidget(new QWidget(this)) - , m_back(new QLabel(m_headerWidget)) - , m_title(new QLabel(m_headerWidget)) - , m_container(new QWidget(this)) - , m_topWidget(nullptr) - , m_containerLayout(new QVBoxLayout(m_container)) - , m_isBack(false) -{ - initUi(); - m_back->installEventFilter(this); -} - -PluginChildPage::~PluginChildPage() -{ -} - -void PluginChildPage::pushWidget(QWidget *widget) -{ - // 首先将界面其他的窗体移除 - for (int i = m_containerLayout->count() - 1; i >= 0; i--) { - QLayoutItem *item = m_containerLayout->itemAt(i); - item->widget()->removeEventFilter(this); - item->widget()->hide(); - m_containerLayout->removeItem(item); - } - m_topWidget = widget; - widget->installEventFilter(this); - m_containerLayout->addWidget(widget); - widget->show(); - m_isBack = false; - QMetaObject::invokeMethod(this, &PluginChildPage::resetHeight, Qt::QueuedConnection); -} - -void PluginChildPage::setTitle(const QString &text) -{ - m_title->setText(text); -} - -bool PluginChildPage::isBack() -{ - return m_isBack; -} - -void PluginChildPage::initUi() -{ - m_back->setFixedWidth(24); - m_title->setAlignment(Qt::AlignCenter); - QHBoxLayout *headerLayout = new QHBoxLayout(m_headerWidget); - headerLayout->setContentsMargins(11, 12, 24 + 11, 12); - headerLayout->setSpacing(0); - headerLayout->addWidget(m_back); - headerLayout->addWidget(m_title); - m_headerWidget->setFixedHeight(48); - - QVBoxLayout *mainLayout = new QVBoxLayout(this); - mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->setSpacing(0); - - mainLayout->addWidget(m_headerWidget); - mainLayout->addWidget(m_container); - m_containerLayout->setContentsMargins(11, 0, 11, 0); - m_containerLayout->setSpacing(0); -} - -bool PluginChildPage::eventFilter(QObject *watched, QEvent *event) -{ - if (watched == m_back && event->type() == QEvent::MouseButtonRelease) { - m_isBack = true; - Q_EMIT back(); - return true; - } - if (watched == m_topWidget) { - if (event->type() == QEvent::Hide) { - Q_EMIT closeSelf(); - return true; - } - if (event->type() == QEvent::Resize) - resetHeight(); - } - return QWidget::eventFilter(watched, event); -} - -void PluginChildPage::resetHeight() -{ - QMargins m = m_containerLayout->contentsMargins(); - m_container->setFixedHeight(m.top() + m.bottom() + m_topWidget->height()); - setFixedHeight(m_headerWidget->height() + m_container->height()); -} diff --git a/frame/window/quicksettingcontainer.h b/frame/window/quicksettingcontainer.h index 090d28698..12b74ae2a 100644 --- a/frame/window/quicksettingcontainer.h +++ b/frame/window/quicksettingcontainer.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef QUICKSETTINGCONTAINER_H #define QUICKSETTINGCONTAINER_H @@ -31,9 +51,13 @@ class QuickSettingContainer : public QWidget public: static DockPopupWindow *popWindow(); + static void setPosition(Dock::Position position); protected: void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + explicit QuickSettingContainer(QWidget *parent = nullptr); ~QuickSettingContainer() override; void showHomePage(); @@ -57,8 +81,12 @@ private: void initQuickItem(QuickSettingItem *quickItem); // 显示具体的窗体 void showWidget(QWidget *widget, const QString &title); + // 清除移动轨迹 + void clearDragPoint(); private: + static DockPopupWindow *m_popWindow; + static Dock::Position m_position; QStackedLayout *m_switchLayout; QWidget *m_mainWidget; QWidget *m_pluginWidget; @@ -71,52 +99,20 @@ private: VolumeDevicesWidget *m_volumeSettingWidget; BrightnessMonitorWidget *m_brightSettingWidget; PluginChildPage *m_childPage; + QPoint m_dragPluginPosition; }; -class CustomMimeData : public QMimeData +class QuickPluginMimeData : public QMimeData { Q_OBJECT public: - CustomMimeData() : QMimeData(), m_data(nullptr) {} - ~CustomMimeData() {} - void setData(void *data) { m_data = data; } - void *data() { return m_data; } + explicit QuickPluginMimeData(QuickSettingItem *item) : QMimeData(), m_item(item) {} + ~QuickPluginMimeData() {} + QuickSettingItem *quickSettingItem() const { return m_item; } private: - void *m_data; -}; - -class PluginChildPage : public QWidget -{ - Q_OBJECT - -Q_SIGNALS: - void back(); - void closeSelf(); - -public: - explicit PluginChildPage(QWidget *parent); - ~PluginChildPage() override; - void pushWidget(QWidget *widget); - void setTitle(const QString &text); - bool isBack(); - -protected: - bool eventFilter(QObject *watched, QEvent *event) override; - -private: - void initUi(); - void resetHeight(); - -private: - QWidget *m_headerWidget; - QLabel *m_back; - QLabel *m_title; - QWidget *m_container; - QWidget *m_topWidget; - QVBoxLayout *m_containerLayout; - bool m_isBack; + QuickSettingItem *m_item; }; #endif // PLUGINCONTAINER_H diff --git a/frame/window/systempluginwindow.cpp b/frame/window/systempluginwindow.cpp index ce6e8fdbe..db4f3e230 100644 --- a/frame/window/systempluginwindow.cpp +++ b/frame/window/systempluginwindow.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "systempluginwindow.h" #include "systemplugincontroller.h" #include "systempluginitem.h" @@ -110,7 +130,6 @@ int SystemPluginWindow::calcIconSize() const if (height() <= 40) return MINICONSIZE; return height() - ICONMARGIN * 2; - break; } case Dock::Position::Left: case Dock::Position::Right: { @@ -153,15 +172,12 @@ FixedPluginController::FixedPluginController(QObject *parent) { } -const QVariant FixedPluginController::getValue(PluginsItemInterface * const itemInter, const QString &key, const QVariant &fallback) -{ - if (key == "enable") - return (itemInter->pluginName().compare("shutdown") == 0); - - return AbstractPluginsController::getValue(itemInter, key, fallback); -} - PluginsItem *FixedPluginController::createPluginsItem(PluginsItemInterface * const itemInter, const QString &itemKey, const QString &pluginApi) { return new StretchPluginsItem(itemInter, itemKey, pluginApi); } + +bool FixedPluginController::needLoad(PluginsItemInterface *itemInter) +{ + return (itemInter->pluginName().compare("shutdown") == 0); +} diff --git a/frame/window/systempluginwindow.h b/frame/window/systempluginwindow.h index 56b68f0ef..27a362f36 100644 --- a/frame/window/systempluginwindow.h +++ b/frame/window/systempluginwindow.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef SYSTEMPLUGINWINDOW_H #define SYSTEMPLUGINWINDOW_H @@ -18,15 +38,15 @@ class SystemPluginWindow : public DBlurEffectWidget { Q_OBJECT -Q_SIGNALS: - void pluginSizeChanged(); - public: explicit SystemPluginWindow(QWidget *parent = nullptr); ~SystemPluginWindow() override; void setPositon(Dock::Position position); QSize suitableSize(); +Q_SIGNALS: + void pluginSizeChanged(); + private: void initUi(); int calcIconSize() const; @@ -49,11 +69,11 @@ class FixedPluginController : public DockPluginsController Q_OBJECT public: - FixedPluginController(QObject *parent); + explicit FixedPluginController(QObject *parent); protected: - const QVariant getValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant& fallback = QVariant()) override; PluginsItem *createPluginsItem(PluginsItemInterface *const itemInter, const QString &itemKey, const QString &pluginApi) override; + bool needLoad(PluginsItemInterface *itemInter) override; }; #endif // SYSTEMPLUGINWINDOW_H diff --git a/frame/window/tray/tray_delegate.cpp b/frame/window/tray/tray_delegate.cpp index 1a3a601a9..276d9f706 100644 --- a/frame/window/tray/tray_delegate.cpp +++ b/frame/window/tray/tray_delegate.cpp @@ -28,18 +28,22 @@ #include "widgets/expandiconwidget.h" #include "utils.h" +#include + #include #include #include #include #include +#include #include #include -TrayDelegate::TrayDelegate(QObject *parent) +TrayDelegate::TrayDelegate(QListView *view, QObject *parent) : QStyledItemDelegate(parent) , m_position(Dock::Position::Bottom) + , m_listView(view) { } @@ -65,7 +69,7 @@ QWidget *TrayDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem int screenp = 0; static xcb_connection_t *xcb_connection = xcb_connect(qgetenv("DISPLAY"), &screenp); static Display *m_display = XOpenDisplay(nullptr); - trayWidget = new XEmbedTrayItemWidget(winId, xcb_connection, m_display, parent) ; + trayWidget = new XEmbedTrayItemWidget(winId, xcb_connection, m_display, parent); } const TrayModel *model = qobject_cast(index.model()); @@ -74,40 +78,53 @@ QWidget *TrayDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem } else if (type == TrayIconType::SNI) { trayWidget = new SNITrayItemWidget(servicePath, parent); } else if (type == TrayIconType::EXPANDICON) { - ExpandIconWidget *widget = new ExpandIconWidget(parent); - widget->setPositonValue(m_position); - connect(widget, &ExpandIconWidget::trayVisbleChanged, this, [ = ](bool visible) { + ExpandIconWidget *expandWidget = new ExpandIconWidget(parent); + expandWidget->setPositonValue(m_position); + connect(expandWidget, &ExpandIconWidget::trayVisbleChanged, this, [ = ](bool visible) { Q_EMIT visibleChanged(index, visible); }); - connect(this, &TrayDelegate::requestDrag, this, [ = ](bool on) { - if (on) { - widget->setTrayPanelVisible(true); - } else { - // 如果释放鼠标,则判断当前鼠标的位置是否在托盘内部,如果在,则无需隐藏 - QPoint currentPoint = QCursor::pos(); - TrayGridView *view = widget->popupTrayView(); - if (view->geometry().contains(currentPoint)) - widget->setTrayPanelVisible(true); - else - widget->setTrayPanelVisible(false); - } - }); - trayWidget = widget; + connect(this, &TrayDelegate::requestDrag, this, &TrayDelegate::onRequestDrag); + trayWidget = expandWidget; } else if (type == TrayIconType::INDICATOR) { QString indicateName = key; int flagIndex = indicateName.indexOf("indicator:"); if (flagIndex >= 0) indicateName = indicateName.right(indicateName.length() - QString("indicator:").length()); IndicatorTrayItem *indicatorWidget = new IndicatorTrayItem(indicateName, parent); - connect(indicatorWidget, &IndicatorTrayItem::removed, this, [ = ]{ - Q_EMIT removeRow(index); - }); + TrayModel *dataModel = qobject_cast(m_listView->model()); + if (IndicatorTrayItem *sourceIndicatorWidget = dataModel->indicatorWidget(key)) { + const QByteArray pixmapData = sourceIndicatorWidget->pixmapData(); + if (!pixmapData.isEmpty()) + indicatorWidget->setPixmapData(pixmapData); + const QString text = sourceIndicatorWidget->text(); + if (!text.isEmpty()) + indicatorWidget->setText(text); + } trayWidget = indicatorWidget; } + if (trayWidget) + trayWidget->setFixedSize(16, 16); + return trayWidget; } +void TrayDelegate::onRequestDrag(bool on) +{ + ExpandIconWidget *expandwidget = expandWidget(); + if (!expandwidget) + return; + + if (on) { + expandwidget->setTrayPanelVisible(true); + } else { + // 如果释放鼠标,则判断当前鼠标的位置是否在托盘内部,如果在,则无需隐藏 + QPoint currentPoint = QCursor::pos(); + QWidget *view = expandwidget->popupTrayView(); + expandwidget->setTrayPanelVisible(view->geometry().contains(currentPoint)); + } +} + void TrayDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { BaseTrayWidget *widget = static_cast(editor); @@ -128,5 +145,67 @@ void TrayDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewI { Q_UNUSED(index); QRect rect = option.rect; - editor->setGeometry(rect.x() + ITEM_SPACING, rect.y() + ITEM_SPACING, ITEM_SIZE - (2 * ITEM_SPACING), ITEM_SIZE - 2 * ITEM_SPACING); + // 让控件居中显示 + editor->setGeometry(rect.x() + (rect.width() - ICON_SIZE) / 2, + rect.y() + (rect.height() - ICON_SIZE) / 2, + ICON_SIZE, ICON_SIZE); +} + +void TrayDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (needDrawBackground()) { + QColor borderColor; + QColor backColor; + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { + // 白色主题的情况下 + borderColor = Qt::black; + borderColor.setAlpha(static_cast(255 * 0.05)); + backColor = Qt::white; + backColor.setAlpha(static_cast(255 * 0.4)); + } else { + borderColor = Qt::black; + borderColor.setAlpha(static_cast(255 * 0.2)); + backColor = Qt::black; + backColor.setAlpha(static_cast(255 * 0.4)); + } + painter->save(); + QPainterPath path; + path.addRoundedRect(option.rect, 8, 8); + painter->setRenderHint(QPainter::Antialiasing); + painter->fillPath(path, backColor); + painter->setPen(borderColor); + painter->drawPath(path); + painter->restore(); + } +} + +ExpandIconWidget *TrayDelegate::expandWidget() +{ + if (!m_listView) + return nullptr; + + QAbstractItemModel *dataModel = m_listView->model(); + if (!dataModel) + return nullptr; + + for (int i = 0; i < dataModel->rowCount() - 1; i++) { + QModelIndex index = dataModel->index(i, 0); + ExpandIconWidget *widget = qobject_cast(m_listView->indexWidget(index)); + if (widget) + return widget; + } + + return nullptr; +} + +bool TrayDelegate::needDrawBackground() const +{ + if (!m_listView) + return false; + + TrayModel *dataModel = qobject_cast(m_listView->model()); + if (!dataModel) + return false; + + return dataModel->isIconTray(); } diff --git a/frame/window/tray/tray_delegate.h b/frame/window/tray/tray_delegate.h index 294153029..85125819e 100644 --- a/frame/window/tray/tray_delegate.h +++ b/frame/window/tray/tray_delegate.h @@ -26,31 +26,44 @@ #include #define ITEM_SIZE 30 +// 托盘图标固定16个像素 +#define ICON_SIZE 16 #define ITEM_SPACING 5 struct WinInfo; +class ExpandIconWidget; +class QListView; class TrayDelegate : public QStyledItemDelegate { Q_OBJECT +public: + explicit TrayDelegate(QListView *view, QObject *parent = nullptr); + void setPositon(Dock::Position position); + Q_SIGNALS: void removeRow(const QModelIndex &) const; void visibleChanged(const QModelIndex &, bool) const; void requestDrag(bool) const; -public: - explicit TrayDelegate(QObject *parent = nullptr); - void setPositon(Dock::Position position); +private Q_SLOTS: + void onRequestDrag(bool on); protected: QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; void setEditorData(QWidget *editor, const QModelIndex &index) const override ; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +private: + ExpandIconWidget *expandWidget(); + bool needDrawBackground() const; private: Dock::Position m_position; + QListView *m_listView; }; #endif // TRAYDELEGATE_H diff --git a/frame/window/tray/tray_gridview.cpp b/frame/window/tray/tray_gridview.cpp index cb5247e7b..f346d04d4 100644 --- a/frame/window/tray/tray_gridview.cpp +++ b/frame/window/tray/tray_gridview.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "tray_gridview.h" #include @@ -23,10 +43,66 @@ TrayGridView::TrayGridView(QWidget *parent) , m_aniStartTime(new QTimer(this)) , m_pressed(false) , m_aniRunning(false) + , m_positon(Dock::Position::Bottom) { initUi(); } +void TrayGridView::setPosition(Dock::Position position) +{ + m_positon = position; +} + +QSize TrayGridView::suitableSize() const +{ + TrayModel *dataModel = qobject_cast(model()); + if (!dataModel) + return QSize(-1, -1); + + if (dataModel->isIconTray()) { + // 如果是托盘图标 + int width = 2; + int height = 0; + int count = dataModel->rowCount(); + if (count > 0) { + int columnCount = qMin(count, 3); + for (int i = 0; i < columnCount; i ++) { + QModelIndex index = dataModel->index(i, 0); + width += visualRect(index).width() + spacing() * 2; // 左右边距加上单元格宽度 + } + int rowCount = count / 3; + if (count % 3 > 0) + rowCount++; + for (int i = 0; i < rowCount; i++) { + QModelIndex index = dataModel->index(i * 3); + height += visualRect(index).height() + spacing() * 2; + } + } else { + width = spacing() * 2 + 30; + height = spacing() * 2 + 30; + } + return QSize(width, height); + } + if (m_positon == Dock::Position::Top || m_positon == Dock::Position::Bottom) { + int length = spacing() + 2; + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + length += indexRect.width() + spacing(); + } + + return QSize(length, -1); + } + int height = spacing() + 2; + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + height += indexRect.height() + spacing(); + } + + return QSize(-1, height); +} + void TrayGridView::setDragDistance(int pixel) { m_dragDistance = pixel; @@ -171,6 +247,9 @@ void TrayGridView::mousePressEvent(QMouseEvent *e) void TrayGridView::mouseMoveEvent(QMouseEvent *e) { + if (!m_pressed) + return DListView::mouseMoveEvent(e); + setState(QAbstractItemView::NoState); e->accept(); @@ -181,15 +260,22 @@ void TrayGridView::mouseMoveEvent(QMouseEvent *e) if (!index.isValid()) return DListView::mouseMoveEvent(e); - if (m_pressed && (qAbs(e->pos().x() - m_dragPos.x()) > m_dragDistance || + // 如果当前拖动的位置是托盘展开按钮,则不让其拖动 + TrayIconType iconType = index.data(TrayModel::Role::TypeRole).value(); + if (iconType == TrayIconType::EXPANDICON) + return DListView::mouseMoveEvent(e); + + if ((qAbs(e->pos().x() - m_dragPos.x()) > m_dragDistance || qAbs(e->pos().y() - m_dragPos.y()) > m_dragDistance)) { qDebug() << "start drag"; - beginDrag(Qt::CopyAction | Qt::MoveAction); + if (!beginDrag(Qt::CopyAction | Qt::MoveAction)) + DListView::mouseMoveEvent(e); } } void TrayGridView::mouseReleaseEvent(QMouseEvent *e) { + Q_UNUSED(e); m_pressed = false; } @@ -198,7 +284,7 @@ void TrayGridView::dragEnterEvent(QDragEnterEvent *e) const QModelIndex index = indexAt(e->pos()); if (model()->canDropMimeData(e->mimeData(), e->dropAction(), index.row(), - index.column(), QModelIndex())) + index.column(), index)) e->accept(); else e->ignore(); @@ -219,9 +305,13 @@ void TrayGridView::dragMoveEvent(QDragMoveEvent *e) if (m_aniRunning) return; + QModelIndex index = indexAt(e->pos()); + if (!model()->canDropMimeData(e->mimeData(), e->dropAction(), index.row(), + index.column(), index)) + return; + setState(QAbstractItemView::DraggingState); - QModelIndex index = indexAt(e->pos()); if (index.isValid()) { if (m_dropPos != indexRect(index).center()) { qDebug() << "update drop position: " << index.row(); @@ -233,6 +323,43 @@ void TrayGridView::dragMoveEvent(QDragMoveEvent *e) m_aniStartTime->start(); } +const QModelIndex TrayGridView::getIndexFromPos(QPoint currentPoint) const +{ + QModelIndex index = indexAt(currentPoint); + if (index.isValid()) + return index; + + if (model()->rowCount() == 0) + return index; + + // 如果在第一个之前,则认为拖到了第一个的位置 + QRect indexRect0 = visualRect(model()->index(0, 0)); + if (currentPoint.x() < indexRect0.x() || currentPoint.y() < indexRect0.y()) + return model()->index(0, 0); + + // 如果从指定的位置没有找到索引,则依次从每个index中查找,先横向查找 + for (int i = 1; i < model()->rowCount(); i++) { + QModelIndex lastIndex = model()->index(i - 1, 0); + QModelIndex currentIndex = model()->index(i, 0); + QRect lastIndexRect = visualRect(lastIndex); + QRect indexRect = visualRect(currentIndex); + if (lastIndexRect.x() + lastIndexRect.width() <= currentPoint.x() + && indexRect.x() >= currentPoint.x()) + return currentIndex; + } + // 如果鼠标位置刚好在上下两个索引中间 + for (int i = 0; i < model()->rowCount(); i++) { + QModelIndex currentIndex = model()->index(i, 0); + QRect indexRect = visualRect(currentIndex); + + if (currentPoint.y() >= indexRect.y() - spacing() && currentPoint.y() < indexRect.y() + && currentPoint.x() >= indexRect.x() - spacing() && currentPoint.x() < indexRect.x()) + return currentIndex; + } + + return QModelIndex(); +} + void TrayGridView::dropEvent(QDropEvent *e) { setState(DListView::NoState); @@ -245,39 +372,45 @@ void TrayGridView::dropEvent(QDropEvent *e) e->setDropAction(Qt::CopyAction); e->accept(); - TrayModel *m = qobject_cast(model()); - if (m) { + TrayModel *dataModel = qobject_cast(model()); + if (dataModel) { WinInfo info; info.type = static_cast(e->mimeData()->data("type").toInt()); info.key = static_cast(e->mimeData()->data("key")); info.winId = static_cast(e->mimeData()->data("winId").toInt()); info.servicePath = static_cast(e->mimeData()->data("servicePath")); - m->addRow(info); + QModelIndex targetIndex = getIndexFromPos(e->pos()); + if (targetIndex.isValid() && targetIndex.row() < dataModel->rowCount() - 1) { + // 如果拖动的位置是合法的位置,则让其插入到当前的位置 + dataModel->insertRow(targetIndex.row(), info); + } else { + // 在其他的情况下,让其插入到最后 + dataModel->addRow(info); + } } } else { e->ignore(); + DListView::dropEvent(e); } - - DListView::dropEvent(e); } -void TrayGridView::beginDrag(Qt::DropActions supportedActions) +bool TrayGridView::beginDrag(Qt::DropActions supportedActions) { QModelIndex modelIndex = indexAt(m_dragPos); TrayIconType trayType = modelIndex.data(TrayModel::Role::TypeRole).value(); // 展开图标不能移动 if (trayType == TrayIconType::EXPANDICON) - return; + return false; m_dropPos = indexRect(modelIndex).center(); TrayModel *listModel = qobject_cast(model()); if (!listModel) - return; + return false; BaseTrayWidget *widget = qobject_cast(indexWidget(modelIndex)); if (!widget) - return; + return false; auto pixmap = widget->icon(); @@ -315,7 +448,7 @@ void TrayGridView::beginDrag(Qt::DropActions supportedActions) Q_EMIT dragEntered(); if (dropAct == Qt::IgnoreAction) { QPropertyAnimation *posAni = new QPropertyAnimation(pixLabel, "pos", pixLabel); - connect(posAni, &QPropertyAnimation::finished, [&, listModel, pixLabel] () { + connect(posAni, &QPropertyAnimation::finished, [ &, listModel, pixLabel ] () { pixLabel->hide(); pixLabel->deleteLater(); listModel->setDragKey(QString()); @@ -339,6 +472,8 @@ void TrayGridView::beginDrag(Qt::DropActions supportedActions) Q_EMIT requestRemove(itemKey); } + + return true; } void TrayGridView::initUi() diff --git a/frame/window/tray/tray_gridview.h b/frame/window/tray/tray_gridview.h index 0009370a4..fee65b42e 100644 --- a/frame/window/tray/tray_gridview.h +++ b/frame/window/tray/tray_gridview.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef TRAYGRIDVIEW_H #define TRAYGRIDVIEW_H @@ -14,8 +34,10 @@ class TrayGridView : public DListView Q_OBJECT public: - TrayGridView(QWidget *parent = Q_NULLPTR); + explicit TrayGridView(QWidget *parent = Q_NULLPTR); + void setPosition(Dock::Position position); + QSize suitableSize() const; void setDragDistance(int pixel); void setAnimationProperty(const QEasingCurve::Type easing, const int duringTime = 250); void moveAnimation(); @@ -40,11 +62,12 @@ protected: void dragLeaveEvent(QDragLeaveEvent *e) Q_DECL_OVERRIDE; void dragMoveEvent(QDragMoveEvent *e) Q_DECL_OVERRIDE; void dropEvent(QDropEvent *e) Q_DECL_OVERRIDE; - void beginDrag(Qt::DropActions supportedActions); + bool beginDrag(Qt::DropActions supportedActions); private: void initUi(); void createAnimation(const int pos, const bool moveNext, const bool isLastAni); + const QModelIndex getIndexFromPos(QPoint currentPoint) const; private: QEasingCurve::Type m_aniCurveType; @@ -58,6 +81,7 @@ private: QTimer *m_aniStartTime; bool m_pressed; bool m_aniRunning; + Dock::Position m_positon; }; #endif // GRIDVIEW_H diff --git a/frame/window/tray/tray_model.cpp b/frame/window/tray/tray_model.cpp index b878ffb86..2640eb7d3 100644 --- a/frame/window/tray/tray_model.cpp +++ b/frame/window/tray/tray_model.cpp @@ -1,4 +1,24 @@ -#include "tray_model.h" +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ +#include "tray_model.h" #include "tray_monitor.h" #include "indicatortrayitem.h" @@ -104,6 +124,16 @@ bool TrayModel::indexDragging(const QModelIndex &index) const || (start >= end && current <= start && current >= end); } +IndicatorTrayItem *TrayModel::indicatorWidget(const QString &indicatorName) const +{ + QString indicatorKey = indicatorName; + indicatorKey = indicatorKey.remove(0, QString("indicator:").length()); + if (m_indicatorMap.contains(indicatorKey)) + return m_indicatorMap.value(indicatorKey)->widget(); + + return nullptr; +} + QMimeData *TrayModel::mimeData(const QModelIndexList &indexes) const { Q_ASSERT(indexes.size() == 1); @@ -132,7 +162,7 @@ QVariant TrayModel::data(const QModelIndex &index, int role) const return QVariant(); int itemIndex = index.row(); - auto info = m_winInfos.at(itemIndex); + const WinInfo &info = m_winInfos[itemIndex]; switch (role) { case Role::TypeRole: @@ -170,7 +200,10 @@ bool TrayModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, in Q_UNUSED(action) Q_UNUSED(row) Q_UNUSED(column) - Q_UNUSED(parent) + + TrayIconType iconType = parent.data(TrayModel::Role::TypeRole).value(); + if (iconType == TrayIconType::EXPANDICON) + return false; return data->formats().contains(TRAY_DRAG_FALG); } @@ -186,7 +219,6 @@ Qt::ItemFlags TrayModel::flags(const QModelIndex &index) const int TrayModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); - return m_winInfos.size(); } @@ -204,7 +236,7 @@ void TrayModel::clear() void TrayModel::onXEmbedTrayAdded(quint32 winId) { - for (auto info : m_winInfos) { + for (const WinInfo &info : m_winInfos) { if (info.winId == winId) return; } @@ -260,7 +292,7 @@ QString TrayModel::fileNameByServiceName(const QString &serviceName) bool TrayModel::isTypeWriting(const QString &servicePath) { const QString appFilePath = fileNameByServiceName(servicePath); - return appFilePath.startsWith("/usr/bin/fcitx"); + return (appFilePath.startsWith("/usr/bin/fcitx") || appFilePath.endsWith("chinime-qim")); } void TrayModel::onSniTrayAdded(const QString &servicePath) @@ -304,7 +336,7 @@ void TrayModel::onSniTrayAdded(const QString &servicePath) void TrayModel::onSniTrayRemoved(const QString &servicePath) { - for (WinInfo info : m_winInfos) { + for (const WinInfo &info : m_winInfos) { if (info.servicePath == servicePath) { int index = m_winInfos.indexOf(info); @@ -356,7 +388,7 @@ void TrayModel::onIndicatorFounded(const QString &indicatorName) void TrayModel::onIndicatorAdded(const QString &indicatorName) { const QString &itemKey = IndicatorTrayItem::toIndicatorKey(indicatorName); - for (auto info : m_winInfos) { + for (const WinInfo &info : m_winInfos) { if (info.key == itemKey) return; } @@ -377,7 +409,7 @@ void TrayModel::onIndicatorRemoved(const QString &indicatorName) void TrayModel::removeRow(const QString &itemKey) { - for (auto info : m_winInfos) { + for (const WinInfo &info : m_winInfos) { if (info.key == itemKey) { int index = m_winInfos.indexOf(info); beginRemoveRows(QModelIndex(), index, index); @@ -390,8 +422,8 @@ void TrayModel::removeRow(const QString &itemKey) void TrayModel::addRow(WinInfo info) { - for (auto i : m_winInfos) { - if (i.key == info.key) + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.key == info.key) return; } @@ -400,10 +432,26 @@ void TrayModel::addRow(WinInfo info) endInsertRows(); } +void TrayModel::insertRow(int index, WinInfo info) +{ + for (int i = 0; i < m_winInfos.size(); i++) { + const WinInfo &wininfo = m_winInfos[i]; + if (wininfo.key == info.key) { + beginResetModel(); + m_winInfos.swap(index, i); + endResetModel(); + return; + } + } + beginInsertRows(QModelIndex(), index, index); + m_winInfos.insert(index, info); + endInsertRows(); +} + bool TrayModel::exist(const QString &itemKey) { - for (auto w : m_winInfos) { - if (w.key == itemKey) + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.key == itemKey) return true; } diff --git a/frame/window/tray/tray_model.h b/frame/window/tray/tray_model.h index 3a09e5128..893c3f203 100644 --- a/frame/window/tray/tray_model.h +++ b/frame/window/tray/tray_model.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef TRAYMODEL_H #define TRAYMODEL_H @@ -7,6 +27,7 @@ class TrayMonitor; class IndicatorPlugin; +class IndicatorTrayItem; enum TrayIconType { UNKNOW, @@ -23,13 +44,12 @@ struct WinInfo { QString servicePath; bool isTypeWriting; - WinInfo() { - type = UNKNOW; - key = QString(); - winId = 0; - servicePath = QString(); - isTypeWriting = false; - } + WinInfo() : type(UNKNOW) + , key(QString()) + , winId(0) + , servicePath(QString()) + , isTypeWriting(false) {} + bool operator==(const WinInfo &other) { return this->type == other.type && this->key == other.key @@ -67,19 +87,22 @@ public: bool indexDragging(const QModelIndex &index) const; + IndicatorTrayItem *indicatorWidget(const QString &indicatorName) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; bool isIconTray(); void clear(); -public Q_SLOTS: - void removeRow(const QString &itemKey); - void addRow(WinInfo info); - Q_SIGNALS: void requestUpdateIcon(quint32); void requestUpdateWidget(const QList &); +public Q_SLOTS: + void removeRow(const QString &itemKey); + void addRow(WinInfo info); + void insertRow(int index, WinInfo info); + private Q_SLOTS: void onXEmbedTrayAdded(quint32 winId); void onXEmbedTrayRemoved(quint32 winId); diff --git a/frame/window/tray/tray_monitor.cpp b/frame/window/tray/tray_monitor.cpp index 6a45ff5e2..bb92f9dbc 100644 --- a/frame/window/tray/tray_monitor.cpp +++ b/frame/window/tray/tray_monitor.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "tray_monitor.h" TrayMonitor::TrayMonitor(QObject *parent) diff --git a/frame/window/tray/tray_monitor.h b/frame/window/tray/tray_monitor.h index 3a413126c..de2ee566d 100644 --- a/frame/window/tray/tray_monitor.h +++ b/frame/window/tray/tray_monitor.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef TRAYMONITOR_H #define TRAYMONITOR_H @@ -14,12 +34,6 @@ class TrayMonitor : public QObject public: explicit TrayMonitor(QObject *parent = nullptr); -public Q_SLOTS: - void onTrayIconsChanged(); - void onSniItemsChanged(); - - void startLoadIndicators(); - Q_SIGNALS: void requestUpdateIcon(quint32); void xEmbedTrayAdded(quint32); @@ -30,6 +44,12 @@ Q_SIGNALS: void indicatorFounded(const QString &); +public Q_SLOTS: + void onTrayIconsChanged(); + void onSniItemsChanged(); + + void startLoadIndicators(); + private: DBusTrayManager *m_trayInter; StatusNotifierWatcher *m_sniWatcher; diff --git a/frame/window/tray/widgets/basetraywidget.cpp b/frame/window/tray/widgets/basetraywidget.cpp index 9cb0ddccf..f17ebda96 100644 --- a/frame/window/tray/widgets/basetraywidget.cpp +++ b/frame/window/tray/widgets/basetraywidget.cpp @@ -1,9 +1,9 @@ /* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. * - * Author: sbw + * Author: donghualin * - * Maintainer: sbw + * Maintainer: donghualin * * 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 @@ -18,7 +18,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - #include "constants.h" #include "basetraywidget.h" @@ -40,7 +39,6 @@ BaseTrayWidget::BaseTrayWidget(QWidget *parent, Qt::WindowFlags f) BaseTrayWidget::~BaseTrayWidget() { - } void BaseTrayWidget::mousePressEvent(QMouseEvent *event) @@ -60,7 +58,6 @@ void BaseTrayWidget::mousePressEvent(QMouseEvent *event) void BaseTrayWidget::mouseReleaseEvent(QMouseEvent *e) { //e->accept(); - // 由于 XWindowTrayWidget 中对 发送鼠标事件到X窗口的函数, 如 sendClick/sendHoverEvent 中 // 使用了 setX11PassMouseEvent, 而每次调用 setX11PassMouseEvent 时都会导致产生 mousePress 和 mouseRelease 事件 // 因此如果直接在这里处理事件会导致一些问题, 所以使用 Timer 来延迟处理 100 毫秒内的最后一个事件 diff --git a/frame/window/tray/widgets/basetraywidget.h b/frame/window/tray/widgets/basetraywidget.h index 6f3124c20..d5e6c38ca 100644 --- a/frame/window/tray/widgets/basetraywidget.h +++ b/frame/window/tray/widgets/basetraywidget.h @@ -1,9 +1,9 @@ /* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. * - * Author: sbw + * Author: donghualin * - * Maintainer: sbw + * Maintainer: donghualin * * 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 @@ -18,7 +18,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - #pragma once #include diff --git a/frame/window/tray/widgets/expandiconwidget.cpp b/frame/window/tray/widgets/expandiconwidget.cpp index 62bfd857c..2d7670ed3 100644 --- a/frame/window/tray/widgets/expandiconwidget.cpp +++ b/frame/window/tray/widgets/expandiconwidget.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "expandiconwidget.h" #include "tray_gridview.h" #include "tray_model.h" @@ -6,7 +26,9 @@ #include #include +#include #include +#include #include @@ -16,17 +38,25 @@ ExpandIconWidget::ExpandIconWidget(QWidget *parent, Qt::WindowFlags f) : BaseTrayWidget(parent, f) , m_regionInter(new DRegionMonitor(this)) , m_position(Dock::Position::Bottom) - , m_trayView(nullptr) + , m_gridParentView(new RoundWidget(nullptr)) + , m_trayView(new TrayGridView(m_gridParentView)) + , m_trayDelegate(new TrayDelegate(m_trayView, m_trayView)) + , m_trayModel(new TrayModel(m_trayView, true, false)) { - connect(m_regionInter, &DRegionMonitor::buttonPress, this, &ExpandIconWidget::onGlobMousePress); + initUi(); + initConnection(); } ExpandIconWidget::~ExpandIconWidget() { + m_gridParentView->deleteLater(); } void ExpandIconWidget::setPositonValue(Dock::Position position) { + if (m_position == position) + return; + m_position = position; } @@ -38,19 +68,17 @@ void ExpandIconWidget::sendClick(uint8_t mouseButton, int x, int y) if (mouseButton != XCB_BUTTON_INDEX_1) return; - TrayGridView *trayIcon = popupTrayView(); - setTrayPanelVisible(!trayIcon->isVisible()); + setTrayPanelVisible(!m_gridParentView->isVisible()); } void ExpandIconWidget::setTrayPanelVisible(bool visible) { - TrayGridView *trayIcon = popupTrayView(); if (visible) { resetPosition(); - trayIcon->show(); + m_gridParentView->show(); m_regionInter->registerRegion(); } else { - trayIcon->hide(); + m_gridParentView->hide(); m_regionInter->unregisterRegion(); } } @@ -98,42 +126,9 @@ const QString ExpandIconWidget::dropIconFile() const return iconFile + ".svg"; } -TrayGridView *ExpandIconWidget::popupTrayView() +QWidget *ExpandIconWidget::popupTrayView() { - if (m_trayView) - return m_trayView; - - m_trayView = new TrayGridView(nullptr); - TrayModel *model = new TrayModel(m_trayView, true, false); - TrayDelegate *trayDelegate = new TrayDelegate(m_trayView); - m_trayView->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); - m_trayView->setModel(model); - m_trayView->setItemDelegate(trayDelegate); - m_trayView->setSpacing(3); - m_trayView->setDragDistance(5); - - connect(m_trayView, &TrayGridView::rowCountChanged, this, [ this ] { - int count = m_trayView->model()->rowCount(); - if (count > 0) { - int lineCount = (count % 3) != 0 ? (count / 3 + 1) : (count / 3); - // 如果只有一行,则根据实际的数量显示宽度 - int columnCount = qMin(count, 3); - int width = ITEM_SIZE * columnCount + m_trayView->spacing() * 2;; - int height = lineCount * ITEM_SIZE + m_trayView->spacing() * (lineCount - 1) + ITEM_SPACING; - m_trayView->setFixedSize(width, height); - resetPosition(); - } else if (m_trayView->isVisible()) { - m_trayView->hide(); - } - Q_EMIT trayVisbleChanged(count > 0); - }); - - connect(trayDelegate, &TrayDelegate::removeRow, this, [ = ](const QModelIndex &index) { - QAbstractItemModel *abModel = model; - abModel->removeRow(index.row(),index.parent()); - }); - connect(m_trayView, &TrayGridView::requestRemove, model, &TrayModel::removeRow); - return m_trayView; + return m_gridParentView; } void ExpandIconWidget::resetPosition() @@ -141,27 +136,122 @@ void ExpandIconWidget::resetPosition() if (!parentWidget()) return; - TrayGridView *trayView = popupTrayView(); QPoint ptPos = parentWidget()->mapToGlobal(this->pos()); - ptPos.setY(ptPos.y() - trayView->height()); - ptPos.setX(ptPos.x() - trayView->width()); - trayView->move(ptPos); + switch (m_position) { + case Dock::Position::Bottom: { + ptPos.setY(ptPos.y() - m_gridParentView->height()); + ptPos.setX(ptPos.x() - m_gridParentView->width()); + break; + } + case Dock::Position::Top: { + ptPos.setY(ptPos.y() + m_gridParentView->height()); + ptPos.setX(ptPos.x() - m_gridParentView->width()); + break; + } + case Dock::Position::Left: { + ptPos.setX(ptPos.x() + m_gridParentView->width() / 2); + break; + } + case Dock::Position::Right: { + ptPos.setX(ptPos.x() - m_gridParentView->width() / 2); + break; + } + } + m_gridParentView->move(ptPos); +} + +void ExpandIconWidget::initUi() +{ + m_gridParentView->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); + m_trayView->setModel(m_trayModel); + m_trayView->setItemDelegate(m_trayDelegate); + m_trayView->setSpacing(ITEM_SPACING); + m_trayView->setDragDistance(2); + + QVBoxLayout *layout = new QVBoxLayout(m_gridParentView); + layout->setContentsMargins(ITEM_SPACING, ITEM_SPACING, ITEM_SPACING, ITEM_SPACING); + layout->setSpacing(0); + layout->addWidget(m_trayView); +} + +void ExpandIconWidget::initConnection() +{ + connect(m_trayView, &TrayGridView::rowCountChanged, this, &ExpandIconWidget::onRowCountChanged); + + connect(m_trayDelegate, &TrayDelegate::removeRow, this, [ = ](const QModelIndex &index) { + m_trayView->model()->removeRow(index.row(),index.parent()); + }); + connect(m_trayView, &TrayGridView::requestRemove, m_trayModel, &TrayModel::removeRow); + connect(m_regionInter, &DRegionMonitor::buttonPress, this, &ExpandIconWidget::onGlobMousePress); + + QMetaObject::invokeMethod(this, &ExpandIconWidget::onRowCountChanged, Qt::QueuedConnection); +} + +void ExpandIconWidget::onRowCountChanged() +{ + int count = m_trayModel->rowCount(); + m_trayView->setFixedSize(m_trayView->suitableSize()); + m_gridParentView->setFixedSize(m_trayView->size() + QSize(ITEM_SPACING * 2, ITEM_SPACING * 2)); + if (count > 0) + resetPosition(); + else if (m_gridParentView->isVisible()) + m_gridParentView->hide(); + + Q_EMIT trayVisbleChanged(count > 0); } void ExpandIconWidget::onGlobMousePress(const QPoint &mousePos, const int flag) { - if (!isVisible() || !((flag == DRegionMonitor::WatchedFlags::Button_Left) || (flag == DRegionMonitor::WatchedFlags::Button_Right))) + // 如果当前是隐藏,那么在点击任何地方都隐藏 + if (!isVisible()) { + m_gridParentView->hide(); + return; + } + + if ((flag != DRegionMonitor::WatchedFlags::Button_Left) && (flag != DRegionMonitor::WatchedFlags::Button_Right)) return; - TrayGridView *trayView = popupTrayView(); QPoint ptPos = parentWidget()->mapToGlobal(this->pos()); const QRect rect = QRect(ptPos, size()); if (rect.contains(mousePos)) return; - const QRect rctView(trayView->pos(), trayView->size()); + const QRect rctView(m_gridParentView->pos(), m_gridParentView->size()); if (rctView.contains(mousePos)) return; - trayView->hide(); + m_gridParentView->hide(); +} + +/** + * @brief 圆角窗体的绘制 + * @param parent + */ +RoundWidget::RoundWidget(QWidget *parent) + : QWidget (parent) + , m_dockInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) +{ + setAttribute(Qt::WA_TranslucentBackground); +} + +void RoundWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + QPainterPath path; + path.addRoundedRect(rect(), 18, 18); + painter.setCompositionMode(QPainter::CompositionMode_Xor); + painter.setClipPath(path); + + painter.fillPath(path, maskColor()); +} + +QColor RoundWidget::maskColor() const +{ + QColor color = DGuiApplicationHelper::standardPalette(DGuiApplicationHelper::instance()->themeType()).window().color(); + int maskAlpha(static_cast(255 * m_dockInter->opacity())); + color.setAlpha(maskAlpha); + return color; } diff --git a/frame/window/tray/widgets/expandiconwidget.h b/frame/window/tray/widgets/expandiconwidget.h index d9316d258..4208ffa20 100644 --- a/frame/window/tray/widgets/expandiconwidget.h +++ b/frame/window/tray/widgets/expandiconwidget.h @@ -1,11 +1,36 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef EXPANDICONWIDGET_H #define EXPANDICONWIDGET_H #include "constants.h" #include "basetraywidget.h" +#include + class TrayGridView; class TrayModel; +class TrayDelegate; + +using DBusDock = com::deepin::dde::daemon::Dock; namespace Dtk { namespace Gui { class DRegionMonitor; } } @@ -13,9 +38,6 @@ class ExpandIconWidget : public BaseTrayWidget { Q_OBJECT -Q_SIGNALS: - void trayVisbleChanged(bool); - public: explicit ExpandIconWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); ~ExpandIconWidget() override; @@ -26,10 +48,14 @@ public: QString itemKeyForConfig() override { return "Expand"; } void updateIcon() override {} QPixmap icon() override; - TrayGridView *popupTrayView(); + QWidget *popupTrayView(); + +Q_SIGNALS: + void trayVisbleChanged(bool); private Q_SLOTS: void onGlobMousePress(const QPoint &mousePos, const int flag); + void onRowCountChanged(); protected: void paintEvent(QPaintEvent *e) override; @@ -37,10 +63,35 @@ protected: void resetPosition(); +private: + void initUi(); + void initConnection(); + private: Dtk::Gui::DRegionMonitor *m_regionInter; Dock::Position m_position; + QWidget *m_gridParentView; TrayGridView *m_trayView; + TrayDelegate *m_trayDelegate; + TrayModel *m_trayModel; +}; + +// 绘制圆角窗体 +class RoundWidget : public QWidget +{ + Q_OBJECT + +public: + explicit RoundWidget(QWidget *parent); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QColor maskColor() const; + +private: + DBusDock *m_dockInter; }; #endif // EXPANDICONWIDGET_H diff --git a/frame/window/tray/widgets/indicatorplugin.cpp b/frame/window/tray/widgets/indicatorplugin.cpp index 2ee9793fc..7eea2536d 100644 --- a/frame/window/tray/widgets/indicatorplugin.cpp +++ b/frame/window/tray/widgets/indicatorplugin.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "indicatorplugin.h" #include @@ -148,17 +168,11 @@ void IndicatorPluginPrivate::initDBus(const QString &indicatorName) if (data.contains("text")) { featData("text", data, SLOT(textPropertyChanged(QDBusMessage)), [ = ](QVariant v) { -#ifdef QT_DEBUG // TODO - if (!v.toString().isEmpty()) { -#else if (v.toString().isEmpty()) { -#endif Q_EMIT q->removed(); return; } - else { - Q_EMIT q->delayLoaded(); - } + Q_EMIT q->delayLoaded(); indicatorTrayWidget->setText(v.toString()); updateContent(); }); @@ -170,9 +184,7 @@ void IndicatorPluginPrivate::initDBus(const QString &indicatorName) Q_EMIT q->removed(); return; } - else { - Q_EMIT q->delayLoaded(); - } + Q_EMIT q->delayLoaded(); indicatorTrayWidget->setPixmapData(v.toByteArray()); updateContent(); }); @@ -181,7 +193,7 @@ void IndicatorPluginPrivate::initDBus(const QString &indicatorName) const QJsonObject action = config.value("action").toObject(); if (!action.isEmpty() && indicatorTrayWidget) q->connect(indicatorTrayWidget, &IndicatorTrayItem::clicked, q, [ = ](uint8_t button_index, int x, int y) { - /*std::thread t([=]() -> void { + std::thread t([ = ] ()-> void { auto triggerConfig = action.value("trigger").toObject(); auto dbusService = triggerConfig.value("dbus_service").toString(); auto dbusPath = triggerConfig.value("dbus_path").toString(); @@ -192,14 +204,9 @@ void IndicatorPluginPrivate::initDBus(const QString &indicatorName) QDBusInterface interface(dbusService, dbusPath, dbusInterface, bus); QDBusReply reply = interface.call(methodName, button_index, x, y); - if (!reply.isValid()) { - qDebug() << interface.call(methodName); - } - else { - qDebug() << reply.error(); - } + qDebug() << (reply.isValid() ? reply.error() : interface.call(methodName)); }); - t.detach();*/ + t.detach(); }); }); } diff --git a/frame/window/tray/widgets/indicatorplugin.h b/frame/window/tray/widgets/indicatorplugin.h index 81c1a81b0..3c649f70b 100644 --- a/frame/window/tray/widgets/indicatorplugin.h +++ b/frame/window/tray/widgets/indicatorplugin.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #pragma once #include "indicatortrayitem.h" diff --git a/frame/window/tray/widgets/indicatortrayitem.cpp b/frame/window/tray/widgets/indicatortrayitem.cpp index 6da397fee..b37a9a81c 100644 --- a/frame/window/tray/widgets/indicatortrayitem.cpp +++ b/frame/window/tray/widgets/indicatortrayitem.cpp @@ -20,7 +20,6 @@ */ #include "indicatortrayitem.h" -//#include "util/utils.h" #include #include @@ -39,7 +38,6 @@ IndicatorTrayItem::IndicatorTrayItem(const QString &indicatorName, QWidget *parent, Qt::WindowFlags f) : BaseTrayWidget(parent, f) , m_indicatorName(indicatorName) -// , m_gsettings(Utils::ModuleSettingsPtr("keyboard", QByteArray(), this)) , m_enableClick(true) { setAttribute(Qt::WA_TranslucentBackground); @@ -66,15 +64,6 @@ IndicatorTrayItem::IndicatorTrayItem(const QString &indicatorName, QWidget *pare interface, this, QDBusConnection::ExportScriptableSlots); - - initDBus(m_indicatorName); -// if (m_gsettings) { -// // 显示键盘布局时更新label的状态 -// if (m_gsettings->keys().contains("itemEnable")) -// enableLabel(m_gsettings->get("itemEnable").toBool()); - -// connect(m_gsettings, &QGSettings::changed, this, &IndicatorTrayWidget::onGSettingsChanged); -// } } IndicatorTrayItem::~IndicatorTrayItem() @@ -121,8 +110,19 @@ QPixmap IndicatorTrayItem::icon() return QPixmap(); } +const QByteArray &IndicatorTrayItem::pixmapData() const +{ + return m_pixmapData; +} + +const QString IndicatorTrayItem::text() const +{ + return m_label->text(); +} + void IndicatorTrayItem::setPixmapData(const QByteArray &data) { + m_pixmapData = data; auto rawPixmap = QPixmap::fromImage(QImage::fromData(data)); rawPixmap.setDevicePixelRatio(devicePixelRatioF()); m_label->setPixmap(rawPixmap); @@ -132,127 +132,3 @@ void IndicatorTrayItem::setText(const QString &text) { m_label->setText(text); } - -void IndicatorTrayItem::onGSettingsChanged(const QString &key) -{ - Q_UNUSED(key); - -// if (m_gsettings && m_gsettings->keys().contains("itemEnable")) { -// const bool itemEnable = m_gsettings->get("itemEnable").toBool(); -// enableLabel(itemEnable); - // } -} - -template -void IndicatorTrayItem::featData(const QString &key, - const QJsonObject &data, - const char *propertyChangedSlot, - Func const &callback) -{ - auto dataConfig = data.value(key).toObject(); - auto dbusService = dataConfig.value("dbus_service").toString(); - auto dbusPath = dataConfig.value("dbus_path").toString(); - auto dbusInterface = dataConfig.value("dbus_interface").toString(); - auto isSystemBus = dataConfig.value("system_dbus").toBool(false); - auto bus = isSystemBus ? QDBusConnection::systemBus() : QDBusConnection::sessionBus(); - - QDBusInterface interface(dbusService, dbusPath, dbusInterface, bus, this); - - if (dataConfig.contains("dbus_method")) { - QString methodName = dataConfig.value("dbus_method").toString(); - auto ratio = qApp->devicePixelRatio(); - QDBusReply reply = interface.call(methodName.toStdString().c_str(), ratio); - callback(reply.value()); - } - - qInfo() << dataConfig; - if (dataConfig.contains("dbus_properties")) { - auto propertyName = dataConfig.value("dbus_properties").toString(); - auto propertyNameCStr = propertyName.toStdString(); - //propertyInterfaceNames.insert(key, dbusInterface); - //propertyNames.insert(key, QString::fromStdString(propertyNameCStr)); - QDBusConnection::sessionBus().connect(dbusService, - dbusPath, - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - "sa{sv}as", - this, - propertyChangedSlot); - - // FIXME(sbw): hack for qt dbus property changed signal. - // see: https://bugreports.qt.io/browse/QTBUG-48008 - QDBusConnection::sessionBus().connect(dbusService, - dbusPath, - dbusInterface, - QString("%1Changed").arg(propertyName), - "s", - this, - propertyChangedSlot); - - qInfo() << dbusService << dbusPath << dbusInterface; - qInfo() << propertyName << propertyNameCStr.c_str(); - callback(interface.property(propertyNameCStr.c_str())); - } -} - -void IndicatorTrayItem::initDBus(const QString &indicatorName) -{ - QString filepath = QString("/etc/dde-dock/indicator/%1.json").arg(indicatorName); - QFile confFile(filepath); - if (!confFile.open(QIODevice::ReadOnly)) { - qInfo() << "read indicator config Error"; - } - - QJsonDocument doc = QJsonDocument::fromJson(confFile.readAll()); - confFile.close(); - - QJsonObject config = doc.object(); - - auto delay = config.value("delay").toInt(0); - - QTimer::singleShot(delay, [ = ]() { - QJsonObject data = config.value("data").toObject(); - if (data.contains("text")) { - featData("text", data, SLOT(textPropertyChanged(QDBusMessage)), [ = ](QVariant v) { - if (v.toString().isEmpty()) { - Q_EMIT removed(); - return; - } - Q_EMIT delayLoaded(); - setText(v.toString()); - //updateContent(); - }); - } - - if (data.contains("icon")) { - featData("icon", data, SLOT(iconPropertyChanged(QDBusMessage)), [ = ](QVariant v) { - if (v.toByteArray().isEmpty()) { - Q_EMIT removed(); - return; - } - Q_EMIT delayLoaded(); - setPixmapData(v.toByteArray()); - //updateContent(); - }); - } - - const QJsonObject action = config.value("action").toObject(); - if (!action.isEmpty()) - connect(this, &IndicatorTrayItem::clicked, this, [ = ](uint8_t button_index, int x, int y) { - std::thread t([=]() -> void { - auto triggerConfig = action.value("trigger").toObject(); - auto dbusService = triggerConfig.value("dbus_service").toString(); - auto dbusPath = triggerConfig.value("dbus_path").toString(); - auto dbusInterface = triggerConfig.value("dbus_interface").toString(); - auto methodName = triggerConfig.value("dbus_method").toString(); - auto isSystemBus = triggerConfig.value("system_dbus").toBool(false); - auto bus = isSystemBus ? QDBusConnection::systemBus() : QDBusConnection::sessionBus(); - - QDBusInterface interface(dbusService, dbusPath, dbusInterface, bus); - interface.call(methodName, button_index, x, y); - }); - t.detach(); - }); - }); -} - diff --git a/frame/window/tray/widgets/indicatortrayitem.h b/frame/window/tray/widgets/indicatortrayitem.h index b687c011a..9bf8c1b06 100644 --- a/frame/window/tray/widgets/indicatortrayitem.h +++ b/frame/window/tray/widgets/indicatortrayitem.h @@ -32,10 +32,6 @@ class IndicatorTrayItem: public BaseTrayWidget { Q_OBJECT -Q_SIGNALS: - void removed(); - void delayLoaded(); - public: explicit IndicatorTrayItem(const QString &indicatorName, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); ~IndicatorTrayItem() override; @@ -47,27 +43,20 @@ public: static QString toIndicatorKey(const QString &indicatorName) { return QString("indicator:%1").arg(indicatorName); } static bool isIndicatorKey(const QString &itemKey) { return itemKey.startsWith("indicator:"); } QPixmap icon() override; + const QByteArray &pixmapData() const; + const QString text() const; public Q_SLOTS: Q_SCRIPTABLE void setPixmapData(const QByteArray &data); Q_SCRIPTABLE void setText(const QString &text); -private slots: - void onGSettingsChanged(const QString &key); - -private: - void initDBus(const QString &indicatorName); - template - void featData(const QString &key, const QJsonObject &data, const char *propertyChangedSlot, Func const &callback); - Q_SIGNALS: void clicked(uint8_t, int, int); private: QLabel *m_label; - QString m_indicatorName; -// const QGSettings *m_gsettings; bool m_enableClick; // 置灰时设置为false,不触发click信号 + QByteArray m_pixmapData; }; diff --git a/frame/window/traymanagerwindow.cpp b/frame/window/traymanagerwindow.cpp index a62579d8c..f963f7df5 100644 --- a/frame/window/traymanagerwindow.cpp +++ b/frame/window/traymanagerwindow.cpp @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #include "traymanagerwindow.h" #include "quickpluginwindow.h" #include "tray_gridview.h" @@ -33,7 +53,9 @@ TrayManagerWindow::TrayManagerWindow(QWidget *parent) , m_mainLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this)) , m_trayView(new TrayGridView(this)) , m_model(new TrayModel(m_trayView, false, true)) + , m_delegate(new TrayDelegate(m_trayView, m_trayView)) , m_postion(Dock::Position::Bottom) + , m_splitLine(new QLabel(m_appPluginDatetimeWidget)) { initUi(); initConnection(); @@ -52,42 +74,48 @@ void TrayManagerWindow::setPositon(Dock::Position position) return; m_postion = position; + + if (position == Dock::Position::Top || position == Dock::Position::Bottom) + m_trayView->setOrientation(QListView::Flow::LeftToRight, false); + else + m_trayView->setOrientation(QListView::Flow::TopToBottom, false); + QModelIndex index = m_model->index(0, 0); m_trayView->closePersistentEditor(index); TrayDelegate *delegate = static_cast(m_trayView->itemDelegate()); delegate->setPositon(position); m_trayView->openPersistentEditor(index); + m_trayView->setPosition(position); m_quickIconWidget->setPositon(position); m_dateTimeWidget->setPositon(position); m_systemPluginWidget->setPositon(position); - QTimer::singleShot(0, this, [ this ]{ + QMetaObject::invokeMethod(this, [ this ]{ if (showSingleRow()) resetSingleDirection(); else resetMultiDirection(); resetChildWidgetSize(); - }); + }, Qt::QueuedConnection); } int TrayManagerWindow::appDatetimeSize() { - int count = m_trayView->model()->rowCount(); if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) { - QMargins m = m_appDatetimeLayout->contentsMargins(); - int trayWidth = count * ITEM_SIZE + m_trayView->spacing() * (count - 1) + 5; - int topWidth = trayWidth + m_quickIconWidget->suitableSize().width() + m.left() + m.right() + m_appPluginLayout->spacing(); - int spacing = m.left() + m.right() + m_appPluginLayout->spacing(); - if (m_appDatetimeLayout->direction() == QBoxLayout::Direction::LeftToRight) - return topWidth + m_appDatetimeLayout->spacing() + m_dateTimeWidget->suitableSize().width() + m_appDatetimeLayout->spacing() + 10; - + // 如果是一行 + if (m_appDatetimeLayout->direction() == QBoxLayout::Direction::LeftToRight) { + return m_trayView->suitableSize().width() + m_quickIconWidget->suitableSize().width() + + m_dateTimeWidget->suitableSize().width(); + } + //如果是两行 + int topWidth = m_trayView->suitableSize().width() + m_quickIconWidget->width(); int bottomWidth = m_dateTimeWidget->suitableSize().width(); - return (topWidth > bottomWidth ? topWidth : bottomWidth) + m_appDatetimeLayout->spacing() + spacing + 10; + return qMax(topWidth, bottomWidth); } - int trayHeight = count * ITEM_SIZE + m_trayView->spacing() * (count - 1) + 5; + int trayHeight = m_trayView->suitableSize().height(); int datetimeHeight = m_dateTimeWidget->suitableSize().height(); QMargins m = m_appDatetimeLayout->contentsMargins(); int traypluginHeight = trayHeight + m_quickIconWidget->suitableSize().height() + m.top() + m.bottom() + m_appPluginLayout->spacing(); @@ -124,9 +152,17 @@ void TrayManagerWindow::resizeEvent(QResizeEvent *event) void TrayManagerWindow::initUi() { - TrayDelegate *delegate = new TrayDelegate(m_trayView); m_trayView->setModel(m_model); - m_trayView->setItemDelegate(delegate); + m_trayView->setItemDelegate(m_delegate); + m_trayView->setDragDistance(2); + + m_splitLine->setFixedHeight(1); + QPalette pal; + QColor lineColor(Qt::black); + lineColor.setAlpha(static_cast(255 * 0.2)); + pal.setColor(QPalette::Background, lineColor); + m_splitLine->setAutoFillBackground(true); + m_splitLine->setPalette(pal); WinInfo info; info.type = TrayIconType::EXPANDICON; @@ -139,6 +175,7 @@ void TrayManagerWindow::initUi() m_appPluginDatetimeWidget->setMaskAlpha(uint8_t(0.1 * 255)); m_appPluginDatetimeWidget->installEventFilter(this); + m_appPluginLayout->setContentsMargins(0, 0, 0, 0); m_appPluginLayout->setSpacing(0); m_appPluginWidget->setLayout(m_appPluginLayout); m_appPluginLayout->addWidget(m_trayView); @@ -146,8 +183,9 @@ void TrayManagerWindow::initUi() m_appPluginDatetimeWidget->setLayout(m_appDatetimeLayout); m_appDatetimeLayout->setContentsMargins(0, 0, 0, 0); - m_appDatetimeLayout->setSpacing(3); + m_appDatetimeLayout->setSpacing(0); m_appDatetimeLayout->addWidget(m_appPluginWidget); + m_appDatetimeLayout->addWidget(m_splitLine); m_appDatetimeLayout->addWidget(m_dateTimeWidget); m_systemPluginWidget->setBlurRectXRadius(10); @@ -157,7 +195,7 @@ void TrayManagerWindow::initUi() setLayout(m_mainLayout); m_mainLayout->setContentsMargins(8, 8, 8, 8); - m_mainLayout->setSpacing(10); + m_mainLayout->setSpacing(7); m_mainLayout->addWidget(m_appPluginDatetimeWidget); m_mainLayout->addWidget(m_systemPluginWidget); } @@ -165,8 +203,20 @@ void TrayManagerWindow::initUi() void TrayManagerWindow::initConnection() { connect(m_trayView, &TrayGridView::requestRemove, m_model, &TrayModel::removeRow); - connect(m_trayView, &TrayGridView::rowCountChanged, this, &TrayManagerWindow::sizeChanged); + connect(m_trayView, &TrayGridView::rowCountChanged, this, [ this ] { + if (m_quickIconWidget->x() == 0) { + // 在加载界面的时候,会出现快捷设置区域的图标和左侧的托盘图标挤在一起(具体原因未知),此时需要延时50毫秒重新刷新界面来保证界面布局正常(临时解决方案) + QTimer::singleShot(50, this, [ this ] { + resetChildWidgetSize(); + Q_EMIT sizeChanged(); + }); + } else { + resetChildWidgetSize(); + Q_EMIT sizeChanged(); + } + }); connect(m_quickIconWidget, &QuickPluginWindow::itemCountChanged, this, [ this ] { + // 当插件数量发生变化的时候,需要调整尺寸 m_quickIconWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) m_quickIconWidget->setFixedWidth(m_quickIconWidget->suitableSize().width()); @@ -177,6 +227,7 @@ void TrayManagerWindow::initConnection() }); connect(m_systemPluginWidget, &SystemPluginWindow::pluginSizeChanged, this, [ this ] { + // 当系统插件发生变化的时候,同样需要调整尺寸 m_systemPluginWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) m_systemPluginWidget->setFixedWidth(m_systemPluginWidget->suitableSize().width()); @@ -186,18 +237,17 @@ void TrayManagerWindow::initConnection() Q_EMIT sizeChanged(); }); - TrayDelegate *trayDelegate = static_cast(m_trayView->itemDelegate()); - connect(trayDelegate, &TrayDelegate::visibleChanged, this, [ this ](const QModelIndex &index, bool visible) { + connect(m_delegate, &TrayDelegate::visibleChanged, this, [ this ](const QModelIndex &index, bool visible) { m_trayView->setRowHidden(index.row(), !visible); resetChildWidgetSize(); Q_EMIT sizeChanged(); }); - connect(m_trayView, &TrayGridView::dragLeaved, trayDelegate, [ trayDelegate ]{ - Q_EMIT trayDelegate->requestDrag(true); + connect(m_trayView, &TrayGridView::dragLeaved, m_delegate, [ this ]{ + Q_EMIT m_delegate->requestDrag(true); }); - connect(m_trayView, &TrayGridView::dragEntered, trayDelegate, [ trayDelegate ]{ - Q_EMIT trayDelegate->requestDrag(false); + connect(m_trayView, &TrayGridView::dragEntered, m_delegate, [ this ]{ + Q_EMIT m_delegate->requestDrag(false); }); connect(m_model, &TrayModel::requestUpdateWidget, this, [ this ](const QList &idxs) { for (int i = 0; i < idxs.size(); i++) { @@ -235,7 +285,7 @@ void TrayManagerWindow::resetChildWidgetSize() switch (m_postion) { case Dock::Position::Top: case Dock::Position::Bottom: { - int trayWidth = count * ITEM_SIZE + m_trayView->spacing() * (count - 1) + 5; + int trayWidth = m_trayView->suitableSize().width(); QMargins m = m_appPluginLayout->contentsMargins(); m_appPluginDatetimeWidget->setFixedHeight(QWIDGETSIZE_MAX);// 取消固定高度显示 if (m_appDatetimeLayout->direction() == QBoxLayout::Direction::LeftToRight) { @@ -243,37 +293,33 @@ void TrayManagerWindow::resetChildWidgetSize() int trayHeight = m_appPluginDatetimeWidget->height() - m.top() - m.bottom(); m_trayView->setFixedSize(trayWidth, trayHeight); m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize().width(), trayHeight); + m_appPluginWidget->setFixedSize(trayWidth + m_quickIconWidget->suitableSize().width(), trayHeight); m_dateTimeWidget->setFixedSize(m_dateTimeWidget->suitableSize().width(), trayHeight); } else { // 多行显示 int trayHeight = m_appPluginDatetimeWidget->height() / 2 - m.top() - m.bottom(); m_trayView->setFixedSize(trayWidth, trayHeight); m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize().width(), trayHeight); - m_dateTimeWidget->setFixedSize(m_dateTimeWidget->suitableSize().width(), m_appPluginDatetimeWidget->height() / 2); + m_appPluginWidget->setFixedSize(trayWidth + m_quickIconWidget->suitableSize().width(), trayHeight); + // 因为是两行,所以对于时间控件的尺寸,只能设置最小值 + m_dateTimeWidget->setMinimumSize(m_dateTimeWidget->suitableSize().width(), m_appPluginDatetimeWidget->height() / 2); } m_appPluginDatetimeWidget->setFixedWidth(appDatetimeSize()); break; } case Dock::Position::Left: case Dock::Position::Right: { - int trayHeight = count * ITEM_SIZE + m_trayView->spacing() * (count - 1) + 5; + int trayHeight = m_trayView->suitableSize().height(); int quickAreaHeight = m_quickIconWidget->suitableSize().height(); QMargins m = m_appPluginLayout->contentsMargins(); m_appPluginDatetimeWidget->setFixedWidth(QWIDGETSIZE_MAX);// 取消固定宽度显示 - if (m_appDatetimeLayout->direction() == QBoxLayout::Direction::TopToBottom) { - // 宽度较小的情况下,显示一列 - int datetimeHeight = m_dateTimeWidget->suitableSize().height(); - int sizeWidth = m_appPluginDatetimeWidget->width() - m.left() - m.right(); - m_trayView->setFixedSize(sizeWidth, trayHeight); - m_quickIconWidget->setFixedSize(sizeWidth, quickAreaHeight); - m_dateTimeWidget->setFixedSize(sizeWidth, datetimeHeight); - } else { - // 显示两列 - int trayWidth = m_appPluginDatetimeWidget->width() / 2 - m.left() - m.right(); - m_trayView->setFixedSize(trayWidth, trayHeight); - m_quickIconWidget->setFixedSize(trayWidth, quickAreaHeight); - m_dateTimeWidget->setFixedSize(m_appPluginDatetimeWidget->width() / 2, m_dateTimeWidget->suitableSize().height()); - } + // 左右方向始终只有一列 + int datetimeHeight = m_dateTimeWidget->suitableSize().height(); + int sizeWidth = m_appPluginDatetimeWidget->width() - m.left() - m.right(); + m_trayView->setFixedSize(sizeWidth, trayHeight); + m_quickIconWidget->setFixedSize(sizeWidth, quickAreaHeight); + m_dateTimeWidget->setFixedSize(sizeWidth, datetimeHeight); + m_appPluginWidget->setFixedSize(sizeWidth, trayHeight + quickAreaHeight); m_appPluginDatetimeWidget->setFixedHeight(appDatetimeSize()); break; } @@ -283,33 +329,19 @@ void TrayManagerWindow::resetChildWidgetSize() void TrayManagerWindow::resetSingleDirection() { switch (m_postion) { - case Dock::Position::Top: { + case Dock::Position::Top: + case Dock::Position::Bottom: { m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); // 应用和时间在一行显示 m_appDatetimeLayout->setDirection(QBoxLayout::Direction::LeftToRight); m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_appPluginLayout->setContentsMargins(2, 2, 2, 4); break; } - case Dock::Position::Bottom: { - m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_appPluginLayout->setContentsMargins(2, 4, 2, 2); - break; - } - case Dock::Position::Left: { + case Dock::Position::Left: + case Dock::Position::Right:{ m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appPluginLayout->setContentsMargins(2, 2, 4, 2); - break; - } - case Dock::Position::Right: { - m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appPluginLayout->setContentsMargins(4, 2, 2, 2); break; } } @@ -322,28 +354,19 @@ void TrayManagerWindow::resetMultiDirection() m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); m_appDatetimeLayout->setDirection(QBoxLayout::Direction::BottomToTop); m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_appPluginLayout->setContentsMargins(2, 2, 2, 4); break; } case Dock::Position::Bottom: { m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_appPluginLayout->setContentsMargins(2, 4, 2, 2); - break; - } - case Dock::Position::Left: { - m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appPluginLayout->setContentsMargins(2, 2, 4, 2); break; } + case Dock::Position::Left: case Dock::Position::Right: { m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appPluginLayout->setContentsMargins(4, 2, 2, 2); break; } } @@ -363,16 +386,16 @@ void TrayManagerWindow::dragMoveEvent(QDragMoveEvent *e) void TrayManagerWindow::dropEvent(QDropEvent *e) { - CustomMimeData *mimeData = const_cast(qobject_cast(e->mimeData())); + const QuickPluginMimeData *mimeData = qobject_cast(e->mimeData()); if (!mimeData) return; if (e->source() == this) return; - QuickSettingItem *pluginItem = static_cast(mimeData->data()); + QuickSettingItem *pluginItem = static_cast(mimeData->quickSettingItem()); if (pluginItem) - m_quickIconWidget->addPlugin(pluginItem); + m_quickIconWidget->dragPlugin(pluginItem); } void TrayManagerWindow::dragLeaveEvent(QDragLeaveEvent *event) diff --git a/frame/window/traymanagerwindow.h b/frame/window/traymanagerwindow.h index 80da2deb6..8892ff0dc 100644 --- a/frame/window/traymanagerwindow.h +++ b/frame/window/traymanagerwindow.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ #ifndef TRAYMANAGERWINDOW_H #define TRAYMANAGERWINDOW_H @@ -18,6 +38,7 @@ class QuickPluginWindow; class QBoxLayout; class TrayGridView; class TrayModel; +class TrayDelegate; class SystemPluginWindow; class QLabel; class QDropEvent; @@ -66,7 +87,9 @@ private: QBoxLayout *m_mainLayout; TrayGridView *m_trayView; TrayModel *m_model; + TrayDelegate *m_delegate; Dock::Position m_postion; + QLabel *m_splitLine; }; #endif // PLUGINWINDOW_H