// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later #include "graphicsdriverapplet.h" #include #include #include #include #include #include #include #include #include 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 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 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 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 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"