mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-06-11 08:57:21 +00:00
Detect the device class, stage the selected experience, and write the resulting setup choices through SetupState. Load the new device and experience modules before the existing setup pages, and use the Shift icon on the finished page.
158 lines
4.6 KiB
C++
158 lines
4.6 KiB
C++
// SPDX-FileCopyrightText: 2026 Marco Allegretti
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
#include "devicecontext.h"
|
|
|
|
#include <KRuntimePlatform>
|
|
|
|
#include <QCoreApplication>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QFileInfo>
|
|
#include <QGuiApplication>
|
|
#include <QInputDevice>
|
|
#include <QJSEngine>
|
|
#include <QQmlEngine>
|
|
#include <QScreen>
|
|
|
|
#include <algorithm>
|
|
|
|
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<const QInputDevice *> 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<QScreen *> screens = QGuiApplication::screens();
|
|
m_displayCount = std::max(1, static_cast<int>(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;
|
|
}
|