feat: 初始化项目骨架
- 创建插件元数据 package/metadata.json - 实现主插件类 GraphicsDriverApplet (D-Bus通信) - 实现GPU指示器类 GpuIndicator (设备信息解析) - 创建QML界面 driverview.qml (驱动管理UI) - 添加CMake构建配置 - 编写开发指南文档 docs/DEVELOPMENT.md
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(dde-graphics-driver-applet VERSION 1.0.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Widgets DBus Quick)
|
||||||
|
find_package(Dtk6 REQUIRED COMPONENTS Widget Core)
|
||||||
|
find_package(dde-shell REQUIRED)
|
||||||
|
|
||||||
|
add_library(dde-graphics-driver SHARED
|
||||||
|
graphicsdriverapplet.h
|
||||||
|
graphicsdriverapplet.cpp
|
||||||
|
gpuindicator.h
|
||||||
|
gpuindicator.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(dde-graphics-driver PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(dde-graphics-driver PRIVATE
|
||||||
|
dde-shell-frame
|
||||||
|
Qt6::Widgets
|
||||||
|
Qt6::DBus
|
||||||
|
Qt6::Quick
|
||||||
|
Dtk6::Widget
|
||||||
|
Dtk6::Core
|
||||||
|
)
|
||||||
|
|
||||||
|
ds_install_package(PACKAGE org.deepin.ds.graphics-driver TARGET dde-graphics-driver)
|
||||||
@@ -1,2 +1,107 @@
|
|||||||
# 显卡切换任务栏插件
|
# 显卡切换任务栏插件
|
||||||
|
|
||||||
|
Deepin显卡驱动管理任务栏插件,集成到DDE Shell任务栏中,提供显卡设备检测、驱动安装和切换功能。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- 自动检测系统显卡设备
|
||||||
|
- 显示当前安装的驱动版本
|
||||||
|
- 列出可用的驱动版本
|
||||||
|
- 一键切换显卡驱动
|
||||||
|
- 实时显示安装进度
|
||||||
|
- 安装完成后提示重启
|
||||||
|
|
||||||
|
## 依赖项
|
||||||
|
|
||||||
|
- dde-shell >= 2.0
|
||||||
|
- Qt6 >= 6.0
|
||||||
|
- Dtk6 >= 6.0
|
||||||
|
- deepin-graphics-driver-manager(运行时依赖)
|
||||||
|
|
||||||
|
## 构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装构建依赖
|
||||||
|
sudo apt build-dep .
|
||||||
|
|
||||||
|
# 构建项目
|
||||||
|
cmake -Bbuild
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
# 安装插件
|
||||||
|
cmake --install build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
├── package/
|
||||||
|
│ ├── metadata.json # 插件元数据
|
||||||
|
│ └── driverview.qml # QML界面
|
||||||
|
├── graphicsdriverapplet.h # 主插件类头文件
|
||||||
|
├── graphicsdriverapplet.cpp # 主插件类实现
|
||||||
|
├── gpuindicator.h # GPU指示器类头文件
|
||||||
|
├── gpuindicator.cpp # GPU指示器类实现
|
||||||
|
├── CMakeLists.txt # 构建配置
|
||||||
|
└── README.md # 项目说明
|
||||||
|
```
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 架构设计
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ DDE Shell Taskbar │
|
||||||
|
├─────────────────────────────────────────────────────────┤
|
||||||
|
│ dde-graphics-driver-applet │
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ GPU检测模块 │ │ 驱动管理 │ │ UI界面 │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
├─────────────────────────────────────────────────────────┤
|
||||||
|
│ D-Bus Interface │
|
||||||
|
│ com.deepin.daemon.GraphicsDriver │
|
||||||
|
├─────────────────────────────────────────────────────────┤
|
||||||
|
│ deepin-graphics-driver-manager │
|
||||||
|
│ (现有的驱动管理服务,无需修改) │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### D-Bus接口
|
||||||
|
|
||||||
|
插件通过D-Bus与deepin-graphics-driver-manager服务通信:
|
||||||
|
|
||||||
|
- `GetDevice()` - 获取显卡设备信息
|
||||||
|
- `GetCurrDriverName()` - 获取当前驱动名称
|
||||||
|
- `GetNewDriverName()` - 获取推荐驱动名称
|
||||||
|
- `PrepareInstall(name, language)` - 准备安装驱动
|
||||||
|
- `TestInstall()` - 测试安装
|
||||||
|
- `RealInstall()` - 实际安装
|
||||||
|
- `CancelInstall()` - 取消安装
|
||||||
|
|
||||||
|
### 信号
|
||||||
|
|
||||||
|
- `ReportProgress(ratio)` - 安装进度报告
|
||||||
|
- `Cancel()` - 安装取消通知
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
1. 插件安装后会自动加载到任务栏
|
||||||
|
2. 点击任务栏图标打开驱动管理界面
|
||||||
|
3. 查看当前显卡设备和驱动信息
|
||||||
|
4. 选择要切换的驱动版本
|
||||||
|
5. 确认后开始安装过程
|
||||||
|
6. 安装完成后选择重启系统
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
GPL-3.0-or-later
|
||||||
|
|
||||||
|
## 贡献
|
||||||
|
|
||||||
|
欢迎提交Issue和Pull Request。
|
||||||
|
|
||||||
|
## 相关项目
|
||||||
|
|
||||||
|
- [dde-shell](https://github.com/linuxdeepin/dde-shell) - Deepin Shell插件系统
|
||||||
|
- [deepin-graphics-driver-manager](https://github.com/linuxdeepin/deepin-graphics-driver-manager) - 显卡驱动管理器
|
||||||
|
|||||||
@@ -0,0 +1,254 @@
|
|||||||
|
# 开发指南
|
||||||
|
|
||||||
|
## 环境准备
|
||||||
|
|
||||||
|
### 1. 克隆dde-shell仓库
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆dde-shell到本地
|
||||||
|
git clone https://github.com/linuxdeepin/dde-shell.git ~/dde-shell
|
||||||
|
|
||||||
|
# 或者作为子模块引入
|
||||||
|
git submodule add https://github.com/linuxdeepin/dde-shell.git third_party/dde-shell
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 安装构建依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Debian/Deepin系统
|
||||||
|
sudo apt build-dep .
|
||||||
|
|
||||||
|
# 或手动安装依赖
|
||||||
|
sudo apt install -y \
|
||||||
|
cmake \
|
||||||
|
g++ \
|
||||||
|
qt6-base-dev \
|
||||||
|
qt6-tools-dev \
|
||||||
|
libdtk6-core-dev \
|
||||||
|
libdtk6-widget-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 配置CMake
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 创建构建目录
|
||||||
|
mkdir build && cd build
|
||||||
|
|
||||||
|
# 配置,指定dde-shell路径
|
||||||
|
cmake .. -Ddde-shell_DIR=~/dde-shell/build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发步骤
|
||||||
|
|
||||||
|
### 步骤1: 获取D-Bus接口定义
|
||||||
|
|
||||||
|
查看deepin-graphics-driver-manager的D-Bus接口:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆仓库
|
||||||
|
git clone https://github.com/linuxdeepin/deepin-graphics-driver-manager.git
|
||||||
|
|
||||||
|
# 查看接口定义
|
||||||
|
cat deepin-graphics-driver-manager/com.deepin.daemon.GraphicsDriver.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
接口方法:
|
||||||
|
- `GetDevice()` - 获取显卡设备信息(返回JSON字符串)
|
||||||
|
- `GetCurrDriverName()` - 获取当前驱动名称
|
||||||
|
- `GetNewDriverName()` - 获取推荐驱动名称
|
||||||
|
- `PrepareInstall(name, language)` - 准备安装驱动
|
||||||
|
- `TestInstall()` - 测试安装
|
||||||
|
- `RealInstall()` - 实际安装
|
||||||
|
- `CancelInstall()` - 取消安装
|
||||||
|
|
||||||
|
信号:
|
||||||
|
- `ReportProgress(ratio)` - 安装进度报告(ratio为百分比字符串)
|
||||||
|
- `Cancel()` - 安装取消通知
|
||||||
|
|
||||||
|
### 步骤2: 适配D-Bus接口
|
||||||
|
|
||||||
|
编辑`graphicsdriverapplet.cpp`,根据实际接口调整:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 检查D-Bus服务是否可用
|
||||||
|
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||||
|
if (!bus.isConnected()) {
|
||||||
|
qWarning() << "Cannot connect to D-Bus session bus";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查服务是否存在
|
||||||
|
QDBusInterface interface(
|
||||||
|
"com.deepin.daemon.GraphicsDriver",
|
||||||
|
"/com/deepin/daemon/GraphicsDriver",
|
||||||
|
"com.deepin.daemon.GraphicsDriver",
|
||||||
|
bus
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!interface.isValid()) {
|
||||||
|
qWarning() << "GraphicsDriver service is not available";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤3: 完善GPU设备检测
|
||||||
|
|
||||||
|
根据`GetDevice()`返回的JSON格式,调整解析逻辑:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"vendor": "NVIDIA",
|
||||||
|
"model": "GeForce GTX 1660 Ti",
|
||||||
|
"driverVersion": "470.103.01",
|
||||||
|
"driverStatus": "installed",
|
||||||
|
"drivers": [
|
||||||
|
{
|
||||||
|
"name": "nvidia-driver-470",
|
||||||
|
"version": "470.103.01",
|
||||||
|
"description": "NVIDIA Driver 470 (推荐)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nvidia-driver-460",
|
||||||
|
"version": "460.103.01",
|
||||||
|
"description": "NVIDIA Driver 460"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤4: 添加图标资源
|
||||||
|
|
||||||
|
创建`icons/`目录并添加图标:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir icons
|
||||||
|
|
||||||
|
# 添加显卡图标(可以从deepin图标库获取)
|
||||||
|
wget https://github.com/linuxdeepin/deepin-icon-theme/raw/master/icons/deepin/scalable/apps/graphics-card.svg -P icons/
|
||||||
|
```
|
||||||
|
|
||||||
|
在QML中引用:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
Image {
|
||||||
|
source: "qrc:/icons/graphics-card.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤5: 测试插件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建
|
||||||
|
cmake -Bbuild
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
# 安装到本地测试
|
||||||
|
cmake --install build --prefix ~/.local
|
||||||
|
|
||||||
|
# 启动dde-shell测试模式
|
||||||
|
dde-shell -t
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤6: 调试技巧
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看D-Bus服务
|
||||||
|
qdbus | grep GraphicsDriver
|
||||||
|
|
||||||
|
# 监听D-Bus信号
|
||||||
|
dbus-monitor "interface='com.deepin.daemon.GraphicsDriver'"
|
||||||
|
|
||||||
|
# 查看插件日志
|
||||||
|
QT_LOGGING_RULES="dde.shell*=true" dde-shell -t
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 1. 插件未加载
|
||||||
|
|
||||||
|
检查`metadata.json`格式是否正确:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Plugin": {
|
||||||
|
"Version": "1.0",
|
||||||
|
"Id": "org.deepin.ds.graphics-driver",
|
||||||
|
"Url": "driverview.qml",
|
||||||
|
"Category": "DDE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. D-Bus连接失败
|
||||||
|
|
||||||
|
确认deepin-graphics-driver-manager服务已启动:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查服务状态
|
||||||
|
systemctl status deepin-graphics-driver-manager
|
||||||
|
|
||||||
|
# 手动启动服务
|
||||||
|
sudo deepin-graphics-driver-manager -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 权限问题
|
||||||
|
|
||||||
|
安装驱动需要root权限,确保PolicyKit配置正确:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查PolicyKit规则
|
||||||
|
pkaction --action-id com.deepin.daemon.GraphicsDriver --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码规范
|
||||||
|
|
||||||
|
### 命名规范
|
||||||
|
|
||||||
|
- 类名:`PascalCase`(如`GraphicsDriverApplet`)
|
||||||
|
- 方法名:`camelCase`(如`refreshDeviceInfo`)
|
||||||
|
- 常量:`UPPER_SNAKE_CASE`(如`DBUS_SERVICE`)
|
||||||
|
- 成员变量:`m_`前缀(如`m_dbusInterface`)
|
||||||
|
|
||||||
|
### 文件组织
|
||||||
|
|
||||||
|
- 头文件:类声明、信号、槽、Q_PROPERTY
|
||||||
|
- 实现文件:构造函数、方法实现、D_APPLET_CLASS宏
|
||||||
|
- QML文件:界面布局、交互逻辑
|
||||||
|
|
||||||
|
## 发布流程
|
||||||
|
|
||||||
|
### 1. 版本号更新
|
||||||
|
|
||||||
|
更新`CMakeLists.txt`中的版本号:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
project(dde-graphics-driver-applet VERSION 1.0.0 LANGUAGES CXX)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 构建Debian包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dpkg-buildpackage -uc -us -nc -b
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 测试安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo dpkg -i ../dde-graphics-driver-applet_1.0.0_amd64.deb
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 提交到官方仓库
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fork仓库后
|
||||||
|
git remote add upstream https://github.com/linuxdeepin/dde-shell.git
|
||||||
|
git push origin master
|
||||||
|
# 创建Pull Request
|
||||||
|
```
|
||||||
|
|
||||||
|
## 相关资源
|
||||||
|
|
||||||
|
- [dde-shell插件开发文档](https://github.com/linuxdeepin/dde-shell/tree/master/docs/plugin)
|
||||||
|
- [deepin-graphics-driver-manager](https://github.com/linuxdeepin/deepin-graphics-driver-manager)
|
||||||
|
- [DTK开发文档](https://linuxdeepin.github.io/dtk/)
|
||||||
|
- [Qt D-Bus文档](https://doc.qt.io/qt-6/qtdbus-index.html)
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "gpuindicator.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
GpuIndicator::GpuIndicator(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GpuIndicator::~GpuIndicator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GpuIndicator::vendor() const
|
||||||
|
{
|
||||||
|
return m_vendor;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GpuIndicator::model() const
|
||||||
|
{
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GpuIndicator::driverVersion() const
|
||||||
|
{
|
||||||
|
return m_driverVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GpuIndicator::driverStatus() const
|
||||||
|
{
|
||||||
|
return m_driverStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GpuIndicator::icon() const
|
||||||
|
{
|
||||||
|
return determineIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpuIndicator::isNvidia() const
|
||||||
|
{
|
||||||
|
return m_vendor.toLower().contains("nvidia");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpuIndicator::isAmd() const
|
||||||
|
{
|
||||||
|
return m_vendor.toLower().contains("amd") || m_vendor.toLower().contains("ati");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpuIndicator::isIntel() const
|
||||||
|
{
|
||||||
|
return m_vendor.toLower().contains("intel");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuIndicator::updateFromJson(const QJsonObject &json)
|
||||||
|
{
|
||||||
|
parseDeviceInfo(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuIndicator::updateFromDeviceInfo(const QString &jsonStr)
|
||||||
|
{
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8());
|
||||||
|
if (doc.isNull() || !doc.isObject()) {
|
||||||
|
qWarning() << "Invalid JSON:" << jsonStr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseDeviceInfo(doc.object());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuIndicator::parseDeviceInfo(const QJsonObject &obj)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (obj.contains("vendor")) {
|
||||||
|
QString vendor = obj["vendor"].toString();
|
||||||
|
if (m_vendor != vendor) {
|
||||||
|
m_vendor = vendor;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.contains("model")) {
|
||||||
|
QString model = obj["model"].toString();
|
||||||
|
if (m_model != model) {
|
||||||
|
m_model = model;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.contains("driverVersion")) {
|
||||||
|
QString version = obj["driverVersion"].toString();
|
||||||
|
if (m_driverVersion != version) {
|
||||||
|
m_driverVersion = version;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.contains("driverStatus")) {
|
||||||
|
QString status = obj["driverStatus"].toString();
|
||||||
|
if (m_driverStatus != status) {
|
||||||
|
m_driverStatus = status;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
emit infoChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GpuIndicator::determineIcon() const
|
||||||
|
{
|
||||||
|
if (isNvidia()) {
|
||||||
|
return "nvidia";
|
||||||
|
} else if (isAmd()) {
|
||||||
|
return "amd";
|
||||||
|
} else if (isIntel()) {
|
||||||
|
return "intel";
|
||||||
|
}
|
||||||
|
return "graphics-card";
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
class GpuIndicator : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString vendor READ vendor NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(QString model READ model NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(QString driverVersion READ driverVersion NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(QString driverStatus READ driverStatus NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(QString icon READ icon NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(bool isNvidia READ isNvidia NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(bool isAmd READ isAmd NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(bool isIntel READ isIntel NOTIFY infoChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GpuIndicator(QObject *parent = nullptr);
|
||||||
|
~GpuIndicator();
|
||||||
|
|
||||||
|
QString vendor() const;
|
||||||
|
QString model() const;
|
||||||
|
QString driverVersion() const;
|
||||||
|
QString driverStatus() const;
|
||||||
|
QString icon() const;
|
||||||
|
bool isNvidia() const;
|
||||||
|
bool isAmd() const;
|
||||||
|
bool isIntel() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void updateFromJson(const QJsonObject &json);
|
||||||
|
Q_INVOKABLE void updateFromDeviceInfo(const QString &jsonStr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void infoChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parseDeviceInfo(const QJsonObject &obj);
|
||||||
|
QString determineIcon() const;
|
||||||
|
|
||||||
|
QString m_vendor;
|
||||||
|
QString m_model;
|
||||||
|
QString m_driverVersion;
|
||||||
|
QString m_driverStatus;
|
||||||
|
};
|
||||||
@@ -0,0 +1,330 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "graphicsdriverapplet.h"
|
||||||
|
#include "pluginfactory.h"
|
||||||
|
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusError>
|
||||||
|
#include <QDBusPendingReply>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <DConfig>
|
||||||
|
|
||||||
|
DCORE_USE_NAMESPACE
|
||||||
|
|
||||||
|
DS_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
static const QString DBUS_SERVICE = "com.deepin.daemon.GraphicsDriver";
|
||||||
|
static const QString DBUS_PATH = "/com/deepin/daemon/GraphicsDriver";
|
||||||
|
static const QString DBUS_INTERFACE = "com.deepin.daemon.GraphicsDriver";
|
||||||
|
|
||||||
|
GraphicsDriverApplet::GraphicsDriverApplet(QObject *parent)
|
||||||
|
: DApplet(parent)
|
||||||
|
, m_dbusInterface(nullptr)
|
||||||
|
, m_progressTimer(new QTimer(this))
|
||||||
|
, m_installProgress(0)
|
||||||
|
, m_isInstalling(false)
|
||||||
|
, m_isTestSuccess(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsDriverApplet::~GraphicsDriverApplet()
|
||||||
|
{
|
||||||
|
if (m_dbusInterface) {
|
||||||
|
delete m_dbusInterface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsDriverApplet::load()
|
||||||
|
{
|
||||||
|
initDBusConnection();
|
||||||
|
|
||||||
|
connect(m_progressTimer, &QTimer::timeout, this, &GraphicsDriverApplet::onPollProgress);
|
||||||
|
|
||||||
|
return DApplet::load();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsDriverApplet::init()
|
||||||
|
{
|
||||||
|
refreshDeviceInfo();
|
||||||
|
|
||||||
|
return DApplet::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GraphicsDriverApplet::currentDriver() const
|
||||||
|
{
|
||||||
|
return m_currentDriver;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GraphicsDriverApplet::newDriver() const
|
||||||
|
{
|
||||||
|
return m_newDriver;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GraphicsDriverApplet::deviceInfo() const
|
||||||
|
{
|
||||||
|
return m_deviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GraphicsDriverApplet::installProgress() const
|
||||||
|
{
|
||||||
|
return m_installProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsDriverApplet::isInstalling() const
|
||||||
|
{
|
||||||
|
return m_isInstalling;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsDriverApplet::isTestSuccess() const
|
||||||
|
{
|
||||||
|
return m_isTestSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray GraphicsDriverApplet::availableDrivers() const
|
||||||
|
{
|
||||||
|
return m_availableDrivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::refreshDeviceInfo()
|
||||||
|
{
|
||||||
|
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
||||||
|
qWarning() << "DBus interface is not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDBusPendingCall call = m_dbusInterface->asyncCall("GetDevice");
|
||||||
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
|
||||||
|
connect(watcher, &QDBusPendingCallWatcher::finished, this, &GraphicsDriverApplet::onDBusReply);
|
||||||
|
|
||||||
|
QDBusPendingCall currCall = m_dbusInterface->asyncCall("GetCurrDriverName");
|
||||||
|
QDBusPendingCallWatcher *currWatcher = new QDBusPendingCallWatcher(currCall, this);
|
||||||
|
connect(currWatcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) {
|
||||||
|
QDBusPendingReply<QString> reply = *call;
|
||||||
|
if (reply.isError()) {
|
||||||
|
qWarning() << "Failed to get current driver:" << reply.error().message();
|
||||||
|
} else {
|
||||||
|
m_currentDriver = reply.value();
|
||||||
|
emit currentDriverChanged();
|
||||||
|
}
|
||||||
|
call->deleteLater();
|
||||||
|
});
|
||||||
|
|
||||||
|
QDBusPendingCall newCall = m_dbusInterface->asyncCall("GetNewDriverName");
|
||||||
|
QDBusPendingCallWatcher *newWatcher = new QDBusPendingCallWatcher(newCall, this);
|
||||||
|
connect(newWatcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) {
|
||||||
|
QDBusPendingReply<QString> reply = *call;
|
||||||
|
if (reply.isError()) {
|
||||||
|
qWarning() << "Failed to get new driver:" << reply.error().message();
|
||||||
|
} else {
|
||||||
|
m_newDriver = reply.value();
|
||||||
|
emit newDriverChanged();
|
||||||
|
}
|
||||||
|
call->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::prepareInstall(const QString &driverName)
|
||||||
|
{
|
||||||
|
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
||||||
|
qWarning() << "DBus interface is not valid";
|
||||||
|
emit installFailed("DBus interface is not valid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pendingInstallDriver = driverName;
|
||||||
|
|
||||||
|
QLocale locale;
|
||||||
|
QString language = locale.name();
|
||||||
|
|
||||||
|
QDBusPendingCall call = m_dbusInterface->asyncCall("PrepareInstall", driverName, language);
|
||||||
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
|
||||||
|
connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) {
|
||||||
|
QDBusPendingReply<> reply = *call;
|
||||||
|
if (reply.isError()) {
|
||||||
|
qWarning() << "Failed to prepare install:" << reply.error().message();
|
||||||
|
emit installFailed(reply.error().message());
|
||||||
|
} else {
|
||||||
|
qDebug() << "Prepare install succeeded";
|
||||||
|
}
|
||||||
|
call->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::testInstall()
|
||||||
|
{
|
||||||
|
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
||||||
|
qWarning() << "DBus interface is not valid";
|
||||||
|
emit installFailed("DBus interface is not valid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setInstalling(true);
|
||||||
|
|
||||||
|
QDBusPendingCall call = m_dbusInterface->asyncCall("TestInstall");
|
||||||
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
|
||||||
|
connect(watcher, &QDBusPendingCallWatcher::finished, this, &GraphicsDriverApplet::onDBusReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::realInstall()
|
||||||
|
{
|
||||||
|
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
||||||
|
qWarning() << "DBus interface is not valid";
|
||||||
|
emit installFailed("DBus interface is not valid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDBusPendingCall call = m_dbusInterface->asyncCall("RealInstall");
|
||||||
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
|
||||||
|
connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) {
|
||||||
|
QDBusPendingReply<> reply = *call;
|
||||||
|
if (reply.isError()) {
|
||||||
|
qWarning() << "Failed to real install:" << reply.error().message();
|
||||||
|
emit installFailed(reply.error().message());
|
||||||
|
setInstalling(false);
|
||||||
|
} else {
|
||||||
|
qDebug() << "Real install succeeded";
|
||||||
|
emit installSuccess();
|
||||||
|
emit requestReboot();
|
||||||
|
}
|
||||||
|
call->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::cancelInstall()
|
||||||
|
{
|
||||||
|
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dbusInterface->asyncCall("CancelInstall");
|
||||||
|
setInstalling(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::onDBusReply(QDBusPendingCallWatcher *call)
|
||||||
|
{
|
||||||
|
QDBusPendingReply<QString> reply = *call;
|
||||||
|
if (reply.isError()) {
|
||||||
|
qWarning() << "DBus call failed:" << reply.error().message();
|
||||||
|
} else {
|
||||||
|
QString result = reply.value();
|
||||||
|
qDebug() << "DBus call result:" << result;
|
||||||
|
parseDeviceInfo(result);
|
||||||
|
}
|
||||||
|
call->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::onReportProgress(const QString &ratio)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int progress = ratio.toInt(&ok);
|
||||||
|
if (ok) {
|
||||||
|
m_installProgress = progress;
|
||||||
|
emit installProgressChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::onCancel()
|
||||||
|
{
|
||||||
|
setInstalling(false);
|
||||||
|
m_installProgress = 0;
|
||||||
|
emit installProgressChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::onPollProgress()
|
||||||
|
{
|
||||||
|
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDBusPendingCall call = m_dbusInterface->asyncCall("GetCurrDriverName");
|
||||||
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
|
||||||
|
connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) {
|
||||||
|
QDBusPendingReply<QString> reply = *call;
|
||||||
|
if (!reply.isError()) {
|
||||||
|
QString newDriver = reply.value();
|
||||||
|
if (newDriver != m_currentDriver) {
|
||||||
|
m_newDriver = newDriver;
|
||||||
|
emit newDriverChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::initDBusConnection()
|
||||||
|
{
|
||||||
|
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||||
|
|
||||||
|
if (!bus.isConnected()) {
|
||||||
|
qWarning() << "Cannot connect to D-Bus session bus";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dbusInterface = new QDBusInterface(
|
||||||
|
DBUS_SERVICE,
|
||||||
|
DBUS_PATH,
|
||||||
|
DBUS_INTERFACE,
|
||||||
|
bus,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!m_dbusInterface->isValid()) {
|
||||||
|
qWarning() << "DBus interface is not valid:" << m_dbusInterface->lastError().message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(m_dbusInterface, SIGNAL(ReportProgress(QString)),
|
||||||
|
this, SLOT(onReportProgress(QString)));
|
||||||
|
connect(m_dbusInterface, SIGNAL(Cancel()),
|
||||||
|
this, SLOT(onCancel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::updateDeviceInfo()
|
||||||
|
{
|
||||||
|
refreshDeviceInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::parseDeviceInfo(const QString &jsonStr)
|
||||||
|
{
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8());
|
||||||
|
if (doc.isNull() || !doc.isObject()) {
|
||||||
|
qWarning() << "Invalid JSON:" << jsonStr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject obj = doc.object();
|
||||||
|
m_deviceInfo = jsonStr;
|
||||||
|
emit deviceInfoChanged();
|
||||||
|
|
||||||
|
if (obj.contains("drivers")) {
|
||||||
|
m_availableDrivers = obj["drivers"].toArray();
|
||||||
|
emit availableDriversChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::setInstalling(bool installing)
|
||||||
|
{
|
||||||
|
if (m_isInstalling != installing) {
|
||||||
|
m_isInstalling = installing;
|
||||||
|
emit isInstallingChanged();
|
||||||
|
|
||||||
|
if (installing) {
|
||||||
|
m_progressTimer->start(1000);
|
||||||
|
} else {
|
||||||
|
m_progressTimer->stop();
|
||||||
|
m_installProgress = 0;
|
||||||
|
emit installProgressChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D_APPLET_CLASS(GraphicsDriverApplet)
|
||||||
|
|
||||||
|
DS_END_NAMESPACE
|
||||||
|
|
||||||
|
#include "graphicsdriverapplet.moc"
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "applet.h"
|
||||||
|
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusPendingCallWatcher>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
DS_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class GraphicsDriverApplet : public DApplet
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString currentDriver READ currentDriver NOTIFY currentDriverChanged)
|
||||||
|
Q_PROPERTY(QString newDriver READ newDriver NOTIFY newDriverChanged)
|
||||||
|
Q_PROPERTY(QString deviceInfo READ deviceInfo NOTIFY deviceInfoChanged)
|
||||||
|
Q_PROPERTY(int installProgress READ installProgress NOTIFY installProgressChanged)
|
||||||
|
Q_PROPERTY(bool isInstalling READ isInstalling NOTIFY isInstallingChanged)
|
||||||
|
Q_PROPERTY(bool isTestSuccess READ isTestSuccess NOTIFY isTestSuccessChanged)
|
||||||
|
Q_PROPERTY(QJsonArray availableDrivers READ availableDrivers NOTIFY availableDriversChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GraphicsDriverApplet(QObject *parent = nullptr);
|
||||||
|
~GraphicsDriverApplet();
|
||||||
|
|
||||||
|
virtual bool load() override;
|
||||||
|
virtual bool init() override;
|
||||||
|
|
||||||
|
QString currentDriver() const;
|
||||||
|
QString newDriver() const;
|
||||||
|
QString deviceInfo() const;
|
||||||
|
int installProgress() const;
|
||||||
|
bool isInstalling() const;
|
||||||
|
bool isTestSuccess() const;
|
||||||
|
QJsonArray availableDrivers() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void refreshDeviceInfo();
|
||||||
|
Q_INVOKABLE void prepareInstall(const QString &driverName);
|
||||||
|
Q_INVOKABLE void testInstall();
|
||||||
|
Q_INVOKABLE void realInstall();
|
||||||
|
Q_INVOKABLE void cancelInstall();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void currentDriverChanged();
|
||||||
|
void newDriverChanged();
|
||||||
|
void deviceInfoChanged();
|
||||||
|
void installProgressChanged();
|
||||||
|
void isInstallingChanged();
|
||||||
|
void isTestSuccessChanged();
|
||||||
|
void availableDriversChanged();
|
||||||
|
void installSuccess();
|
||||||
|
void installFailed(const QString &error);
|
||||||
|
void requestReboot();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onDBusReply(QDBusPendingCallWatcher *call);
|
||||||
|
void onReportProgress(const QString &ratio);
|
||||||
|
void onCancel();
|
||||||
|
void onPollProgress();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initDBusConnection();
|
||||||
|
void updateDeviceInfo();
|
||||||
|
void parseDeviceInfo(const QString &jsonStr);
|
||||||
|
void setInstalling(bool installing);
|
||||||
|
|
||||||
|
QDBusInterface *m_dbusInterface;
|
||||||
|
QTimer *m_progressTimer;
|
||||||
|
|
||||||
|
QString m_currentDriver;
|
||||||
|
QString m_newDriver;
|
||||||
|
QString m_deviceInfo;
|
||||||
|
int m_installProgress;
|
||||||
|
bool m_isInstalling;
|
||||||
|
bool m_isTestSuccess;
|
||||||
|
QJsonArray m_availableDrivers;
|
||||||
|
QString m_pendingInstallDriver;
|
||||||
|
};
|
||||||
|
|
||||||
|
DS_END_NAMESPACE
|
||||||
@@ -0,0 +1,387 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
import QtQuick 2.11
|
||||||
|
import QtQuick.Controls 2.4
|
||||||
|
import QtQuick.Layouts 1.11
|
||||||
|
import org.deepin.ds 1.0
|
||||||
|
|
||||||
|
AppletItem {
|
||||||
|
id: root
|
||||||
|
objectName: "graphics driver applet"
|
||||||
|
implicitWidth: 320
|
||||||
|
implicitHeight: 400
|
||||||
|
|
||||||
|
property var applet: Applet
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.applet
|
||||||
|
function onInstallSuccess() {
|
||||||
|
successDialog.open()
|
||||||
|
}
|
||||||
|
function onInstallFailed(error) {
|
||||||
|
errorDialog.text = error
|
||||||
|
errorDialog.open()
|
||||||
|
}
|
||||||
|
function onRequestReboot() {
|
||||||
|
rebootDialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: palette.window
|
||||||
|
radius: 8
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 16
|
||||||
|
spacing: 12
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: "qrc:/icons/graphics-card.svg"
|
||||||
|
Layout.preferredWidth: 24
|
||||||
|
Layout.preferredHeight: 24
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("Graphics Driver Manager")
|
||||||
|
font.pixelSize: 14
|
||||||
|
font.bold: true
|
||||||
|
color: palette.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Refresh")
|
||||||
|
flat: true
|
||||||
|
onClicked: root.applet.refreshDeviceInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
color: palette.separator
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBox {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
title: qsTr("Device Information")
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Text {
|
||||||
|
text: qsTr("Vendor:")
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.placeholderText
|
||||||
|
Layout.preferredWidth: 80
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: root.applet.deviceInfo ? JSON.parse(root.applet.deviceInfo).vendor || "-" : "-"
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Text {
|
||||||
|
text: qsTr("Model:")
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.placeholderText
|
||||||
|
Layout.preferredWidth: 80
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: root.applet.deviceInfo ? JSON.parse(root.applet.deviceInfo).model || "-" : "-"
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Text {
|
||||||
|
text: qsTr("Current Driver:")
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.placeholderText
|
||||||
|
Layout.preferredWidth: 80
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: root.applet.currentDriver || "-"
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBox {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
title: qsTr("Available Drivers")
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
anchors.fill: parent
|
||||||
|
model: root.applet.availableDrivers
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
delegate: ItemDelegate {
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Text {
|
||||||
|
text: modelData.name || qsTr("Unknown Driver")
|
||||||
|
font.pixelSize: 13
|
||||||
|
font.bold: true
|
||||||
|
color: palette.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Badge {
|
||||||
|
visible: modelData.name === root.applet.currentDriver
|
||||||
|
text: qsTr("Current")
|
||||||
|
color: "green"
|
||||||
|
}
|
||||||
|
|
||||||
|
Badge {
|
||||||
|
visible: modelData.name === root.applet.newDriver && modelData.name !== root.applet.currentDriver
|
||||||
|
text: qsTr("Recommended")
|
||||||
|
color: "blue"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: modelData.description || ""
|
||||||
|
font.pixelSize: 11
|
||||||
|
color: palette.placeholderText
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
visible: modelData.name !== root.applet.currentDriver && !root.applet.isInstalling
|
||||||
|
text: qsTr("Switch")
|
||||||
|
flat: true
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
onClicked: {
|
||||||
|
root.applet.prepareInstall(modelData.name)
|
||||||
|
installConfirmDialog.driverName = modelData.name
|
||||||
|
installConfirmDialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.applet.isInstalling
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Text {
|
||||||
|
text: qsTr("Installing...")
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: root.applet.installProgress + "%"
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: palette.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
value: root.applet.installProgress / 100
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
flat: true
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
onClicked: root.applet.cancelInstall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog {
|
||||||
|
id: installConfirmDialog
|
||||||
|
property string driverName
|
||||||
|
title: qsTr("Confirm Driver Switch")
|
||||||
|
modal: true
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 300
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("Are you sure you want to switch to driver: %1?").arg(installConfirmDialog.driverName)
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
flat: true
|
||||||
|
onClicked: installConfirmDialog.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Confirm")
|
||||||
|
onClicked: {
|
||||||
|
root.applet.testInstall()
|
||||||
|
installConfirmDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog {
|
||||||
|
id: successDialog
|
||||||
|
title: qsTr("Installation Success")
|
||||||
|
modal: true
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 300
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("Driver has been installed successfully. Do you want to reboot now?")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Later")
|
||||||
|
flat: true
|
||||||
|
onClicked: successDialog.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Reboot Now")
|
||||||
|
onClicked: {
|
||||||
|
DUtil.reboot()
|
||||||
|
successDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog {
|
||||||
|
id: errorDialog
|
||||||
|
property string text
|
||||||
|
title: qsTr("Installation Failed")
|
||||||
|
modal: true
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 300
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: errorDialog.text
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("OK")
|
||||||
|
onClicked: errorDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog {
|
||||||
|
id: rebootDialog
|
||||||
|
title: qsTr("Reboot Required")
|
||||||
|
modal: true
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 300
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("A reboot is required to apply the driver changes. Do you want to reboot now?")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Later")
|
||||||
|
flat: true
|
||||||
|
onClicked: rebootDialog.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Reboot Now")
|
||||||
|
onClicked: {
|
||||||
|
DUtil.reboot()
|
||||||
|
rebootDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component Badge: Rectangle {
|
||||||
|
property string text
|
||||||
|
property color color: "blue"
|
||||||
|
|
||||||
|
width: badgeText.implicitWidth + 12
|
||||||
|
height: 18
|
||||||
|
radius: 9
|
||||||
|
color: Qt.rgba(color.r, color.g, color.b, 0.2)
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: badgeText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: root.text
|
||||||
|
font.pixelSize: 10
|
||||||
|
color: root.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Plugin": {
|
||||||
|
"Version": "1.0",
|
||||||
|
"Id": "org.deepin.ds.graphics-driver",
|
||||||
|
"Url": "driverview.qml",
|
||||||
|
"Category": "DDE"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user