aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/DesktopSettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina/DesktopSettings.cpp')
-rw-r--r--src-qt5/core/libLumina/DesktopSettings.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/src-qt5/core/libLumina/DesktopSettings.cpp b/src-qt5/core/libLumina/DesktopSettings.cpp
new file mode 100644
index 00000000..bfd149ca
--- /dev/null
+++ b/src-qt5/core/libLumina/DesktopSettings.cpp
@@ -0,0 +1,255 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "DesktopSettings.h"
+#include <QFile>
+#include <QDir>
+#include <QDebug>
+
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#define FILEPREFIX QString("/lumina-desktop/desktop/")
+
+// === PUBLIC ===
+DesktopSettings::DesktopSettings(QObject *parent) : QObject(parent){
+ watcher = 0;
+ runmode = DesktopSettings::UserFull;
+}
+
+DesktopSettings::~DesktopSettings(){
+ if(!files.isEmpty()){ stop(); }
+}
+
+//Start/stop routines
+void DesktopSettings::start(){
+ files.clear(); settings.clear(); //clear the internal hashes (just in case)
+ if(watcher==0){
+ watcher = new QFileSystemWatcher(this);
+ connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString)) );
+ connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString)) );
+ }
+ parseSystemSettings(); //set the runmode appropriately
+ locateFiles(); //
+
+}
+
+void DesktopSettings::stop(){
+ QStringList watch; watch << watcher->files() << watcher->directories();
+ if(!watch.isEmpty()){ watcher->removePaths(watch); }
+ files.clear(); //clear the internal hash
+ settings.clear();
+}
+
+//Main Read/Write functions
+QVariant DesktopSettings::value(DesktopSettings::File file, QString variable, QVariant defaultvalue){
+ if(!files.contains(file)){ return defaultvalue; }
+ for(int i=0; i<files[file].length(); i++){
+ if( settings.contains(files[file][i])){ //make sure this file is in the settings hash
+ if(settings[files[file][i]]->contains(variable)){ //if this file does not have the variable - go to the next one
+ return settings[files[file][i]]->value(variable, defaultvalue);
+ }
+ }
+ }
+ return defaultvalue; //none of the files contain the variable - return the default
+}
+
+bool DesktopSettings::setValue(DesktopSettings::File file, QString variable, QVariant value){
+ if(!files.contains(file)){ return false; }
+ for(int i=0; i<files[file].length(); i++){
+ if( settings.contains(files[file][i])){ //make sure this file is in the settings hash
+ if(settings[files[file][i]]->isWritable() ){ //Check write permissions
+ settings[files[file][i]]->setValue(variable, value);
+ settings[files[file][i]]->sync(); //make sure this is synced to disk ASAP
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+QStringList DesktopSettings::keys(DesktopSettings::File file){
+ if(!files.contains(file)){ return QStringList(); }
+ QStringList keyList;
+ for(int i=0; i<files[file].length(); i++){
+ if( settings.contains(files[file][i])){ //make sure this file is in the settings hash
+ keyList << settings[files[file][i]]->allKeys();
+ }
+ }
+ keyList.removeDuplicates();
+ return keyList;
+}
+
+//Information functions
+QStringList DesktopSettings::filePaths(DesktopSettings::File file){
+ if(!files.contains(file)){ return QStringList(); }
+ return files.value(file);
+}
+
+//=== PRIVATE ===
+void DesktopSettings::parseSystemSettings(){
+ //run at start - determine the RunMode for this user/session
+ //This will also load the DesktopSettings::System file into the hashes
+ runmode = DesktopSettings::UserFull; //default value unless otherwise specified
+ QStringList dirs;
+ dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":") << QString(getenv("XDG_DATA_DIRS")).split(":");
+ for(int i=0; i<dirs.length(); i++){
+ if(dirs[i].endsWith("/xdg")){ dirs[i] = dirs[i].section("/",0,-2); } //Chop off the xdg subdir - need the generic configuration directory
+ QString path = dirs[i]+rel_path(DesktopSettings::System);
+ if(!QFile::exists(path)){ continue; }
+ //Load the system file into the hashes
+ files.insert(DesktopSettings::System, QStringList() << path);
+ settings.insert(path, new QSettings(path, QSettings::IniFormat, this) );
+ //Read off the default mode for the system
+ QString defMode = settings[path]->value("default_mode","fulluser").toString().toLower();
+ if(defMode=="fullsystem"){ runmode= DesktopSettings::SystemFull; }
+ else if(defMode=="staticinterface"){ runmode = DesktopSettings::SystemInterface; }
+
+ //Now determine the runmode for this user
+ struct passwd *pw = getpwuid(getuid());
+ if(pw!=0){
+ QString cuser = QString(pw->pw_name);
+ free(pw); //done with this structure
+ if( settings[path]->value("fulluser_users", QStringList()).toStringList().contains(cuser) ){ runmode = DesktopSettings::UserFull; }
+ else if( settings[path]->value("fullsystem_users", QStringList()).toStringList().contains(cuser) ){ runmode = DesktopSettings::SystemFull; }
+ else if( settings[path]->value("staticinterface_users", QStringList()).toStringList().contains(cuser) ){ runmode = DesktopSettings::SystemInterface; }
+ else{
+ //No rule found for this specific user - check the group rules
+ //Read off the list of groups
+ gid_t grpList[100];
+ int grpSize = 100;
+ if( getgrouplist(cuser.toLocal8Bit(), getgid(), grpList, &grpSize) > 0 ){
+ QStringList groups;
+ for(int i=0; i<grpSize; i++){
+ struct group *g = getgrgid(grpList[i]);
+ if(g!=0){
+ groups << QString(g->gr_name);
+ free(g);
+ }
+ }
+ QStringList fromfile = settings[path]->value("fulluser_groups", QStringList()).toStringList();
+ fromfile.removeDuplicates();
+ if( (fromfile+groups).removeDuplicates() > 0 ){ runmode = DesktopSettings::UserFull; }
+ else{
+ fromfile = settings[path]->value("fullsystem_groups", QStringList()).toStringList();
+ fromfile.removeDuplicates();
+ if((fromfile+groups).removeDuplicates() > 0 ){ runmode = DesktopSettings::SystemFull; }
+ else{
+ fromfile = settings[path]->value("staticinterface_groups", QStringList()).toStringList();
+ fromfile.removeDuplicates();
+ if((fromfile+groups).removeDuplicates() > 0 ){ runmode = DesktopSettings::SystemInterface; }
+ }
+ }
+ } //end group list read
+ }
+ }else{
+ runmode = DesktopSettings::SystemFull; //could not read user name - assume system files only
+ }
+
+ break; //found this file - go ahead and stop now (no hierarchy for this special file)
+ }
+ //Now report the run mode that was detected
+ QString mode;
+ if(runmode == DesktopSettings::UserFull){ mode = "Full User"; }
+ else if(runmode == DesktopSettings::SystemFull){ mode = "Full System"; }
+ else if(runmode == DesktopSettings::SystemInterface){ mode = "System Interface"; }
+ qDebug() << "Detected Lumina Runtime Mode:" << mode;
+}
+
+void DesktopSettings::locateFiles(){
+ //run at start - finds the locations of the various files (based on RunMode)
+ QString userdir;
+ QStringList systemdirs;
+ userdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop";
+ systemdirs << QString(getenv("XDG_CONFIG_DIRS")).split(":") << QString(getenv("XDG_DATA_DIRS")).split(":");
+ //Load all the user-level files for this run mode
+ QList< DesktopSettings::File > tmp;
+ if(runmode == DesktopSettings::UserFull){ tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session << DesktopSettings::Desktop << DesktopSettings::Keys << DesktopSettings::Theme; }
+ else if(runmode == DesktopSettings::SystemInterface){ tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session << DesktopSettings::Desktop << DesktopSettings::Keys << DesktopSettings::Theme; }
+ for(int i=0; i<tmp.length(); i++){
+ QString path = userdir+rel_path(tmp[i]);
+ touchFile(path);
+ files.insert(tmp[i], QStringList() << path);
+ settings.insert(path, new QSettings(path, QSettings::IniFormat, this) );
+ watcher->addPath(path);
+ }
+ //Now load all the system-level files
+ tmp.clear();
+ tmp << DesktopSettings::Favorites << DesktopSettings::Environment << DesktopSettings::Session << DesktopSettings::Desktop << DesktopSettings::Keys << DesktopSettings::Theme;
+ for(int i=0; i<systemdirs.length(); i++){
+ if(systemdirs[i].endsWith("/xdg")){ systemdirs[i] = systemdirs[i].section("/",0,-2); }
+ if( !QFile::exists(systemdirs[i]+"/lumina-desktop") ){ continue; }
+ for(int j=0; j<tmp.length(); j++){
+ QString path = systemdirs[i]+rel_path(tmp[j]);
+ if(QFile::exists(path)){
+ files.insert(tmp[j], QStringList() << path);
+ settings.insert(path, new QSettings(path, QSettings::IniFormat, this) );
+ watcher->addPath(path);
+ }
+ }
+ }
+
+}
+
+void DesktopSettings::touchFile(QString path){
+ if(QFile::exists(path)){ return; } //already exists
+ //Make sure the parent directory exists
+ if(!QFile::exists(path.section("/",0,-2)) ){
+ QDir dir;
+ dir.mkpath(path.section("/",0,-2));
+ }
+ //Now create the empty file
+ QFile file(path);
+ if( file.open(QIODevice::ReadWrite) ){ //if it opens successfully, then it has created the file
+ file.close();
+ }
+}
+
+QString DesktopSettings::rel_path(DesktopSettings::File file){
+ QString name;
+ switch(file){
+ case DesktopSettings::System:
+ name="system"; break;
+ case DesktopSettings::Favorites:
+ name="favorites"; break;
+ case DesktopSettings::Environment:
+ name="environment"; break;
+ case DesktopSettings::Session:
+ name="session"; break;
+ case DesktopSettings::Desktop:
+ name="desktop"; break;
+ case DesktopSettings::Keys:
+ name="keys"; break;
+ case DesktopSettings::Theme:
+ name="theme"; break;
+ }
+ return FILEPREFIX+name+".conf";
+}
+
+//=== PRIVATE SLOTS ===
+void DesktopSettings::fileChanged(QString file){
+ //QFileSystemWatcher change detected
+ if(!watcher->files().contains(file)){
+ //Make sure this file stays watched for changes
+ touchFile(file);
+ watcher->addPath(file);
+ }
+ //Make sure the settings structure for this file is updated to match what is on disk
+ if(settings.contains(file)){ settings[file]->sync(); }
+ //Find which file type this is and send out the signal about it
+ QList< DesktopSettings::File > types = files.keys();
+ for(int i=0; i<types.length(); i++){
+ if(files[types[i]].contains(file)){
+ emit FileModified(types[i]);
+ break;
+ }
+ }
+}
+
+void DesktopSettings::dirChanged(QString){
+ //Not used yet - placeholder in case we need it later on
+}
bgstack15