Loading...
Searching...
No Matches
System.cpp
/*
* Copyright (C) 2018 The UBports project
* Copyright (C) 2014-2016 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "System.h"
#include <QDBusPendingCall>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDBusMetaType>
#include <QDir>
#include <QFile>
#include <QLocale>
#include <QMap>
#include <QProcess>
#include <QDebug>
#include <QSettings>
#include <QStringBuilder>
#include <glib.h>
System::System()
: QObject()
{
// Register the argument needed for UpdateActivationEnvironment below
qDBusRegisterMetaType<QMap<QString,QString>>();
if(!wizardEnabled()) {
m_fsWatcher.addPath(wizardEnabledPath());
}
connect(&m_fsWatcher, &QFileSystemWatcher::fileChanged, this, &System::watcherFileChanged);
}
QString System::wizardEnabledPath()
{
return QDir::home().filePath(QStringLiteral(".config/lomiri/wizard-has-run"));
}
QString System::currentFrameworkPath()
{
QFileInfo f("/usr/share/click/frameworks/current");
return f.canonicalFilePath();
}
/*
wizardEnabled and isUpdate logic
if wizard-has-run does NOT exist == is new install
if wizard-has-run exists but does NOT match current framework == is update
if wizard-has-run exists but does match current framework == show no wizard
*/
bool System::wizardPathExists() {
return QFile::exists(wizardEnabledPath());
}
bool System::wizardEnabled() const
{
if (!wizardPathExists()) {
return true;
}
return isUpdate();
}
QString System::readCurrentFramework()
{
QFile f(currentFrameworkPath());
if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
QTextStream in(&f);
return in.readAll();
}
QString System::readWizardEnabled()
{
QFile f(wizardEnabledPath());
if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
QTextStream in(&f);
return in.readAll();
}
QString System::version() const
{
return readCurrentFramework();
}
bool System::isUpdate() const
{
if (!wizardPathExists()) {
return false;
}
return readCurrentFramework() != readWizardEnabled();
}
void System::setWizardEnabled(bool enabled)
{
if (wizardEnabled() == enabled && !isUpdate())
return;
if (enabled) {
QFile::remove(wizardEnabledPath());
} else {
QDir(wizardEnabledPath()).mkpath(QStringLiteral(".."));
if (QFile::exists(wizardEnabledPath())) {
QFile::remove(wizardEnabledPath());
}
// For special cases check if wizardEnabledPath is a folder
if (QDir(wizardEnabledPath()).exists()) {
QDir(wizardEnabledPath()).removeRecursively();
}
if (!QFile::copy(currentFrameworkPath(), wizardEnabledPath())) {
// Make en empty file if framework does not exist
QFile f(wizardEnabledPath());
f.open(QFile::WriteOnly);
}
m_fsWatcher.addPath(wizardEnabledPath());
Q_EMIT wizardEnabledChanged();
Q_EMIT isUpdateChanged();
}
}
void System::watcherFileChanged()
{
Q_EMIT wizardEnabledChanged();
Q_EMIT isUpdateChanged();
m_fsWatcher.removePath(wizardEnabledPath());
}
void System::setSessionVariable(const QString &variable, const QString &value)
{
// We need to update both systemd's and DBus's environment
QStringList vars = { variable % QChar('=') % value };
QDBusMessage systemdMsg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"),
QStringLiteral("/org/freedesktop/systemd1"),
QStringLiteral("org.freedesktop.systemd1.Manager"),
QStringLiteral("SetEnvironment"));
systemdMsg << QVariant::fromValue(vars);
QDBusConnection::sessionBus().asyncCall(systemdMsg);
QMap<QString,QString> valueMap;
valueMap.insert(variable, value);
QDBusMessage dbusMsg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"),
QStringLiteral("/org/freedesktop/DBus"),
QStringLiteral("org.freedesktop.DBus"),
QStringLiteral("UpdateActivationEnvironment"));
dbusMsg << QVariant::fromValue(valueMap);
QDBusConnection::sessionBus().asyncCall(dbusMsg);
}
void System::restartUnit(const QString &unitName)
{
QDBusMessage systemdMsg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"),
QStringLiteral("/org/freedesktop/systemd1"),
QStringLiteral("org.freedesktop.systemd1.Manager"),
QStringLiteral("TryRestartUnit"));
systemdMsg << QVariant::fromValue(unitName);
systemdMsg << QVariant::fromValue(QStringLiteral("replace"));
QDBusConnection::sessionBus().asyncCall(systemdMsg);
}
void System::updateSessionLocale(const QString &locale)
{
const QString language = locale.split(QStringLiteral("."))[0];
setSessionVariable(QStringLiteral("LANGUAGE"), language);
setSessionVariable(QStringLiteral("LANG"), locale);
setSessionVariable(QStringLiteral("LC_ALL"), locale);
// QLocale caches the default locale on startup, and Qt uses that cached
// copy when formatting dates. So manually update it here.
QLocale::setDefault(QLocale(locale));
// Restart bits of the session to pick up new language.
const QStringList units {
"lomiri-indicators.target",
"lomiri-location-service-trust-stored.service",
"pulseaudio-trust-stored.service",
"sync-monitor.service",
"maliit-server.service",
"ciborium.service",
};
for (const QString& unit : units) {
restartUnit(unit);
}
}
void System::skipUntilFinishedPage()
{
QSettings settings;
settings.setValue(QStringLiteral("Wizard/SkipUntilFinishedPage"), true);
settings.sync();
}
QString System::distroName() const
{
#ifdef LOMIRI_DISPLAYED_DISTRO_NAME
return QStringLiteral(LOMIRI_DISPLAYED_DISTRO_NAME);
#else
g_autofree gchar * name = g_get_os_info(G_OS_INFO_KEY_NAME);
if (name)
return QString::fromLocal8Bit(name);
return QStringLiteral("Lomiri");
#endif
}