aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina')
-rw-r--r--src-qt5/core/libLumina/DesktopSettings.cpp255
-rw-r--r--src-qt5/core/libLumina/DesktopSettings.h65
-rw-r--r--src-qt5/core/libLumina/DesktopSettings.pri7
-rw-r--r--src-qt5/core/libLumina/ExternalProcess.h3
4 files changed, 330 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
+}
diff --git a/src-qt5/core/libLumina/DesktopSettings.h b/src-qt5/core/libLumina/DesktopSettings.h
new file mode 100644
index 00000000..737fd6af
--- /dev/null
+++ b/src-qt5/core/libLumina/DesktopSettings.h
@@ -0,0 +1,65 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This is a simple class for managing all the various desktop
+// setting files, and sending out notifications about changes
+//===========================================
+// NOTE:
+// This class has a heirarchy-based lookup/write system
+// USER Settings > SYSTEM Settings > DEFAULT Settings
+// XDG_CONFIG_HOME/lumina-desktop > XDG_CONFIG_DIRS/lumina-desktop > XDG_DATA_DIRS/lumina-desktop
+//===========================================
+#ifndef _LUMINA_DESKTOP_SETTINGS_CLASS_H
+#define _LUMINA_DESKTOP_SETTINGS_CLASS_H
+
+#include <QSettings>
+#include <QFileSystemWatcher>
+#include <QString>
+#include <QStringList>
+#include <QHash>
+#include <QVariant>
+
+class DesktopSettings : public QObject{
+ Q_OBJECT
+public:
+ enum File{ System, Favorites, Environment, Session, Desktop, Keys, Theme };
+
+ DesktopSettings(QObject *parent = 0);
+ ~DesktopSettings();
+
+ //Start/stop routines
+ void start();
+ void stop();
+
+ //Main Read/Write functions
+ QVariant value(DesktopSettings::File, QString variable, QVariant defaultvalue);
+ bool setValue(DesktopSettings::File, QString variable, QVariant value);
+ QStringList keys(DesktopSettings::File); //return a list of all variables which are available in this file
+
+ //Information functions
+ QStringList filePaths(DesktopSettings::File); //just in case we need to access any of these files outside this class
+
+private:
+ enum RunMode{UserFull, SystemFull, SystemInterface };
+ DesktopSettings::RunMode runmode; //simple flag for which mode the current session is running in
+ QFileSystemWatcher *watcher;
+ QHash< DesktopSettings::File, QStringList > files; //location hash for where files are actually located on disk
+ QHash< QString, QSettings*> settings; //location hash for the settings files themselves
+
+ void parseSystemSettings(); //run at start - determine the RunMode for this user/session
+ void locateFiles(); //run at start - finds the locations of the various files (based on RunMode)
+ void touchFile(QString path); //used to create an empty file so it can be watched for changes later
+ QString rel_path(DesktopSettings::File); //return the relative file path (starting with "/")
+
+private slots:
+ void fileChanged(QString); //QFileSystemWatcher change detected
+ void dirChanged(QString); //QFileSystemWatcher change detected
+
+signals:
+ void FileModified(DesktopSettings::File);
+
+};
+#endif
diff --git a/src-qt5/core/libLumina/DesktopSettings.pri b/src-qt5/core/libLumina/DesktopSettings.pri
new file mode 100644
index 00000000..19290797
--- /dev/null
+++ b/src-qt5/core/libLumina/DesktopSettings.pri
@@ -0,0 +1,7 @@
+HEADERS *= $${PWD}/DesktopSettings.h
+SOURCES *= $${PWD}/DesktopSettings.cpp
+
+INCLUDEPATH *= ${PWD}
+
+#Now the other dependendies of it
+#include(LUtils.pri)
diff --git a/src-qt5/core/libLumina/ExternalProcess.h b/src-qt5/core/libLumina/ExternalProcess.h
index 2106f296..4cf91ccd 100644
--- a/src-qt5/core/libLumina/ExternalProcess.h
+++ b/src-qt5/core/libLumina/ExternalProcess.h
@@ -33,6 +33,9 @@ public:
connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished()) );
}
~ExternalProcess(){
+ if(this->state() == QProcess::Running){
+ this->detach(); //about to close down the QProcess - detach the other program so it can continue functioning normally.
+ }
}
static void launch(QString program, QStringList args = QStringList()){
bgstack15