/* SPDX-FileCopyrightText: 2018 Roman Gilg SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez SPDX-License-Identifier: GPL-2.0-or-later */ #include "devicesmodel.h" #include "inputdevice.h" #include #include "logging.h" DevicesModel *DevicesModel::self() { static DevicesModel s_self; return &s_self; } DevicesModel::DevicesModel(QObject *parent) : QAbstractListModel(parent) { m_deviceManager = new QDBusInterface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice"), QStringLiteral("org.kde.KWin.InputDeviceManager"), QDBusConnection::sessionBus(), this); resetModel(); m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice"), QStringLiteral("org.kde.KWin.InputDeviceManager"), QStringLiteral("deviceAdded"), this, SLOT(onDeviceAdded(QString))); m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice"), QStringLiteral("org.kde.KWin.InputDeviceManager"), QStringLiteral("deviceRemoved"), this, SLOT(onDeviceRemoved(QString))); } void DevicesModel::resetModel() { beginResetModel(); qDeleteAll(m_devices); m_devices.clear(); QStringList devicesSysNames; const QVariant reply = m_deviceManager->property("devicesSysNames"); if (reply.isValid()) { qCDebug(KCM_TABLET) << "Devices list received successfully from KWin."; devicesSysNames = reply.toStringList(); } else { qCCritical(KCM_TABLET) << "Error on receiving device list from KWin."; return; } for (const QString &sysname : devicesSysNames) { addDevice(sysname, false); } endResetModel(); } QVariant DevicesModel::data(const QModelIndex &index, int role) const { if (!checkIndex(index, CheckIndexOption::IndexIsValid) || index.column() != 0) return {}; switch (role) { case Qt::DisplayRole: return m_devices.at(index.row())->name(); case Qt::UserRole: return QVariant::fromValue(m_devices.at(index.row())); } return {}; } int DevicesModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_devices.count(); } void DevicesModel::onDeviceAdded(const QString &sysName) { if (std::any_of(m_devices.constBegin(), m_devices.constEnd(), [sysName](InputDevice *t) { return t->sysName() == sysName; })) { return; } addDevice(sysName, true); } void DevicesModel::addDevice(const QString &sysName, bool tellModel) { QDBusInterface deviceIface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice/") + sysName, QStringLiteral("org.kde.KWin.InputDevice"), QDBusConnection::sessionBus(), this); QVariant reply = deviceIface.property("tabletTool"); if (reply.isValid() && reply.toBool()) { InputDevice *dev = new InputDevice(sysName); connect(dev, &InputDevice::needsSaveChanged, this, &DevicesModel::needsSaveChanged); if (tellModel) { beginInsertRows({}, m_devices.count(), m_devices.count()); } m_devices.append(dev); qCDebug(KCM_TABLET).nospace() << "Device connected: " << dev->name() << " (" << dev->sysName() << ")"; if (tellModel) { endInsertRows(); } } } void DevicesModel::onDeviceRemoved(const QString &sysName) { QVector::const_iterator it = std::find_if(m_devices.constBegin(), m_devices.constEnd(), [sysName](InputDevice *t) { return t->sysName() == sysName; }); if (it == m_devices.cend()) { return; } InputDevice *dev = static_cast(*it); qCDebug(KCM_TABLET).nospace() << "Device disconnected: " << dev->name() << " (" << dev->sysName() << ")"; int index = m_devices.indexOf(*it); beginRemoveRows({}, index, index); m_devices.removeAt(index); endInsertRows(); } InputDevice *DevicesModel::deviceAt(int row) const { return m_devices.value(row, nullptr); } QHash DevicesModel::roleNames() const { return { {Qt::DisplayRole, "display"}, }; } void DevicesModel::defaults() { for (auto device : qAsConst(m_devices)) { device->defaults(); } } void DevicesModel::load() { for (auto device : qAsConst(m_devices)) { device->load(); } } void DevicesModel::save() { for (auto device : qAsConst(m_devices)) { device->save(); } } bool DevicesModel::isDefaults() const { return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](InputDevice *dev) { return dev->isDefaults(); }); } bool DevicesModel::isSaveNeeded() const { return std::any_of(m_devices.constBegin(), m_devices.constEnd(), [](InputDevice *dev) { return dev->isSaveNeeded(); }); }