eb90da12f3
- 创建插件元数据 package/metadata.json - 实现主插件类 GraphicsDriverApplet (D-Bus通信) - 实现GPU指示器类 GpuIndicator (设备信息解析) - 创建QML界面 driverview.qml (驱动管理UI) - 添加CMake构建配置 - 编写开发指南文档 docs/DEVELOPMENT.md
331 lines
9.0 KiB
C++
331 lines
9.0 KiB
C++
// 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"
|