[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings.spec
^
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -1,8 +1,8 @@
<services>
<service name="tar_git">
- <param name="url">https://github.com/sailfish-on-davinci/nemo-qml-plugin-systemsettings.git</param>
- <param name="branch">0.5.38-pro1</param>
- <param name="revision">0.5.38.davinci</param>
+ <param name="url">https://git.sailfishos.org/mer-core/nemo-qml-plugin-systemsettings</param>
+ <param name="branch">upgrade-3.4.0</param>
+ <param name="revision">HEAD</param>
<param name="debian">N</param>
<param name="dumb">N</param>
</service>
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/setlocale/main.cpp
^
|
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 Jolla Ltd.
+ * Copyright (C) 2020 Open Mobile Platform LLC.
* Contact: Pekka Vuorela <pekka.vuorela@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@@ -30,7 +31,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
+#include <QDir>
#include <QFile>
+#include <QFileInfo>
#include <QRegularExpression>
#include <QDebug>
@@ -38,9 +41,68 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sailfishaccesscontrol.h>
#include "../src/localeconfig.h"
+static bool ensureDirectory(QString filePath)
+{
+ auto directory = QFileInfo(filePath).dir();
+
+ if (directory.exists())
+ return true;
+
+ // Ensure parent with correct rights (recursion)
+ if (!ensureDirectory(directory.path()))
+ return false;
+
+ // Create this directory
+ if (!directory.mkpath(QStringLiteral(".")))
+ return false;
+
+ // Set correct access perms, root:root 755
+ auto pathArray = directory.path().toUtf8();
+ const char *path = pathArray.data();
+
+ if (chmod(path, S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
+ qWarning() << "Failed to set directory permissions" << directory.path() << ":" << strerror(errno);
+
+ if (chown(path, 0, 0) == -1)
+ qWarning() << "Failed to set directory as root:root" << directory.path() << ":" << strerror(errno);
+
+ return true;
+}
+
+static bool writeLocale(QString &configPath, QString &locale)
+{
+ QFile localeConfig(configPath);
+ if (!ensureDirectory(configPath)) {
+ qWarning() << "Unable to create directory for locale configuration file";
+ return false;
+ }
+
+ if (!localeConfig.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
+ qWarning() << "Unable to open locale configuration file for writing:" << configPath
+ << "-" << localeConfig.errorString();
+ return false;
+ }
+
+ localeConfig.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner |
+ QFileDevice::ReadGroup | QFileDevice::ReadOther);
+
+ if (fchown(localeConfig.handle(), 0, 0) == -1) {
+ qWarning() << "Failed to set localeconfig as root:root:" << configPath << ":" << strerror(errno);
+ }
+
+ if (!configPath.startsWith("/etc/"))
+ localeConfig.write("# Autogenerated by settings\n");
+
+ localeConfig.write(QString("LANG=%1\n").arg(locale).toLatin1());
+ localeConfig.close();
+ return true;
+}
+
int main(int argc, char *argv[])
{
if (argc != 2) {
@@ -48,6 +110,11 @@
return EXIT_FAILURE;
}
+ if (!sailfish_access_control_hasgroup(getuid(), "users")) {
+ qWarning() << "User with id" << getuid() << "is not member of users group";
+ return EXIT_FAILURE;
+ }
+
QString configPath = localeConfigPath();
if (configPath.isEmpty()) {
@@ -61,23 +128,19 @@
return EXIT_FAILURE;
}
- QFile localeConfig(configPath);
- if (!localeConfig.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
- qWarning() << "Unable to open locale configuration file for writing:" << configPath
- << "-" << localeConfig.errorString();
+ if (!writeLocale(configPath, newLocale))
return EXIT_FAILURE;
- }
- localeConfig.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner |
- QFileDevice::ReadGroup | QFileDevice::ReadOther);
-
- if (fchown(localeConfig.handle(), 0, 0)) {
- qWarning() << "Failed to set localeconfig as root:root" << strerror(errno);
+ // Set system locale as well if the user is device owner
+ if (sailfish_access_control_hasgroup(getuid(), "sailfish-system")) {
+ QString configPath = systemLocaleConfigPath();
+
+ if (configPath.isEmpty()) {
+ qWarning() << "No path for system locale";
+ } else if (!writeLocale(configPath, newLocale)) {
+ qWarning() << "Could not set system locale";
+ } // else success
}
- localeConfig.write("# Autogenerated by settings\n");
- localeConfig.write(QString("LANG=%1\n").arg(newLocale).toLatin1());
- localeConfig.close();
-
return EXIT_SUCCESS;
}
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/setlocale/setlocale.pro
^
|
@@ -5,6 +5,9 @@
QT = core
+CONFIG += link_pkgconfig
+PKGCONFIG += sailfishaccesscontrol
+
SOURCES += \
main.cpp \
../src/localeconfig.cpp
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/developermodesettings.cpp
^
|
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013 – 2019 Jolla Ltd.
- * Copyright (c) 2019 Open Mobile Platform LLC.
+ * Copyright (c) 2019 – 2020 Open Mobile Platform LLC.
* Contact: Thomas Perl <thomas.perl@jollamobile.com>
* Contact: Raine Makelainen <raine.makelainen@jolla.com>
*
@@ -41,9 +41,6 @@
#include <QNetworkInterface>
#include <transaction.h>
-#include <getdef.h>
-#include <pwd.h>
-
/* Symbolic constants */
#define PROGRESS_INDETERMINATE (-1)
@@ -71,6 +68,9 @@
#define USB_MODED_CONFIG_IP "ip"
#define USB_MODED_CONFIG_INTERFACE "interface"
+/* Package which will move debug folder to /home/.system/usr/lib */
+#define DEBUG_HOME_PACKAGE "jolla-developer-mode-home-debug-location"
+
static QMap<QString,QString> enumerate_network_interfaces()
{
QMap<QString,QString> result;
@@ -97,13 +97,24 @@
return dir.absoluteFilePath(preloaded.last());
}
+namespace {
+ bool debugHomeFolderExists()
+ {
+ QDir pathDir("/home/.system/usr/lib/debug");
+ if (pathDir.exists()) {
+ return true;
+ }
+ return false;
+ }
+}
+
DeveloperModeSettings::DeveloperModeSettings(QObject *parent)
: QObject(parent)
, m_usbModeDaemon(USB_MODED_SERVICE, USB_MODED_PATH, USB_MODED_INTERFACE, QDBusConnection::systemBus())
, m_wlanIpAddress("-")
, m_usbInterface(USB_NETWORK_FALLBACK_INTERFACE)
, m_usbIpAddress(USB_NETWORK_FALLBACK_IP)
- , m_username("nemo")
+ , m_username(qgetenv("USER"))
, m_developerModeEnabled(QFile::exists(DEVELOPER_MODE_PROVIDED_FILE))
, m_workStatus(Idle)
, m_workProgress(PROGRESS_INDETERMINATE)
@@ -112,15 +123,9 @@
, m_refreshedForInstall(false)
, m_localInstallFailed(false)
, m_localDeveloperModePackagePath(get_cached_package(QStringLiteral("*"))) // Initialized to possibly incompatible package
+ , m_debugHomeEnabled(debugHomeFolderExists())
+ , m_installationType(None)
{
- int uid = getdef_num("UID_MIN", -1);
- struct passwd *pwd;
- if ((pwd = getpwuid(uid)) != NULL) {
- m_username = QString(pwd->pw_name);
- } else {
- qCWarning(lcDeveloperModeLog) << "Failed to return username using getpwuid()";
- }
-
// Resolve and update local package path
if (!m_localDeveloperModePackagePath.isEmpty()) {
PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE"-preload", PackageKit::Transaction::FilterInstalled);
@@ -184,6 +189,35 @@
return m_localInstallFailed || m_localDeveloperModePackagePath.isEmpty();
}
+bool DeveloperModeSettings::debugHomeEnabled() const
+{
+ return m_debugHomeEnabled;
+}
+
+enum DeveloperModeSettings::InstallationType DeveloperModeSettings::installationType() const
+{
+ return m_installationType;
+}
+
+QString DeveloperModeSettings::packageName()
+{
+ if (m_installationType == DeveloperMode) {
+ return DEVELOPER_MODE_PACKAGE;
+ } else if (m_installationType == DebugHome) {
+ return DEBUG_HOME_PACKAGE;
+ } else {
+ return QString();
+ }
+}
+
+void DeveloperModeSettings::setInstallationType(InstallationType type)
+{
+ if (m_installationType != type) {
+ m_installationType = type;
+ emit installationTypeChanged();
+ }
+}
+
void DeveloperModeSettings::setDeveloperMode(bool enabled)
{
if (m_developerModeEnabled != enabled) {
@@ -193,6 +227,25 @@
}
m_refreshedForInstall = false;
+ setInstallationType(DeveloperMode);
+ if (enabled) {
+ resolveAndExecute(InstallCommand);
+ } else {
+ resolveAndExecute(RemoveCommand);
+ }
+ }
+}
+
+void DeveloperModeSettings::moveDebugToHome(bool enabled)
+{
+ if (m_debugHomeEnabled != enabled) {
+ if (m_workStatus != Idle) {
+ qCWarning(lcDeveloperModeLog) << "Debug home state change requested during activity, ignored.";
+ return;
+ }
+
+ m_refreshedForInstall = false;
+ setInstallationType(DebugHome);
if (enabled) {
resolveAndExecute(InstallCommand);
} else {
@@ -272,9 +325,9 @@
{
setWorkStatus(Preparing);
m_workProgress = 0;
- m_developerModePackageId.clear(); // might differ between installed/available
+ m_packageId.clear(); // might differ between installed/available
- if (command == InstallCommand && !m_localInstallFailed && !m_localDeveloperModePackagePath.isEmpty()) {
+ if (command == InstallCommand && !m_localInstallFailed && !m_localDeveloperModePackagePath.isEmpty() && m_installationType == DeveloperMode) {
// Resolve which version of developer mode package is expected
PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE"-preload", PackageKit::Transaction::FilterInstalled);
connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode);
@@ -314,71 +367,86 @@
});
} else {
- PackageKit::Transaction::Filters filters;
- if (command == RemoveCommand) {
- filters = PackageKit::Transaction::FilterInstalled;
- } else {
- filters = PackageKit::Transaction::FilterNewest;
- }
- PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE, filters);
+ // Install package form repos
+ installAndRemove(command);
+ }
+}
- connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode);
- connect(resolvePackage, &PackageKit::Transaction::package,
- this, [this](PackageKit::Transaction::Info info, const QString &packageId, const QString &summary) {
- qCDebug(lcDeveloperModeLog) << "Package transaction:" << info << packageId << "summary:" << summary;
- m_developerModePackageId = packageId;
- });
+bool DeveloperModeSettings::installAndRemove(Command command)
+{
+ if (packageName().isEmpty()) {
+ qCWarning(lcDeveloperModeLog) << "No installation package name set. Shouldn't happen.";
+ resetState();
+ return false;
+ }
- connect(resolvePackage, &PackageKit::Transaction::finished,
- this, [this, command](PackageKit::Transaction::Exit status, uint runtime) {
- Q_UNUSED(runtime)
+ PackageKit::Transaction::Filters filters;
+ if (command == RemoveCommand) {
+ filters = PackageKit::Transaction::FilterInstalled;
+ } else {
+ filters = PackageKit::Transaction::FilterNewest;
+ }
- if (status != PackageKit::Transaction::ExitSuccess || m_developerModePackageId.isEmpty()) {
- if (command == InstallCommand) {
- if (m_refreshedForInstall) {
- qCWarning(lcDeveloperModeLog) << "Failed to install developer mode, package didn't resolve.";
- resetState();
- } else {
- refreshPackageCacheAndInstall(); // try once if it helps
- }
- } else if (command == RemoveCommand) {
- qCWarning(lcDeveloperModeLog) << "Removing developer mode but package didn't resolve into anything. Shouldn't happen.";
- resetState();
- }
+ PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(packageName(), filters);
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/developermodesettings.h
^
|
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013 – 2019 Jolla Ltd.
- * Copyright (c) 2019 Open Mobile Platform LLC.
+ * Copyright (c) 2019 – 2020 Open Mobile Platform LLC.
* Contact: Thomas Perl <thomas.perl@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
@@ -49,6 +49,7 @@
{
Q_OBJECT
Q_ENUMS(Status)
+ Q_ENUMS(InstallationType)
Q_PROPERTY(QString wlanIpAddress READ wlanIpAddress NOTIFY wlanIpAddressChanged)
Q_PROPERTY(QString usbIpAddress READ usbIpAddress NOTIFY usbIpAddressChanged)
@@ -57,6 +58,8 @@
Q_PROPERTY(enum DeveloperModeSettings::Status workStatus READ workStatus NOTIFY workStatusChanged)
Q_PROPERTY(int workProgress READ workProgress NOTIFY workProgressChanged)
Q_PROPERTY(bool repositoryAccessRequired READ repositoryAccessRequired NOTIFY repositoryAccessRequiredChanged)
+ Q_PROPERTY(bool debugHomeEnabled READ debugHomeEnabled NOTIFY debugHomeEnabledChanged)
+ Q_PROPERTY(enum DeveloperModeSettings::InstallationType installationType READ installationType NOTIFY installationTypeChanged)
public:
explicit DeveloperModeSettings(QObject *parent = NULL);
@@ -68,6 +71,11 @@
DownloadingPackages,
InstallingPackages,
RemovingPackages
+ };
+ enum InstallationType {
+ None,
+ DeveloperMode,
+ DebugHome
};
QString wlanIpAddress() const;
@@ -77,10 +85,14 @@
enum DeveloperModeSettings::Status workStatus() const;
int workProgress() const;
bool repositoryAccessRequired() const;
+ bool debugHomeEnabled() const;
+ QString packageName();
+ enum DeveloperModeSettings::InstallationType installationType() const;
Q_INVOKABLE void setDeveloperMode(bool enabled);
Q_INVOKABLE void setUsbIpAddress(const QString &usbIpAddress);
Q_INVOKABLE void refresh();
+ Q_INVOKABLE void moveDebugToHome(bool enabled);
signals:
void wlanIpAddressChanged();
@@ -89,6 +101,8 @@
void workStatusChanged();
void workProgressChanged();
void repositoryAccessRequiredChanged();
+ void debugHomeEnabledChanged();
+ void installationTypeChanged();
private slots:
void reportTransactionErrorCode(PackageKit::Transaction::Error code, const QString &details);
@@ -104,7 +118,9 @@
void setWorkStatus(Status status);
void refreshPackageCacheAndInstall();
void resolveAndExecute(Command command);
+ bool installAndRemove(Command command);
void connectCommandSignals(PackageKit::Transaction *transaction);
+ void setInstallationType(InstallationType type);
QString usbModedGetConfig(const QString &key, const QString &fallback);
void usbModedSetConfig(const QString &key, const QString &value);
@@ -114,7 +130,7 @@
QString m_usbInterface;
QString m_usbIpAddress;
QString m_username;
- QString m_developerModePackageId;
+ QString m_packageId;
bool m_developerModeEnabled;
DeveloperModeSettings::Status m_workStatus;
int m_workProgress;
@@ -123,8 +139,11 @@
bool m_refreshedForInstall;
bool m_localInstallFailed;
QString m_localDeveloperModePackagePath;
+ bool m_debugHomeEnabled;
+ DeveloperModeSettings::InstallationType m_installationType;
};
Q_DECLARE_METATYPE(DeveloperModeSettings::Status)
+Q_DECLARE_METATYPE(DeveloperModeSettings::InstallationType)
#endif /* DEVELOPERMODESETTINGS_H */
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/languagemodel.cpp
^
|
@@ -204,7 +204,7 @@
QString localeCode = settings.value("LocaleCode").toString();
QString region = settings.value("Region").toString();
//% "Region: %1"
- QString regionLabel = settings.value("RegionLabel", qtTrId("settings_system-la-region")).toString();
+ QString regionLabel = settings.value("RegionLabel", qtTrId("systemsettings-la-region")).toString();
if (name.isEmpty() || localeCode.isEmpty()) {
continue;
}
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/localeconfig.cpp
^
|
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 Jolla Ltd.
+ * Copyright (C) 2020 Open Mobile Platform LLC.
* Contact: Pekka Vuorela <pekka.vuorela@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@@ -36,17 +37,15 @@
#include <unistd.h>
#include <sys/types.h>
-#include <pwd.h>
QString localeConfigPath()
{
- struct passwd *passwdInfo = getpwuid(getuid());
+ // User-wide locale config
+ return QString("/home/.system/var/lib/environment/%1/locale.conf").arg(getuid());
+}
- if (passwdInfo) {
- QString userName = passwdInfo->pw_name;
- return QString("/var/lib/environment/%1/locale.conf").arg(userName);
- } else {
- qWarning() << "Unable to get user info";
- return QString();
- }
+QString systemLocaleConfigPath()
+{
+ // System-wide locale config
+ return QString("/etc/locale.conf");
}
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/localeconfig.h
^
|
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 Jolla Ltd.
+ * Copyright (C) 2020 Open Mobile Platform LLC.
* Contact: Pekka Vuorela <pekka.vuorela@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@@ -36,5 +37,6 @@
#include <QString>
QString localeConfigPath();
+QString systemLocaleConfigPath();
#endif
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/locationsettings.cpp
^
|
@@ -209,7 +209,7 @@
"/net/connman/technology/gps",
"net.connman.Technology",
"PropertyChanged",
- this, SLOT(gpsTechPropertyChanged(QString,QVariant)));
+ this, SLOT(gpsTechPropertyChanged(QString, QDBusVariant)));
} else {
m_connMan = NetworkManagerFactory::createInstance();
connect(m_connMan, &NetworkManager::technologiesChanged,
@@ -359,7 +359,7 @@
writeSettings();
}
-void LocationSettingsPrivate::gpsTechPropertyChanged(const QString &propertyName, const QVariant &)
+void LocationSettingsPrivate::gpsTechPropertyChanged(const QString &propertyName, const QDBusVariant &)
{
if (propertyName == PoweredPropertyName) {
emit q->gpsFlightModeChanged();
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/locationsettings_p.h
^
|
@@ -82,7 +82,7 @@
private slots:
void readSettings();
void findGpsTech();
- void gpsTechPropertyChanged(const QString &propertyName, const QVariant &value);
+ void gpsTechPropertyChanged(const QString &propertyName, const QDBusVariant &value);
};
// TODO: replace this with DBus calls to a central settings service...
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/logging.cpp
^
|
@@ -34,3 +34,4 @@
Q_LOGGING_CATEGORY(lcVpnLog, "org.sailfishos.settings.vpn", QtWarningMsg)
Q_LOGGING_CATEGORY(lcDeveloperModeLog, "org.sailfishos.settings.developermode", QtWarningMsg)
Q_LOGGING_CATEGORY(lcMemoryCardLog, "org.sailfishos.settings.memorycard", QtWarningMsg)
+Q_LOGGING_CATEGORY(lcUsersLog, "org.sailfishos.settings.users", QtWarningMsg)
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/logging_p.h
^
|
@@ -37,5 +37,6 @@
Q_DECLARE_LOGGING_CATEGORY(lcVpnLog)
Q_DECLARE_LOGGING_CATEGORY(lcDeveloperModeLog)
Q_DECLARE_LOGGING_CATEGORY(lcMemoryCardLog)
+Q_DECLARE_LOGGING_CATEGORY(lcUsersLog)
#endif
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/partitionmanager.cpp
^
|
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2016 Jolla Ltd. <andrew.den.exter@jolla.com>
+ * Copyright (c) 2016 - 2020 Jolla Ltd. <andrew.den.exter@jolla.com>
+ * Copyright (c) 2019 - 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
@@ -37,10 +38,13 @@
#include <QFile>
#include <QRegularExpression>
+#include <algorithm>
#include <blkid/blkid.h>
#include <linux/limits.h>
#include <mntent.h>
#include <sys/statvfs.h>
+#include <sys/quota.h>
+#include <unistd.h>
static const auto userName = QString(qgetenv("USER"));
static const auto externalMountPath = QString("/run/media/%1/").arg(userName);
@@ -274,11 +278,17 @@
for (auto partition : partitions) {
if (partition->status == Partition::Mounted) {
+ qint64 quotaAvailable = std::numeric_limits<qint64>::max();
+ struct if_dqblk quota;
+ if (::quotactl(QCMD(Q_GETQUOTA, USRQUOTA), partition->devicePath.toUtf8().constData(), ::getuid(), (caddr_t)"a) == 0
+ && quota.dqb_bsoftlimit != 0)
+ quotaAvailable = std::max((qint64)dbtob(quota.dqb_bsoftlimit) - (qint64)quota.dqb_curspace, 0LL);
+
struct statvfs64 stat;
if (::statvfs64(partition->mountPath.toUtf8().constData(), &stat) == 0) {
partition->bytesTotal = stat.f_blocks * stat.f_frsize;
qint64 bytesFree = stat.f_bfree * stat.f_frsize;
- qint64 bytesAvailable = stat.f_bavail * stat.f_frsize;
+ qint64 bytesAvailable = std::min((qint64)(stat.f_bavail * stat.f_frsize), quotaAvailable);
partition->readOnly = (stat.f_flag & ST_RDONLY) != 0;
if (partition->bytesFree != bytesFree || partition->bytesAvailable != bytesAvailable) {
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/partitionmanager_p.h
^
|
@@ -43,7 +43,7 @@
class Monitor;
}
-static const auto externalDevice = QStringLiteral("mmcblk\\d+(?:p\\d+$)?|(sd[g-z]\\d*)|(dm[_-]\\d+(?:d\\d+)?)");
+static const auto externalDevice = QStringLiteral("mmcblk(?!0)\\d+(?:p\\d+$)?|(sd[a-z]\\d*)|(dm[_-]\\d+(?:d\\d+)?)");
class PartitionManagerPrivate : public QObject, public QSharedData
{
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/partitionmodel.cpp
^
|
@@ -175,6 +175,8 @@
args.insert(QLatin1String("label"), arguments.value(QLatin1String("label"), QString()).toString());
args.insert(QLatin1String("no-block"), true);
args.insert(QLatin1String("take-ownership"), true);
+ // set-group-permissions is a custom option patched into udisks2 (JB#50288)
+ args.insert(QLatin1String("set-group-permissions"), true);
args.insert(QLatin1String("update-partition-type"), true);
args.insert(QLatin1String("auto-mount"), arguments.value(QLatin1String("auto-mount"), false).toBool());
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/plugin/plugin.cpp
^
|
@@ -33,6 +33,7 @@
#include <QtQml>
#include <QQmlEngine>
#include <QQmlExtensionPlugin>
+#include <QTranslator>
#include <qusbmoded.h>
@@ -51,6 +52,24 @@
#include "locationsettings.h"
#include "deviceinfo.h"
#include "nfcsettings.h"
+#include "userinfo.h"
+#include "usermodel.h"
+
+class AppTranslator: public QTranslator
+{
+ Q_OBJECT
+public:
+ AppTranslator(QObject *parent)
+ : QTranslator(parent)
+ {
+ qApp->installTranslator(this);
+ }
+
+ virtual ~AppTranslator()
+ {
+ qApp->removeTranslator(this);
+ }
+};
template<class T>
static QObject *api_factory(QQmlEngine *, QJSEngine *)
@@ -66,8 +85,11 @@
public:
void initializeEngine(QQmlEngine *engine, const char *uri)
{
- Q_UNUSED(engine)
- Q_UNUSED(uri)
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("org.nemomobile.systemsettings"));
+ AppTranslator *engineeringEnglish = new AppTranslator(engine);
+ engineeringEnglish->load("qml_plugin_systemsettings_eng_en", "/usr/share/translations");
+ AppTranslator *translator = new AppTranslator(engine);
+ translator->load(QLocale(), "qml_plugin_systemsettings", "-", "/usr/share/translations");
}
void registerTypes(const char *uri)
@@ -91,6 +113,8 @@
qmlRegisterType<LocationSettings>(uri, 1, 0, "LocationSettings");
qmlRegisterType<DeviceInfo>(uri, 1, 0, "DeviceInfo");
qmlRegisterType<NfcSettings>(uri, 1, 0, "NfcSettings");
+ qmlRegisterType<UserInfo>(uri, 1, 0, "UserInfo");
+ qmlRegisterType<UserModel>(uri, 1, 0, "UserModel");
}
};
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/src.pro
^
|
@@ -6,8 +6,8 @@
QT -= gui
CONFIG += c++11 hide_symbols link_pkgconfig
-PKGCONFIG += profile mlite5 mce timed-qt5 libshadowutils blkid libcrypto nemomodels-qt5 libsailfishkeyprovider connman-qt5 glib-2.0
-PKGCONFIG += ssu-sysinfo nemodbus packagekitqt5
+PKGCONFIG += profile mlite5 mce timed-qt5 blkid libcrypto nemomodels-qt5 libsailfishkeyprovider connman-qt5 glib-2.0
+PKGCONFIG += ssu-sysinfo nemodbus packagekitqt5 libsystemd sailfishusermanager sailfishaccesscontrol
system(qdbusxml2cpp -p mceiface.h:mceiface.cpp mce.xml)
@@ -37,7 +37,9 @@
udisks2block.cpp \
udisks2blockdevices.cpp \
udisks2job.cpp \
- udisks2monitor.cpp
+ udisks2monitor.cpp \
+ userinfo.cpp \
+ usermodel.cpp
PUBLIC_HEADERS = \
languagemodel.h \
@@ -60,7 +62,9 @@
systemsettingsglobal.h \
deviceinfo.h \
locationsettings.h \
- timezoneinfo.h
+ timezoneinfo.h \
+ userinfo.h \
+ usermodel.h
HEADERS += \
$$PUBLIC_HEADERS \
@@ -76,7 +80,8 @@
partitionmanager_p.h \
udisks2blockdevices_p.h \
udisks2job_p.h \
- udisks2monitor_p.h
+ udisks2monitor_p.h \
+ userinfo_p.h
DEFINES += \
SYSTEMSETTINGS_BUILD_LIBRARY
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/udisks2blockdevices.cpp
^
|
@@ -321,11 +321,17 @@
bool willAccept = !unlocked && (block->isPartition() || block->isMountable() || block->isEncrypted() || block->isFormatting() || forceAccept);
qCInfo(lcMemoryCardLog) << "Completed block" << qPrintable(block->path())
- << "is" << (willAccept ? "accepted" : "rejected");
+ << "is" << (willAccept ? "accepted" : block->isPartition() ? "kept" : "rejected");
block->dumpInfo();
if (willAccept) {
+ // Hope that somebody will handle this signal and call insert()
+ // to add this block to m_blockDevices.
emit newBlock(block);
+ } else if (block->isPartition()) {
+ // Silently keep partitions around so that we can filter out
+ // partition tables in timerEvent().
+ insert(block->path(), block);
} else {
// This is garbage block device that should not be exposed
// from the partition model.
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/userinfo.cpp
^
|
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2020 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#include "userinfo.h"
+#include "userinfo_p.h"
+#include "logging_p.h"
+
+#include <QFile>
+#include <QFileSystemWatcher>
+#include <QSocketNotifier>
+#include <grp.h>
+#include <poll.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <systemd/sd-login.h>
+
+#include <sailfishusermanagerinterface.h>
+
+namespace {
+
+const auto UserDatabaseFile = QStringLiteral("/etc/passwd");
+const auto GroupDatabaseFile = QStringLiteral("/etc/group");
+
+enum SpecialIds : uid_t {
+ DeviceOwnerId = 100000,
+ UnknownCurrentUserId = (uid_t)(-2),
+ InvalidId = (uid_t)(-1),
+};
+
+QString nameFromGecos(const char *gecos)
+{
+ // typically GECOS has (sub)fields separated by ","
+ // and the first one of them is full name of the user.
+ // Sometimes it contains just the full name or it might be empty,
+ // thus do this on best effort basis.
+ auto name = QString::fromUtf8(gecos);
+ int i = name.indexOf(QStringLiteral(","));
+ if (i != -1)
+ name.truncate(i);
+ return name;
+}
+
+}
+
+UserInfoPrivate::UserInfoPrivate()
+ : m_uid(InvalidId)
+ , m_loggedIn(false)
+ , m_watcher(nullptr)
+ , m_alone(Unknown)
+{
+}
+
+UserInfoPrivate::UserInfoPrivate(struct passwd *pwd)
+ : m_uid(pwd->pw_uid)
+ , m_username(QString::fromUtf8(pwd->pw_name))
+ , m_name(nameFromGecos(pwd->pw_gecos))
+ // require_active == true -> only active user is logged in.
+ // Specifying seat should make sure that remote users are not
+ // counted as they don't have seats.
+ , m_loggedIn(sd_uid_is_on_seat(m_uid, 1, "seat0") > 0)
+ , m_watcher(nullptr)
+ , m_alone(Unknown)
+{
+}
+
+UserInfoPrivate::~UserInfoPrivate()
+{
+ delete m_watcher;
+}
+
+QWeakPointer<UserInfoPrivate> UserInfoPrivate::s_current;
+
+void UserInfoPrivate::set(struct passwd *pwd)
+{
+ QString username;
+ QString name;
+
+ if (pwd) {
+ Q_ASSERT(pwd->pw_uid == m_uid);
+ username = QString::fromUtf8(pwd->pw_name);
+ name = nameFromGecos(pwd->pw_gecos);
+ } else if (m_uid != InvalidId) {
+ m_uid = InvalidId;
+ emit uidChanged();
+ }
+
+ if (m_username != username) {
+ m_username = username;
+ emit usernameChanged();
+ // Username is used as displayName only if name is empty, avoid emitting changed twice
+ if (m_name.isEmpty() && name.isEmpty())
+ emit displayNameChanged();
+ }
+
+ if (m_name != name) {
+ m_name = name;
+ emit nameChanged();
+ emit displayNameChanged();
+ }
+}
+
+bool UserInfoPrivate::alone()
+{
+ if (m_alone == Unknown)
+ updateAlone(true);
+ return m_alone == Yes;
+}
+
+void UserInfoPrivate::updateAlone(bool force)
+{
+ if (!force && m_alone == Unknown) {
+ // Skip if the value is not needed and the check is not forced
+ return;
+ }
+
+ Tristated alone = Yes;
+
+ if (m_uid != InvalidId && m_uid != UnknownCurrentUserId && m_uid != DeviceOwnerId) {
+ // There must be at least one other user besides device owner
+ // if the uid is valid and known and it's not device owner
+ alone = No;
+ } else {
+ // Can not determine from uid, check users group
+ errno = 0;
+ struct group *grp = getgrnam("users");
+ if (!grp) {
+ qCWarning(lcUsersLog) << "Could not read users group:" << strerror(errno);
+ // Guessing that user is probably alone
+ } else {
+ for (int i = 0; grp->gr_mem[i] != nullptr; ++i) {
+ struct passwd *pwd = getpwnam(grp->gr_mem[i]);
+ if (pwd && pwd->pw_uid != DeviceOwnerId) {
+ // Found someone that's not device owner
+ alone = No;
+ break;
+ }
+ // pwd must not be free'd
+ }
+ // grp must not be free'd
+ }
+ }
+
+ if (m_alone != alone) {
+ m_alone = alone;
+ if (!force) {
+ // Emit only if something needed the value already, i.e. it was known
+ emit aloneChanged();
+ }
+ }
+}
+
+/**
+ * Construct UserInfo for the current user
+ *
+ * If it has been constructed before, this reuses the old data.
+ * If it can not determine the current user, then it constructs
+ * an object that doesn't point to any user until a user becomes
+ * active on seat0. That should happen very soon after user
+ * session has been started.
+ */
+UserInfo::UserInfo()
+{
+ d_ptr = UserInfoPrivate::s_current.toStrongRef();
+ if (d_ptr.isNull()) {
+ uid_t uid = InvalidId;
+ struct passwd *pwd;
+ if (sd_seat_get_active("seat0", NULL, &uid) >= 0 && uid != InvalidId) {
+ if ((pwd = getpwuid(uid))) {
+ d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate(pwd));
+ } else {
+ // User did not exist, should not happen
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/userinfo.h
^
|
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2020 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef USERINFO_H
+#define USERINFO_H
+
+#include <QObject>
+#include <QList>
+#include <QSharedPointer>
+
+#include "systemsettingsglobal.h"
+
+class UserInfoPrivate;
+class UserModel;
+
+class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(UserInfo)
+
+ Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
+ Q_PROPERTY(QString username READ username NOTIFY usernameChanged)
+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
+ Q_PROPERTY(UserType type READ type CONSTANT)
+ Q_PROPERTY(int uid READ uid WRITE setUid NOTIFY uidChanged)
+ Q_PROPERTY(bool current READ current NOTIFY currentChanged)
+ Q_PROPERTY(bool alone READ alone NOTIFY aloneChanged)
+ Q_PROPERTY(bool watched READ watched WRITE setWatched NOTIFY watchedChanged)
+
+ friend class UserModel;
+
+public:
+ enum UserType {
+ User = 0,
+ DeviceOwner = 1,
+ Guest = 2,
+ };
+ Q_ENUM(UserType)
+
+ UserInfo();
+ UserInfo(const UserInfo &other);
+ ~UserInfo();
+
+ static UserInfo placeholder();
+
+ bool isValid() const;
+
+ QString displayName() const;
+ QString username() const;
+ QString name() const;
+ UserType type() const;
+ int uid() const;
+ void setUid(int uid);
+ bool current() const;
+ bool alone();
+ bool watched();
+ void setWatched(bool watch);
+
+ Q_INVOKABLE void reset();
+
+ UserInfo &operator=(const UserInfo &other);
+ bool operator==(const UserInfo &other) const;
+ bool operator!=(const UserInfo &other) const;
+
+signals:
+ void displayNameChanged();
+ void usernameChanged();
+ void nameChanged();
+ void uidChanged();
+ void currentChanged();
+ void aloneChanged();
+ void watchedChanged();
+
+private:
+ explicit UserInfo(int uid);
+ explicit UserInfo(QString username);
+
+ void setUsername(QString username);
+ void setName(QString name);
+ bool updateCurrent();
+ void replace(QSharedPointer<UserInfoPrivate> other);
+
+ void connectSignals();
+ void watchForChanges();
+ void waitForActivation();
+
+ QSharedPointer<UserInfoPrivate> d_ptr;
+};
+#endif /* USERINFO_H */
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/userinfo_p.h
^
|
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef USERINFOPRIVATE_H
+#define USERINFOPRIVATE_H
+
+#include <sys/types.h>
+
+#include <QObject>
+#include <QString>
+#include <QWeakPointer>
+
+class QFileSystemWatcher;
+
+class UserInfoPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ UserInfoPrivate();
+ UserInfoPrivate(struct passwd *pwd);
+ ~UserInfoPrivate();
+
+ enum Tristated {
+ Yes = 1,
+ No = 0,
+ Unknown = -1
+ };
+
+ uid_t m_uid;
+ QString m_username;
+ QString m_name;
+ bool m_loggedIn;
+ static QWeakPointer<UserInfoPrivate> s_current;
+ QFileSystemWatcher *m_watcher;
+ Tristated m_alone;
+
+ void set(struct passwd *pwd);
+ bool alone();
+ void updateAlone(bool force = false);
+
+public slots:
+ void databaseChanged(const QString &path);
+
+signals:
+ void displayNameChanged();
+ void usernameChanged();
+ void nameChanged();
+ void uidChanged();
+ void currentChanged();
+ void watchedChanged();
+ void aloneChanged();
+};
+
+#endif /* USERINFOPRIVATE_H */
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/usermodel.cpp
^
|
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2020 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#include "usermodel.h"
+#include "logging_p.h"
+
+#include <QDBusConnection>
+#include <QDBusConnectionInterface>
+#include <QDBusInterface>
+#include <QDBusMetaType>
+#include <QDBusPendingCall>
+#include <QDBusPendingReply>
+#include <QDBusServiceWatcher>
+#include <QString>
+#include <functional>
+#include <grp.h>
+#include <pwd.h>
+#include <sailfishaccesscontrol.h>
+#include <sailfishusermanagerinterface.h>
+#include <sys/types.h>
+
+namespace {
+const auto UserManagerService = QStringLiteral(SAILFISH_USERMANAGER_DBUS_INTERFACE);
+const auto UserManagerPath = QStringLiteral(SAILFISH_USERMANAGER_DBUS_OBJECT_PATH);
+const auto UserManagerInterface = QStringLiteral(SAILFISH_USERMANAGER_DBUS_INTERFACE);
+
+const QHash<const QString, int> errorTypeMap = {
+ { QStringLiteral(SailfishUserManagerErrorBusy), UserModel::Busy },
+ { QStringLiteral(SailfishUserManagerErrorHomeCreateFailed), UserModel::HomeCreateFailed },
+ { QStringLiteral(SailfishUserManagerErrorHomeRemoveFailed), UserModel::HomeRemoveFailed },
+ { QStringLiteral(SailfishUserManagerErrorGroupCreateFailed), UserModel::GroupCreateFailed },
+ { QStringLiteral(SailfishUserManagerErrorUserAddFailed), UserModel::UserAddFailed },
+ { QStringLiteral(SailfishUserManagerErrorMaxUsersReached), UserModel::MaximumNumberOfUsersReached },
+ { QStringLiteral(SailfishUserManagerErrorUserModifyFailed), UserModel::UserModifyFailed },
+ { QStringLiteral(SailfishUserManagerErrorUserRemoveFailed), UserModel::UserRemoveFailed },
+ { QStringLiteral(SailfishUserManagerErrorGetUidFailed), UserModel::GetUidFailed },
+ { QStringLiteral(SailfishUserManagerErrorUserNotFound), UserModel::UserNotFound },
+ { QStringLiteral(SailfishUserManagerErrorAddToGroupFailed), UserModel::AddToGroupFailed },
+ { QStringLiteral(SailfishUserManagerErrorRemoveFromGroupFailed), UserModel::RemoveFromGroupFailed },
+};
+
+int getErrorType(QDBusError &error)
+{
+ if (error.type() != QDBusError::Other)
+ return error.type();
+
+ return errorTypeMap.value(error.name(), UserModel::OtherError);
+}
+}
+
+UserModel::UserModel(QObject *parent)
+ : QAbstractListModel(parent)
+ , m_dBusInterface(nullptr)
+ , m_dBusWatcher(new QDBusServiceWatcher(UserManagerService, QDBusConnection::systemBus(),
+ QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this))
+ , m_guestEnabled(getpwuid((uid_t)SAILFISH_USERMANAGER_GUEST_UID))
+{
+ connect(this, &UserModel::guestEnabledChanged,
+ this, &UserModel::maximumCountChanged);
+ qDBusRegisterMetaType<SailfishUserManagerEntry>();
+ connect(m_dBusWatcher, &QDBusServiceWatcher::serviceRegistered,
+ this, &UserModel::createInterface);
+ connect(m_dBusWatcher, &QDBusServiceWatcher::serviceUnregistered,
+ this, &UserModel::destroyInterface);
+ if (QDBusConnection::systemBus().interface()->isServiceRegistered(UserManagerService))
+ createInterface();
+ struct group *grp = getgrnam("users");
+ if (!grp) {
+ qCWarning(lcUsersLog) << "Could not read users group:" << strerror(errno);
+ } else {
+ for (int i = 0; grp->gr_mem[i] != nullptr; ++i) {
+ UserInfo user(QString(grp->gr_mem[i]));
+ if (user.isValid()) { // Skip invalid users here
+ m_users.append(user);
+ m_uidsToRows.insert(user.uid(), m_users.count()-1);
+ }
+ }
+ }
+ // grp must not be free'd
+}
+
+UserModel::~UserModel()
+{
+}
+
+bool UserModel::placeholder() const
+{
+ // Placeholder is always last and the only item that can be invalid
+ if (m_users.count() == 0)
+ return false;
+ return !m_users.last().isValid();
+}
+
+void UserModel::setPlaceholder(bool value)
+{
+ if (placeholder() == value)
+ return;
+
+ if (value) {
+ int row = m_users.count();
+ beginInsertRows(QModelIndex(), row, row);
+ m_users.append(UserInfo::placeholder());
+ endInsertRows();
+ } else {
+ int row = m_users.count()-1;
+ beginRemoveRows(QModelIndex(), row, row);
+ m_users.remove(row);
+ endRemoveRows();
+ }
+ emit placeholderChanged();
+}
+
+/*
+ * Number of existing users
+ *
+ * If placeholder = false, then this is the same as rowCount.
+ */
+int UserModel::count() const
+{
+ return (placeholder()) ? m_users.count()-1 : m_users.count();
+}
+
+/*
+ * Maximum number of users that can be created
+ *
+ * If more users are created after count reaches this,
+ * MaximumNumberOfUsersReached may be thrown and user creation fails.
+ */
+int UserModel::maximumCount() const
+{
+ return m_guestEnabled ? SAILFISH_USERMANAGER_MAX_USERS+1 : SAILFISH_USERMANAGER_MAX_USERS;
+}
+
+QHash<int, QByteArray> UserModel::roleNames() const
+{
+ static const QHash<int, QByteArray> roles = {
+ { Qt::DisplayRole, "displayName" },
+ { UsernameRole, "username" },
+ { NameRole, "name" },
+ { TypeRole, "type" },
+ { UidRole, "uid" },
+ { CurrentRole, "current" },
+ { PlaceholderRole, "placeholder" },
+ { TransitioningRole, "transitioning" },
+ };
+ return roles;
+}
+
+int UserModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return m_users.count();
+}
+
+QVariant UserModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= m_users.count() || index.column() != 0)
+ return QVariant();
+
+ const UserInfo &user = m_users.at(index.row());
+ switch (role) {
+ case Qt::DisplayRole:
+ return user.displayName();
+ case UsernameRole:
+ return user.username();
+ case NameRole:
+ return user.name();
+ case TypeRole:
+ return user.type();
+ case UidRole:
+ return user.uid();
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/src/usermodel.h
^
|
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2020 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef USERMODEL_H
+#define USERMODEL_H
+
+#include <QAbstractListModel>
+#include <QDBusError>
+#include <QHash>
+#include <QSet>
+#include <QVector>
+
+#include "systemsettingsglobal.h"
+#include "userinfo.h"
+
+class QDBusInterface;
+class QDBusPendingCallWatcher;
+class QDBusServiceWatcher;
+struct SailfishUserManagerEntry;
+
+class SYSTEMSETTINGS_EXPORT UserModel: public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(bool placeholder READ placeholder WRITE setPlaceholder NOTIFY placeholderChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(int maximumCount READ maximumCount NOTIFY maximumCountChanged)
+ Q_PROPERTY(bool guestEnabled READ guestEnabled WRITE setGuestEnabled NOTIFY guestEnabledChanged)
+
+public:
+ enum Roles {
+ UsernameRole = Qt::UserRole,
+ NameRole,
+ TypeRole,
+ UidRole,
+ CurrentRole,
+ PlaceholderRole,
+ TransitioningRole,
+ };
+ Q_ENUM(Roles)
+
+ enum UserType {
+ User = 0,
+ DeviceOwner = 1,
+ Guest = 2,
+ };
+ Q_ENUM(UserType)
+
+ enum ErrorType {
+ Failure = QDBusError::Failed,
+ OtherError = QDBusError::Other,
+ InvalidArgs = QDBusError::InvalidArgs,
+ Busy = 100,
+ HomeCreateFailed,
+ HomeRemoveFailed,
+ GroupCreateFailed,
+ UserAddFailed,
+ UserModifyFailed,
+ UserRemoveFailed,
+ GetUidFailed,
+ UserNotFound,
+ AddToGroupFailed,
+ RemoveFromGroupFailed,
+ MaximumNumberOfUsersReached,
+ };
+ Q_ENUM(ErrorType)
+
+ explicit UserModel(QObject *parent = 0);
+ ~UserModel();
+
+ bool placeholder() const;
+ void setPlaceholder(bool value);
+ int count() const;
+ int maximumCount() const;
+
+ QHash<int, QByteArray> roleNames() const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+
+ // Methods to modify users
+ Q_INVOKABLE void createUser();
+ Q_INVOKABLE void removeUser(int row);
+ Q_INVOKABLE void reset(int row);
+ Q_INVOKABLE void setCurrentUser(int row);
+ Q_INVOKABLE UserInfo * getCurrentUser() const;
+
+ // Methods to modify user's groups
+ Q_INVOKABLE bool hasGroup(int row, const QString &group) const;
+ Q_INVOKABLE void addGroups(int row, const QStringList &groups);
+ Q_INVOKABLE void removeGroups(int row, const QStringList &groups);
+
+ // Guest methods
+ bool guestEnabled() const;
+ Q_INVOKABLE void setGuestEnabled(bool enabled);
+
+signals:
+ void placeholderChanged();
+ void countChanged();
+ void maximumCountChanged();
+ void guestEnabledChanged();
+ void userGroupsChanged(int row);
+ void userAddFailed(int error);
+ void userModifyFailed(int row, int error);
+ void userRemoveFailed(int row, int error);
+ void setCurrentUserFailed(int row, int error);
+ void addGroupsFailed(int row, int error);
+ void removeGroupsFailed(int row, int error);
+ void setGuestEnabledFailed(bool enabling, int error);
+
+private slots:
+ void onUserAdded(const SailfishUserManagerEntry &entry);
+ void onUserModified(uint uid, const QString &newName);
+ void onUserRemoved(uint uid);
+ void onCurrentUserChanged(uint uid);
+ void onCurrentUserChangeFailed(uint uid);
+ void onGuestUserEnabled(bool enabled);
+
+ void userAddFinished(QDBusPendingCallWatcher *call);
+ void userModifyFinished(QDBusPendingCallWatcher *call, uint uid);
+ void userRemoveFinished(QDBusPendingCallWatcher *call, uint uid);
+ void setCurrentUserFinished(QDBusPendingCallWatcher *call, uint uid);
+ void addToGroupsFinished(QDBusPendingCallWatcher *call, uint uid);
+ void removeFromGroupsFinished(QDBusPendingCallWatcher *call, uint uid);
+ void enableGuestUserFinished(QDBusPendingCallWatcher *call, bool enabling);
+
+ void createInterface();
+ void destroyInterface();
+
+private:
+ void add(UserInfo &user);
+
+ QVector<UserInfo> m_users;
+ QHash<uint, int> m_uidsToRows;
+ QSet<uint> m_transitioning;
+ QDBusInterface *m_dBusInterface;
+ QDBusServiceWatcher *m_dBusWatcher;
+ bool m_guestEnabled;
+};
+#endif /* USERMODEL_H */
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/systemsettings.pro
^
|
@@ -6,4 +6,4 @@
OTHER_FILES += rpm/nemo-qml-plugin-systemsettings.spec
-SUBDIRS = src src_plugins setlocale tests
+SUBDIRS = src src_plugins setlocale tests translations
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/tests/tests.pro
^
|
@@ -10,7 +10,7 @@
TEMPLATE = app
TARGET = ut_diskusage
-target.path = /usr/lib/$${PACKAGENAME}-tests
+target.path = $$[QT_INSTALL_LIBS]/$${PACKAGENAME}-tests
xml.path = /usr/share/$${PACKAGENAME}-tests
xml.files = tests.xml
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.52.3.tar.bz2/translations/translations.pro
^
|
@@ -0,0 +1,34 @@
+TEMPLATE = aux
+
+TRANSLATION_CATALOG = qml_plugin_systemsettings
+
+# Translation Source
+TS_FILE = $$OUT_PWD/$${TRANSLATION_CATALOG}.ts
+
+ts.commands += lupdate $$PWD/.. -ts $$TS_FILE
+ts.CONFIG += no_check_exist no_link
+ts.output = $$TS_FILE
+ts.input = ..
+
+ts_install.files = $$TS_FILE
+ts_install.path = /usr/share/translations/source
+ts_install.CONFIG += no_check_exist
+
+# Engineering English Translation
+EE_QM = $$OUT_PWD/$${TRANSLATION_CATALOG}_eng_en.qm
+
+# XXX should add -markuntranslated "-" when proper translations are in place
+qm.commands += lrelease -idbased $$TS_FILE -qm $$EE_QM
+qm.CONFIG += no_check_exist no_link
+qm.depends = ts
+qm.input = $$TS_FILE
+qm.output = $$EE_QM
+
+qm_install.path = /usr/share/translations
+qm_install.files = $$EE_QM
+qm_install.CONFIG += no_check_exist
+
+QMAKE_EXTRA_TARGETS += ts qm
+PRE_TARGETDEPS += ts qm
+
+INSTALLS += ts_install qm_install
|