feat: 参照dde-weather重构插件,修复显示与弹窗定位
- QML 根元素使用 AppletItem,参照 dde-weather 插件实现 - 使用 Panel.rootObject.dockItemMaxSize 适配任务栏图标尺寸 - dockOrder 设为 21,定位在系统托盘左侧 - 使用 PanelPopup + PanelToolTip + TapHandler 实现点击弹窗和悬停提示 - 弹窗打开前设置 DockPanelPositioner.bounding 修正弹窗定位 - C++ 后端新增 dbusAvailable 属性,D-Bus 不可用时优雅降级 - 使用 isServiceRegistered 正确检测 D-Bus 服务可用性 - install.sh 改用 SCRIPT_DIR 自动定位项目根目录
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include <pluginfactory.h>
|
#include <pluginfactory.h>
|
||||||
|
|
||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusConnectionInterface>
|
||||||
#include <QDBusPendingReply>
|
#include <QDBusPendingReply>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
@@ -26,6 +27,7 @@ GraphicsDriverApplet::GraphicsDriverApplet(QObject *parent)
|
|||||||
, m_progressTimer(new QTimer(this))
|
, m_progressTimer(new QTimer(this))
|
||||||
, m_installProgress(0)
|
, m_installProgress(0)
|
||||||
, m_isInstalling(false)
|
, m_isInstalling(false)
|
||||||
|
, m_dbusAvailable(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,15 +38,14 @@ GraphicsDriverApplet::~GraphicsDriverApplet()
|
|||||||
bool GraphicsDriverApplet::load()
|
bool GraphicsDriverApplet::load()
|
||||||
{
|
{
|
||||||
initDBusConnection();
|
initDBusConnection();
|
||||||
connect(m_progressTimer, &QTimer::timeout, [this]() {
|
|
||||||
// Poll progress
|
|
||||||
});
|
|
||||||
return DApplet::load();
|
return DApplet::load();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsDriverApplet::init()
|
bool GraphicsDriverApplet::init()
|
||||||
{
|
{
|
||||||
refreshDeviceInfo();
|
if (m_dbusAvailable) {
|
||||||
|
refreshDeviceInfo();
|
||||||
|
}
|
||||||
return DApplet::init();
|
return DApplet::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +69,11 @@ bool GraphicsDriverApplet::isInstalling() const
|
|||||||
return m_isInstalling;
|
return m_isInstalling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GraphicsDriverApplet::dbusAvailable() const
|
||||||
|
{
|
||||||
|
return m_dbusAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsDriverApplet::refreshDeviceInfo()
|
void GraphicsDriverApplet::refreshDeviceInfo()
|
||||||
{
|
{
|
||||||
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
||||||
@@ -215,6 +221,13 @@ void GraphicsDriverApplet::initDBusConnection()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查服务是否已注册
|
||||||
|
bool registered = bus.interface()->isServiceRegistered(DBUS_SERVICE);
|
||||||
|
if (!registered) {
|
||||||
|
qWarning() << "GraphicsDriver D-Bus service is not registered";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_dbusInterface = new QDBusInterface(
|
m_dbusInterface = new QDBusInterface(
|
||||||
DBUS_SERVICE,
|
DBUS_SERVICE,
|
||||||
DBUS_PATH,
|
DBUS_PATH,
|
||||||
@@ -228,8 +241,13 @@ void GraphicsDriverApplet::initDBusConnection()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dbusAvailable = true;
|
||||||
|
emit dbusAvailableChanged();
|
||||||
|
|
||||||
connect(m_dbusInterface, SIGNAL(ReportProgress(QString)),
|
connect(m_dbusInterface, SIGNAL(ReportProgress(QString)),
|
||||||
this, SLOT(onReportProgress(QString)));
|
this, SLOT(onReportProgress(QString)));
|
||||||
|
|
||||||
|
qDebug() << "GraphicsDriver D-Bus connected successfully";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsDriverApplet::setInstalling(bool installing)
|
void GraphicsDriverApplet::setInstalling(bool installing)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class GraphicsDriverApplet : public DApplet
|
|||||||
Q_PROPERTY(QString deviceInfo READ deviceInfo NOTIFY deviceInfoChanged)
|
Q_PROPERTY(QString deviceInfo READ deviceInfo NOTIFY deviceInfoChanged)
|
||||||
Q_PROPERTY(int installProgress READ installProgress NOTIFY installProgressChanged)
|
Q_PROPERTY(int installProgress READ installProgress NOTIFY installProgressChanged)
|
||||||
Q_PROPERTY(bool isInstalling READ isInstalling NOTIFY isInstallingChanged)
|
Q_PROPERTY(bool isInstalling READ isInstalling NOTIFY isInstallingChanged)
|
||||||
|
Q_PROPERTY(bool dbusAvailable READ dbusAvailable NOTIFY dbusAvailableChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GraphicsDriverApplet(QObject *parent = nullptr);
|
explicit GraphicsDriverApplet(QObject *parent = nullptr);
|
||||||
@@ -34,6 +35,7 @@ public:
|
|||||||
QString deviceInfo() const;
|
QString deviceInfo() const;
|
||||||
int installProgress() const;
|
int installProgress() const;
|
||||||
bool isInstalling() const;
|
bool isInstalling() const;
|
||||||
|
bool dbusAvailable() const;
|
||||||
|
|
||||||
Q_INVOKABLE void refreshDeviceInfo();
|
Q_INVOKABLE void refreshDeviceInfo();
|
||||||
Q_INVOKABLE void prepareInstall(const QString &driverName);
|
Q_INVOKABLE void prepareInstall(const QString &driverName);
|
||||||
@@ -49,6 +51,7 @@ signals:
|
|||||||
void installSuccess();
|
void installSuccess();
|
||||||
void installFailed(const QString &error);
|
void installFailed(const QString &error);
|
||||||
void requestReboot();
|
void requestReboot();
|
||||||
|
void dbusAvailableChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onGetDeviceReply(QDBusPendingCallWatcher *call);
|
void onGetDeviceReply(QDBusPendingCallWatcher *call);
|
||||||
@@ -61,6 +64,7 @@ private:
|
|||||||
|
|
||||||
QDBusInterface *m_dbusInterface;
|
QDBusInterface *m_dbusInterface;
|
||||||
QTimer *m_progressTimer;
|
QTimer *m_progressTimer;
|
||||||
|
bool m_dbusAvailable;
|
||||||
|
|
||||||
QString m_currentDriver;
|
QString m_currentDriver;
|
||||||
QString m_deviceInfo;
|
QString m_deviceInfo;
|
||||||
|
|||||||
+4
-1
@@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# 切换到项目根目录
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
echo "=== 构建插件 ==="
|
echo "=== 构建插件 ==="
|
||||||
cd ~/Documents/projects/JSwitchDisplayApplet
|
|
||||||
rm -rf build
|
rm -rf build
|
||||||
cmake -Bbuild
|
cmake -Bbuild
|
||||||
cmake --build build
|
cmake --build build
|
||||||
|
|||||||
+149
-88
@@ -11,39 +11,70 @@ import org.deepin.ds.dock 1.0
|
|||||||
AppletItem {
|
AppletItem {
|
||||||
id: root
|
id: root
|
||||||
objectName: "graphics driver applet"
|
objectName: "graphics driver applet"
|
||||||
|
property int dockOrder: 21
|
||||||
|
property int dockSize: Panel.rootObject.dockItemMaxSize || 48
|
||||||
|
|
||||||
property bool useColumnLayout: Panel.position % 2
|
implicitWidth: dockSize
|
||||||
property int dockOrder: 20
|
|
||||||
property int dockSize: Panel.rootObject.dockSize || 48
|
|
||||||
|
|
||||||
implicitWidth: useColumnLayout ? dockSize : 80
|
|
||||||
implicitHeight: dockSize
|
implicitHeight: dockSize
|
||||||
|
|
||||||
property var applet: Applet
|
// 访问 C++ 后端
|
||||||
|
readonly property var applet: Applet
|
||||||
|
readonly property bool dbusAvailable: applet && applet.dbusAvailable
|
||||||
|
readonly property string currentDriver: applet ? (applet.currentDriver || qsTr("Unknown")) : qsTr("Unknown")
|
||||||
|
readonly property string deviceInfo: applet ? (applet.deviceInfo || qsTr("Unknown")) : qsTr("Unknown")
|
||||||
|
readonly property bool isInstalling: applet ? applet.isInstalling : false
|
||||||
|
readonly property int installProgress: applet ? applet.installProgress : 0
|
||||||
|
|
||||||
|
// 图标区域
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "#3498db"
|
||||||
|
radius: 8
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "GPU"
|
||||||
|
font.pixelSize: root.dockSize * 0.3
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 悬停提示
|
||||||
PanelToolTip {
|
PanelToolTip {
|
||||||
id: toolTip
|
id: toolTip
|
||||||
text: qsTr("Graphics Driver Manager")
|
text: qsTr("Graphics Driver: ") + root.currentDriver
|
||||||
toolTipX: DockPanelPositioner.x
|
toolTipX: DockPanelPositioner.x
|
||||||
toolTipY: DockPanelPositioner.y
|
toolTipY: DockPanelPositioner.y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: toolTipShowTimer
|
||||||
|
interval: 50
|
||||||
|
onTriggered: {
|
||||||
|
const point = root.mapToItem(null, root.width / 2, root.height / 2)
|
||||||
|
toolTip.DockPanelPositioner.bounding = Qt.rect(point.x, point.y, toolTip.width, toolTip.height)
|
||||||
|
toolTip.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered && !driverPopup.popupVisible) {
|
if (hovered && !driverPopup.popupVisible) {
|
||||||
const point = root.mapToItem(null, root.width / 2, root.height / 2)
|
toolTipShowTimer.start()
|
||||||
toolTip.DockPanelPositioner.bounding = Qt.rect(point.x, point.y, toolTip.width, toolTip.height)
|
|
||||||
toolTip.open()
|
|
||||||
} else {
|
} else {
|
||||||
|
if (toolTipShowTimer.running) {
|
||||||
|
toolTipShowTimer.stop()
|
||||||
|
}
|
||||||
toolTip.close()
|
toolTip.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 弹出窗口
|
||||||
PanelPopup {
|
PanelPopup {
|
||||||
id: driverPopup
|
id: driverPopup
|
||||||
width: 300
|
width: 320
|
||||||
height: 360
|
height: 400
|
||||||
popupX: DockPanelPositioner.x
|
popupX: DockPanelPositioner.x
|
||||||
popupY: DockPanelPositioner.y
|
popupY: DockPanelPositioner.y
|
||||||
|
|
||||||
@@ -53,96 +84,121 @@ AppletItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
Control {
|
||||||
|
id: popupContainer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 16
|
padding: 16
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
Text {
|
contentItem: ColumnLayout {
|
||||||
text: qsTr("Graphics Driver Manager")
|
spacing: 12
|
||||||
font.pixelSize: 16
|
|
||||||
font.bold: true
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 1
|
|
||||||
color: "#ccc"
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupBox {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
title: qsTr("Device Information")
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Current Driver: " + (root.applet ? root.applet.currentDriver || "Unknown" : "Unknown")
|
|
||||||
font.pixelSize: 12
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Device Info: " + (root.applet ? root.applet.deviceInfo || "Unknown" : "Unknown")
|
|
||||||
font.pixelSize: 12
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
text: qsTr("Refresh")
|
|
||||||
Layout.fillWidth: true
|
|
||||||
onClicked: {
|
|
||||||
if (root.applet) {
|
|
||||||
root.applet.refreshDeviceInfo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
text: qsTr("Test Install")
|
|
||||||
Layout.fillWidth: true
|
|
||||||
enabled: root.applet && !root.applet.isInstalling
|
|
||||||
onClicked: {
|
|
||||||
if (root.applet) {
|
|
||||||
root.applet.testInstall()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
visible: root.applet && root.applet.isInstalling
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Installing... ") + (root.applet ? root.applet.installProgress + "%" : "0%")
|
text: qsTr("Graphics Driver Manager")
|
||||||
font.pixelSize: 12
|
font.pixelSize: 16
|
||||||
|
font.bold: true
|
||||||
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressBar {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
value: root.applet ? root.applet.installProgress / 100 : 0
|
Layout.preferredHeight: 1
|
||||||
|
color: "#cccccc"
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
// D-Bus 不可用提示
|
||||||
text: qsTr("Cancel")
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
onClicked: {
|
height: 40
|
||||||
if (root.applet) {
|
visible: !root.dbusAvailable
|
||||||
root.applet.cancelInstall()
|
color: "#fff3cd"
|
||||||
|
radius: 6
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: qsTr("Driver service is not available")
|
||||||
|
color: "#856404"
|
||||||
|
font.pixelSize: 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设备信息
|
||||||
|
GroupBox {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
title: qsTr("Device Information")
|
||||||
|
visible: root.dbusAvailable
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("Current Driver: ") + root.currentDriver
|
||||||
|
font.pixelSize: 12
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("Device: ") + root.deviceInfo
|
||||||
|
font.pixelSize: 12
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
// 操作按钮
|
||||||
Layout.fillHeight: true
|
Button {
|
||||||
|
text: qsTr("Refresh")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
enabled: root.dbusAvailable && !root.isInstalling
|
||||||
|
onClicked: {
|
||||||
|
if (root.applet) {
|
||||||
|
root.applet.refreshDeviceInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Test Install")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
enabled: root.dbusAvailable && !root.isInstalling
|
||||||
|
onClicked: {
|
||||||
|
if (root.applet) {
|
||||||
|
root.applet.testInstall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 安装进度
|
||||||
|
ColumnLayout {
|
||||||
|
visible: root.isInstalling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("Installing... ") + root.installProgress + "%"
|
||||||
|
font.pixelSize: 12
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
value: root.installProgress / 100
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
onClicked: {
|
||||||
|
if (root.applet) {
|
||||||
|
root.applet.cancelInstall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +210,7 @@ AppletItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 点击处理
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
gesturePolicy: TapHandler.ReleaseWithinBounds
|
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||||
@@ -163,12 +220,16 @@ AppletItem {
|
|||||||
driverPopup.close()
|
driverPopup.close()
|
||||||
} else {
|
} else {
|
||||||
Panel.requestClosePopup()
|
Panel.requestClosePopup()
|
||||||
|
// 在打开前设置定位,确保弹窗出现在插件附近
|
||||||
|
const point = root.mapToItem(null, root.width / 2, root.height / 2)
|
||||||
|
driverPopup.DockPanelPositioner.bounding = Qt.rect(point.x, point.y, driverPopup.width, driverPopup.height)
|
||||||
driverPopup.open()
|
driverPopup.open()
|
||||||
}
|
}
|
||||||
toolTip.close()
|
toolTip.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 后端信号处理
|
||||||
Connections {
|
Connections {
|
||||||
target: root.applet
|
target: root.applet
|
||||||
function onInstallSuccess() {
|
function onInstallSuccess() {
|
||||||
|
|||||||
Reference in New Issue
Block a user