// SPDX-FileCopyrightText: 2026 Marco Allegretti // SPDX-License-Identifier: EUPL-1.2 #include "devicecontext.h" #include #include #include #include #include #include #include #include #include #include #include namespace { bool pathExists(const QString &path) { return QFileInfo::exists(path); } bool systemHasBattery() { const QDir powerSupply(QStringLiteral("/sys/class/power_supply")); const QStringList entries = powerSupply.entryList(QDir::Dirs | QDir::NoDotAndDotDot); for (const QString &entry : entries) { if (entry.startsWith(QStringLiteral("BAT"), Qt::CaseInsensitive)) { return true; } if (pathExists(powerSupply.filePath(entry + QStringLiteral("/type")))) { QFile typeFile(powerSupply.filePath(entry + QStringLiteral("/type"))); if (typeFile.open(QIODevice::ReadOnly) && QString::fromUtf8(typeFile.readAll()).trimmed() == QLatin1String("Battery")) { return true; } } } return false; } } DeviceContext::DeviceContext(QObject *parent) : QObject(parent) , m_runtimePlatform(KRuntimePlatform::runtimePlatform().join(QLatin1Char(','))) , m_hasBattery(systemHasBattery()) { const QList devices = QInputDevice::devices(); for (const QInputDevice *device : devices) { if (!device) { continue; } const auto type = device->type(); m_hasTouch = m_hasTouch || type == QInputDevice::DeviceType::TouchScreen; m_hasKeyboard = m_hasKeyboard || type == QInputDevice::DeviceType::Keyboard; m_hasMouse = m_hasMouse || type == QInputDevice::DeviceType::Mouse; } const QList screens = QGuiApplication::screens(); m_displayCount = std::max(1, static_cast(screens.size())); if (QScreen *screen = QGuiApplication::primaryScreen()) { const QSize size = screen->geometry().size(); m_primaryDisplayLandscape = size.width() >= size.height(); } const QString platform = m_runtimePlatform; if (m_displayCount > 1) { m_recommendedDeviceClass = QStringLiteral("dual-screen"); m_recommendedExperienceProfile = QStringLiteral("hybrid"); } else if (platform.contains(QStringLiteral("phone"))) { m_recommendedDeviceClass = QStringLiteral("phone"); m_recommendedExperienceProfile = QStringLiteral("mobile"); } else if (platform.contains(QStringLiteral("handheld"))) { m_recommendedDeviceClass = QStringLiteral("handheld"); m_recommendedExperienceProfile = QStringLiteral("gaming"); } else if (platform.contains(QStringLiteral("tablet"))) { m_recommendedDeviceClass = QStringLiteral("tablet"); m_recommendedExperienceProfile = QStringLiteral("mobile"); } else if (m_hasBattery && m_hasTouch && (m_hasKeyboard || m_hasMouse)) { m_recommendedDeviceClass = QStringLiteral("tablet"); m_recommendedExperienceProfile = QStringLiteral("hybrid"); } else if (m_hasBattery && (m_hasKeyboard || m_hasMouse)) { m_recommendedDeviceClass = QStringLiteral("laptop"); m_recommendedExperienceProfile = QStringLiteral("desktop"); } else if (!m_hasBattery && !m_hasTouch) { m_recommendedDeviceClass = QStringLiteral("desktop"); m_recommendedExperienceProfile = QStringLiteral("desktop"); } else { m_recommendedDeviceClass = QStringLiteral("tablet"); m_recommendedExperienceProfile = QStringLiteral("mobile"); } } DeviceContext *DeviceContext::self() { static auto *instance = new DeviceContext(qApp); return instance; } DeviceContext *DeviceContext::create(QQmlEngine *qmlEngine, QJSEngine *jsEngine) { Q_UNUSED(qmlEngine) Q_UNUSED(jsEngine) return self(); } QString DeviceContext::runtimePlatform() const { return m_runtimePlatform; } QString DeviceContext::recommendedDeviceClass() const { return m_recommendedDeviceClass; } QString DeviceContext::recommendedExperienceProfile() const { return m_recommendedExperienceProfile; } bool DeviceContext::hasTouch() const { return m_hasTouch; } bool DeviceContext::hasKeyboard() const { return m_hasKeyboard; } bool DeviceContext::hasMouse() const { return m_hasMouse; } bool DeviceContext::hasBattery() const { return m_hasBattery; } int DeviceContext::displayCount() const { return m_displayCount; } bool DeviceContext::hasExternalDisplay() const { return m_displayCount > 1; } bool DeviceContext::primaryDisplayLandscape() const { return m_primaryDisplayLandscape; }