diff --git a/Maia/BackendLib/MFrontendModel.cpp b/Maia/BackendLib/MFrontendModel.cpp index 4d7fff2..6c513d0 100644 --- a/Maia/BackendLib/MFrontendModel.cpp +++ b/Maia/BackendLib/MFrontendModel.cpp @@ -1,7 +1,8 @@ #include "MFrontendModel.hpp" + +#include #include -#include -#include +#include #include #include #include @@ -12,98 +13,128 @@ MFrontendModel::MFrontendModel(QObject *parent) qDBusRegisterMetaType(); qDBusRegisterMetaType(); - m_dbusInterface = new QDBusInterface("org.maia.FrontendManager", - "/FrontendManager", - "org.maia.FrontendManager", - QDBusConnection::sessionBus(), - this); - - // Connect D-Bus signals to slots - connect(m_dbusInterface, - SIGNAL(frontendAdded(QString, QString, QString, QString)), - this, - SLOT(handleFrontendAdded(QString, QString, QString, QString))); - connect(m_dbusInterface, - SIGNAL(frontendRemoved(QString)), - this, - SLOT(handleFrontendRemoved(QString))); - connect(m_dbusInterface, - SIGNAL(activeFrontendChanged(QString)), - this, - SLOT(handleActiveFrontendChanged(QString))); - - QDBusPendingCall call = m_dbusInterface->asyncCall("getFrontendList"); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); - connect(watcher, - &QDBusPendingCallWatcher::finished, - this, - &MFrontendModel::handleFrontendListReply); - - // Load initial activeFrontendId + m_dbusInterface = new QDBusInterface( + "org.maia.FrontendManager", + "/FrontendManager", + "org.maia.FrontendManager", + QDBusConnection::sessionBus(), + this); + + connect( + m_dbusInterface, + SIGNAL(frontendAdded(QString,QString,QString,QString)), + this, + SLOT(handleFrontendAdded(QString,QString,QString,QString))); + + connect( + m_dbusInterface, + SIGNAL(frontendRemoved(QString)), + this, + SLOT(handleFrontendRemoved(QString))); + + connect( + m_dbusInterface, + SIGNAL(activeFrontendChanged(QString)), + this, + SLOT(handleActiveFrontendChanged(QString))); + + loadFrontends(); loadActiveFrontend(); } -void MFrontendModel::loadActiveFrontend() +void MFrontendModel::loadFrontends() { - QDBusPendingCall call = m_dbusInterface->asyncCall("activeFrontend"); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); - connect(watcher, - &QDBusPendingCallWatcher::finished, - this, - [this](QDBusPendingCallWatcher *watcher) { - QDBusPendingReply reply = *watcher; - if (!reply.isError()) { - handleGetActiveFrontend(reply.value()); - } else { - qDebug() << "Failed to get initial activeFrontendId:" - << reply.error().message(); - } - watcher->deleteLater(); - }); + QDBusPendingCall call = + m_dbusInterface->asyncCall("getFrontendList"); + + auto *watcher = + new QDBusPendingCallWatcher(call, this); + + connect( + watcher, + &QDBusPendingCallWatcher::finished, + this, + &MFrontendModel::handleFrontendListReply); } -MFrontendModel::~MFrontendModel() +void MFrontendModel::loadActiveFrontend() { - m_dbusInterface->deleteLater(); - m_dbusInterface = nullptr; + QDBusPendingCall call = + m_dbusInterface->asyncCall("activeFrontend"); + + auto *watcher = + new QDBusPendingCallWatcher(call, this); + + connect( + watcher, + &QDBusPendingCallWatcher::finished, + this, + [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + + if (reply.isError()) { + qDebug() + << "Failed to get initial active frontend:" + << reply.error().message(); + } else { + handleGetActiveFrontend(reply.value()); + } + + watcher->deleteLater(); + }); } int MFrontendModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); + return m_frontends.size(); } -QVariant MFrontendModel::data(const QModelIndex &index, int role) const +QVariant MFrontendModel::data( + const QModelIndex &index, + int role) const { - if (!index.isValid() || index.row() >= m_frontends.size()) - return QVariant(); + if (!index.isValid() || + index.row() < 0 || + index.row() >= m_frontends.size()) { + return {}; + } + + const Frontend &frontend = + m_frontends.at(index.row()); - const Frontend &frontend = m_frontends[index.row()]; switch (role) { case IdRole: return frontend.id; + case NameRole: return frontend.name; + case DescriptionRole: return frontend.description; + case PathRole: return frontend.path; + case ActiveRole: return frontend.active; + default: - return QVariant(); + return {}; } } QHash MFrontendModel::roleNames() const { QHash roles; + roles[IdRole] = "frontendId"; roles[NameRole] = "frontendName"; roles[DescriptionRole] = "frontendDescription"; roles[PathRole] = "frontendPath"; roles[ActiveRole] = "frontendActive"; + return roles; } @@ -112,124 +143,258 @@ QString MFrontendModel::activeFrontend() const return m_activeFrontendIdMirror; } -void MFrontendModel::setActiveFrontend(const QString &frontendId) +void MFrontendModel::setActiveFrontend( + const QString &frontendId) { - //qDebug() << "Client 1 " << __PRETTY_FUNCTION__ << " Client side, befor send request via d-bus"; - QDBusPendingCall call = m_dbusInterface->asyncCall("setActiveFrontend", frontendId); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [](QDBusPendingCallWatcher *watcher) { - if (watcher->isError()) { - qDebug() << "Failed to switch frontend:" << watcher->error().message(); + if (frontendId.isEmpty()) { + qDebug() + << "Cannot switch to an empty frontend ID."; + + return; + } + + bool frontendExists = false; + + for (const Frontend &frontend : m_frontends) { + if (frontend.id == frontendId) { + frontendExists = true; + break; } - watcher->deleteLater(); - }); + } + + if (!frontendExists) { + qDebug() + << "Cannot switch to unknown frontend:" + << frontendId; + + return; + } + + if (frontendId == m_activeFrontendIdMirror) { + return; + } + + QDBusPendingCall call = + m_dbusInterface->asyncCall( + "setActiveFrontend", + frontendId); + + auto *watcher = + new QDBusPendingCallWatcher(call, this); + + connect( + watcher, + &QDBusPendingCallWatcher::finished, + this, + [watcher]() { + if (watcher->isError()) { + qDebug() + << "Failed to switch frontend:" + << watcher->error().message(); + } + + watcher->deleteLater(); + }); } -void MFrontendModel::handleFrontendListReply(QDBusPendingCallWatcher *watcher) +void MFrontendModel::handleFrontendListReply( + QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; + if (reply.isError()) { - qDebug() << "[ERROR] D-Bus error:" << reply.error().message(); + qDebug() + << "Failed to get frontend list:" + << reply.error().message(); + watcher->deleteLater(); return; } beginResetModel(); + m_frontends.clear(); - QVariantList frontends = reply.value(); - //qDebug() << "REPLY = " << frontends; + const QVariantList frontends = reply.value(); for (const QVariant &frontendVar : frontends) { - // Check if QVariant contains QDBusArgument - if (frontendVar.canConvert()) { - QDBusArgument dbusArg = frontendVar.value(); - QVariantMap map; - - // Deserialize QDBusArgument as QVariantMap - if (dbusArg.currentSignature() == "a{sv}") { - dbusArg >> map; - } else { - qDebug() << "Unexpected D-Bus argument signature:" << dbusArg.currentSignature(); - continue; + if (!frontendVar.canConvert()) { + qDebug() + << "Unexpected frontend QVariant type:" + << frontendVar.typeName(); + + continue; + } + + QDBusArgument dbusArg = + frontendVar.value(); + + if (dbusArg.currentSignature() != "a{sv}") { + qDebug() + << "Unexpected D-Bus argument signature:" + << dbusArg.currentSignature(); + + continue; + } + + QVariantMap map; + dbusArg >> map; + + Frontend frontend; + + frontend.id = + map.value("id").toString(); + + frontend.name = + map.value("name").toString(); + + frontend.description = + map.value("description").toString(); + + frontend.path = + map.value("path").toString(); + + frontend.active = + map.value("active").toBool(); + + if (frontend.id.isEmpty()) { + continue; + } + + bool duplicate = false; + + for (const Frontend &existing : m_frontends) { + if (existing.id == frontend.id) { + duplicate = true; + break; } + } - Frontend frontend; - frontend.id = map["id"].toString(); - frontend.name = map["name"].toString(); - frontend.description = map["description"].toString(); - frontend.path = map["path"].toString(); - frontend.active = map["active"].toBool(); - - //qDebug() << "FRONTEND NAME =" << frontend.name; - //qDebug() << "FRONTEND ID = " << frontend.id; - //qDebug() << "FRONTEND DESCRIPTION = " << frontend.description; - //qDebug() << "FRONTEND PATH = " << frontend.path; - //qDebug() << "FRONTEND ACTIVE = " << frontend.active; - //qDebug() << "------------------"; + if (!duplicate) { m_frontends.append(frontend); - } else { - qDebug() << "[ERROR] Unexpected QVariant type:" << frontendVar.typeName(); + } + } + + if (!m_activeFrontendIdMirror.isEmpty()) { + for (Frontend &frontend : m_frontends) { + frontend.active = + frontend.id == m_activeFrontendIdMirror; } } endResetModel(); + watcher->deleteLater(); } -void MFrontendModel::handleFrontendAdded(const QString &id, - const QString &name, - const QString &description, - const QString &path) +void MFrontendModel::handleFrontendAdded( + const QString &id, + const QString &name, + const QString &description, + const QString &path) { - beginInsertRows(QModelIndex(), m_frontends.size(), m_frontends.size()); + if (id.isEmpty()) { + return; + } + + for (const Frontend &frontend : m_frontends) { + if (frontend.id == id) { + return; + } + } + Frontend frontend; + frontend.id = id; frontend.name = name; frontend.description = description; frontend.path = path; - frontend.active = (id == m_activeFrontendIdMirror); + frontend.active = + (id == m_activeFrontendIdMirror); + + const int row = m_frontends.size(); + + beginInsertRows( + QModelIndex(), + row, + row); + m_frontends.append(frontend); + endInsertRows(); } -void MFrontendModel::handleFrontendRemoved(const QString &id) +void MFrontendModel::handleFrontendRemoved( + const QString &id) { - for (int i = 0; i < m_frontends.size(); ++i) { - if (m_frontends[i].id == id) { - beginRemoveRows(QModelIndex(), i, i); - m_frontends.removeAt(i); - endRemoveRows(); - return; + for (int i = 0; + i < m_frontends.size(); + ++i) { + + if (m_frontends.at(i).id != id) { + continue; } + + beginRemoveRows( + QModelIndex(), + i, + i); + + m_frontends.removeAt(i); + + endRemoveRows(); + + return; } } -void MFrontendModel::handleActiveFrontendChanged(const QString &frontendId) +void MFrontendModel::handleActiveFrontendChanged( + const QString &frontendId) { - //qDebug() << "##################### " << __PRETTY_FUNCTION__; - //qDebug() << "Frontend id = " << frontendId; - // if (frontendId.startsWith("862")) { - // qDebug() << "Gnome"; - // } else if (frontendId.startsWith("351")) { - // qDebug() << "LunaXP"; - // } - if (m_activeFrontendIdMirror != frontendId) { - // Update active status for all frontends - for (int i = 0; i < m_frontends.size(); ++i) { - bool newActive = m_frontends[i].id == frontendId; - if (m_frontends[i].active != newActive) { - m_frontends[i].active = newActive; - emit dataChanged(index(i), index(i), {ActiveRole}); - } + updateActiveFrontendState(frontendId); +} + +void MFrontendModel::handleGetActiveFrontend( + const QString &frontendId) +{ + updateActiveFrontendState(frontendId); +} + +void MFrontendModel::updateActiveFrontendState( + const QString &frontendId) +{ + if (frontendId.isEmpty()) { + return; + } + + bool changed = false; + + for (int i = 0; + i < m_frontends.size(); + ++i) { + + const bool newActive = + m_frontends.at(i).id == frontendId; + + if (m_frontends[i].active != newActive) { + m_frontends[i].active = newActive; + + emit dataChanged( + index(i), + index(i), + {ActiveRole}); + + changed = true; } + } + + if (m_activeFrontendIdMirror != frontendId) { m_activeFrontendIdMirror = frontendId; + emit activeFrontendChanged(); + + changed = true; } -} -void MFrontendModel::handleGetActiveFrontend(const QString &frontendId) -{ - //qDebug() << "##################### " << __PRETTY_FUNCTION__; - //qDebug() << "Frontend id = " << frontendId; + Q_UNUSED(changed); }