1 #include <QDir>
2 #include <QLocale>
3 #include "lthemeengine.h"
4 
5 #ifndef LTHEMEENGINE_DATADIR
6 #define LTHEMEENGINE_DATADIR "/usr/local/share"
7 #endif
8 
9 #include <QDebug>
10 
readFile(QString filepath)11 QStringList lthemeengine::readFile(QString filepath){
12   QStringList out;
13   QFile file(filepath);
14   if(file.open(QIODevice::Text | QIODevice::ReadOnly)){
15     QTextStream in(&file);
16     while(!in.atEnd()){
17       out << in.readLine();
18     }
19     file.close();
20   }
21   return out;
22 }
23 
configPath()24 QString lthemeengine::configPath(){
25   return QDir::homePath() + "/.config/lthemeengine/";
26 }
27 
configFile()28 QString lthemeengine::configFile(){
29   return configPath() + "lthemeengine.conf";
30 }
31 
iconPaths()32 QStringList lthemeengine::iconPaths(){
33   QString xdgDataDirs = qgetenv("XDG_DATA_DIRS");
34   QString xdgDataHome = qgetenv("XDG_DATA_HOME");
35   QStringList paths;
36   paths << QDir::homePath() + "/.icons/";
37   if(xdgDataDirs.isEmpty()){
38     paths << "/usr/share/icons";
39     paths << "/usr/local/share/icons";
40     }
41   else{
42     foreach (QString p, xdgDataDirs.split(":")){ paths << QDir(p + "/icons/").absolutePath(); }
43     }
44   if(xdgDataHome.isEmpty()){ xdgDataHome = QDir::homePath() + "/.local/share"; }
45   paths << "/usr/share/pixmaps";
46   paths << xdgDataHome + "/icons";
47   paths.removeDuplicates();
48   //remove invalid
49   foreach (QString p, paths){
50     if(!QDir(p).exists()){ paths.removeAll(p); }
51     }
52   return paths;
53 }
54 
userStyleSheetPath()55 QString lthemeengine::userStyleSheetPath(){
56   return configPath() + "qss/";
57 }
58 
sharedStyleSheetPath()59 QStringList lthemeengine::sharedStyleSheetPath(){
60   QStringList dirs;
61   dirs << QString(getenv("XDG_CONFIG_HOME"));
62   dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":");
63   dirs << QString(getenv("XDG_DATA_DIRS")).split(":");
64   for(int i=0; i<dirs.length(); i++){
65       if (!dirs[i].endsWith("/")){ dirs[i].append("/"); }
66       dirs[i].append("lthemeengine/qss/");
67   }
68   if(dirs.isEmpty()){ dirs << LTHEMEENGINE_DATADIR"/lthemeengine/qss/"; } //no XDG settings - use the hardcoded path
69   return dirs;
70  }
71 
userDesktopStyleSheetPath()72 QString lthemeengine::userDesktopStyleSheetPath(){
73   return configPath() + "desktop_qss/";
74 }
75 
sharedDesktopStyleSheetPath()76 QStringList lthemeengine::sharedDesktopStyleSheetPath(){
77   QStringList dirs;
78   dirs << QString(getenv("XDG_CONFIG_HOME"));
79   dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":");
80   dirs << QString(getenv("XDG_DATA_DIRS")).split(":");
81   for(int i=0; i<dirs.length(); i++){
82       if (!dirs[i].endsWith("/")){ dirs[i].append("/"); }
83       dirs[i].append("lthemeengine/desktop_qss/");
84   }
85   if(dirs.isEmpty()){ dirs << LTHEMEENGINE_DATADIR"/lthemeengine/desktop_qss/"; } //no XDG settings - use the hardcoded path
86   return dirs;
87  }
88 
userColorSchemePath()89 QString lthemeengine::userColorSchemePath(){
90   return configPath() + "colors/";
91 }
92 
sharedColorSchemePath()93 QStringList lthemeengine::sharedColorSchemePath(){
94   QStringList dirs;
95   dirs << QString(getenv("XDG_CONFIG_HOME"));
96   dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":");
97   dirs << QString(getenv("XDG_DATA_DIRS")).split(":");
98   for(int i=0; i<dirs.length(); i++){
99       if (!dirs[i].endsWith("/")){ dirs[i].append("/"); }
100       dirs[i].append("lthemeengine/colors/");
101   }
102   if(dirs.isEmpty()){ dirs << LTHEMEENGINE_DATADIR"/lthemeengine/colors/"; } //no XDG settings - use the hardcoded path
103   qDebug() << "Got Color Dirs:" << dirs;
104   return dirs;
105 }
106 
systemLanguageID()107 QString lthemeengine::systemLanguageID(){
108 #ifdef Q_OS_UNIX
109   QByteArray v = qgetenv ("LC_ALL");
110   if (v.isEmpty()){ v = qgetenv ("LC_MESSAGES"); }
111   if (v.isEmpty()){ v = qgetenv ("LANG"); }
112   if (!v.isEmpty()){ return QLocale (v).name(); }
113 #endif
114   return  QLocale::system().name();
115 }
116 
availableSystemCursors()117 QStringList lthemeengine::availableSystemCursors(){	//returns: [name] for each item
118   //Find all the directories which could contain themes
119  QStringList paths;
120   paths << QDir::homePath()+"/.icons";
121   QStringList xdd = QString(getenv("XDG_DATA_HOME")).split(":");
122   xdd << QString(getenv("XDG_DATA_DIRS")).split(":");
123   for(int i=0; i<xdd.length(); i++){
124     if(QFile::exists(xdd[i]+"/icons")){
125       paths << xdd[i]+"/icons";
126     }
127   }
128   //Now get all the icon themes in these directories
129   QStringList themes, tmpthemes;
130   QDir dir;
131   for(int i=0; i<paths.length(); i++){
132     if(dir.cd(paths[i])){
133        tmpthemes = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
134        for(int j=0; j<tmpthemes.length(); j++){
135 	 if(tmpthemes[j].startsWith("default")){ continue; }
136          if( QFile::exists(dir.absoluteFilePath(tmpthemes[j]+"/cursors")) ){ themes << tmpthemes[j]; }
137        }
138     }
139   }
140   //Clean up the list and return
141   themes.removeDuplicates();
142   themes.sort();
143   return themes;
144 }
145 
146 //Return the currently-selected Cursor theme
currentCursor()147 QString lthemeengine::currentCursor(){
148   //qDebug() << "Reading Current Cursor Theme:";
149   QStringList info = readFile(QDir::homePath()+"/.icons/default/index.theme");
150   if(info.isEmpty()){ return ""; }
151   QString cursor;
152   bool insection = false;
153   for(int i=0; i<info.length(); i++){
154     if(info[i]=="[Icon Theme]"){ insection = true; continue;}
155     else if(insection && info[i].startsWith("Inherits=")){
156       cursor = info[i].section("=",1,1).simplified();
157       break;
158     }
159   }
160   //qDebug() << " - found theme:" << cursor;
161   return cursor;
162 }
163 
164 //Change the current Cursor Theme
setCursorTheme(QString cursorname)165 bool lthemeengine::setCursorTheme(QString cursorname){
166 //qDebug() << "Set Cursor Theme:" << cursorname;
167   if(cursorname=="default"){
168     //special case - this will cause a recursive inheritance loop - just remove the file instead
169     if(QFile::exists(QDir::homePath()+"/.icons/default/index.theme")){
170       return QFile::remove(QDir::homePath()+"/.icons/default/index.theme");
171     }
172     return true; //already does not exist
173   }
174   QStringList info = readFile(QDir::homePath()+"/.icons/default/index.theme");
175     bool insection = false;
176     bool changed = false;
177     QString newval = "Inherits="+cursorname;
178     for(int i=0; i<info.length() && !changed; i++){
179       if(info[i]=="[Icon Theme]"){
180 	insection = true;
181       }else if( info[i].startsWith("[") && insection){
182 	//Section does not have the setting - add it
183 	info.insert(i, newval);
184 	changed =true;
185       }else if( info[i].startsWith("[") ){
186 	insection = false;
187       }else if(insection && info[i].startsWith("Inherits=")){
188         info[i] = newval; //replace the current setting
189         changed = true;
190       }
191     } //end loop over file contents
192     if(!changed){ //Could not change the file contents for some reason
193       if(insection){ info << newval; } //end of file while in the section
194       else{ info << "[Icon Theme]" << newval; } //entire section missing from file
195     }
196     //Now save the file
197     QFile file(QDir::homePath()+"/.icons/default/index.theme");
198     bool ok = false;
199     if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){
200       QTextStream out(&file);
201       out << info.join("\n");
202       if(!info.last().isEmpty()){ out << "\n"; } //always end with a new line
203       file.close();
204       ok = true;
205     }
206     //qDebug() << "Done saving the cursor:" << info;
207     return ok;
208 }
209