diff options
Diffstat (limited to 'src-qt5/core/libLumina')
42 files changed, 1829 insertions, 2514 deletions
diff --git a/src-qt5/core/libLumina/LuminaUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index 1ab3faac..978ce70b 100644 --- a/src-qt5/core/libLumina/LuminaUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -1,452 +1,40 @@ //=========================================== // Lumina-DE source code -// Copyright (c) 2013-2015, Ken Moore +// Copyright (c) 2012-2016, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== -#include "LuminaUtils.h" +#include "LDesktopUtils.h" -#include <QString> -#include <QFile> -#include <QStringList> -#include <QObject> -#include <QTextCodec> -#include <QDebug> #include <QDesktopWidget> -#include <QImageReader> -#include <QRegExp> -#include <QFuture> -#include <QtConcurrent> +#include <QApplication> +#include <QScreen> -#include <LuminaOS.h> -#include <LuminaThemes.h> -#include <LuminaXDG.h> +#include "LuminaThemes.h" static QStringList fav; -inline QStringList ProcessRun(QString cmd, QStringList args){ - //Assemble outputs - QStringList out; out << "1" << ""; //error code, string output - QProcess proc; - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("LANG", "C"); - env.insert("LC_MESSAGES", "C"); - proc.setProcessEnvironment(env); - proc.setProcessChannelMode(QProcess::MergedChannels); - if(args.isEmpty()){ - proc.start(cmd, QIODevice::ReadOnly); - }else{ - proc.start(cmd,args ,QIODevice::ReadOnly); - } - QString info; - while(!proc.waitForFinished(1000)){ - if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal - QString tmp = proc.readAllStandardOutput(); - if(tmp.isEmpty()){ proc.terminate(); } - else{ info.append(tmp); } - } - out[0] = QString::number(proc.exitCode()); - out[1] = info+QString(proc.readAllStandardOutput()); - return out; -} -//============= -// LUtils Functions -//============= -QString LUtils::LuminaDesktopVersion(){ - QString ver = "1.0.1"; +QString LDesktopUtils::LuminaDesktopVersion(){ + QString ver = "1.1.2"; #ifdef GIT_VERSION ver.append( QString(" (Git Revision: %1)").arg(GIT_VERSION) ); #endif return ver; } -QString LUtils::LuminaDesktopBuildDate(){ +QString LDesktopUtils::LuminaDesktopBuildDate(){ #ifdef BUILD_DATE return BUILD_DATE; #endif return ""; } -int LUtils::runCmd(QString cmd, QStringList args){ - /*QProcess proc; - proc.setProcessChannelMode(QProcess::MergedChannels); - if(args.isEmpty()){ - proc.start(cmd); - }else{ - proc.start(cmd, args); - } - //if(!proc.waitForStarted(30000)){ return 1; } //process never started - max wait of 30 seconds - while(!proc.waitForFinished(300)){ - if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal - QCoreApplication::processEvents(); - } - int ret = proc.exitCode(); - return ret;*/ - QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args); - return future.result()[0].toInt(); //turn it back into an integer return code - -} - -QStringList LUtils::getCmdOutput(QString cmd, QStringList args){ - /*QProcess proc; - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("LANG", "C"); - env.insert("LC_MESSAGES", "C"); - proc.setProcessEnvironment(env); - proc.setProcessChannelMode(QProcess::MergedChannels); - if(args.isEmpty()){ - proc.start(cmd); - }else{ - proc.start(cmd,args); - } - //if(!proc.waitForStarted(30000)){ return QStringList(); } //process never started - max wait of 30 seconds - while(!proc.waitForFinished(300)){ - if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal - QCoreApplication::processEvents(); - } - QStringList out = QString(proc.readAllStandardOutput()).split("\n"); - return out;*/ - QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args); - return future.result()[1].split("\n"); //Split the return message into lines -} - -QStringList LUtils::readFile(QString filepath){ - QStringList out; - QFile file(filepath); - if(file.open(QIODevice::Text | QIODevice::ReadOnly)){ - QTextStream in(&file); - while(!in.atEnd()){ - out << in.readLine(); - } - file.close(); - } - return out; -} - -bool LUtils::writeFile(QString filepath, QStringList contents, bool overwrite){ - QFile file(filepath); - if(file.exists() && !overwrite){ return false; } - bool ok = false; - if(contents.isEmpty()){ contents << "\n"; } - if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){ - QTextStream out(&file); - out << contents.join("\n"); - if(!contents.last().isEmpty()){ out << "\n"; } //always end with a new line - file.close(); - ok = true; - } - return ok; -} - -bool LUtils::isValidBinary(QString& bin){ - if(!bin.startsWith("/")){ - //Relative path: search for it on the current "PATH" settings - QStringList paths = QString(qgetenv("PATH")).split(":"); - for(int i=0; i<paths.length(); i++){ - if(QFile::exists(paths[i]+"/"+bin)){ bin = paths[i]+"/"+bin; break;} - } - } - //bin should be the full path by now - if(!bin.startsWith("/")){ return false; } - QFileInfo info(bin); - bool good = (info.exists() && info.isExecutable()); - if(good){ bin = info.absoluteFilePath(); } - return good; -} - -QString LUtils::GenerateOpenTerminalExec(QString term, QString dirpath){ - //Check the input terminal application (default/fallback - determined by calling application) - //if(!LUtils::isValidBinary(term)){ - if(term.endsWith(".desktop")){ - //Pull the binary name out of the shortcut - bool ok = false; - XDGDesktop DF = LXDG::loadDesktopFile(term,ok); - if(!ok){ term = "xterm"; } - else{ term= DF.exec.section(" ",0,0); } //only take the binary name - not any other flags - }else{ - term = "xterm"; //fallback - } - //} - //Now create the calling command for the designated terminal - // NOTE: While the "-e" routine is supposed to be universal, many terminals do not properly use it - // so add some special/known terminals here as necessary - QString exec; - qWarning() << " - Reached terminal initialization" << term; - if(term=="mate-terminal" || term=="lxterminal" || term=="gnome-terminal"){ - exec = term+" --working-directory=\""+dirpath+"\""; - }else if(term=="xfce4-terminal"){ - exec = term+" --default-working-directory=\""+dirpath+"\""; - }else if(term=="konsole" || term == "qterminal"){ - exec = term+" --workdir \""+dirpath+"\""; - }else{ - //-e is the parameter for most of the terminal appliction to execute an external command. - //In this case we start a shell in the selected directory - //Need the user's shell first - QString shell = QString(getenv("SHELL")); - if(!LUtils::isValidBinary(shell)){ shell = "/bin/sh"; } //universal fallback for a shell - exec = term + " -e \"cd " + dirpath + " && " + shell + " \" "; - } - qDebug() << exec; - return exec; -} - -QStringList LUtils::listSubDirectories(QString dir, bool recursive){ - //This is a recursive method for returning the full paths of all subdirectories (if recursive flag is enabled) - QDir maindir(dir); - QStringList out; - QStringList subs = maindir.entryList(QDir::NoDotAndDotDot | QDir::Dirs, QDir::Name); - for(int i=0; i<subs.length(); i++){ - out << maindir.absoluteFilePath(subs[i]); - if(recursive){ - out << LUtils::listSubDirectories(maindir.absoluteFilePath(subs[i]), recursive); - } - } - return out; -} - -QString LUtils::PathToAbsolute(QString path){ - //Convert an input path to an absolute path (this does not check existance ot anything) - if(path.startsWith("/")){ return path; } //already an absolute path - if(path.startsWith("~")){ path.replace(0,1,QDir::homePath()); } - if(!path.startsWith("/")){ - //Must be a relative path - if(path.startsWith("./")){ path = path.remove(2); } - path.prepend( QDir::currentPath()+"/"); - } - return path; -} -QString LUtils::AppToAbsolute(QString path){ - if(path.startsWith("~/")){ path = path.replace("~/", QDir::homePath()+"/" ); } - if(path.startsWith("/") || QFile::exists(path)){ return path; } - if(path.endsWith(".desktop")){ - //Look in the XDG dirs - QStringList dirs = LXDG::systemApplicationDirs(); - for(int i=0; i<dirs.length(); i++){ - if(QFile::exists(dirs[i]+"/"+path)){ return (dirs[i]+"/"+path); } - } - }else{ - //Look on $PATH for the binary - QStringList paths = QString(getenv("PATH")).split(":"); - for(int i=0; i<paths.length(); i++){ - if(QFile::exists(paths[i]+"/"+path)){ return (paths[i]+"/"+path); } - } - } - return path; -} - -QStringList LUtils::imageExtensions(bool wildcards){ - //Note that all the image extensions are lowercase!! - static QStringList imgExtensions; - if(imgExtensions.isEmpty()){ - QList<QByteArray> fmt = QImageReader::supportedImageFormats(); - for(int i=0; i<fmt.length(); i++){ - if(wildcards){ imgExtensions << "*."+QString::fromLocal8Bit(fmt[i]); } - else{ imgExtensions << QString::fromLocal8Bit(fmt[i]); } - } - } - return imgExtensions; -} - - QTranslator* LUtils::LoadTranslation(QApplication *app, QString appname, QString locale, QTranslator *cTrans){ - //Get the current localization - QString langEnc = "UTF-8"; //default value - QString langCode = locale; //provided locale - if(langCode.isEmpty()){ langCode = getenv("LC_ALL"); } - if(langCode.isEmpty()){ langCode = getenv("LANG"); } - if(langCode.isEmpty()){ langCode = "en_US.UTF-8"; } //default to US english - //See if the encoding is included and strip it out as necessary - if(langCode.contains(".")){ - langEnc = langCode.section(".",-1); - langCode = langCode.section(".",0,0); - } - //Now verify the encoding for the locale - if(langCode =="C" || langCode=="POSIX" || langCode.isEmpty()){ - langEnc = "System"; //use the Qt system encoding - } - if(app !=0){ - qDebug() << "Loading Locale:" << appname << langCode << langEnc; - //If an existing translator was provided, remove it first (will be replaced) - if(cTrans!=0){ app->removeTranslator(cTrans); } - //Setup the translator - cTrans = new QTranslator(); - //Use the shortened locale code if specific code does not have a corresponding file - if(!QFile::exists(LOS::LuminaShare()+"i18n/"+appname+"_" + langCode + ".qm") && langCode!="en_US" ){ - langCode.truncate( langCode.indexOf("_") ); - } - QString filename = appname+"_"+langCode+".qm"; - //qDebug() << "FileName:" << filename << "Dir:" << LOS::LuminaShare()+"i18n/"; - if( cTrans->load( filename, LOS::LuminaShare()+"i18n/" ) ){ - app->installTranslator( cTrans ); - }else{ - //Translator could not be loaded for some reason - cTrans = 0; - if(langCode!="en_US"){ - qWarning() << " - Could not load Locale:" << langCode; - } - } - }else{ - //Only going to set the encoding since no application given - qDebug() << "Loading System Encoding:" << langEnc; - } - //Load current encoding for this locale - QTextCodec::setCodecForLocale( QTextCodec::codecForName(langEnc.toUtf8()) ); - return cTrans; -} - -QStringList LUtils::knownLocales(){ - QDir i18n = QDir(LOS::LuminaShare()+"i18n"); - if( !i18n.exists() ){ return QStringList(); } - QStringList files = i18n.entryList(QStringList() << "lumina-desktop_*.qm", QDir::Files, QDir::Name); - if(files.isEmpty()){ return QStringList(); } - //Now strip off the filename and just leave the locale tag - for(int i=0; i<files.length(); i++){ - files[i].chop(3); //remove the ".qm" on the end - files[i] = files[i].section("_",1,50).simplified(); - } - files << "en_US"; //default locale - files.sort(); - return files; -} - -void LUtils::setLocaleEnv(QString lang, QString msg, QString time, QString num,QString money,QString collate, QString ctype){ - //Adjust the current locale environment variables - bool all = false; - if(msg.isEmpty() && time.isEmpty() && num.isEmpty() && money.isEmpty() && collate.isEmpty() && ctype.isEmpty() ){ - if(lang.isEmpty()){ return; } //nothing to do - no changes requested - all = true; //set everything to the "lang" value - } - //If no lang given, but others are given, then use the current setting - if(lang.isEmpty()){ lang = getenv("LC_ALL"); } - if(lang.isEmpty()){ lang = getenv("LANG"); } - if(lang.isEmpty()){ lang = "en_US"; } - //Now go through and set/unset the environment variables - // - LANG & LC_ALL - if(!lang.contains(".")){ lang.append(".UTF-8"); } - setenv("LANG",lang.toUtf8() ,1); //overwrite setting (this is always required as the fallback) - if(all){ setenv("LC_ALL",lang.toUtf8() ,1); } - else{ unsetenv("LC_ALL"); } //make sure the custom settings are used - // - LC_MESSAGES - if(msg.isEmpty()){ unsetenv("LC_MESSAGES"); } - else{ - if(!msg.contains(".")){ msg.append(".UTF-8"); } - setenv("LC_MESSAGES",msg.toUtf8(),1); - } - // - LC_TIME - if(time.isEmpty()){ unsetenv("LC_TIME"); } - else{ - if(!time.contains(".")){ time.append(".UTF-8"); } - setenv("LC_TIME",time.toUtf8(),1); - } - // - LC_NUMERIC - if(num.isEmpty()){ unsetenv("LC_NUMERIC"); } - else{ - if(!num.contains(".")){ num.append(".UTF-8"); } - setenv("LC_NUMERIC",num.toUtf8(),1); - } - // - LC_MONETARY - if(money.isEmpty()){ unsetenv("LC_MONETARY"); } - else{ - if(!money.contains(".")){ money.append(".UTF-8"); } - setenv("LC_MONETARY",money.toUtf8(),1); - } - // - LC_COLLATE - if(collate.isEmpty()){ unsetenv("LC_COLLATE"); } - else{ - if(!collate.contains(".")){ collate.append(".UTF-8"); } - setenv("LC_COLLATE",collate.toUtf8(),1); - } - // - LC_CTYPE - if(ctype.isEmpty()){ unsetenv("LC_CTYPE"); } - else{ - if(!ctype.contains(".")){ ctype.append(".UTF-8"); } - setenv("LC_CTYPE",ctype.toUtf8(),1); - } -} - -QString LUtils::currentLocale(){ - QString curr = getenv("LC_ALL");// = QLocale::system(); - if(curr.isEmpty()){ curr = getenv("LANG"); } - if(curr.isEmpty()){ curr = "en_US"; } - curr = curr.section(".",0,0); //remove any encodings off the end - return curr; -} - -double LUtils::DisplaySizeToBytes(QString num){ - //qDebug() << "Convert Num to Bytes:" << num; - num = num.toLower().simplified(); - num = num.remove(" "); - if(num.isEmpty()){ return 0.0; } - if(num.endsWith("b")){ num.chop(1); } //remove the "bytes" marker (if there is one) - QString lab = "b"; - if(!num[num.size()-1].isNumber()){ - lab = num.right(1); num.chop(1); - } - double N = num.toDouble(); - QStringList labs; labs <<"b"<<"k"<<"m"<<"g"<<"t"<<"p"; //go up to petabytes for now - for(int i=0; i<labs.length(); i++){ - if(lab==labs[i]){ break; }//already at the right units - break out - N = N*1024.0; //Move to the next unit of measurement - } - //qDebug() << " - Done:" << QString::number(N) << lab << num; - return N; -} - -QString LUtils::BytesToDisplaySize(qint64 ibytes){ - static QStringList labs = QStringList(); - if(labs.isEmpty()){ labs << "B" << "K" << "M" << "G" << "T" << "P"; } - //Now get the dominant unit - int c=0; - double bytes = ibytes; //need to keep decimel places for calculations - while(bytes>=1000 && c<labs.length() ){ - bytes = bytes/1024; - c++; - } //labs[c] is the unit - //Bytes are now - //Now format the number (up to 3 digits, not including decimel places) - QString num; - if(bytes>=100){ - //No decimel places - num = QString::number(qRound(bytes)); - }else if(bytes>=10){ - //need 1 decimel place - num = QString::number( (qRound(bytes*10)/10.0) ); - }else if(bytes>1){ - //need 2 decimel places - num = QString::number( (qRound(bytes*100)/100.0) ); - }else{ - //Fully decimel (3 places) - num = "0."+QString::number(qRound(bytes*1000)); - } - return (num+labs[c]); -} - -QString LUtils::SecondsToDisplay(int secs){ - if(secs < 0){ return "??"; } - QString rem; //remaining - if(secs > 3600){ - int hours = secs/3600; - rem.append( QString::number(hours)+"h "); - secs = secs - (hours*3600); - } - if(secs > 60){ - int min = secs/60; - rem.append( QString::number(min)+"m "); - secs = secs - (min*60); - } - if(secs > 0){ - rem.append( QString::number(secs)+"s"); - }else{ - rem.append( "0s" ); - } - return rem; -} - //Various function for finding valid QtQuick plugins on the system -bool LUtils::validQuickPlugin(QString ID){ - return ( !LUtils::findQuickPluginFile(ID).isEmpty() ); +bool LDesktopUtils::validQuickPlugin(QString ID){ + return ( !LDesktopUtils::findQuickPluginFile(ID).isEmpty() ); } -QString LUtils::findQuickPluginFile(QString ID){ +QString LDesktopUtils::findQuickPluginFile(QString ID){ if(ID.startsWith("quick-")){ ID = ID.section("-",1,50); } //just in case //Give preference to any user-supplied plugins (overwrites for system plugins) QString path = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/quickplugins/quick-"+ID+".qml"; @@ -456,7 +44,7 @@ QString LUtils::findQuickPluginFile(QString ID){ return ""; //could not be found } -QStringList LUtils::listQuickPlugins(){ +QStringList LDesktopUtils::listQuickPlugins(){ QDir dir(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/quickplugins"); QStringList files = dir.entryList(QStringList() << "quick-*.qml", QDir::Files | QDir::NoDotAndDotDot, QDir::Name); dir.cd(LOS::LuminaShare()+"quickplugins"); @@ -469,7 +57,7 @@ QStringList LUtils::listQuickPlugins(){ return files; } -QStringList LUtils::infoQuickPlugin(QString ID){ //Returns: [Name, Description, Icon] +QStringList LDesktopUtils::infoQuickPlugin(QString ID){ //Returns: [Name, Description, Icon] //qDebug() << "Find Quick Info:" << ID; QString path = findQuickPluginFile(ID); //qDebug() << " - path:" << path; @@ -490,7 +78,7 @@ QStringList LUtils::infoQuickPlugin(QString ID){ //Returns: [Name, Description, return info; } -QStringList LUtils::listFavorites(){ +QStringList LDesktopUtils::listFavorites(){ static QDateTime lastRead; QDateTime cur = QDateTime::currentDateTime(); if(lastRead.isNull() || lastRead<QFileInfo( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list").lastModified()){ @@ -503,22 +91,22 @@ QStringList LUtils::listFavorites(){ return fav; } -bool LUtils::saveFavorites(QStringList list){ +bool LDesktopUtils::saveFavorites(QStringList list){ list.removeDuplicates(); bool ok = LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list", list, true); if(ok){ fav = list; } //also save internally in case of rapid write/read of the file return ok; } -bool LUtils::isFavorite(QString path){ - QStringList fav = LUtils::listFavorites(); +bool LDesktopUtils::isFavorite(QString path){ + QStringList fav = LDesktopUtils::listFavorites(); for(int i=0; i<fav.length(); i++){ if(fav[i].endsWith("::::"+path)){ return true; } } return false; } -bool LUtils::addFavorite(QString path, QString name){ +bool LDesktopUtils::addFavorite(QString path, QString name){ //Generate the type of favorite this is QFileInfo info(path); QString type; @@ -528,30 +116,30 @@ bool LUtils::addFavorite(QString path, QString name){ //Assign a name if none given if(name.isEmpty()){ name = info.fileName(); } //Now add it to the list - QStringList favs = LUtils::listFavorites(); + QStringList favs = LDesktopUtils::listFavorites(); bool found = false; for(int i=0; i<favs.length(); i++){ if(favs[i].endsWith("::::"+path)){ favs[i] = name+"::::"+type+"::::"+path; } } if(!found){ favs << name+"::::"+type+"::::"+path; } - return LUtils::saveFavorites(favs); + return LDesktopUtils::saveFavorites(favs); } -void LUtils::removeFavorite(QString path){ - QStringList fav = LUtils::listFavorites(); +void LDesktopUtils::removeFavorite(QString path){ + QStringList fav = LDesktopUtils::listFavorites(); bool changed = false; for(int i=0; i<fav.length(); i++){ if(fav[i].endsWith("::::"+path)){ fav.removeAt(i); i--; changed=true;} } - if(changed){ LUtils::saveFavorites(fav); } + if(changed){ LDesktopUtils::saveFavorites(fav); } } -void LUtils::upgradeFavorites(int fromoldversionnumber){ +void LDesktopUtils::upgradeFavorites(int fromoldversionnumber){ /*if(fromoldversionnumber <= 8004){ // < pre-0.8.4>, sym-links in the ~/.lumina/favorites dir} //Include 0.8.4-devel versions in this upgrade (need to distinguish b/w devel and release versions later somehow) QDir favdir(QDir::homePath()+"/.lumina/favorites"); QFileInfoList symlinks = favdir.entryInfoList(QDir::Files | QDir::Dirs | QDir::System | QDir::NoDotAndDotDot); - QStringList favfile = LUtils::listFavorites(); //just in case some already exist + QStringList favfile = LDesktopUtils::listFavorites(); //just in case some already exist bool newentry = false; for(int i=0; i<symlinks.length(); i++){ if(!symlinks[i].isSymLink()){ continue; } //not a symlink @@ -568,13 +156,13 @@ void LUtils::upgradeFavorites(int fromoldversionnumber){ newentry = true; } if(newentry){ - LUtils::saveFavorites(favfile); + LDesktopUtils::saveFavorites(favfile); } }*/ //end check for version <= 0.8.4 } -void LUtils::LoadSystemDefaults(bool skipOS){ +void LDesktopUtils::LoadSystemDefaults(bool skipOS){ //Will create the Lumina configuration files based on the current system template (if any) qDebug() << "Loading System Defaults"; QStringList sysDefaults; @@ -603,7 +191,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){ QStringList tmp = sysDefaults.filter("session_"); if(tmp.isEmpty()){ tmp = sysDefaults.filter("session."); }//for backwards compat sesset << "[General]"; //everything is in this section - sesset << "DesktopVersion="+LUtils::LuminaDesktopVersion(); + sesset << "DesktopVersion="+LDesktopUtils::LuminaDesktopVersion(); for(int i=0; i<tmp.length(); i++){ if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; } QString var = tmp[i].section("=",0,0).toLower().simplified(); @@ -614,7 +202,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){ if(var.contains(".")){ var.replace(".","_"); } //Now parse the variable and put the value in the proper file - if(var.contains("_default_")){ val = AppToAbsolute(val); } //got an application/binary + if(var.contains("_default_")){ val = LUtils::AppToAbsolute(val); } //got an application/binary //Special handling for values which need to exist first if(var.endsWith("_ifexists") ){ var = var.remove("_ifexists"); //remove this flag from the variable @@ -668,7 +256,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){ //Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while if(var.contains(".")){ var.replace(".","_"); } //Now parse the variable and put the value in the proper file - val = AppToAbsolute(val); + val = LUtils::AppToAbsolute(val); //Special handling for values which need to exist first if(var.endsWith("_ifexists") ){ var = var.remove("_ifexists"); //remove this flag from the variable @@ -681,10 +269,11 @@ void LUtils::LoadSystemDefaults(bool skipOS){ } // -- DESKTOP SETTINGS -- + QString deskID = QApplication::primaryScreen()->name(); //(only works for the primary desktop at the moment) tmp = sysDefaults.filter("desktop_"); if(tmp.isEmpty()){ tmp = sysDefaults.filter("desktop."); }//for backwards compat - if(!tmp.isEmpty()){deskset << "[desktop-"+screen+"]"; } + if(!tmp.isEmpty()){deskset << "[desktop-"+deskID+"]"; } for(int i=0; i<tmp.length(); i++){ if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; } QString var = tmp[i].section("=",0,0).toLower().simplified(); @@ -707,7 +296,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){ for(int i=1; i<11; i++){ QString panvar = "panel"+QString::number(i); tmp = sysDefaults.filter(panvar); - if(!tmp.isEmpty()){deskset << "[panel"+screen+"."+QString::number(i-1)+"]"; } + if(!tmp.isEmpty()){deskset << "[panel_"+deskID+"."+QString::number(i-1)+"]"; } for(int i=0; i<tmp.length(); i++){ if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; } QString var = tmp[i].section("=",0,0).toLower().simplified(); @@ -764,10 +353,10 @@ void LUtils::LoadSystemDefaults(bool skipOS){ if(var.contains(".")){ var.replace(".","_"); } //Now parse the variable and put the value in the proper file qDebug() << "Favorite entry:" << var << val; - val = AppToAbsolute(val); //turn any relative files into absolute - if(var=="favorites_add_ifexists" && QFile::exists(val)){ qDebug() << " - Exists/Adding:"; LUtils::addFavorite(val); } - else if(var=="favorites_add"){ qDebug() << " - Adding:"; LUtils::addFavorite(val); } - else if(var=="favorites_remove"){ qDebug() << " - Removing:"; LUtils::removeFavorite(val); } + val = LUtils::AppToAbsolute(val); //turn any relative files into absolute + if(var=="favorites_add_ifexists" && QFile::exists(val)){ qDebug() << " - Exists/Adding:"; LDesktopUtils::addFavorite(val); } + else if(var=="favorites_add"){ qDebug() << " - Adding:"; LDesktopUtils::addFavorite(val); } + else if(var=="favorites_remove"){ qDebug() << " - Removing:"; LDesktopUtils::removeFavorite(val); } } // -- QUICKLAUNCH -- @@ -781,7 +370,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){ //Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while if(var.contains(".")){ var.replace(".","_"); } //Now parse the variable and put the value in the proper file - val = AppToAbsolute(val); //turn any relative files into absolute + val = LUtils::AppToAbsolute(val); //turn any relative files into absolute if(var=="quicklaunch_add_ifexists" && QFile::exists(val)){ quickL << val; } else if(var=="quicklaunch_add"){ quickL << val; } } @@ -874,12 +463,12 @@ void LUtils::LoadSystemDefaults(bool skipOS){ } -bool LUtils::checkUserFiles(QString lastversion){ +bool LDesktopUtils::checkUserFiles(QString lastversion){ //internal version conversion examples: // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] //returns true if something changed - int oldversion = LUtils::VersionStringToNumber(lastversion); - int nversion = LUtils::VersionStringToNumber(QApplication::applicationVersion()); + int oldversion = LDesktopUtils::VersionStringToNumber(lastversion); + int nversion = LDesktopUtils::VersionStringToNumber(QApplication::applicationVersion()); bool newversion = ( oldversion < nversion ); //increasing version number bool newrelease = ( lastversion.contains("-devel", Qt::CaseInsensitive) && QApplication::applicationVersion().contains("-release", Qt::CaseInsensitive) ); //Moving from devel to release @@ -890,56 +479,37 @@ bool LUtils::checkUserFiles(QString lastversion){ if(!QFile::exists(dset) || oldversion < 5000){ if( oldversion < 100000 && nversion>=100000 ){ system("rm -rf ~/.lumina"); qDebug() << "Current desktop settings obsolete: Re-implementing defaults"; } else{ firstrun = true; } - LUtils::LoadSystemDefaults(); + LDesktopUtils::LoadSystemDefaults(); } //Convert the favorites framework as necessary (change occured with 0.8.4) if(newversion || newrelease){ - LUtils::upgradeFavorites(oldversion); - } - //Convert any "userbutton" and "appmenu" panel plugins to the new "systemstart" plugin (0.8.7) - /*if(oldversion <= 8007 && (newversion || newrelease) && nversion < 8008){ - QSettings dset(QSettings::UserScope, "LuminaDE","desktopsettings"); - QStringList plugKeys = dset.allKeys().filter("panel").filter("/pluginlist"); - for(int i=0; i<plugKeys.length(); i++){ - QStringList plugs = dset.value(plugKeys[i],QStringList()).toStringList(); - //Do the appmenu/userbutton -> systemstart conversion - plugs = plugs.join(";;;;").replace("userbutton","systemstart").replace("appmenu","systemstart").split(";;;;"); - //Remove any system dashboard plugins - plugs.removeAll("systemdashboard"); - //Now save that back to the file - dset.setValue(plugKeys[i], plugs); - } - //Also remove any "desktopview" desktop plugin and enable the automatic desktop icons instead - plugKeys = dset.allKeys().filter("desktop-").filter("/pluginlist"); - for(int i=0; i<plugKeys.length(); i++){ - QStringList plugs = dset.value(plugKeys[i], QStringList()).toStringList(); - QStringList old = plugs.filter("desktopview"); - bool found = !old.isEmpty(); - for(int j=0; j<old.length(); j++){ plugs.removeAll(old[j]); } - if(found){ - dset.setValue(plugKeys[i],plugs); //save the modified plugin list - //Also set the auto-generate flag on this desktop - dset.setValue(plugKeys[i].section("/",0,0)+"/generateDesktopIcons", true); + LDesktopUtils::upgradeFavorites(oldversion); + } + //Convert from the old desktop numbering system to the new one (change occured with 1.0.1) + if(oldversion<=1000001){ + QStringList DS = LUtils::readFile(dset); + QList<QScreen*> screens = QApplication::screens(); + for(int i=0; i<DS.length(); i++){ + if(!DS[i].startsWith("[")){ continue; } + if(DS[i].startsWith("[desktop-")){ + bool ok = false; + int num = DS[i].section("desktop-",-1).section("]",0,0).toInt(&ok); + if(num>=0 && ok && num< screens.length()){ + //This one needs to be converted + DS[i] = "[desktop-"+screens[num]->name()+"]"; + } + }else if(DS[i].startsWith("[panel")){ + bool ok = false; + int num = DS[i].section("panel",-1).section(".",0,0).toInt(&ok); + if(num>=0 && ok && num< screens.length()){ + //This one needs to be converted + QString rest = DS[i].section(".",1,-1); //everything after the desktop number in the current setting + DS[i] = "[panel_"+screens[num]->name()+"."+rest; + } } } - dset.sync(); - //Due to the grid size change for desktop plugins, need to remove any old plugin geometries - if(QFile::exists(QDir::homePath()+"/.lumina/pluginsettings/desktopsettings.conf")){ - QFile::remove(QDir::homePath()+"/.lumina/pluginsettings/desktopsettings.conf"); - } - }*/ - - //Convert to the XDG autostart spec as necessary (Change occured with 0.8.5) - /*if(QFile::exists(QDir::homePath()+"/.lumina/startapps") ){ - QStringList cmds = LUtils::readFile(QDir::homePath()+"/.lumina/startapps"); - for(int i=0; i<cmds.length(); i++){ - cmds[i] = cmds[i].remove("lumina-open").simplified(); //remove the file opener - if(cmds[i].startsWith("#") || cmds[i].isEmpty()){ continue; } //invalid line - - LXDG::setAutoStarted(true, cmds[i]); - } - QFile::remove(QDir::homePath()+"/.lumina/startapps"); //delete the old file - }*/ + LUtils::writeFile(dset, DS, true); + } //Check the fluxbox configuration files dset = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/"; @@ -966,7 +536,7 @@ bool LUtils::checkUserFiles(QString lastversion){ return (firstrun || newversion || newrelease); } -int LUtils::VersionStringToNumber(QString version){ +int LDesktopUtils::VersionStringToNumber(QString version){ version = version.section("-",0,0); //trim any extra labels off the end int maj, mid, min; //major/middle/minor version numbers (<Major>.<Middle>.<Minor>) maj = mid = min = 0; @@ -979,102 +549,3 @@ int LUtils::VersionStringToNumber(QString version){ //NOTE: This format allows numbers to be anywhere from 0->999 without conflict return (maj*1000000 + mid*1000 + min); } - -// ======================= -// RESIZEMENU CLASS -// ======================= -ResizeMenu::ResizeMenu(QWidget *parent) : QMenu(parent){ - this->setContentsMargins(1,1,1,1); - this->setMouseTracking(true); - resizeSide = NONE; - cAct = new QWidgetAction(this); - contents = 0; - connect(this, SIGNAL(aboutToShow()), this, SLOT(clearFlags()) ); - connect(this, SIGNAL(aboutToHide()), this, SLOT(clearFlags()) ); - connect(cAct, SIGNAL(hovered()), this, SLOT(clearFlags()) ); -} - -ResizeMenu::~ResizeMenu(){ - -} - -void ResizeMenu::setContents(QWidget *con){ - this->clear(); - cAct->setDefaultWidget(con); - this->addAction(cAct); - contents = con; //save for later - contents->setCursor(Qt::ArrowCursor); -} - -void ResizeMenu::mouseMoveEvent(QMouseEvent *ev){ - QRect geom = this->geometry(); - //Note: The exact position does not matter as much as the size - // since the window will be moved again the next time it is shown - // The "-2" in the sizing below accounts for the menu margins - QPoint gpos = this->mapToGlobal(ev->pos()); - bool handled = false; - switch(resizeSide){ - case TOP: - if(gpos.y() >= geom.bottom()-1){ break; } - geom.setTop(gpos.y()); - this->setGeometry(geom); - if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} - handled = true; - break; - case BOTTOM: - if(gpos.y() <= geom.top()+1){ break; } - geom.setBottom( gpos.y()); - this->setGeometry(geom); - if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} - handled = true; - break; - case LEFT: - if(gpos.x() >= geom.right()-1){ break; } - geom.setLeft(gpos.x()); - this->setGeometry(geom); - if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} - handled = true; - break; - case RIGHT: - if(gpos.x() <= geom.left()+1){ break; } - geom.setRight(gpos.x()); - this->setGeometry(geom); - if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} - handled = true; - break; - default: //NONE - //qDebug() << " - Mouse At:" << ev->pos(); - //Just adjust the mouse cursor which is shown - if(ev->pos().x()<=1 && ev->pos().x() >= -1){ this->setCursor(Qt::SizeHorCursor); } - else if(ev->pos().x() >= this->width()-1 && ev->pos().x() <= this->width()+1){ this->setCursor(Qt::SizeHorCursor); } - else if(ev->pos().y()<=1 && ev->pos().y() >= -1){ this->setCursor(Qt::SizeVerCursor); } - else if(ev->pos().y() >= this->height()-1 && ev->pos().y() <= this->height()+1){ this->setCursor(Qt::SizeVerCursor); } - else{ this->setCursor(Qt::ArrowCursor); } - } - if(!handled){ QMenu::mouseMoveEvent(ev); } //do normal processing as well -} - -void ResizeMenu::mousePressEvent(QMouseEvent *ev){ - bool used = false; - if(ev->buttons().testFlag(Qt::LeftButton) && resizeSide==NONE){ - //qDebug() << "Mouse Press Event:" << ev->pos() << resizeSide; - if(ev->pos().x()<=1 && ev->pos().x() >= -1){resizeSide = LEFT; used = true;} - else if(ev->pos().x() >= this->width()-1 && ev->pos().x() <= this->width()+1){ resizeSide = RIGHT; used = true;} - else if(ev->pos().y()<=1 && ev->pos().y() >= -1){ resizeSide = TOP; used = true; } - else if(ev->pos().y() >= this->height()-1 && ev->pos().y() <= this->height()+1){ resizeSide = BOTTOM; used = true; } - } - if(used){ ev->accept(); this->grabMouse(); } - else{ QMenu::mousePressEvent(ev); } //do normal processing -} - -void ResizeMenu::mouseReleaseEvent(QMouseEvent *ev){ - this->releaseMouse(); - if(ev->button() == Qt::LeftButton && resizeSide!=NONE ){ - //qDebug() << "Mouse Release Event:" << ev->pos() << resizeSide; - resizeSide = NONE; - emit MenuResized(contents->size()); - ev->accept(); - }else{ - QMenu::mouseReleaseEvent(ev); //do normal processing - } -} diff --git a/src-qt5/core/libLumina/LDesktopUtils.h b/src-qt5/core/libLumina/LDesktopUtils.h new file mode 100644 index 00000000..dbad8757 --- /dev/null +++ b/src-qt5/core/libLumina/LDesktopUtils.h @@ -0,0 +1,49 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2012-2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_LIBRARY_DESKTOP_UTILS_H +#define _LUMINA_LIBRARY_DESKTOP_UTILS_H + +#include <QString> +#include <QStringList> +#include <QFile> +#include <QDir> +#include <QDateTime> + +//Other classes needed +#include <LUtils.h> +#include <LuminaXDG.h> +#include <LuminaOS.h> + +class LDesktopUtils{ +public: + //Get the current version/build of the Lumina desktop + static QString LuminaDesktopVersion(); + static QString LuminaDesktopBuildDate(); + + //Various function for finding valid QtQuick plugins on the system + static bool validQuickPlugin(QString ID); + static QString findQuickPluginFile(QString ID); + static QStringList listQuickPlugins(); //List of valid ID's + static QStringList infoQuickPlugin(QString ID); //Returns: [Name, Description, Icon] + + //Various functions for the favorites sub-system + // Formatting Note: "<name>::::[dir/app/<mimetype>]::::<path>" + // the <name> field might not be used for "app" flagged entries + static QStringList listFavorites(); + static bool saveFavorites(QStringList); + static bool isFavorite(QString path); + static bool addFavorite(QString path, QString name = ""); + static void removeFavorite(QString path); + static void upgradeFavorites(int fromoldversionnumber); + + //Load the default setup for the system + static void LoadSystemDefaults(bool skipOS = false); + static bool checkUserFiles(QString lastversion); //returns true if something changed + static int VersionStringToNumber(QString version); //convert the lumina version string to a number for comparisons +}; + +#endif diff --git a/src-qt5/core/libLumina/LDesktopUtils.pri b/src-qt5/core/libLumina/LDesktopUtils.pri new file mode 100644 index 00000000..80bbcfa8 --- /dev/null +++ b/src-qt5/core/libLumina/LDesktopUtils.pri @@ -0,0 +1,7 @@ +SOURCES *= $${PWD}/LDesktopUtils.cpp +HEADERS *= $${PWD}/LDesktopUtils.h + +INCLUDEPATH *= ${PWD} + +#Now the other dependendies of it +include(LUtils.pri) diff --git a/src-qt5/core/libLumina/LInputDevice.cpp b/src-qt5/core/libLumina/LInputDevice.cpp new file mode 100644 index 00000000..a04dd607 --- /dev/null +++ b/src-qt5/core/libLumina/LInputDevice.cpp @@ -0,0 +1,275 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "LInputDevice.h" + +//Qt Library includes +#include <QString> +#include <QX11Info> +#include <QDebug> + +//XCB Library includes +#include <xcb/xcb.h> +#include <xcb/xcb_atom.h> +#include <xcb/xinput.h> +#include <xcb/xproto.h> + +#include <LUtils.h> + +//=================== +// LInputDevice Class +//=================== +// === PUBLIC === +LInputDevice::LInputDevice(unsigned int id, unsigned int type){ + devID = id; + devType = type; + //ATOM_FLOAT = 0; //init this when needed later + //devName = name; + getProperties(); //need to populate the name/atom correlations for properties + readProperties(); //populate the hash with the current values of the properties +} + +LInputDevice::~LInputDevice(){ + +} + +unsigned int LInputDevice::devNumber(){ + return devID; +} + +bool LInputDevice::isPointer(){ + return (devType==XCB_INPUT_DEVICE_USE_IS_X_POINTER \ + || devType==XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_POINTER); +} + +bool LInputDevice::isKeyboard(){ + return (devType==XCB_INPUT_DEVICE_USE_IS_X_KEYBOARD \ + || devType==XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_KEYBOARD); +} + +bool LInputDevice::isExtension(){ + return (devType==XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_DEVICE \ + || devType==XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_KEYBOARD \ + || devType==XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_POINTER); +} + +// Property Management +QList<int> LInputDevice::listProperties(){ + return devProps.keys(); +} + +QString LInputDevice::propertyName(int prop){ + if(devProps.contains(prop)){ return devProps[prop].name; } + else{ return ""; } +} + +QVariant LInputDevice::getPropertyValue(int prop){ + if(devProps.contains(prop)){ return devProps[prop].value; } + else{ return QVariant(); } +} + +bool LInputDevice::setPropertyValue(int prop, QVariant value){ + if(!devProps.contains(prop)){ return false; } + //Need the float atom for some properties - make sure we have that first + /*if(ATOM_FLOAT==0){ + xcb_intern_atom_reply_t *ar = xcb_intern_atom_reply(QX11Info::connection(), \ + xcb_intern_atom(QX11Info::connection(), 0, 1, "FLOAT"), NULL); + if(ar!=0){ + ATOM_FLOAT = ar->atom; + free(ar); + } + }*/ + //Now setup the argument + bool ok = false; + QStringList args; + args << "--set-prop"; + args << QString::number(devID); + args << QString::number(prop); //prop ID + args << variantToString(value); + ok = (0 == LUtils::runCmd("xinput", args) ); + if(ok){ + //Need to update the value in the hash as well + propData dat = devProps[prop]; + dat.value = value; + devProps.insert(prop, dat); + } + return ok; +} + +// === PRIVATE === +void LInputDevice::getProperties(){ + devProps.clear(); + xcb_input_list_device_properties_cookie_t cookie = xcb_input_list_device_properties_unchecked(QX11Info::connection(), devID); + xcb_input_list_device_properties_reply_t *reply = xcb_input_list_device_properties_reply(QX11Info::connection(), cookie, NULL); + //Get the atoms + xcb_atom_t *atoms = xcb_input_list_device_properties_atoms(reply); + //qDebug() << "Property Response Type:" << reply->response_type; //Always seems to be "1" + QList<xcb_get_atom_name_cookie_t> cookies; + for(int i=0; i<reply->num_atoms; i++){ cookies << xcb_get_atom_name(QX11Info::connection(), atoms[i]); } + for(int i=0; i<reply->num_atoms; i++){ + xcb_get_atom_name_reply_t *nr = xcb_get_atom_name_reply(QX11Info::connection(), cookies[i], NULL); + propData DATA; + DATA.name = QString::fromUtf8( xcb_get_atom_name_name(nr), xcb_get_atom_name_name_length(nr) ); + DATA.atom = atoms[i]; + DATA.id = (int)(atoms[i]); + devProps.insert(DATA.id,DATA); + ::free(nr); + } + //Done with data structure + ::free(reply); +} + +void LInputDevice::readProperties(){ + QList<int> props = devProps.keys(); + //XINPUT UTILITY USAGE (alternative to XCB which actually works right now) + QStringList info = LUtils::getCmdOutput("xinput list-props "+QString::number(devID)); + for(int i=0; i<props.length(); i++){ + propData PROP = devProps[props[i]]; + QStringList filter = info.filter(" ("+QString::number(PROP.id)+"):"); + if(filter.length()==1){ + QString val = filter.first().section("):",1,-1).simplified(); + //Now figure out what type of value this is and save it into the QVariant + QVariant variant; + if(val.split(", ").length()>1){ + //some kind of array + QList<QVariant> list; + QStringList valList = val.split(", "); + for(int j=0; j<valList.length(); j++){ list << valueToVariant(valList[j]); } + variant = QVariant(list); + }else{ + variant = valueToVariant(val); + } + PROP.value = variant; + } + devProps.insert(props[i], PROP); + } + +//XCB Code (non-functional - issue with library itself? 12/6/16 - Ken Moore) + /*QVariant result; + if(!devProps.contains(prop)){qDebug() << "Invalid Property"; return result; } + //Now generate the property request + xcb_input_get_device_property_cookie_t cookie = xcb_input_get_device_property_unchecked( QX11Info::connection(), devProps.value(prop).atom, \ + XCB_ATOM_ATOM, 0, 1000, devID, 0); + xcb_input_get_device_property_reply_t *reply = xcb_input_get_device_property_reply(QX11Info::connection(), cookie, NULL); + if(reply==0){ qDebug() << "Could not get reply!"; return result; } + //Now read off the value of the property + if(ATOM_FLOAT==0){ + xcb_intern_atom_reply_t *ar = xcb_intern_atom_reply(QX11Info::connection(), \ + xcb_intern_atom(QX11Info::connection(), 0, 1, "FLOAT"), NULL); + if(ar!=0){ + ATOM_FLOAT = ar->atom; + free(ar); + } + } + //Turn the reply into the proper items array (depends on format of the return data) + xcb_input_get_device_property_items_t items; + qDebug() <<QByteArray::fromRawData( (char*)(xcb_input_get_device_property_items(reply) ) , reply->num_items); + void *buffer = xcb_input_get_device_property_items(reply); + xcb_input_get_device_property_items_serialize( &buffer, reply->num_items, reply->format, &items); + + //if(reply->num_items > 0){ + //qDebug() << "Format:" << reply->format << "Length:" << length; + //qDebug() << "Response Type:" << reply->response_type << "Pads:" << reply->pad0 << reply->pad1; + switch(reply->type){ + case XCB_ATOM_INTEGER: + //qDebug() << "Got Integer"; + + break; + case XCB_ATOM_CARDINAL: + //qDebug() << "Got Cardinal"; + + break; + case XCB_ATOM_STRING: + qDebug() << "Got String:"; + if(reply->format==8){ + result.setValue( QByteArray::fromRawData( (char*) xcb_input_get_device_property_items_data_8(&items), sizeof(xcb_input_get_device_property_items_data_8(&items))/sizeof(char)) ); + } + break; + case XCB_ATOM_ATOM: + //qDebug() << "Got Atom"; + + break; + default: + qDebug() << "Other Type:" << reply->type; + } + //} + free(reply); //done with this structure + return result;*/ +} + +QVariant LInputDevice::valueToVariant(QString value){ + //Read through the string and see what type of value it is + if(value.count("\"")==2){ + //String value or atom + if(value.endsWith(")")){ + //ATOM (name string +(atomID)) + return QVariant(value); //don't strip off the atom number -- keep that within the parenthesis + }else{ + //String + value = value.section("\"",1,-2); //everything between the quotes + return QVariant(value); + } + }else if(value.contains(".")){ + //float/double number + return QVariant( value.toDouble() ); + }else{ + //integer or boolian (no way to tell right now - assume all int) + bool ok = false; + int intval = value.toInt(&ok); + if(ok){ return QVariant(intval); } + } + return QVariant(); +} + +QString LInputDevice::variantToString(QVariant value){ + if( value.canConvert< QList<QVariant> >() ){ + //List of variants + QStringList out; + QList<QVariant> list = value.toList(); + for(int i=0; i<list.length(); i++){ out << variantToString(list[i]); } + return out.join(", "); + }else{ + //Single value + if(value.canConvert<double>() ){ + return QString::number(value.toDouble()); + }else if(value.canConvert<int>() ){ + return QString::number(value.toInt()); + }else if( value.canConvert<QString>() ){ + //See if this is an atom first + QString val = value.toString(); + if(val.contains("(")){ val = val.section("(",1,-1).section(")",0,0); } + return val; + } + } + return ""; //nothing to return +} + +//====================== +// LInput Static Functions +//====================== +QList<LInputDevice*> LInput::listDevices(){ + QList<LInputDevice*> devices; + xcb_input_list_input_devices_cookie_t cookie = xcb_input_list_input_devices_unchecked(QX11Info::connection()); + xcb_input_list_input_devices_reply_t *reply = xcb_input_list_input_devices_reply(QX11Info::connection(), cookie, NULL); + if(reply==0){ return devices; } //error - nothing returned + //Use the iterator for going through the reply + //qDebug() << "Create iterator"; + xcb_input_device_info_iterator_t iter = xcb_input_list_input_devices_devices_iterator(reply); + //xcb_str_iterator_t nameiter = xcb_input_list_input_devices_names_iterator(reply); + + //Now step through the reply + while(iter.data != 0 ){ + devices << new LInputDevice(iter.data->device_id, iter.data->device_use); + //qDebug() << "Found Input Device:" << iter.data->device_id; + //qDebug() << " - num_class_info:" << iter.data->num_class_info; + if(iter.rem>0){ xcb_input_device_info_next(&iter); } + else{ break; } + } + //Free the reply (done with it) + ::free(reply); + //return the information + return devices; +} diff --git a/src-qt5/core/libLumina/LInputDevice.h b/src-qt5/core/libLumina/LInputDevice.h new file mode 100644 index 00000000..82dee4fd --- /dev/null +++ b/src-qt5/core/libLumina/LInputDevice.h @@ -0,0 +1,67 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This class governs all the XCB input device interactions +// and provides simpler Qt-based functions for use elsewhere +//=========================================== +#ifndef _LUMINA_XCB_INPUT_DEVICES_H +#define _LUMINA_XCB_INPUT_DEVICES_H + +#include <QList> +#include <QString> +#include <QStringList> +#include <QHash> +#include <QVariant> + +#include <xcb/xproto.h> + +//Internal data structure for storing the property information +struct propData{ + int id; + QString name; + QVariant value; + xcb_atom_t atom; +}; + +class LInputDevice{ +public: + LInputDevice(unsigned int id, unsigned int type); //don't use this directly - use the "listDevices()" function instead + ~LInputDevice(); + + //Device Information + //QString name(); //Return the name of this device + unsigned int devNumber(); + bool isPointer(); + bool isKeyboard(); + bool isExtension(); + + //Property Management + QList<int> listProperties(); + QString propertyName(int prop); + QVariant getPropertyValue(int prop); + bool setPropertyValue(int prop, QVariant value); + +private: + unsigned int devID; //device ID number - assigned at class creation + unsigned int devType; //device "use" identifier - assigned at class creation + QHash<int, propData> devProps; //Known device properties <id#, properties struct> + + void getProperties(); + void readProperties(); + QVariant valueToVariant(QString value); //xinput output to QVariant + QString variantToString(QVariant value); //QVariant to xinput input string + + //QString devName; //device name - use this for cross-session management (id #'s can get changed every session) +}; + +//Static functions for overall management +class LInput{ + public: + static QList<LInputDevice*> listDevices(); //NOTE: Make sure you "free()" all the LInputDevice objects when finished + +}; + +#endif diff --git a/src-qt5/core/libLumina/LInputDevice.pri b/src-qt5/core/libLumina/LInputDevice.pri new file mode 100644 index 00000000..a5f88a05 --- /dev/null +++ b/src-qt5/core/libLumina/LInputDevice.pri @@ -0,0 +1,13 @@ + +QT *= x11extras + +LIBS *= -lc -lxcb -lxcb-xinput + +#LUtils Files +SOURCES *= $${PWD}/LInputDevice.cpp +HEADERS *= $${PWD}/LInputDevice.h + +INCLUDEPATH *= ${PWD} + +#include LUtils and LuminaOS +include(LUtils.pri) diff --git a/src-qt5/core/libLumina/LUtils.cpp b/src-qt5/core/libLumina/LUtils.cpp new file mode 100644 index 00000000..78831231 --- /dev/null +++ b/src-qt5/core/libLumina/LUtils.cpp @@ -0,0 +1,436 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2013-2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "LUtils.h" + +#include "LuminaOS.h" +#include "LuminaXDG.h" + +#include <QApplication> +#include <QtConcurrent> + +inline QStringList ProcessRun(QString cmd, QStringList args){ + //Assemble outputs + QStringList out; out << "1" << ""; //error code, string output + QProcess proc; + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("LANG", "C"); + env.insert("LC_MESSAGES", "C"); + proc.setProcessEnvironment(env); + proc.setProcessChannelMode(QProcess::MergedChannels); + if(args.isEmpty()){ + proc.start(cmd, QIODevice::ReadOnly); + }else{ + proc.start(cmd,args ,QIODevice::ReadOnly); + } + QString info; + while(!proc.waitForFinished(1000)){ + if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal + QString tmp = proc.readAllStandardOutput(); + if(tmp.isEmpty()){ proc.terminate(); } + else{ info.append(tmp); } + } + out[0] = QString::number(proc.exitCode()); + out[1] = info+QString(proc.readAllStandardOutput()); + return out; +} +//============= +// LUtils Functions +//============= +int LUtils::runCmd(QString cmd, QStringList args){ + /*QProcess proc; + proc.setProcessChannelMode(QProcess::MergedChannels); + if(args.isEmpty()){ + proc.start(cmd); + }else{ + proc.start(cmd, args); + } + //if(!proc.waitForStarted(30000)){ return 1; } //process never started - max wait of 30 seconds + while(!proc.waitForFinished(300)){ + if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal + QCoreApplication::processEvents(); + } + int ret = proc.exitCode(); + return ret;*/ + QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args); + return future.result()[0].toInt(); //turn it back into an integer return code + +} + +QStringList LUtils::getCmdOutput(QString cmd, QStringList args){ + /*QProcess proc; + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("LANG", "C"); + env.insert("LC_MESSAGES", "C"); + proc.setProcessEnvironment(env); + proc.setProcessChannelMode(QProcess::MergedChannels); + if(args.isEmpty()){ + proc.start(cmd); + }else{ + proc.start(cmd,args); + } + //if(!proc.waitForStarted(30000)){ return QStringList(); } //process never started - max wait of 30 seconds + while(!proc.waitForFinished(300)){ + if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal + QCoreApplication::processEvents(); + } + QStringList out = QString(proc.readAllStandardOutput()).split("\n"); + return out;*/ + QFuture<QStringList> future = QtConcurrent::run(ProcessRun, cmd, args); + return future.result()[1].split("\n"); //Split the return message into lines +} + +QStringList LUtils::readFile(QString filepath){ + QStringList out; + QFile file(filepath); + if(file.open(QIODevice::Text | QIODevice::ReadOnly)){ + QTextStream in(&file); + while(!in.atEnd()){ + out << in.readLine(); + } + file.close(); + } + return out; +} + +bool LUtils::writeFile(QString filepath, QStringList contents, bool overwrite){ + QFile file(filepath); + if(file.exists() && !overwrite){ return false; } + bool ok = false; + if(contents.isEmpty()){ contents << "\n"; } + if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){ + QTextStream out(&file); + out << contents.join("\n"); + if(!contents.last().isEmpty()){ out << "\n"; } //always end with a new line + file.close(); + ok = true; + } + return ok; +} + +bool LUtils::isValidBinary(QString& bin){ + if(!bin.startsWith("/")){ + //Relative path: search for it on the current "PATH" settings + QStringList paths = QString(qgetenv("PATH")).split(":"); + for(int i=0; i<paths.length(); i++){ + if(QFile::exists(paths[i]+"/"+bin)){ bin = paths[i]+"/"+bin; break;} + } + } + //bin should be the full path by now + if(!bin.startsWith("/")){ return false; } + QFileInfo info(bin); + bool good = (info.exists() && info.isExecutable()); + if(good){ bin = info.absoluteFilePath(); } + return good; +} + +QStringList LUtils::systemApplicationDirs(){ + //Returns a list of all the directories where *.desktop files can be found + QStringList appDirs = QString(getenv("XDG_DATA_HOME")).split(":"); + appDirs << QString(getenv("XDG_DATA_DIRS")).split(":"); + if(appDirs.isEmpty()){ appDirs << "/usr/local/share" << "/usr/share" << LOS::AppPrefix()+"/share" << LOS::SysPrefix()+"/share" << L_SHAREDIR; } + appDirs.removeDuplicates(); + //Now create a valid list + QStringList out; + for(int i=0; i<appDirs.length(); i++){ + if( QFile::exists(appDirs[i]+"/applications") ){ + out << appDirs[i]+"/applications"; + //Also check any subdirs within this directory + // (looking at you KDE - stick to the standards!!) + out << LUtils::listSubDirectories(appDirs[i]+"/applications"); + } + } + //qDebug() << "System Application Dirs:" << out; + return out; +} + +QString LUtils::GenerateOpenTerminalExec(QString term, QString dirpath){ + //Check the input terminal application (default/fallback - determined by calling application) + //if(!LUtils::isValidBinary(term)){ + if(term.endsWith(".desktop")){ + //Pull the binary name out of the shortcut + XDGDesktop DF(term); + if(DF.type == XDGDesktop::BAD){ term = "xterm"; } + else{ term= DF.exec.section(" ",0,0); } //only take the binary name - not any other flags + }else{ + term = "xterm"; //fallback + } + //} + //Now create the calling command for the designated terminal + // NOTE: While the "-e" routine is supposed to be universal, many terminals do not properly use it + // so add some special/known terminals here as necessary + QString exec; + qWarning() << " - Reached terminal initialization" << term; + if(term=="mate-terminal" || term=="lxterminal" || term=="gnome-terminal"){ + exec = term+" --working-directory=\""+dirpath+"\""; + }else if(term=="xfce4-terminal"){ + exec = term+" --default-working-directory=\""+dirpath+"\""; + }else if(term=="konsole" || term == "qterminal"){ + exec = term+" --workdir \""+dirpath+"\""; + }else{ + //-e is the parameter for most of the terminal appliction to execute an external command. + //In this case we start a shell in the selected directory + //Need the user's shell first + QString shell = QString(getenv("SHELL")); + if(!LUtils::isValidBinary(shell)){ shell = "/bin/sh"; } //universal fallback for a shell + exec = term + " -e \"cd " + dirpath + " && " + shell + " \" "; + } + qDebug() << exec; + return exec; +} + +QStringList LUtils::listSubDirectories(QString dir, bool recursive){ + //This is a recursive method for returning the full paths of all subdirectories (if recursive flag is enabled) + QDir maindir(dir); + QStringList out; + QStringList subs = maindir.entryList(QDir::NoDotAndDotDot | QDir::Dirs, QDir::Name); + for(int i=0; i<subs.length(); i++){ + out << maindir.absoluteFilePath(subs[i]); + if(recursive){ + out << LUtils::listSubDirectories(maindir.absoluteFilePath(subs[i]), recursive); + } + } + return out; +} + +QString LUtils::PathToAbsolute(QString path){ + //Convert an input path to an absolute path (this does not check existance ot anything) + if(path.startsWith("/")){ return path; } //already an absolute path + if(path.startsWith("~")){ path.replace(0,1,QDir::homePath()); } + if(!path.startsWith("/")){ + //Must be a relative path + if(path.startsWith("./")){ path = path.remove(2); } + path.prepend( QDir::currentPath()+"/"); + } + return path; +} + +QString LUtils::AppToAbsolute(QString path){ + if(path.startsWith("~/")){ path = path.replace("~/", QDir::homePath()+"/" ); } + if(path.startsWith("/") || QFile::exists(path)){ return path; } + if(path.endsWith(".desktop")){ + //Look in the XDG dirs + QStringList dirs = systemApplicationDirs(); + for(int i=0; i<dirs.length(); i++){ + if(QFile::exists(dirs[i]+"/"+path)){ return (dirs[i]+"/"+path); } + } + }else{ + //Look on $PATH for the binary + QStringList paths = QString(getenv("PATH")).split(":"); + for(int i=0; i<paths.length(); i++){ + if(QFile::exists(paths[i]+"/"+path)){ return (paths[i]+"/"+path); } + } + } + return path; +} + +QStringList LUtils::imageExtensions(bool wildcards){ + //Note that all the image extensions are lowercase!! + static QStringList imgExtensions; + if(imgExtensions.isEmpty()){ + QList<QByteArray> fmt = QImageReader::supportedImageFormats(); + for(int i=0; i<fmt.length(); i++){ + if(wildcards){ imgExtensions << "*."+QString::fromLocal8Bit(fmt[i]); } + else{ imgExtensions << QString::fromLocal8Bit(fmt[i]); } + } + } + return imgExtensions; +} + + QTranslator* LUtils::LoadTranslation(QApplication *app, QString appname, QString locale, QTranslator *cTrans){ + //Get the current localization + QString langEnc = "UTF-8"; //default value + QString langCode = locale; //provided locale + if(langCode.isEmpty()){ langCode = getenv("LC_ALL"); } + if(langCode.isEmpty()){ langCode = getenv("LANG"); } + if(langCode.isEmpty()){ langCode = "en_US.UTF-8"; } //default to US english + //See if the encoding is included and strip it out as necessary + if(langCode.contains(".")){ + langEnc = langCode.section(".",-1); + langCode = langCode.section(".",0,0); + } + //Now verify the encoding for the locale + if(langCode =="C" || langCode=="POSIX" || langCode.isEmpty()){ + langEnc = "System"; //use the Qt system encoding + } + if(app !=0){ + qDebug() << "Loading Locale:" << appname << langCode << langEnc; + //If an existing translator was provided, remove it first (will be replaced) + if(cTrans!=0){ app->removeTranslator(cTrans); } + //Setup the translator + cTrans = new QTranslator(); + //Use the shortened locale code if specific code does not have a corresponding file + if(!QFile::exists(LOS::LuminaShare()+"i18n/"+appname+"_" + langCode + ".qm") && langCode!="en_US" ){ + langCode.truncate( langCode.indexOf("_") ); + } + QString filename = appname+"_"+langCode+".qm"; + //qDebug() << "FileName:" << filename << "Dir:" << LOS::LuminaShare()+"i18n/"; + if( cTrans->load( filename, LOS::LuminaShare()+"i18n/" ) ){ + app->installTranslator( cTrans ); + }else{ + //Translator could not be loaded for some reason + cTrans = 0; + if(langCode!="en_US"){ + qWarning() << " - Could not load Locale:" << langCode; + } + } + }else{ + //Only going to set the encoding since no application given + qDebug() << "Loading System Encoding:" << langEnc; + } + //Load current encoding for this locale + QTextCodec::setCodecForLocale( QTextCodec::codecForName(langEnc.toUtf8()) ); + return cTrans; +} + +QStringList LUtils::knownLocales(){ + QDir i18n = QDir(LOS::LuminaShare()+"i18n"); + if( !i18n.exists() ){ return QStringList(); } + QStringList files = i18n.entryList(QStringList() << "lumina-desktop_*.qm", QDir::Files, QDir::Name); + if(files.isEmpty()){ return QStringList(); } + //Now strip off the filename and just leave the locale tag + for(int i=0; i<files.length(); i++){ + files[i].chop(3); //remove the ".qm" on the end + files[i] = files[i].section("_",1,50).simplified(); + } + files << "en_US"; //default locale + files.sort(); + return files; +} + +void LUtils::setLocaleEnv(QString lang, QString msg, QString time, QString num,QString money,QString collate, QString ctype){ + //Adjust the current locale environment variables + bool all = false; + if(msg.isEmpty() && time.isEmpty() && num.isEmpty() && money.isEmpty() && collate.isEmpty() && ctype.isEmpty() ){ + if(lang.isEmpty()){ return; } //nothing to do - no changes requested + all = true; //set everything to the "lang" value + } + //If no lang given, but others are given, then use the current setting + if(lang.isEmpty()){ lang = getenv("LC_ALL"); } + if(lang.isEmpty()){ lang = getenv("LANG"); } + if(lang.isEmpty()){ lang = "en_US"; } + //Now go through and set/unset the environment variables + // - LANG & LC_ALL + if(!lang.contains(".")){ lang.append(".UTF-8"); } + setenv("LANG",lang.toUtf8() ,1); //overwrite setting (this is always required as the fallback) + if(all){ setenv("LC_ALL",lang.toUtf8() ,1); } + else{ unsetenv("LC_ALL"); } //make sure the custom settings are used + // - LC_MESSAGES + if(msg.isEmpty()){ unsetenv("LC_MESSAGES"); } + else{ + if(!msg.contains(".")){ msg.append(".UTF-8"); } + setenv("LC_MESSAGES",msg.toUtf8(),1); + } + // - LC_TIME + if(time.isEmpty()){ unsetenv("LC_TIME"); } + else{ + if(!time.contains(".")){ time.append(".UTF-8"); } + setenv("LC_TIME",time.toUtf8(),1); + } + // - LC_NUMERIC + if(num.isEmpty()){ unsetenv("LC_NUMERIC"); } + else{ + if(!num.contains(".")){ num.append(".UTF-8"); } + setenv("LC_NUMERIC",num.toUtf8(),1); + } + // - LC_MONETARY + if(money.isEmpty()){ unsetenv("LC_MONETARY"); } + else{ + if(!money.contains(".")){ money.append(".UTF-8"); } + setenv("LC_MONETARY",money.toUtf8(),1); + } + // - LC_COLLATE + if(collate.isEmpty()){ unsetenv("LC_COLLATE"); } + else{ + if(!collate.contains(".")){ collate.append(".UTF-8"); } + setenv("LC_COLLATE",collate.toUtf8(),1); + } + // - LC_CTYPE + if(ctype.isEmpty()){ unsetenv("LC_CTYPE"); } + else{ + if(!ctype.contains(".")){ ctype.append(".UTF-8"); } + setenv("LC_CTYPE",ctype.toUtf8(),1); + } +} + +QString LUtils::currentLocale(){ + QString curr = getenv("LC_ALL");// = QLocale::system(); + if(curr.isEmpty()){ curr = getenv("LANG"); } + if(curr.isEmpty()){ curr = "en_US"; } + curr = curr.section(".",0,0); //remove any encodings off the end + return curr; +} + +double LUtils::DisplaySizeToBytes(QString num){ + //qDebug() << "Convert Num to Bytes:" << num; + num = num.toLower().simplified(); + num = num.remove(" "); + if(num.isEmpty()){ return 0.0; } + if(num.endsWith("b")){ num.chop(1); } //remove the "bytes" marker (if there is one) + QString lab = "b"; + if(!num[num.size()-1].isNumber()){ + lab = num.right(1); num.chop(1); + } + double N = num.toDouble(); + QStringList labs; labs <<"b"<<"k"<<"m"<<"g"<<"t"<<"p"; //go up to petabytes for now + for(int i=0; i<labs.length(); i++){ + if(lab==labs[i]){ break; }//already at the right units - break out + N = N*1024.0; //Move to the next unit of measurement + } + //qDebug() << " - Done:" << QString::number(N) << lab << num; + return N; +} + +QString LUtils::BytesToDisplaySize(qint64 ibytes){ + static QStringList labs = QStringList(); + if(labs.isEmpty()){ labs << "B" << "K" << "M" << "G" << "T" << "P"; } + //Now get the dominant unit + int c=0; + double bytes = ibytes; //need to keep decimel places for calculations + while(bytes>=1000 && c<labs.length() ){ + bytes = bytes/1024; + c++; + } //labs[c] is the unit + //Bytes are now + //Now format the number (up to 3 digits, not including decimel places) + QString num; + if(bytes>=100){ + //No decimel places + num = QString::number(qRound(bytes)); + }else if(bytes>=10){ + //need 1 decimel place + num = QString::number( (qRound(bytes*10)/10.0) ); + }else if(bytes>=1){ + //need 2 decimel places + num = QString::number( (qRound(bytes*100)/100.0) ); + }else{ + //Fully decimel (3 places) + num = "0."+QString::number(qRound(bytes*1000)); + } + //qDebug() << "Bytes to Human-readable:" << bytes << c << num << labs[c]; + return (num+labs[c]); +} + +QString LUtils::SecondsToDisplay(int secs){ + if(secs < 0){ return "??"; } + QString rem; //remaining + if(secs > 3600){ + int hours = secs/3600; + rem.append( QString::number(hours)+"h "); + secs = secs - (hours*3600); + } + if(secs > 60){ + int min = secs/60; + rem.append( QString::number(min)+"m "); + secs = secs - (min*60); + } + if(secs > 0){ + rem.append( QString::number(secs)+"s"); + }else{ + rem.append( "0s" ); + } + return rem; +} diff --git a/src-qt5/core/libLumina/LuminaUtils.h b/src-qt5/core/libLumina/LUtils.h index e07363ca..459fca60 100644 --- a/src-qt5/core/libLumina/LuminaUtils.h +++ b/src-qt5/core/libLumina/LUtils.h @@ -1,6 +1,6 @@ //=========================================== // Lumina-DE source code -// Copyright (c) 2012-2015, Ken Moore +// Copyright (c) 2012-2016, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== @@ -10,6 +10,7 @@ #include <QCoreApplication> #include <QProcess> #include <QTextStream> +#include <QTextCodec> #include <QFile> #include <QDir> #include <QString> @@ -18,17 +19,15 @@ #include <QFileInfo> #include <QObject> #include <QTranslator> -//#include <QApplication> -#include <QMenu> -#include <QMouseEvent> -#include <QSize> -#include <QWidgetAction> +#include <QDebug> +#include <QDesktopWidget> +#include <QImageReader> +#include <QRegExp> +#include <QFuture> +#include <QScreen> class LUtils{ public: - //Get the current version/build of the Lumina desktop - static QString LuminaDesktopVersion(); - static QString LuminaDesktopBuildDate(); //Run an external command and return the exit code static int runCmd(QString cmd, QStringList args = QStringList()); @@ -47,6 +46,9 @@ public: return isValidBinary(bins); //overload for a "junk" binary variable input } + //Return all the dirs on the system which contain .desktop files + static QStringList systemApplicationDirs(); + //Create the exec string to open a terminal in a particular directory static QString GenerateOpenTerminalExec(QString term, QString dirpath); @@ -72,60 +74,5 @@ public: static QString BytesToDisplaySize(qint64 bytes); //convert into a readable size (like 50M or 50KB) static QString SecondsToDisplay(int secs); //convert into a readable time - - //Various function for finding valid QtQuick plugins on the system - static bool validQuickPlugin(QString ID); - static QString findQuickPluginFile(QString ID); - static QStringList listQuickPlugins(); //List of valid ID's - static QStringList infoQuickPlugin(QString ID); //Returns: [Name, Description, Icon] - - //Various functions for the favorites sub-system - // Formatting Note: "<name>::::[dir/app/<mimetype>]::::<path>" - // the <name> field might not be used for "app" flagged entries - static QStringList listFavorites(); - static bool saveFavorites(QStringList); - static bool isFavorite(QString path); - static bool addFavorite(QString path, QString name = ""); - static void removeFavorite(QString path); - static void upgradeFavorites(int fromoldversionnumber); - - //Load the default setup for the system - static void LoadSystemDefaults(bool skipOS = false); - static bool checkUserFiles(QString lastversion); //returns true if something changed - static int VersionStringToNumber(QString version); //convert the lumina version string to a number for comparisons - -}; - -//Special subclass for a menu which the user can grab the edges and resize as necessary -// Note: Make sure that you don't set 0pixel contents margins on this menu -// - it needs at least 1 pixel margins for the user to be able to grab it -class ResizeMenu : public QMenu{ - Q_OBJECT -public: - ResizeMenu(QWidget *parent = 0); - virtual ~ResizeMenu(); - - void setContents(QWidget *con); - -private: - enum SideFlag{NONE, TOP, BOTTOM, LEFT, RIGHT}; - SideFlag resizeSide; - QWidget *contents; - QWidgetAction *cAct; - -private slots: - void clearFlags(){ - resizeSide=NONE; - } - -protected: - virtual void mouseMoveEvent(QMouseEvent *ev); - virtual void mousePressEvent(QMouseEvent *ev); - virtual void mouseReleaseEvent(QMouseEvent *ev); - -signals: - void MenuResized(QSize); //Emitted when the menu is manually resized by the user - }; - #endif diff --git a/src-qt5/core/libLumina/LUtils.pri b/src-qt5/core/libLumina/LUtils.pri new file mode 100644 index 00000000..d5941a41 --- /dev/null +++ b/src-qt5/core/libLumina/LUtils.pri @@ -0,0 +1,34 @@ +#since this is the most common of the include files - make sure it only gets added once +!contains( HEADERS, $${PWD}/LUtils.h ){ + +include("$${PWD}/../../OS-detect.pri") + +QT *= concurrent + +#Setup any special defines (qmake -> C++) +GIT_VERSION=$$system(git describe --always) +!isEmpty(GIT_VERSION){ + DEFINES += GIT_VERSION='"\\\"$${GIT_VERSION}\\\""' +} +#Note: Saving the build date will break reproducible builds (time stamp always different) +# Disable this by default, but leave it possible to re-enable this as needed by user +#DEFINES += BUILD_DATE='"\\\"$$system(date)\\\""' + +#LuminaOS files +HEADERS *= $${PWD}/LuminaOS.h +# LuminaOS support functions (or fall back to generic one) +exists($${PWD}/LuminaOS-$${LINUX_DISTRO}.cpp){ + SOURCES *= $${PWD}/LuminaOS-$${LINUX_DISTRO}.cpp +}else:exists($${PWD}/LuminaOS-$${OS}.cpp){ + SOURCES *= $${PWD}/LuminaOS-$${OS}.cpp +}else{ + SOURCES *= $${PWD}/LuminaOS-template.cpp +} + +#LUtils Files +SOURCES *= $${PWD}/LUtils.cpp +HEADERS *= $${PWD}/LUtils.h + +INCLUDEPATH *= ${PWD} + +} diff --git a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp index 5cdf18bc..b9346565 100644 --- a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp +++ b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp @@ -97,13 +97,14 @@ void LOS::setScreenBrightness(int percent){ //Run the command(s) bool success = false; // - try hardware setting first (TrueOS || or intel_backlight) - if( LUtils::isValidBinary("pc-sysconfig") ){ + bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty(); + if( LUtils::isValidBinary("pc-sysconfig") && !remoteSession){ //Use TrueOS tool (direct sysctl control) QString ret = LUtils::getCmdOutput("pc-sysconfig", QStringList() <<"setscreenbrightness "+QString::number(percent)).join(""); success = ret.toLower().contains("success"); qDebug() << "Set hardware brightness:" << percent << success; } - if( !success && LUtils::isValidBinary("intel_backlight")){ + if( !success && LUtils::isValidBinary("intel_backlight") && !remoteSession){ //Use the intel_backlight utility (only for Intel mobo/hardware?) if(0== LUtils::runCmd("intel_backlight", QStringList() <<QString::number(percent)) ){ //This utility does not report success/failure - run it again to get the current value and ensure it was set properly @@ -131,11 +132,17 @@ int LOS::audioVolume(){ //Returns: audio volume as a percentage (0-100, with -1 QString info = LUtils::readFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentvolume").join(""); if(!info.isEmpty()){ out = info.simplified().toInt(); - audiovolume = out; //unset this internal flag + audiovolume = out; //reset this internal flag return out; } } - + bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty(); + if(remoteSession){ + QStringList info = LUtils::getCmdOutput("pactl list short sinks"); + qDebug() << "Got PA sinks:" << info; + out = 50; //TEMPORARY - still need to write up the info parsing + audiovolume = out; + }else{ //probe the system for the current volume (other utils could be changing it) QString info = LUtils::getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines if(!info.isEmpty()){ @@ -149,7 +156,7 @@ int LOS::audioVolume(){ //Returns: audio volume as a percentage (0-100, with -1 } audiovolume = out; } - + } return out; } @@ -157,35 +164,45 @@ int LOS::audioVolume(){ //Returns: audio volume as a percentage (0-100, with -1 void LOS::setAudioVolume(int percent){ if(percent<0){percent=0;} else if(percent>100){percent=100;} - QString info = LUtils::getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines - if(!info.isEmpty()){ - int L = info.section(":",1,1).toInt(); - int R = info.section(":",2,2).toInt(); - int diff = L-R; - if((percent == L) && (L==R)){ return; } //already set to that volume - if(diff<0){ R=percent; L=percent+diff; } //R Greater - else{ L=percent; R=percent-diff; } //L Greater or equal - //Check bounds - if(L<0){L=0;}else if(L>100){L=100;} - if(R<0){R=0;}else if(R>100){R=100;} - //Run Command - audiovolume = percent; //save for checking later - LUtils::runCmd("mixer vol "+QString::number(L)+":"+QString::number(R)); - LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentvolume", QStringList() << QString::number(percent), true); - } + bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty(); + if(remoteSession){ + LUtils::runCmd(QString("pactl set-sink-volume @DEFAULT_SINK@ ")+QString::number(percent)+"%"); + }else{ + QString info = LUtils::getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines + if(!info.isEmpty()){ + int L = info.section(":",1,1).toInt(); + int R = info.section(":",2,2).toInt(); + int diff = L-R; + if((percent == L) && (L==R)){ return; } //already set to that volume + if(diff<0){ R=percent; L=percent+diff; } //R Greater + else{ L=percent; R=percent-diff; } //L Greater or equal + //Check bounds + if(L<0){L=0;}else if(L>100){L=100;} + if(R<0){R=0;}else if(R>100){R=100;} + //Run Command + LUtils::runCmd("mixer vol "+QString::number(L)+":"+QString::number(R)); + } + } + audiovolume = percent; //save for checking later + LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/.currentvolume", QStringList() << QString::number(percent), true); } //Change the current volume a set amount (+ or -) void LOS::changeAudioVolume(int percentdiff){ - QString info = LUtils::getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines - if(!info.isEmpty()){ - int L = info.section(":",1,1).toInt() + percentdiff; - int R = info.section(":",2,2).toInt() + percentdiff; - //Check bounds - if(L<0){L=0;}else if(L>100){L=100;} - if(R<0){R=0;}else if(R>100){R=100;} - //Run Command - LUtils::runCmd("mixer vol "+QString::number(L)+":"+QString::number(R)); + bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty(); + if(remoteSession){ + LUtils::runCmd(QString("pactl set-sink-volume @DEFAULT_SINK@ ")+((percentdiff>0)?"+" : "") + QString::number(percentdiff)+"%"); + }else{ + QString info = LUtils::getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines + if(!info.isEmpty()){ + int L = info.section(":",1,1).toInt() + percentdiff; + int R = info.section(":",2,2).toInt() + percentdiff; + //Check bounds + if(L<0){L=0;}else if(L>100){L=100;} + if(R<0){R=0;}else if(R>100){R=100;} + //Run Command + LUtils::runCmd("mixer vol "+QString::number(L)+":"+QString::number(R)); + } } } @@ -292,8 +309,10 @@ QString LOS::FileSystemCapacity(QString dir) { //Return: percentage capacity as QStringList LOS::CPUTemperatures(){ //Returns: List containing the temperature of any CPU's ("50C" for example) static QStringList vars = QStringList(); QStringList temps; - if(vars.isEmpty()){ temps = LUtils::getCmdOutput("sysctl -i hw.").filter(".temperature:"); } - else{ temps = LUtils::getCmdOutput("sysctl "+vars.join(" ")); vars.clear(); } + if(vars.isEmpty()){ + temps = LUtils::getCmdOutput("sysctl -i dev.cpu").filter(".temperature:"); //try direct readings first + if(temps.isEmpty()){ temps = LUtils::getCmdOutput("sysctl -i hw.acpi").filter(".temperature:"); } // then try acpi values + }else{ temps = LUtils::getCmdOutput("sysctl "+vars.join(" ")); vars.clear(); } temps.sort(); for(int i=0; i<temps.length(); i++){ diff --git a/src-qt5/core/libLumina/LuminaOS.h b/src-qt5/core/libLumina/LuminaOS.h index 50d6baec..96a587a8 100644 --- a/src-qt5/core/libLumina/LuminaOS.h +++ b/src-qt5/core/libLumina/LuminaOS.h @@ -1,6 +1,6 @@ //=========================================== // Lumina-DE source code -// Copyright (c) 2014-15, Ken Moore +// Copyright (c) 2014-16, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== @@ -18,7 +18,7 @@ #include <QDir> #include <QObject> -#include "LuminaUtils.h" +#include "LUtils.h" class LOS{ public: diff --git a/src-qt5/core/libLumina/LuminaRandR.cpp b/src-qt5/core/libLumina/LuminaRandR.cpp new file mode 100644 index 00000000..eefc5aa8 --- /dev/null +++ b/src-qt5/core/libLumina/LuminaRandR.cpp @@ -0,0 +1 @@ +#include "LuminaRandR.h" diff --git a/src-qt5/core/libLumina/LuminaRandR.h b/src-qt5/core/libLumina/LuminaRandR.h new file mode 100644 index 00000000..3cdff651 --- /dev/null +++ b/src-qt5/core/libLumina/LuminaRandR.h @@ -0,0 +1,35 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This class governs all the xcb/randr interactions +// and provides simpler Qt-based functions for use elsewhere +//=========================================== + +//Qt includes +#include <QSize> + +#include "xcb/randr.h" + +class outputDevice{ +public: + QString id; //output ID + bool enabled; + //Monitor Geometry + QPoint geom; //geometry of monitor within session + //Monitor Resolution + QSize cRes; //current resolution of the monitor (could be different from geom.size() if panning is enabled) + QList<QSize> availRes; //available resolutions supported by the monitor + //Refresh Rate + int cHz; //current refresh rate + QList<int> availHz; //available refresh rates + //Expand this later to include: + // panning (current/possible) + // rotation (current/possible) + + //FUNCTIONS + + //Modification +}; diff --git a/src-qt5/core/libLumina/LuminaSingleApplication.h b/src-qt5/core/libLumina/LuminaSingleApplication.h index 725d8e40..bacf5640 100644 --- a/src-qt5/core/libLumina/LuminaSingleApplication.h +++ b/src-qt5/core/libLumina/LuminaSingleApplication.h @@ -25,7 +25,7 @@ #include <QLockFile> #include <QApplication> -#include <LuminaUtils.h> +#include <LUtils.h> //NOTE: This application type will automatically load the proper translation file(s) // if the application name is set properly diff --git a/src-qt5/core/libLumina/LuminaSingleApplication.pri b/src-qt5/core/libLumina/LuminaSingleApplication.pri new file mode 100644 index 00000000..88ab7726 --- /dev/null +++ b/src-qt5/core/libLumina/LuminaSingleApplication.pri @@ -0,0 +1,12 @@ +include("$${PWD}/../../OS-detect.pri") + +QT *= network x11extras + +#LUtils Files +SOURCES *= $${PWD}/LuminaSingleApplication.cpp +HEADERS *= $${PWD}/LuminaSingleApplication.h + +INCLUDEPATH *= ${PWD} + +#include LUtils and LuminaOS +include(LUtils.pri) diff --git a/src-qt5/core/libLumina/LuminaThemes.cpp b/src-qt5/core/libLumina/LuminaThemes.cpp index b6c18cf0..70cd221d 100644 --- a/src-qt5/core/libLumina/LuminaThemes.cpp +++ b/src-qt5/core/libLumina/LuminaThemes.cpp @@ -6,7 +6,7 @@ //=========================================== #include "LuminaThemes.h" -#include "LuminaUtils.h" +#include "LUtils.h" #include "LuminaOS.h" #include <QIcon> #include <QFont> @@ -15,6 +15,8 @@ #include <QPainter> #include <QPen> +#include "LuminaXDG.h" + #include <unistd.h> //Stuff necesary for Qt Cursor Reloads @@ -292,6 +294,8 @@ QStringList LTHEME::CustomEnvSettings(bool useronly){ //view all the key=value s } void LTHEME::LoadCustomEnvSettings(){ + //Also ensure that the normal XDG_* environment variables are setup (will not overwrite them if already there) + LXDG::setEnvironmentVars(); //will push the custom settings into the environment (recommended before loading the initial QApplication) QStringList info = LTHEME::CustomEnvSettings(false); //all settings if(info.isEmpty()){ diff --git a/src-qt5/core/libLumina/LuminaThemes.pri b/src-qt5/core/libLumina/LuminaThemes.pri new file mode 100644 index 00000000..0fe35b79 --- /dev/null +++ b/src-qt5/core/libLumina/LuminaThemes.pri @@ -0,0 +1,10 @@ +include("$${PWD}/../../OS-detect.pri") + +#LUtils Files +SOURCES *= $${PWD}/LuminaThemes.cpp +HEADERS *= $${PWD}/LuminaThemes.h + +INCLUDEPATH *= ${PWD} + +#include LUtils and LuminaOS +include(LUtils.pri) diff --git a/src-qt5/core/libLumina/LuminaX11.cpp b/src-qt5/core/libLumina/LuminaX11.cpp index ecaa83d2..a8016460 100644 --- a/src-qt5/core/libLumina/LuminaX11.cpp +++ b/src-qt5/core/libLumina/LuminaX11.cpp @@ -1,6 +1,6 @@ //=========================================== // Lumina-DE source code -// Copyright (c) 2014-2015, Ken Moore +// Copyright (c) 2014-2016, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== @@ -531,6 +531,49 @@ uint LXCB::GenerateDamageID(WId win){ return ( (uint) dmgID ); } +// === paintRoot() === +void LXCB::paintRoot(QRect area, const QPixmap *pix){ + //Generate a graphics context for this paint + xcb_gcontext_t gc = xcb_generate_id(QX11Info::connection()); + xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(QX11Info::connection())).data; + uint32_t values[1]; + values[0] = screen->black_pixel; + + xcb_create_gc(QX11Info::connection(), + gc, + screen->root, + XCB_GC_BACKGROUND, + values ); + //Convert the QPixmap to a xcb_drawable_t + QImage qimage = pix->toImage().convertToFormat(QImage::Format_ARGB32); + xcb_image_t *image = xcb_image_create(pix->width(), pix->height(), XCB_IMAGE_FORMAT_XY_PIXMAP, + 32, qimage.depth(), 32, 32, XCB_IMAGE_ORDER_LSB_FIRST, XCB_IMAGE_ORDER_LSB_FIRST, + 0, qimage.byteCount(), qimage.bits()); + + + //Now paint on the root window + xcb_image_put(QX11Info::connection(), + screen->root, //where to put it + gc, + image, + area.x(), + area.y(), + 0); + /*xcb_copy_area(QX11Info::connection(), + //static_cast<xcb_drawable_t>( pix.handle() ) , //image to copy + *image, + screen->root, //where to put it + gc, //graphics context for destination + 0, //x origin of picture + 0, // y origin of picture + area.x(), //x origin of where to place it + area.y(), //y origin of where to place it + area.width(), + area.height() );*/ + //Apply the change right now + xcb_flush(QX11Info::connection()); + xcb_image_destroy(image); +} // === SetAsSticky() === void LXCB::SetAsSticky(WId win){ @@ -1081,6 +1124,7 @@ void LXCB::closeSystemTray(WId trayID){ xcb_destroy_window(QX11Info::connection(), trayID); } + // === SetScreenWorkArea() === /*void LXCB::SetScreenWorkArea(unsigned int screen, QRect rect){ //This is only useful because Fluxbox does not set the _NET_WORKAREA root atom diff --git a/src-qt5/core/libLumina/LuminaX11.h b/src-qt5/core/libLumina/LuminaX11.h index b7310abd..2c741111 100644 --- a/src-qt5/core/libLumina/LuminaX11.h +++ b/src-qt5/core/libLumina/LuminaX11.h @@ -1,6 +1,6 @@ //=========================================== // Lumina-DE source code -// Copyright (c) 2014-2015, Ken Moore +// Copyright (c) 2014-2016, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== @@ -133,6 +133,7 @@ public: // - SubStructure simplifications (not commonly used) void SelectInput(WId win, bool isEmbed = false); //XSelectInput replacement (to see window events) uint GenerateDamageID(WId); + void paintRoot(QRect area, const QPixmap *pix); // - General Window Modifications void SetAsSticky(WId); //Stick to all workspaces @@ -160,7 +161,6 @@ public: WId startSystemTray(int screen = 0); //Startup the system tray (returns window ID for tray) void closeSystemTray(WId); //Close the system tray - //============ // WM Functions (directly changing/reading properties) // - Using these directly may prevent the WM from seeing the change diff --git a/src-qt5/core/libLumina/LuminaX11.pri b/src-qt5/core/libLumina/LuminaX11.pri new file mode 100644 index 00000000..0e472dd4 --- /dev/null +++ b/src-qt5/core/libLumina/LuminaX11.pri @@ -0,0 +1,13 @@ + +QT *= x11extras + +LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lXdamage + +#LUtils Files +SOURCES *= $${PWD}/LuminaX11.cpp +HEADERS *= $${PWD}/LuminaX11.h + +INCLUDEPATH *= ${PWD} + +#include LUtils and LuminaOS +include(LUtils.pri) diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index 48185a38..d6342269 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -6,7 +6,7 @@ //=========================================== #include "LuminaXDG.h" #include "LuminaOS.h" -#include "LuminaUtils.h" +#include "LUtils.h" #include <QObject> #include <QTimer> #include <QMediaPlayer> @@ -15,11 +15,399 @@ static QStringList mimeglobs; static qint64 mimechecktime; +//============================= +// XDGDesktop CLASS +//============================= +XDGDesktop::XDGDesktop(QString file, QObject *parent) : QObject(parent){ + isHidden=false; + useTerminal=false; + startupNotify=false; + useVGL = false; + type = XDGDesktop::BAD; + filePath = file; + exec = tryexec = ""; // just to make sure this is initialized + if(!filePath.isEmpty()){ sync(); } //if an input file is given - go ahead and sync now +} + +void XDGDesktop::sync(){ + //Reset internal vars + isHidden=false; + useTerminal=false; + startupNotify=false; + type = XDGDesktop::BAD; + exec = tryexec = ""; + //Read in the File + if(!filePath.endsWith(".desktop")){ return; } + lastRead = QDateTime::currentDateTime(); + QStringList file = LUtils::readFile(filePath); + if(file.isEmpty()){ return; } //done with init right here - nothing to load + //Get the current localization code + type = XDGDesktop::APP; //assume this initially if we read the file properly + QString lang = QLocale::system().name(); //lang code + QString slang = lang.section("_",0,0); //short lang code + //Now start looping over the information + XDGDesktopAction CDA; //current desktop action + bool insection=false; + bool inaction=false; + for(int i=0; i<file.length(); i++){ + QString line = file[i]; + //if(filePath.contains("pcbsd")){ qDebug() << " - Check Line:" << line << inaction << insection; } + //Check if this is the end of a section + if(line.startsWith("[") && inaction){ + insection=false; inaction=false; + //Add the current Action structure to the main desktop structure if appropriate + if(!CDA.ID.isEmpty()){ actions << CDA; CDA = XDGDesktopAction(); } + }else if(line.startsWith("[")){ insection=false; inaction = false; } + //Now check if this is the beginning of a section + if(line=="[Desktop Entry]"){ insection=true; continue; } + else if(line.startsWith("[Desktop Action ")){ + //Grab the ID of the action out of the label + CDA.ID = line.section("]",0,0).section("Desktop Action",1,1).simplified(); + inaction = true; + continue; + }else if( (!insection && !inaction) || line.startsWith("#")){ continue; } + //Now parse out the file + line = line.simplified(); + QString var = line.section("=",0,0).simplified(); + QString loc = var.section("[",1,1).section("]",0,0).simplified(); // localization + var = var.section("[",0,0).simplified(); //remove the localization + QString val = line.section("=",1,50).simplified(); + //------------------- + if(var=="Name"){ + if(insection){ + if(name.isEmpty() && loc.isEmpty()){ name = val; } + else if(name.isEmpty() && loc==slang){ name = val; } //short locale code + else if(loc == lang){ name = val; } + }else if(inaction){ + if(CDA.name.isEmpty() && loc.isEmpty()){ CDA.name = val; } + else if(CDA.name.isEmpty() && loc==slang){ CDA.name = val; } //short locale code + else if(loc == lang){ CDA.name = val; } + } + //hasName = true; + }else if(var=="GenericName" && insection){ + if(genericName.isEmpty() && loc.isEmpty()){ genericName = val; } + else if(genericName.isEmpty() && loc==slang){ genericName = val; } //short locale code + else if(loc == lang){ genericName = val; } + }else if(var=="Comment" && insection){ + if(comment.isEmpty() && loc.isEmpty()){ comment = val; } + else if(comment.isEmpty() && loc==slang){ comment = val; } //short locale code + else if(loc == lang){ comment = val; } + }else if(var=="Icon"){ + if(insection){ + if(icon.isEmpty() && loc.isEmpty()){ icon = val; } + else if(icon.isEmpty() && loc==slang){ icon = val; } //short locale code + else if(loc == lang){ icon = val; } + }else if(inaction){ + if(CDA.icon.isEmpty() && loc.isEmpty()){ CDA.icon = val; } + else if(CDA.icon.isEmpty() && loc==slang){ CDA.icon = val; } //short locale code + else if(loc == lang){ CDA.icon = val; } + } + } + else if( (var=="TryExec") && (tryexec.isEmpty()) && insection) { tryexec = val; } + else if(var=="Exec"){ + if(insection && exec.isEmpty() ){ exec = val; } + else if(inaction && CDA.exec.isEmpty() ){ CDA.exec = val; } + } + else if( (var=="Path") && (path.isEmpty() ) && insection){ path = val; } + else if(var=="NoDisplay" && !isHidden && insection){ isHidden = (val.toLower()=="true"); } + else if(var=="Hidden" && !isHidden && insection){ isHidden = (val.toLower()=="true"); } + else if(var=="Categories" && insection){ catList = val.split(";",QString::SkipEmptyParts); } + else if(var=="OnlyShowIn" && insection){ showInList = val.split(";",QString::SkipEmptyParts); } + else if(var=="NotShowIn" && insection){ notShowInList = val.split(";",QString::SkipEmptyParts); } + else if(var=="Terminal" && insection){ useTerminal= (val.toLower()=="true"); } + else if(var=="Actions" && insection){ actionList = val.split(";",QString::SkipEmptyParts); } + else if(var=="MimeType" && insection){ mimeList = val.split(";",QString::SkipEmptyParts); } + else if(var=="Keywords" && insection){ + if(keyList.isEmpty() && loc.isEmpty()){ keyList = val.split(";",QString::SkipEmptyParts); } + else if(loc == lang){ keyList = val.split(";",QString::SkipEmptyParts); } + } + else if(var=="StartupNotify" && insection){ startupNotify = (val.toLower()=="true"); } + else if(var=="StartupWMClass" && insection){ startupWM = val; } + else if(var=="URL" && insection){ url = val;} + else if(var=="Type" && insection){ + if(val.toLower()=="application"){ type = XDGDesktop::APP; } + else if(val.toLower()=="link"){ type = XDGDesktop::LINK; } + else if(val.toLower()=="dir"){ type = XDGDesktop::DIR; } + else{ type = XDGDesktop::BAD; } //Unknown type + //hasType = true; + } + } //end reading file + file.clear(); //done with contents of file + //If there are OnlyShowIn desktops listed, add them to the name + if( !showInList.isEmpty() && !showInList.contains("Lumina", Qt::CaseInsensitive) ){ + name.append(" ("+showInList.join(", ")+")"); + } + //Quick fix for showing "wine" applications (which quite often don't list a category, or have other differences) + if(catList.isEmpty() && filePath.contains("/wine/")){ + catList << "Wine"; //Internal Lumina category only (not in XDG specs as of 11/14/14) + //Also add a fix for the location of Wine icons + if( !icon.isEmpty() ){ + QStringList sizes; sizes << "256x256" << "128x128" << "64x64" << "48x48" << "32x32" << "16x16"; + QString upath = QDir::homePath()+"/.local/share/icons/hicolor/%1/apps/%2.png"; + //qDebug() << "Wine App: Check icon" << upath; + for(int i=0; i<sizes.length(); i++){ + if( QFile::exists(upath.arg(sizes[i],icon)) ){ + icon = upath.arg(sizes[i],icon); + //qDebug() << " - Found Icon:" << icon; + break; + } + } + } + } +} + + +bool XDGDesktop::isValid(bool showAll){ + bool ok=true; + //bool DEBUG = false; + //if(DEBUG){ qDebug() << "[LXDG] Check File validity:" << dFile.name << dFile.filePath; } + switch (type){ + case XDGDesktop::BAD: + ok=false; + //if(DEBUG){ qDebug() << " - Bad file type"; } + break; + case XDGDesktop::APP: + if(!tryexec.isEmpty() && !LXDG::checkExec(tryexec)){ ok=false; }//if(DEBUG){ qDebug() << " - tryexec does not exist";} } + else if(exec.isEmpty() || name.isEmpty()){ ok=false; }//if(DEBUG){ qDebug() << " - exec or name is empty";} } + else if(!LXDG::checkExec(exec.section(" ",0,0,QString::SectionSkipEmpty)) ){ ok=false; }//if(DEBUG){ qDebug() << " - first exec binary does not exist";} } + break; + case XDGDesktop::LINK: + ok = !url.isEmpty(); + //if(DEBUG && !ok){ qDebug() << " - Link with missing URL"; } + break; + case XDGDesktop::DIR: + ok = !path.isEmpty(); + //if(DEBUG && !ok){ qDebug() << " - Dir with missing path"; } + break; + default: + ok=false; + //if(DEBUG){ qDebug() << " - Unknown file type"; } + } + if(!showAll){ + QString cdesk = getenv("XDG_CURRENT_DESKTOP"); + if(cdesk.isEmpty()){ cdesk="Lumina"; } + if(!showInList.isEmpty()){ ok = showInList.contains(cdesk, Qt::CaseInsensitive); } + else if(!notShowInList.isEmpty()){ ok = !notShowInList.contains(cdesk,Qt::CaseInsensitive); } + else if(name.isEmpty()){ ok = false; } + } + return ok; +} + +QString XDGDesktop::getDesktopExec(QString ActionID){ + //Generate the executable line for the application + QString out = exec; + if( !ActionID.isEmpty() ){ + //Go through and grab the proper exec for the listed action + for(int i=0; i<actions.length(); i++){ + if(actions[i].ID == ActionID){ + out = actions[i].exec; + break; + } + } + } + + if(out.isEmpty()){ return ""; } + else if(useTerminal){ + //Get the currently default terminal + QString term = LXDG::findDefaultAppForMime("application/terminal"); + if(!QFile::exists(term)){ term = "xterm -lc"; } + else if(term.endsWith(".desktop")){ + XDGDesktop DF(term); + if(DF.isValid()){ term = DF.getDesktopExec(); } + else{ term = "xterm -lc"; } + //DF.deleteLater(); //done with this struct + }else if( !LUtils::isValidBinary(term)){ term = "xterm -lc"; } + out = term+" -e "+out; //-e is a nearly-universal flag for terminal emulators + } + //Now perform any of the XDG flag substitutions as appropriate (9/2014 standards) + if(out.contains("%i") && !icon.isEmpty() ){ out.replace("%i", "--icon \'"+icon+"\'"); } + if(out.contains("%c")){ + if(!name.isEmpty()){ out.replace("%c", "\'"+name+"\'"); } + else if(!genericName.isEmpty()){ out.replace("%c", "\'"+genericName+"\'"); } + else{ out.replace("%c", "\'"+filePath.section("/",-1).section(".desktop",0,0)+"\'"); } + } + if(out.contains("%k")){ out.replace("%k", "\'"+filePath+"\'"); } + return out; +} + +bool XDGDesktop::saveDesktopFile(bool merge){ + qDebug() << "Save Desktop File:" << filePath << "Merge:" << merge; + bool autofile = filePath.contains("/autostart/"); //use the "Hidden" field instead of the "NoDisplay" + int insertloc = -1; + QStringList info; + if(QFile::exists(filePath) && merge){ + //Load the existing file and merge in in any changes + info = LUtils::readFile(filePath); + //set a couple flags based on the contents before we start iterating through + // - determine if a translated field was changed (need to remove all the now-invalid translations) + bool clearName, clearComment, clearGName; + QString tmp = ""; + if(!info.filter("Name=").isEmpty()){ tmp = info.filter("Name=").first().section("=",1,50); } + clearName=(tmp!=name); + tmp.clear(); + if(!info.filter("Comment=").isEmpty()){ tmp = info.filter("Comment=").first().section("=",1,50); } + clearComment=(tmp!=comment); + tmp.clear(); + if(!info.filter("GenericName=").isEmpty()){ tmp = info.filter("GenericName=").first().section("=",1,50); } + clearGName=(tmp!=genericName); + //Now start iterating through the file and changing fields as necessary + bool insection = false; + for(int i=0; i<info.length(); i++){ + if(info[i]=="[Desktop Entry]"){ + insection = true; + continue; + }else if(info[i].startsWith("[")){ + if(insection){ insertloc = i; } //save this location for later insertions + insection = false; + continue; + } + if(!insection || info[i].isEmpty() || info[i].section("#",0,0).simplified().isEmpty()){ continue; } + QString var = info[i].section("=",0,0); + QString val = info[i].section("=",1,50).simplified(); + //NOTE: Clear the dFile variable as it is found/set in the file (to keep track of what has been used already) + // For boolian values, set them to false + // --LOCALIZED VALUES -- + if(var.startsWith("Name")){ + if(var.contains("[") && clearName){ info.removeAt(i); i--; continue;} + else if(!var.contains("[")){ info[i] = var+"="+name; name.clear(); } + }else if(var.startsWith("GenericName")){ + if(var.contains("[") && clearGName){ info.removeAt(i); i--; continue;} + else if(!var.contains("[")){ info[i] = var+"="+genericName; genericName.clear(); } + }else if(var.startsWith("Comment")){ + if(var.contains("[") && clearComment){ info.removeAt(i); i--; continue;} + else if(!var.contains("[")){ info[i] = var+"="+comment; comment.clear(); } + + // --STRING/LIST VALUES-- + }else if(var=="Exec"){ info[i] = var+"="+exec; exec.clear(); } + else if(var=="TryExec"){ info[i] = var+"="+tryexec; tryexec.clear(); } + else if(var=="Path"){ info[i] = var+"="+path; path.clear(); } + else if(var=="Icon"){ info[i] = var+"="+icon; icon.clear(); } + else if(var=="StartupWMClass"){ info[i] = var+"="+startupWM; startupWM.clear(); } + else if(var=="MimeType"){ info[i] = var+"="+mimeList.join(";"); mimeList.clear(); } + else if(var=="Categories"){ info[i] = var+"="+catList.join(";"); catList.clear(); } + else if(var=="Keywords"){ info[i] = var+"="+keyList.join(";"); keyList.clear(); } + else if(var=="Actions"){ info[i] = var+"="+actionList.join(";"); actionList.clear(); } + else if(var=="OnlyShowIn"){ info[i] = var+"="+showInList.join(";"); showInList.clear(); } + else if(var=="NotShowIn"){ info[i] = var+"="+notShowInList.join(";"); notShowInList.clear(); } + else if(var=="URL"){ info[i] = var+"="+url; url.clear(); } + + // --BOOLIAN VALUES-- + else if(var=="Hidden"){ + if(!autofile){ info.removeAt(i); i--; continue; } + else{ info[i] = var+"="+(isHidden ? "true": "false"); isHidden=false;} + }else if(var=="NoDisplay"){ + if(autofile){ info.removeAt(i); i--; continue; } + else{ info[i] = var+"="+(isHidden ? "true": "false"); isHidden=false;} + }else if(var=="Terminal"){ + info[i] = var+"="+(useTerminal ? "true": "false"); useTerminal=false; + }else if(var=="StartupNotify"){ + info[i] = var+"="+(startupNotify ? "true": "false"); startupNotify=false; + } + // Remove any lines that have been un-set or removed from the file + if(info[i].section("=",1,50).simplified().isEmpty()){ info.removeAt(i); i--; } + } + + }else{ + //Just write a new file and overwrite any old one + // (pre-set some values here which are always required) + info << "[Desktop Entry]"; + info << "Version=1.0"; + if(type==XDGDesktop::APP){ info << "Type=Application"; } + else if(type==XDGDesktop::LINK){ info << "Type=Link"; } + else if(type==XDGDesktop::DIR){ info << "Type=Dir"; } + } + + if(insertloc<0){ insertloc = info.size(); }//put it at the end + //Now add in any items that did not exist in the original file + if( !exec.isEmpty() ){ info.insert(insertloc,"Exec="+exec); } + if( !tryexec.isEmpty() ){ info.insert(insertloc,"TryExec="+tryexec); } + if( !path.isEmpty() ){ info.insert(insertloc,"Path="+path); } + if( !icon.isEmpty() ){ info.insert(insertloc,"Icon="+icon); } + if( !name.isEmpty() ){ info.insert(insertloc,"Name="+name); } + if( !genericName.isEmpty() ){ info.insert(insertloc,"GenericName="+genericName); } + if( !comment.isEmpty() ){ info.insert(insertloc,"Comment="+comment); } + if( !startupWM.isEmpty() ){ info.insert(insertloc,"StartupWMClass="+startupWM); } + if( !mimeList.isEmpty() ){ info.insert(insertloc,"MimeType="+mimeList.join(";")); } + if( !catList.isEmpty() ){ info.insert(insertloc,"Categories="+catList.join(";")); } + if( !keyList.isEmpty() ){ info.insert(insertloc,"Keywords="+keyList.join(";")); } + if( !actionList.isEmpty() ){ info.insert(insertloc,"Actions="+actionList.join(";")); } + if( !showInList.isEmpty() ){ info.insert(insertloc,"OnlyShowIn="+showInList.join(";")); } + else if( !notShowInList.isEmpty() ){ info.insert(insertloc,"NotShowIn="+notShowInList.join(";")); } + if( !url.isEmpty() ){ info.insert(insertloc,"URL="+url); } + if( isHidden && autofile ){ info.insert(insertloc,"Hidden=true"); } + else if(isHidden){ info.insert(insertloc,"NoDisplay=true"); } + if( useTerminal){ info.insert(insertloc,"Terminal=true"); } + if( startupNotify ){ info.insert(insertloc,"StartupNotify=true"); } + + //Now save the file + return LUtils::writeFile(filePath, info, true); +} + +bool XDGDesktop::setAutoStarted(bool autostart){ + //First get the list of system directories to search (system first, user-provided files come later and overwrite sys files as needed) + QStringList paths = QString(getenv("XDG_CONFIG_DIRS")).split(":"); + QString upath = QString(getenv("XDG_CONFIG_HOME")).section(":",0,0); + if(upath.isEmpty()){ upath = QDir::homePath()+"/.config/autostart/"; } + else{ upath.append("/autostart/"); } + //Verify that the autostart directory exists + if(!QFile::exists(upath)){ + QDir dir; + dir.mkpath(upath); + } + + //Quick check/finish for user-defined files which are getting disabled (just remove the file) + if(filePath.startsWith(upath) && !autostart){ + return QFile::remove(filePath); + } + bool sysfile = false; + for(int i=0; i<paths.length(); i++){ + if(filePath.startsWith(paths[i]+"/autostart/") ){ + sysfile = true; + //Change it to the user-modifiable directory + filePath = filePath.replace(paths[i]+"/autostart/", upath); + } + } + //Make sure the user-autostart dir is specified, and clean the app structure as necessary + if( !filePath.startsWith(upath) && autostart){ + //Some other non-override autostart file - set it up to open with lumina-open + if(!filePath.endsWith(".desktop")){ + exec = "lumina-open \""+filePath+"\""; + tryexec = filePath; //make sure this file exists + if(name.isEmpty()){ name = filePath.section("/",-1); } + if(icon.isEmpty()){ icon = LXDG::findAppMimeForFile(filePath); icon.replace("/","-"); } + filePath = upath+filePath.section("/",-1)+".desktop"; + type = XDGDesktop::APP; + }else{ + //Some other *.desktop file on the system (keep almost all the existing settings/values) + // - setup a redirect to the other file + exec = "lumina-open \""+filePath+"\""; + tryexec = filePath; //make sure this file exists + // - Adjust the actual path where this file will get saved + filePath = upath+filePath.section("/",-1); + } + } + //Now save the "hidden" value into the file + isHidden = !autostart; //if hidden, it will not be autostarted + //Now save the file as necessary + bool saved = false; + //qDebug() << " - Saving AutoStart File:" << filePath << name << isHidden; + if(sysfile){ + //Just an override file for the "hidden" field - nothing more + QStringList info; + info << "[Desktop Entry]" << "Type=Application" << QString("Hidden=")+ (isHidden ? QString("true"): QString("false")); + saved = LUtils::writeFile(filePath, info, true); + }else{ + //Need to actually save the full file + saved = saveDesktopFile(); + } + return saved; +} + //====XDGDesktopList Functions ==== XDGDesktopList::XDGDesktopList(QObject *parent, bool watchdirs) : QObject(parent){ - synctimer = new QTimer(this); - synctimer->setInterval(60000); //1 minute intervals. since the polling/update only takes a few ms, this is completely reasonable + synctimer = new QTimer(this); //interval set automatically based on changes/interactions connect(synctimer, SIGNAL(timeout()), this, SLOT(updateList()) ); + keepsynced = watchdirs; if(watchdirs){ watcher = new QFileSystemWatcher(this); connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(watcherChanged()) ); @@ -34,7 +422,9 @@ XDGDesktopList::~XDGDesktopList(){ } void XDGDesktopList::watcherChanged(){ - QTimer::singleShot(1000, this, SLOT(updateList()) ); //1 second delay before check kicks off + if(synctimer->isActive()){ synctimer->stop(); } + synctimer->setInterval(1000); //1 second delay before check kicks off + synctimer->start(); } void XDGDesktopList::updateList(){ @@ -47,53 +437,62 @@ void XDGDesktopList::updateList(){ bool firstrun = lastCheck.isNull() || oldkeys.isEmpty(); lastCheck = QDateTime::currentDateTime(); //Variables for internal loop use only (to prevent re-initializing variable on every iteration) - bool ok; QString path; QDir dir; QStringList apps; XDGDesktop dFile; + bool ok; QString path; QDir dir; QStringList apps; for(int i=0; i<appDirs.length(); i++){ if( !dir.cd(appDirs[i]) ){ continue; } //could not open dir for some reason apps = dir.entryList(QStringList() << "*.desktop",QDir::Files, QDir::Name); for(int a=0; a<apps.length(); a++){ path = dir.absoluteFilePath(apps[a]); - if(files.contains(path) && (files.value(path).lastRead>QFileInfo(path).lastModified()) ){ + if(files.contains(path) && (files.value(path)->lastRead>QFileInfo(path).lastModified()) ){ //Re-use previous data for this file (nothing changed) - dFile = files[path]; + found << files[path]->name; //keep track of which files were already found ok=true; }else{ ok=false; - dFile = LXDG::loadDesktopFile(path,ok); //will change the "ok" variable as needed - appschanged = true; //flag that something changed - needed to load a file - } - if(ok && !found.contains(dFile.name)){ - if(!oldkeys.contains(path)){ newfiles << path; } //brand new file (not an update to a previously-read file) - files.insert(path, dFile); - found << dFile.name; - oldkeys.removeAll(path); //make sure this key does not get cleaned up later + if(files.contains(path)){ appschanged = true; files.take(path)->deleteLater(); } //files.remove(path); } + XDGDesktop *dFile = new XDGDesktop(path, this); //will change the "ok" variable as needed + if(dFile->type!=XDGDesktop::BAD){ + appschanged = true; //flag that something changed - needed to load a file + if(!oldkeys.contains(path)){ newfiles << path; } //brand new file (not an update to a previously-read file) + files.insert(path, dFile); + found << dFile->name; + }else{ + dFile->deleteLater(); //bad file - discard it + } } + oldkeys.removeAll(path); //make sure this key does not get cleaned up later } //end loop over apps } //end loop over appDirs //Save the extra info to the internal lists - if(!firstrun){ removedApps = oldkeys; }//files which were removed - if(!firstrun){ newApps = newfiles; }//files which were added + if(!firstrun){ + removedApps = oldkeys;//files which were removed + newApps = newfiles; //files which were added + } //Now go through and cleanup any old keys where the associated file does not exist anymore for(int i=0; i<oldkeys.length(); i++){ - files.remove(oldkeys[i]); + //qDebug() << "Removing file from internal map:" << oldkeys[i]; + if(i==0){ appschanged = true; } + //files.remove(oldkeys[i]); + files.take(oldkeys[i])->deleteLater(); } //If this class is automatically managing the lists, update the watched files/dirs and send out notifications if(watcher!=0){ - //qDebug() << "App List Updated:" << lastCheck << appschanged << newfiles << oldkeys; + if(appschanged){ qDebug() << "Auto App List Update:" << lastCheck << "Files Found:" << files.count(); } watcher->removePaths(QStringList() << watcher->files() << watcher->directories()); watcher->addPaths(appDirs); if(appschanged){ emit appsUpdated(); } + synctimer->setInterval(60000); //Update in 1 minute if nothing changes before then + synctimer->start(); } - synctimer->start(); } -QList<XDGDesktop> XDGDesktopList::apps(bool showAll, bool showHidden){ +QList<XDGDesktop*> XDGDesktopList::apps(bool showAll, bool showHidden){ //showAll: include invalid files, showHidden: include NoShow/Hidden files QStringList keys = files.keys(); - QList<XDGDesktop> out; + QList<XDGDesktop*> out; for(int i=0; i<keys.length(); i++){ - if( LXDG::checkValidity(files[keys[i]], showAll) ){ - if( showHidden || !files[keys[i]].isHidden ){ + if( showHidden || !files[keys[i]]->isHidden ){ //this is faster than the "checkValidity()" function below - so always filter here first + if( files[keys[i]]->isValid(showAll) ){ out << files[keys[i]]; } } @@ -104,6 +503,7 @@ QList<XDGDesktop> XDGDesktopList::apps(bool showAll, bool showHidden){ //==== LFileInfo Functions ==== //Need some extra information not usually available by a QFileInfo void LFileInfo::loadExtraInfo(){ + desk = 0; //Now load the extra information if(this->isDir()){ mime = "inode/directory"; @@ -122,17 +522,19 @@ void LFileInfo::loadExtraInfo(){ }else if( this->suffix()=="desktop"){ mime = "application/x-desktop"; icon = "application-x-desktop"; //default value - bool ok = false; - desk = LXDG::loadDesktopFile(this->absoluteFilePath(), ok); - if(ok){ + desk = new XDGDesktop(this->absoluteFilePath(), 0); + if(desk->type!=XDGDesktop::BAD){ //use the specific desktop file info (if possible) - if(!desk.icon.isEmpty()){ icon = desk.icon; } + if(!desk->icon.isEmpty()){ icon = desk->icon; } } }else{ //Generic file, just determine the mimetype mime = LXDG::findAppMimeForFile(this->fileName()); } } +LFileInfo::LFileInfo(){ + desk = 0; +} LFileInfo::LFileInfo(QString filepath){ //overloaded contructor this->setFile(filepath); loadExtraInfo(); @@ -167,12 +569,13 @@ QString LFileInfo::iconfile(){ // -- Check if this is an XDG desktop file bool LFileInfo::isDesktopFile(){ - return (!desk.filePath.isEmpty()); + if(desk==0){ return false; } + return (!desk->filePath.isEmpty()); } // -- Allow access to the XDG desktop data structure XDGDesktop* LFileInfo::XDG(){ - return &desk; + return desk; } // -- Check if this is a readable image file (for thumbnail support) @@ -188,296 +591,6 @@ bool LFileInfo::isAVFile(){ //==== LXDG Functions ==== -XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){ - //Create the outputs - ok=false; - XDGDesktop DF; - DF.isHidden=false; - DF.useTerminal=false; - DF.startupNotify=false; - DF.type = XDGDesktop::APP; - DF.filePath = filePath; - DF.lastRead = QDateTime::currentDateTime(); - DF.exec = DF.tryexec = ""; // just to make sure this is initialized - - //Get the current localization code - QString lang = QLocale::system().name(); //lang code - QString slang = lang.section("_",0,0); //short lang code - - //Read in the File - bool insection=false; - bool inaction=false; - QStringList file = LUtils::readFile(filePath); - if(file.isEmpty()){ return DF; } - //if(filePath.contains("pcbsd")){ qDebug() << "Check File:" << filePath << lang << slang; } - XDGDesktopAction CDA; //current desktop action - for(int i=0; i<file.length(); i++){ - QString line = file[i]; - //if(filePath.contains("pcbsd")){ qDebug() << " - Check Line:" << line << inaction << insection; } - //Check if this is the end of a section - if(line.startsWith("[") && inaction){ - insection=false; inaction=false; - //Add the current Action structure to the main desktop structure if appropriate - if(!CDA.ID.isEmpty()){ DF.actions << CDA; CDA = XDGDesktopAction(); } - }else if(line.startsWith("[")){ insection=false; inaction = false; } - //Now check if this is the beginning of a section - if(line=="[Desktop Entry]"){ insection=true; continue; } - else if(line.startsWith("[Desktop Action ")){ - //Grab the ID of the action out of the label - CDA.ID = line.section("]",0,0).section("Desktop Action",1,1).simplified(); - inaction = true; - continue; - }else if( (!insection && !inaction) || line.startsWith("#")){ continue; } - //Now parse out the file - line = line.simplified(); - QString var = line.section("=",0,0).simplified(); - QString loc = var.section("[",1,1).section("]",0,0).simplified(); // localization - var = var.section("[",0,0).simplified(); //remove the localization - QString val = line.section("=",1,50).simplified(); - //if(filePath.contains("pcbsd")){ qDebug() << " -- " << var << val << loc; } - //------------------- - if(var=="Name"){ - if(insection){ - if(DF.name.isEmpty() && loc.isEmpty()){ DF.name = val; } - else if(DF.name.isEmpty() && loc==slang){ DF.name = val; } //short locale code - else if(loc == lang){ DF.name = val; } - }else if(inaction){ - if(CDA.name.isEmpty() && loc.isEmpty()){ CDA.name = val; } - else if(CDA.name.isEmpty() && loc==slang){ CDA.name = val; } //short locale code - else if(loc == lang){ CDA.name = val; } - } - //hasName = true; - }else if(var=="GenericName" && insection){ - if(DF.genericName.isEmpty() && loc.isEmpty()){ DF.genericName = val; } - else if(DF.genericName.isEmpty() && loc==slang){ DF.genericName = val; } //short locale code - else if(loc == lang){ DF.genericName = val; } - }else if(var=="Comment" && insection){ - if(DF.comment.isEmpty() && loc.isEmpty()){ DF.comment = val; } - else if(DF.comment.isEmpty() && loc==slang){ DF.comment = val; } //short locale code - else if(loc == lang){ DF.comment = val; } - }else if(var=="Icon"){ - if(insection){ - if(DF.icon.isEmpty() && loc.isEmpty()){ DF.icon = val; } - else if(DF.icon.isEmpty() && loc==slang){ DF.icon = val; } //short locale code - else if(loc == lang){ DF.icon = val; } - }else if(inaction){ - if(CDA.icon.isEmpty() && loc.isEmpty()){ CDA.icon = val; } - else if(CDA.icon.isEmpty() && loc==slang){ CDA.icon = val; } //short locale code - else if(loc == lang){ CDA.icon = val; } - } - } - else if( (var=="TryExec") && (DF.tryexec.isEmpty()) && insection) { DF.tryexec = val; } - else if(var=="Exec"){ - if(insection && DF.exec.isEmpty() ){ DF.exec = val; } - else if(inaction && CDA.exec.isEmpty() ){ CDA.exec = val; } - } - else if( (var=="Path") && (DF.path.isEmpty() ) && insection){ DF.path = val; } - else if(var=="NoDisplay" && !DF.isHidden && insection){ DF.isHidden = (val.toLower()=="true"); } - else if(var=="Hidden" && !DF.isHidden && insection){ DF.isHidden = (val.toLower()=="true"); } - else if(var=="Categories" && insection){ DF.catList = val.split(";",QString::SkipEmptyParts); } - else if(var=="OnlyShowIn" && insection){ DF.showInList = val.split(";",QString::SkipEmptyParts); } - else if(var=="NotShowIn" && insection){ DF.notShowInList = val.split(";",QString::SkipEmptyParts); } - else if(var=="Terminal" && insection){ DF.useTerminal= (val.toLower()=="true"); } - else if(var=="Actions" && insection){ DF.actionList = val.split(";",QString::SkipEmptyParts); } - else if(var=="MimeType" && insection){ DF.mimeList = val.split(";",QString::SkipEmptyParts); } - else if(var=="Keywords" && insection){ - if(DF.keyList.isEmpty() && loc.isEmpty()){ DF.keyList = val.split(";",QString::SkipEmptyParts); } - else if(loc == lang){ DF.keyList = val.split(";",QString::SkipEmptyParts); } - } - else if(var=="StartupNotify" && insection){ DF.startupNotify = (val.toLower()=="true"); } - else if(var=="StartupWMClass" && insection){ DF.startupWM = val; } - else if(var=="URL" && insection){ DF.url = val;} - else if(var=="Type" && insection){ - if(val.toLower()=="application"){ DF.type = XDGDesktop::APP; } - else if(val.toLower()=="link"){ DF.type = XDGDesktop::LINK; } - else if(val.toLower()=="dir"){ DF.type = XDGDesktop::DIR; } - else{ DF.type = XDGDesktop::BAD; } //Unknown type - //hasType = true; - } - } //end reading file - //file.close(); - //If there are OnlyShowIn desktops listed, add them to the name - if( !DF.showInList.isEmpty() && !DF.showInList.contains("Lumina", Qt::CaseInsensitive) ){ - /*QStringList added; - //Need to be careful about case insensitivity here - the QList functions don't understand it - for(int i=0; i<DF.showInList.length(); i++){ - if(DF.showInList[i].toLower()!="lumina"){ added << DF.showInList[i]; } - }*/ - //if(!added.isEmpty()){ - DF.name.append(" ("+DF.showInList.join(", ")+")"); - //} - } - //Quick fix for showing "wine" applications (which quite often don't list a category, or have other differences) - if(DF.catList.isEmpty() && filePath.contains("/wine/")){ - DF.catList << "Wine"; //Internal Lumina category only (not in XDG specs as of 11/14/14) - //Also add a fix for the location of Wine icons - if( !DF.icon.isEmpty() ){ - QStringList sizes; sizes << "256x256" << "128x128" << "64x64" << "48x48" << "32x32" << "16x16"; - QString upath = QDir::homePath()+"/.local/share/icons/hicolor/%1/apps/%2.png"; - //qDebug() << "Wine App: Check icon" << upath; - for(int i=0; i<sizes.length(); i++){ - if( QFile::exists(upath.arg(sizes[i],DF.icon)) ){ - DF.icon = upath.arg(sizes[i],DF.icon); - //qDebug() << " - Found Icon:" << DF.icon; - break; - } - } - } - } - //Return the structure - //if (hasName && hasType) ok = true; //without Name and Type, the structure cannot be a valid .desktop file - ok = true; //was able to open/read the file - validity determined later - return DF; -} - -bool LXDG::saveDesktopFile(XDGDesktop dFile, bool merge){ - qDebug() << "Save Desktop File:" << dFile.filePath << "Merge:" << merge; - bool autofile = dFile.filePath.contains("/autostart/"); //use the "Hidden" field instead of the "NoDisplay" - int insertloc = -1; - QStringList info; - if(QFile::exists(dFile.filePath) && merge){ - //Load the existing file and merge in in any changes - info = LUtils::readFile(dFile.filePath); - //set a couple flags based on the contents before we start iterating through - // - determine if a translated field was changed (need to remove all the now-invalid translations) - bool clearName, clearComment, clearGName; - QString tmp = ""; - if(!info.filter("Name=").isEmpty()){ tmp = info.filter("Name=").first().section("=",1,50); } - clearName=(tmp!=dFile.name); - tmp.clear(); - if(!info.filter("Comment=").isEmpty()){ tmp = info.filter("Comment=").first().section("=",1,50); } - clearComment=(tmp!=dFile.comment); - tmp.clear(); - if(!info.filter("GenericName=").isEmpty()){ tmp = info.filter("GenericName=").first().section("=",1,50); } - clearGName=(tmp!=dFile.genericName); - //Now start iterating through the file and changing fields as necessary - bool insection = false; - for(int i=0; i<info.length(); i++){ - if(info[i]=="[Desktop Entry]"){ - insection = true; - continue; - }else if(info[i].startsWith("[")){ - if(insection){ insertloc = i; } //save this location for later insertions - insection = false; - continue; - } - if(!insection || info[i].isEmpty() || info[i].section("#",0,0).simplified().isEmpty()){ continue; } - QString var = info[i].section("=",0,0); - QString val = info[i].section("=",1,50).simplified(); - //NOTE: Clear the dFile variable as it is found/set in the file (to keep track of what has been used already) - // For boolian values, set them to false - // --LOCALIZED VALUES -- - if(var.startsWith("Name")){ - if(var.contains("[") && clearName){ info.removeAt(i); i--; continue;} - else if(!var.contains("[")){ info[i] = var+"="+dFile.name; dFile.name.clear(); } - }else if(var.startsWith("GenericName")){ - if(var.contains("[") && clearGName){ info.removeAt(i); i--; continue;} - else if(!var.contains("[")){ info[i] = var+"="+dFile.genericName; dFile.genericName.clear(); } - }else if(var.startsWith("Comment")){ - if(var.contains("[") && clearComment){ info.removeAt(i); i--; continue;} - else if(!var.contains("[")){ info[i] = var+"="+dFile.comment; dFile.comment.clear(); } - - // --STRING/LIST VALUES-- - }else if(var=="Exec"){ info[i] = var+"="+dFile.exec; dFile.exec.clear(); } - else if(var=="TryExec"){ info[i] = var+"="+dFile.tryexec; dFile.tryexec.clear(); } - else if(var=="Path"){ info[i] = var+"="+dFile.path; dFile.path.clear(); } - else if(var=="Icon"){ info[i] = var+"="+dFile.icon; dFile.icon.clear(); } - else if(var=="StartupWMClass"){ info[i] = var+"="+dFile.startupWM; dFile.startupWM.clear(); } - else if(var=="MimeType"){ info[i] = var+"="+dFile.mimeList.join(";"); dFile.mimeList.clear(); } - else if(var=="Categories"){ info[i] = var+"="+dFile.catList.join(";"); dFile.catList.clear(); } - else if(var=="Keywords"){ info[i] = var+"="+dFile.keyList.join(";"); dFile.keyList.clear(); } - else if(var=="Actions"){ info[i] = var+"="+dFile.actionList.join(";"); dFile.actionList.clear(); } - else if(var=="OnlyShowIn"){ info[i] = var+"="+dFile.showInList.join(";"); dFile.showInList.clear(); } - else if(var=="NotShowIn"){ info[i] = var+"="+dFile.notShowInList.join(";"); dFile.notShowInList.clear(); } - else if(var=="URL"){ info[i] = var+"="+dFile.url; dFile.url.clear(); } - - // --BOOLIAN VALUES-- - else if(var=="Hidden"){ - if(!autofile){ info.removeAt(i); i--; continue; } - else{ info[i] = var+"="+(dFile.isHidden ? "true": "false"); dFile.isHidden=false;} - }else if(var=="NoDisplay"){ - if(autofile){ info.removeAt(i); i--; continue; } - else{ info[i] = var+"="+(dFile.isHidden ? "true": "false"); dFile.isHidden=false;} - }else if(var=="Terminal"){ - info[i] = var+"="+(dFile.useTerminal ? "true": "false"); dFile.useTerminal=false; - }else if(var=="StartupNotify"){ - info[i] = var+"="+(dFile.startupNotify ? "true": "false"); dFile.startupNotify=false; - } - // Remove any lines that have been un-set or removed from the file - if(info[i].section("=",1,50).simplified().isEmpty()){ info.removeAt(i); i--; } - } - - }else{ - //Just write a new file and overwrite any old one - // (pre-set some values here which are always required) - info << "[Desktop Entry]"; - info << "Version=1.0"; - if(dFile.type==XDGDesktop::APP){ info << "Type=Application"; } - else if(dFile.type==XDGDesktop::LINK){ info << "Type=Link"; } - else if(dFile.type==XDGDesktop::DIR){ info << "Type=Dir"; } - } - - if(insertloc<0){ insertloc = info.size(); }//put it at the end - //Now add in any items that did not exist in the original file - if( !dFile.exec.isEmpty() ){ info.insert(insertloc,"Exec="+dFile.exec); } - if( !dFile.tryexec.isEmpty() ){ info.insert(insertloc,"TryExec="+dFile.tryexec); } - if( !dFile.path.isEmpty() ){ info.insert(insertloc,"Path="+dFile.path); } - if( !dFile.icon.isEmpty() ){ info.insert(insertloc,"Icon="+dFile.icon); } - if( !dFile.name.isEmpty() ){ info.insert(insertloc,"Name="+dFile.name); } - if( !dFile.genericName.isEmpty() ){ info.insert(insertloc,"GenericName="+dFile.genericName); } - if( !dFile.comment.isEmpty() ){ info.insert(insertloc,"Comment="+dFile.comment); } - if( !dFile.startupWM.isEmpty() ){ info.insert(insertloc,"StartupWMClass="+dFile.startupWM); } - if( !dFile.mimeList.isEmpty() ){ info.insert(insertloc,"MimeType="+dFile.mimeList.join(";")); } - if( !dFile.catList.isEmpty() ){ info.insert(insertloc,"Categories="+dFile.catList.join(";")); } - if( !dFile.keyList.isEmpty() ){ info.insert(insertloc,"Keywords="+dFile.keyList.join(";")); } - if( !dFile.actionList.isEmpty() ){ info.insert(insertloc,"Actions="+dFile.actionList.join(";")); } - if( !dFile.showInList.isEmpty() ){ info.insert(insertloc,"OnlyShowIn="+dFile.showInList.join(";")); } - else if( !dFile.notShowInList.isEmpty() ){ info.insert(insertloc,"NotShowIn="+dFile.notShowInList.join(";")); } - if( !dFile.url.isEmpty() ){ info.insert(insertloc,"URL="+dFile.url); } - if( dFile.isHidden && autofile ){ info.insert(insertloc,"Hidden=true"); } - else if(dFile.isHidden){ info.insert(insertloc,"NoDisplay=true"); } - if( dFile.useTerminal){ info.insert(insertloc,"Terminal=true"); } - if( dFile.startupNotify ){ info.insert(insertloc,"StartupNotify=true"); } - - //Now save the file - return LUtils::writeFile(dFile.filePath, info, true); - -} - -bool LXDG::checkValidity(XDGDesktop dFile, bool showAll){ - bool ok=true; - bool DEBUG = false; - if(DEBUG){ qDebug() << "[LXDG] Check File validity:" << dFile.name << dFile.filePath; } - switch (dFile.type){ - case XDGDesktop::BAD: - ok=false; - if(DEBUG){ qDebug() << " - Bad file type"; } - break; - case XDGDesktop::APP: - if(!dFile.tryexec.isEmpty() && !LXDG::checkExec(dFile.tryexec)){ ok=false; if(DEBUG){ qDebug() << " - tryexec does not exist";} } - else if(dFile.exec.isEmpty() || dFile.name.isEmpty()){ ok=false; if(DEBUG){ qDebug() << " - exec or name is empty";} } - else if(!LXDG::checkExec(dFile.exec.section(" ",0,0,QString::SectionSkipEmpty)) ){ ok=false; if(DEBUG){ qDebug() << " - first exec binary does not exist";} } - break; - case XDGDesktop::LINK: - ok = !dFile.url.isEmpty(); - if(DEBUG && !ok){ qDebug() << " - Link with missing URL"; } - break; - case XDGDesktop::DIR: - ok = !dFile.path.isEmpty(); - if(DEBUG && !ok){ qDebug() << " - Dir with missing path"; } - break; - default: - ok=false; - if(DEBUG){ qDebug() << " - Unknown file type"; } - } - if(!showAll){ - if(!dFile.showInList.isEmpty()){ ok = dFile.showInList.contains("Lumina", Qt::CaseInsensitive); } - else if(!dFile.notShowInList.isEmpty()){ ok = !dFile.notShowInList.contains("Lumina",Qt::CaseInsensitive); } - else if(dFile.name.isEmpty()){ ok = false; } - } - return ok; -} - bool LXDG::checkExec(QString exec){ //Return true(good) or false(bad) if(exec.startsWith("/")){ return QFile::exists(exec); } @@ -510,40 +623,28 @@ QStringList LXDG::systemApplicationDirs(){ return out; } -XDGDesktopList* LXDG::systemAppsList(){ - static XDGDesktopList *sysapps = new XDGDesktopList(0,true); //set this to automatically update as needed - if(sysapps->lastCheck.isNull()){ sysapps->updateList(); } //catch the first time the class was used, and prompt for an update right now - return sysapps; -} - -QList<XDGDesktop> LXDG::systemDesktopFiles(bool showAll, bool showHidden){ - //Quick overload for backwards compatibility which uses the static/global class for managing app entries - XDGDesktopList list(0, false); - return list.apps(showAll, showHidden); -} - -QHash<QString,QList<XDGDesktop> > LXDG::sortDesktopCats(QList<XDGDesktop> apps){ +QHash<QString,QList<XDGDesktop*> > LXDG::sortDesktopCats(QList<XDGDesktop*> apps){ //Sort the list of applications into their different categories (main categories only) //Create the category lists - QList<XDGDesktop> multimedia, dev, ed, game, graphics, network, office, science, settings, sys, utility, other, wine; + QList<XDGDesktop*> multimedia, dev, ed, game, graphics, network, office, science, settings, sys, utility, other, wine; //Sort the apps into the lists for(int i=0; i<apps.length(); i++){ - if(apps[i].catList.contains("AudioVideo")){ multimedia << apps[i]; } - else if(apps[i].catList.contains("Development")){ dev << apps[i]; } - else if(apps[i].catList.contains("Education")){ ed << apps[i]; } - else if(apps[i].catList.contains("Game")){ game << apps[i]; } - else if(apps[i].catList.contains("Graphics")){ graphics << apps[i]; } - else if(apps[i].catList.contains("Network")){ network << apps[i]; } - else if(apps[i].catList.contains("Office")){ office << apps[i]; } - else if(apps[i].catList.contains("Science")){ science << apps[i]; } - else if(apps[i].catList.contains("Settings")){ settings << apps[i]; } - else if(apps[i].catList.contains("System")){ sys << apps[i]; } - else if(apps[i].catList.contains("Utility")){ utility << apps[i]; } - else if(apps[i].catList.contains("Wine")){ wine << apps[i]; } + if(apps[i]->catList.contains("AudioVideo")){ multimedia << apps[i]; } + else if(apps[i]->catList.contains("Development")){ dev << apps[i]; } + else if(apps[i]->catList.contains("Education")){ ed << apps[i]; } + else if(apps[i]->catList.contains("Game")){ game << apps[i]; } + else if(apps[i]->catList.contains("Graphics")){ graphics << apps[i]; } + else if(apps[i]->catList.contains("Network")){ network << apps[i]; } + else if(apps[i]->catList.contains("Office")){ office << apps[i]; } + else if(apps[i]->catList.contains("Science")){ science << apps[i]; } + else if(apps[i]->catList.contains("Settings")){ settings << apps[i]; } + else if(apps[i]->catList.contains("System")){ sys << apps[i]; } + else if(apps[i]->catList.contains("Utility")){ utility << apps[i]; } + else if(apps[i]->catList.contains("Wine")){ wine << apps[i]; } else{ other << apps[i]; } } //Now create the output hash - QHash<QString,QList<XDGDesktop> > out; + QHash<QString,QList<XDGDesktop*> > out; if(!multimedia.isEmpty()){ out.insert("Multimedia", LXDG::sortDesktopNames(multimedia)); } if(!dev.isEmpty()){ out.insert("Development", LXDG::sortDesktopNames(dev)); } if(!ed.isEmpty()){ out.insert("Education", LXDG::sortDesktopNames(ed)); } @@ -579,62 +680,22 @@ QString LXDG::DesktopCatToIcon(QString cat){ return icon; } -QList<XDGDesktop> LXDG::sortDesktopNames(QList<XDGDesktop> apps){ +QList<XDGDesktop*> LXDG::sortDesktopNames(QList<XDGDesktop*> apps){ //Sort the list by name of the application - QHash<QString, XDGDesktop> sorter; + QHash<QString, XDGDesktop*> sorter; for(int i=0; i<apps.length(); i++){ - sorter.insert(apps[i].name.toLower(), apps[i]); + sorter.insert(apps[i]->name.toLower(), apps[i]); } QStringList keys = sorter.keys(); keys.sort(); //Re-assemble the output list - QList<XDGDesktop> out; + QList<XDGDesktop*> out; for(int i=0; i<keys.length(); i++){ out << sorter[keys[i]]; } return out; } -QString LXDG::getDesktopExec(XDGDesktop app, QString ActionID){ - //Generate the executable line for the application - QString out; - QString exec = app.exec; - if( !ActionID.isEmpty() ){ - //Go through and grab the proper exec for the listed action - for(int i=0; i<app.actions.length(); i++){ - if(app.actions[i].ID == ActionID){ - exec = app.actions[i].exec; - break; - } - } - } - - if(exec.isEmpty()){ return ""; } - else if(app.useTerminal){ - //Get the currently default terminal - QString term = findDefaultAppForMime("application/terminal"); - if(!QFile::exists(term)){ term = "xterm -lc"; } - else if(term.endsWith(".desktop")){ - bool ok = false; - XDGDesktop DF = LXDG::loadDesktopFile(term, ok); - if(ok){ term = LXDG::getDesktopExec(DF); } - else{ term = "xterm -lc"; } - }else if( !LUtils::isValidBinary(term)){ term = "xterm -lc"; } - out = term+" -e "+exec; //-e is a nearly-universal flag for terminal emulators - }else{ - out =exec; - } - //Now perform any of the XDG flag substitutions as appropriate (9/2014 standards) - if(out.contains("%i") && !app.icon.isEmpty() ){ out.replace("%i", "--icon \'"+app.icon+"\'"); } - if(out.contains("%c")){ - if(!app.name.isEmpty()){ out.replace("%c", "\'"+app.name+"\'"); } - else if(!app.genericName.isEmpty()){ out.replace("%c", "\'"+app.genericName+"\'"); } - else{ out.replace("%c", "\'"+app.filePath.section("/",-1).section(".desktop",0,0)+"\'"); } - } - if(out.contains("%k")){ out.replace("%k", "\'"+app.filePath+"\'"); } - return out; -} - void LXDG::setEnvironmentVars(){ //Set the default XDG environment variables if not already set setenv("XDG_DATA_HOME",QString(QDir::homePath()+"/.local/share").toUtf8(), 0); @@ -1107,19 +1168,23 @@ QStringList LXDG::loadMimeFileGlobs2(){ } file.close(); } - } + if(i==dirs.length()-1 && mimeglobs.isEmpty()){ + //Could not find the mimetype database on the system - use the fallback file distributed with Lumina + dirs << LOS::LuminaShare(); + } + }//end loop over dirs } return mimeglobs; } //Find all the autostart *.desktop files -QList<XDGDesktop> LXDG::findAutoStartFiles(bool includeInvalid){ +QList<XDGDesktop*> LXDG::findAutoStartFiles(bool includeInvalid){ //First get the list of directories to search (system first, user-provided files come later and overwrite sys files as needed) QStringList paths = QString(getenv("XDG_CONFIG_DIRS")).split(":"); paths << QString(getenv("XDG_CONFIG_HOME")).split(":"); //Now go through them and find any valid *.desktop files - QList<XDGDesktop> files; + QList<XDGDesktop*> files; QStringList filenames; //make it easy to see if this filename is an override QDir dir; for(int i=0;i<paths.length(); i++){ @@ -1127,23 +1192,23 @@ QList<XDGDesktop> LXDG::findAutoStartFiles(bool includeInvalid){ dir.cd(paths[i]+"/autostart"); QStringList tmp = dir.entryList(QStringList() << "*.desktop", QDir::Files, QDir::Name); for(int t=0; t<tmp.length(); t++){ - bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(dir.absoluteFilePath(tmp[t]), ok); - if(!ok){ continue; } //could not read file + XDGDesktop *desk = new XDGDesktop(dir.absoluteFilePath(tmp[t])); + if(desk->type == XDGDesktop::BAD){ continue; } //could not read file //Now figure out what to do with it if(filenames.contains(tmp[t])){ //This is an overwrite of a lower-priority (system?) autostart file // find the other file int old = -1; for(int o=0; o<files.length(); o++){ - if(files[o].filePath.endsWith("/"+tmp[t])){ old = o; break; } //found it + if(files[o]->filePath.endsWith("/"+tmp[t])){ old = o; break; } //found it } - if(LXDG::checkValidity(desk, false)){ + if(desk->isValid(false)){ //Full override of the lower-priority file (might be replacing exec/tryexec fields) - files[old] = desk; + files.takeAt(old)->deleteLater(); + files.insert(old,desk); }else{ //Small override file (only the "Hidden" field listed in spec) - files[old].isHidden = desk.isHidden; //replace this value with the override + files[old]->isHidden = desk->isHidden; //replace this value with the override //files << desk; //still add this to the array (will be ignored/skipped later) } }else{ @@ -1157,18 +1222,17 @@ QList<XDGDesktop> LXDG::findAutoStartFiles(bool includeInvalid){ //Now filter the results by validity if desired if(!includeInvalid){ for(int i=0; i<files.length(); i++){ - if( !LXDG::checkValidity(files[i], false) || files[i].isHidden ){ + if( !files[i]->isValid(false) || files[i]->isHidden ){ //Invalid file - go ahead and remove it from the output list - files.removeAt(i); + files.takeAt(i)->deleteLater(); i--; } } } - return files; } -bool LXDG::setAutoStarted(bool autostart, XDGDesktop app){ +/*bool LXDG::setAutoStarted(bool autostart, XDGDesktop *app){ //First get the list of system directories to search (system first, user-provided files come later and overwrite sys files as needed) QStringList paths = QString(getenv("XDG_CONFIG_DIRS")).split(":"); QString upath = QString(getenv("XDG_CONFIG_HOME")).section(":",0,0); @@ -1181,12 +1245,12 @@ bool LXDG::setAutoStarted(bool autostart, XDGDesktop app){ } //Quick check/finish for user-defined files which are getting disabled (just remove the file) - if(app.filePath.startsWith(upath) && !autostart){ - return QFile::remove(app.filePath); + if(app->filePath.startsWith(upath) && !autostart){ + return QFile::remove(app->filePath); } bool sysfile = false; for(int i=0; i<paths.length(); i++){ - if(app.filePath.startsWith(paths[i]+"/autostart/") ){ + if(app->filePath.startsWith(paths[i]+"/autostart/") ){ sysfile = true; //Change it to the user-modifiable directory app.filePath = app.filePath.replace(paths[i]+"/autostart/", upath); @@ -1226,18 +1290,18 @@ bool LXDG::setAutoStarted(bool autostart, XDGDesktop app){ saved = LXDG::saveDesktopFile(app); } return saved; -} +}*/ bool LXDG::setAutoStarted(bool autostart, QString filePath){ //Convenience function for the auto-start setter - XDGDesktop desk; - if(filePath.endsWith(".desktop")){ - bool ok = false; - desk = LXDG::loadDesktopFile(filePath, ok); - if(!ok){ return false; } //error reading input file - }else{ + XDGDesktop desk(filePath); + if(!filePath.endsWith(".desktop")){ + //bool ok = false; + //desk = LXDG::loadDesktopFile(filePath, ok); + //if(!ok){ return false; } //error reading input file + //}else{ desk.filePath = filePath; desk.useTerminal = false; } - return LXDG::setAutoStarted(autostart, desk); + return desk.setAutoStarted(autostart); } diff --git a/src-qt5/core/libLumina/LuminaXDG.h b/src-qt5/core/libLumina/LuminaXDG.h index 996e5a20..1c86cedb 100644 --- a/src-qt5/core/libLumina/LuminaXDG.h +++ b/src-qt5/core/libLumina/LuminaXDG.h @@ -35,8 +35,8 @@ // ====================== // FreeDesktop Desktop Actions Framework (data structure) // ====================== -class XDGDesktopAction{ -public: +struct XDGDesktopAction{ +//public: //Admin variables QString ID; //The ID name for this action (should correspond to an entry in the "actionList" for the XDGDesktop below) //General Variables @@ -46,9 +46,11 @@ public: // ====================== // FreeDesktop Desktop Entry Framework (data structure) // ====================== -class XDGDesktop{ +class XDGDesktop : public QObject{ + Q_OBJECT public: enum XDGDesktopType { BAD, APP, LINK, DIR }; + //Admin variables QString filePath; //which file this structure contains the information for (absolute path) QDateTime lastRead; //when this structure was created from the file @@ -62,12 +64,24 @@ public: QStringList actionList, mimeList, catList, keyList; bool useTerminal, startupNotify; QList<XDGDesktopAction> actions; + //Type 1 Extensions for Lumina (Optional) + bool useVGL; //X-VGL + //Type 2 (LINK) variables QString url; - - //Constructor/destructor - XDGDesktop(){} - ~XDGDesktop(){} + + //Constructor/destructor + XDGDesktop(QString filePath="", QObject *parent = 0); + ~XDGDesktop(){} + + //Functions for using this structure in various ways + void sync(); //syncronize this structure with the backend file(as listed in the "filePath" variable) + bool isValid(bool showAll = true); //See if this is a valid .desktop entry (showAll: don't filter out based on DE exclude/include lists) + + QString getDesktopExec(QString ActionID = ""); + bool saveDesktopFile(bool merge = true); //This will use the "filePath" variable for where to save the file + + bool setAutoStarted(bool autostart = true); }; // ======================== @@ -80,12 +94,12 @@ public: XDGDesktopList(QObject *parent = 0, bool watchdirs = false); ~XDGDesktopList(); //Main Interface functions - QList<XDGDesktop> apps(bool showAll, bool showHidden); //showAll: include invalid files, showHidden: include NoShow/Hidden files + QList<XDGDesktop*> apps(bool showAll, bool showHidden); //showAll: include invalid files, showHidden: include NoShow/Hidden files //Administration variables (not typically used directly) QDateTime lastCheck; QStringList newApps, removedApps; //list of "new/removed" apps found during the last check - QHash<QString, XDGDesktop> files; //<filepath>/<XDGDesktop structure> + QHash<QString, XDGDesktop*> files; //<filepath>/<XDGDesktop structure> public slots: void updateList(); //run the check routine @@ -93,6 +107,7 @@ public slots: private: QFileSystemWatcher *watcher; QTimer *synctimer; + bool keepsynced; private slots: void watcherChanged(); @@ -107,15 +122,18 @@ signals: class LFileInfo : public QFileInfo{ private: QString mime, icon; - XDGDesktop desk; + XDGDesktop *desk; void loadExtraInfo(); public: //Couple overloaded contructors + LFileInfo(); LFileInfo(QString filepath); LFileInfo(QFileInfo info); - ~LFileInfo(){} + ~LFileInfo(){ + desk->deleteLater(); + } //Functions for accessing the extra information // -- Return the mimetype for the file @@ -142,25 +160,25 @@ typedef QList<LFileInfo> LFileInfoList; class LXDG{ public: //Read/write a *.desktop file - static XDGDesktop loadDesktopFile(QString filePath, bool& ok); - static bool saveDesktopFile(XDGDesktop dFile, bool merge = true); + //static XDGDesktop* loadDesktopFile(QString filepath, bool&ok, QObject *parent = 0); + //static bool saveDesktopFile(XDGDesktop *dFile, bool merge = true); //Check a *.desktop file for validity (showAll skips the DE-exclusivity checks) - static bool checkValidity(XDGDesktop dFile, bool showAll = true); + //static bool checkValidity(XDGDesktop *dFile, bool showAll = true); //Check for a valid executable static bool checkExec(QString exec); //Get a list of all the directories where *.desktop files exist static QStringList systemApplicationDirs(); //Get a list of all the *.desktop files available on the system - static XDGDesktopList* systemAppsList(); //return a pointer to the entire class - static QList<XDGDesktop> systemDesktopFiles(bool showAll = false, bool showHidden = false); //simplification for getting just the files + //static XDGDesktopList* systemAppsList(); //return a pointer to the entire class + //static QList<XDGDesktop*> systemDesktopFiles(bool showAll = false, bool showHidden = false); //simplification for getting just the files //Sort a list of Desktop files into the proper categories - static QHash< QString, QList<XDGDesktop> > sortDesktopCats(QList<XDGDesktop> apps); + static QHash< QString, QList<XDGDesktop*> > sortDesktopCats(QList<XDGDesktop*> apps); //Return the icon to use for the given category static QString DesktopCatToIcon(QString cat); //Sort a list of Desktop files by name - static QList<XDGDesktop> sortDesktopNames(QList<XDGDesktop> apps); + static QList<XDGDesktop*> sortDesktopNames(QList<XDGDesktop*> apps); //Get the executable line from a Desktop file - static QString getDesktopExec(XDGDesktop app, QString ActionID = ""); + //static QString getDesktopExec(XDGDesktop *app, QString ActionID = ""); //Set all the default XDG Environment variables static void setEnvironmentVars(); //Find an icon from the current/default theme @@ -191,8 +209,8 @@ public: static QStringList loadMimeFileGlobs2(); //Find all the autostart *.desktop files - static QList<XDGDesktop> findAutoStartFiles(bool includeInvalid = false); - static bool setAutoStarted(bool autostart, XDGDesktop app); + static QList<XDGDesktop*> findAutoStartFiles(bool includeInvalid = false); + //static bool setAutoStarted(bool autostart, XDGDesktop *app); static bool setAutoStarted(bool autostart, QString filePath); //for convenience }; diff --git a/src-qt5/core/libLumina/LuminaXDG.pri b/src-qt5/core/libLumina/LuminaXDG.pri new file mode 100644 index 00000000..6f3a2b7c --- /dev/null +++ b/src-qt5/core/libLumina/LuminaXDG.pri @@ -0,0 +1,10 @@ +QT *= multimedia svg + +#LUtils Files +SOURCES *= $${PWD}/LuminaXDG.cpp +HEADERS *= $${PWD}/LuminaXDG.h + +INCLUDEPATH *= ${PWD} + +#include LUtils and LuminaOS +include(LUtils.pri) diff --git a/src-qt5/core/libLumina/ResizeMenu.cpp b/src-qt5/core/libLumina/ResizeMenu.cpp new file mode 100644 index 00000000..9f291134 --- /dev/null +++ b/src-qt5/core/libLumina/ResizeMenu.cpp @@ -0,0 +1,106 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2013-2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "ResizeMenu.h" + +// ======================= +// RESIZEMENU CLASS +// ======================= +ResizeMenu::ResizeMenu(QWidget *parent) : QMenu(parent){ + this->setContentsMargins(1,1,1,1); + this->setMouseTracking(true); + resizeSide = NONE; + cAct = new QWidgetAction(this); + contents = 0; + connect(this, SIGNAL(aboutToShow()), this, SLOT(clearFlags()) ); + connect(this, SIGNAL(aboutToHide()), this, SLOT(clearFlags()) ); + connect(cAct, SIGNAL(hovered()), this, SLOT(clearFlags()) ); +} + +ResizeMenu::~ResizeMenu(){ + +} + +void ResizeMenu::setContents(QWidget *con){ + this->clear(); + cAct->setDefaultWidget(con); + this->addAction(cAct); + contents = con; //save for later + contents->setCursor(Qt::ArrowCursor); +} + +void ResizeMenu::mouseMoveEvent(QMouseEvent *ev){ + QRect geom = this->geometry(); + //Note: The exact position does not matter as much as the size + // since the window will be moved again the next time it is shown + // The "-2" in the sizing below accounts for the menu margins + QPoint gpos = this->mapToGlobal(ev->pos()); + bool handled = false; + switch(resizeSide){ + case TOP: + if(gpos.y() >= geom.bottom()-1){ break; } + geom.setTop(gpos.y()); + this->setGeometry(geom); + if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} + handled = true; + break; + case BOTTOM: + if(gpos.y() <= geom.top()+1){ break; } + geom.setBottom( gpos.y()); + this->setGeometry(geom); + if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} + handled = true; + break; + case LEFT: + if(gpos.x() >= geom.right()-1){ break; } + geom.setLeft(gpos.x()); + this->setGeometry(geom); + if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} + handled = true; + break; + case RIGHT: + if(gpos.x() <= geom.left()+1){ break; } + geom.setRight(gpos.x()); + this->setGeometry(geom); + if(contents!=0){ contents->setFixedSize(QSize(geom.width()-2, geom.height()-2));} + handled = true; + break; + default: //NONE + //qDebug() << " - Mouse At:" << ev->pos(); + //Just adjust the mouse cursor which is shown + if(ev->pos().x()<=1 && ev->pos().x() >= -1){ this->setCursor(Qt::SizeHorCursor); } + else if(ev->pos().x() >= this->width()-1 && ev->pos().x() <= this->width()+1){ this->setCursor(Qt::SizeHorCursor); } + else if(ev->pos().y()<=1 && ev->pos().y() >= -1){ this->setCursor(Qt::SizeVerCursor); } + else if(ev->pos().y() >= this->height()-1 && ev->pos().y() <= this->height()+1){ this->setCursor(Qt::SizeVerCursor); } + else{ this->setCursor(Qt::ArrowCursor); } + } + if(!handled){ QMenu::mouseMoveEvent(ev); } //do normal processing as well +} + +void ResizeMenu::mousePressEvent(QMouseEvent *ev){ + bool used = false; + if(ev->buttons().testFlag(Qt::LeftButton) && resizeSide==NONE){ + //qDebug() << "Mouse Press Event:" << ev->pos() << resizeSide; + if(ev->pos().x()<=1 && ev->pos().x() >= -1){resizeSide = LEFT; used = true;} + else if(ev->pos().x() >= this->width()-1 && ev->pos().x() <= this->width()+1){ resizeSide = RIGHT; used = true;} + else if(ev->pos().y()<=1 && ev->pos().y() >= -1){ resizeSide = TOP; used = true; } + else if(ev->pos().y() >= this->height()-1 && ev->pos().y() <= this->height()+1){ resizeSide = BOTTOM; used = true; } + } + if(used){ ev->accept(); this->grabMouse(); } + else{ QMenu::mousePressEvent(ev); } //do normal processing +} + +void ResizeMenu::mouseReleaseEvent(QMouseEvent *ev){ + this->releaseMouse(); + if(ev->button() == Qt::LeftButton && resizeSide!=NONE ){ + //qDebug() << "Mouse Release Event:" << ev->pos() << resizeSide; + resizeSide = NONE; + emit MenuResized(contents->size()); + ev->accept(); + }else{ + QMenu::mouseReleaseEvent(ev); //do normal processing + } +} diff --git a/src-qt5/core/libLumina/ResizeMenu.h b/src-qt5/core/libLumina/ResizeMenu.h new file mode 100644 index 00000000..ed909da3 --- /dev/null +++ b/src-qt5/core/libLumina/ResizeMenu.h @@ -0,0 +1,51 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2012-2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_LIBRARY_RESIZE_MENU_H +#define _LUMINA_LIBRARY_RESIZE_MENU_H + +#include <QMenu> +#include <QWidget> +#include <QMouseEvent> +#include <QAction> +#include <QWidgetAction> +#include <QRect> +#include <QCursor> +#include <QPoint> + +//Special subclass for a menu which the user can grab the edges and resize as necessary +// Note: Make sure that you don't set 0pixel contents margins on this menu +// - it needs at least 1 pixel margins for the user to be able to grab it +class ResizeMenu : public QMenu{ + Q_OBJECT +public: + ResizeMenu(QWidget *parent = 0); + virtual ~ResizeMenu(); + + void setContents(QWidget *con); + +private: + enum SideFlag{NONE, TOP, BOTTOM, LEFT, RIGHT}; + SideFlag resizeSide; + QWidget *contents; + QWidgetAction *cAct; + +private slots: + void clearFlags(){ + resizeSide=NONE; + } + +protected: + virtual void mouseMoveEvent(QMouseEvent *ev); + virtual void mousePressEvent(QMouseEvent *ev); + virtual void mouseReleaseEvent(QMouseEvent *ev); + +signals: + void MenuResized(QSize); //Emitted when the menu is manually resized by the user + +}; + +#endif diff --git a/src-qt5/core/libLumina/ResizeMenu.pri b/src-qt5/core/libLumina/ResizeMenu.pri new file mode 100644 index 00000000..247427f1 --- /dev/null +++ b/src-qt5/core/libLumina/ResizeMenu.pri @@ -0,0 +1,6 @@ +#Subproject file for bundling the ResizeMenu class into an application +SOURCES *= $${PWD}/ResizeMenu.cpp +HEADERS *= $${PWD}/ResizeMenu.h +#Add this dir to the include path +# This allows the application to simply use "#include <ResizeMenu.h>" to use it +INCLUDEPATH *= $${PWD} diff --git a/src-qt5/core/libLumina/colors/Black.qss.colors b/src-qt5/core/libLumina/colors/Black.qss.colors deleted file mode 100644 index b6269188..00000000 --- a/src-qt5/core/libLumina/colors/Black.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(204,204,204,200) -ACCENTDISABLECOLOR=rgba(204,204,204,100) -ALTBASECOLOR=rgb(37,37,37) -BASECOLOR=rgb(36,36,36) -HIGHLIGHTCOLOR=rgba(218,222,226,170) -HIGHLIGHTDISABLECOLOR=rgba(218,222,226,160) -PRIMARYCOLOR=rgba(0,0,4,250) -PRIMARYDISABLECOLOR=rgba(0,0,0,180) -SECONDARYCOLOR=rgba(192,192,192,200) -SECONDARYDISABLECOLOR=rgba(192,192,192,100) -TEXTCOLOR=white -TEXTDISABLECOLOR=darkgrey -TEXTHIGHLIGHTCOLOR=black diff --git a/src-qt5/core/libLumina/colors/Blue-Light.qss.colors b/src-qt5/core/libLumina/colors/Blue-Light.qss.colors deleted file mode 100644 index 5bcb85f6..00000000 --- a/src-qt5/core/libLumina/colors/Blue-Light.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(157,161,165,200) -ACCENTDISABLECOLOR=rgba(156,156,157,200) -ALTBASECOLOR=rgb(239,247,255) -BASECOLOR=rgb(165,210,255) -HIGHLIGHTCOLOR=rgb(110,158,208) -HIGHLIGHTDISABLECOLOR=rgba(110,158,208,150) -PRIMARYCOLOR=rgba(181,212,238,200) -PRIMARYDISABLECOLOR=rgba(234,237,238,100) -SECONDARYCOLOR=rgba(200,222,243,200) -SECONDARYDISABLECOLOR=rgba(200,222,243,100) -TEXTCOLOR=black -TEXTDISABLECOLOR=grey -TEXTHIGHLIGHTCOLOR=black diff --git a/src-qt5/core/libLumina/colors/Grey-Dark.qss.colors b/src-qt5/core/libLumina/colors/Grey-Dark.qss.colors deleted file mode 100644 index 207edd04..00000000 --- a/src-qt5/core/libLumina/colors/Grey-Dark.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(43,43,45,200) -ACCENTDISABLECOLOR=rgba(43,43,45,100) -ALTBASECOLOR=rgb(63,61,61) -BASECOLOR=rgb(93,92,92) -HIGHLIGHTCOLOR=rgba(218,222,226,170) -HIGHLIGHTDISABLECOLOR=rgba(218,222,226,160) -PRIMARYCOLOR=rgba(75,77,80,240) -PRIMARYDISABLECOLOR=rgba(75,77,80,180) -SECONDARYCOLOR=rgba(144,140,142,200) -SECONDARYDISABLECOLOR=rgba(144,140,142,100) -TEXTCOLOR=white -TEXTDISABLECOLOR=darkgrey -TEXTHIGHLIGHTCOLOR=black diff --git a/src-qt5/core/libLumina/colors/Lumina-Glass.qss.colors b/src-qt5/core/libLumina/colors/Lumina-Glass.qss.colors deleted file mode 100644 index 89534aaa..00000000 --- a/src-qt5/core/libLumina/colors/Lumina-Glass.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(255,252,234,100) -ACCENTDISABLECOLOR=rgba(0,0,0,100) -ALTBASECOLOR=rgba(255,255,255,125) -BASECOLOR=rgb(247,246,244) -HIGHLIGHTCOLOR=rgba(212,212,212,170) -HIGHLIGHTDISABLECOLOR=rgba(184,184,184,100) -PRIMARYCOLOR=rgba(235,242,242,200) -PRIMARYDISABLECOLOR=rgba(214,220,220,200) -SECONDARYCOLOR=rgba(100,100,100,200) -SECONDARYDISABLECOLOR=rgba(100,100,100,100) -TEXTCOLOR=black -TEXTDISABLECOLOR=grey -TEXTHIGHLIGHTCOLOR=black diff --git a/src-qt5/core/libLumina/colors/Lumina-Gold.qss.colors b/src-qt5/core/libLumina/colors/Lumina-Gold.qss.colors deleted file mode 100644 index cfad7069..00000000 --- a/src-qt5/core/libLumina/colors/Lumina-Gold.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(149,144,122,200) -ACCENTDISABLECOLOR=rgba(74,71,60,200) -ALTBASECOLOR=rgb(230,227,204) -BASECOLOR=rgb(247,247,240) -HIGHLIGHTCOLOR=rgba(252,237,149,170) -HIGHLIGHTDISABLECOLOR=rgba(252,237,149,100) -PRIMARYCOLOR=rgba(238,234,226,200) -PRIMARYDISABLECOLOR=rgba(238,235,224,100) -SECONDARYCOLOR=rgba(247,209,112,200) -SECONDARYDISABLECOLOR=rgba(234,198,106,150) -TEXTCOLOR=black -TEXTDISABLECOLOR=grey -TEXTHIGHLIGHTCOLOR=black
\ No newline at end of file diff --git a/src-qt5/core/libLumina/colors/Lumina-Green.qss.colors b/src-qt5/core/libLumina/colors/Lumina-Green.qss.colors deleted file mode 100644 index 99f16acb..00000000 --- a/src-qt5/core/libLumina/colors/Lumina-Green.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(149,144,122,200) -ACCENTDISABLECOLOR=rgba(74,71,60,200) -ALTBASECOLOR=rgb(230,230,230) -BASECOLOR=rgb(247,246,244) -HIGHLIGHTCOLOR=rgba(66,153,76,170) -HIGHLIGHTDISABLECOLOR=rgba(66,153,76,100) -PRIMARYCOLOR=rgba(229,231,238,200) -PRIMARYDISABLECOLOR=rgba(229,231,238,100) -SECONDARYCOLOR=rgba(76,197,84,200) -SECONDARYDISABLECOLOR=rgba(76,197,84,150) -TEXTCOLOR=black -TEXTDISABLECOLOR=grey -TEXTHIGHLIGHTCOLOR=black diff --git a/src-qt5/core/libLumina/colors/Lumina-Purple.qss.colors b/src-qt5/core/libLumina/colors/Lumina-Purple.qss.colors deleted file mode 100644 index f2ba7e05..00000000 --- a/src-qt5/core/libLumina/colors/Lumina-Purple.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(247,231,255,200) -ACCENTDISABLECOLOR=rgba(167,166,166,200) -ALTBASECOLOR=rgb(63,61,61) -BASECOLOR=rgb(93,92,92) -HIGHLIGHTCOLOR=rgba(76,38,171,170) -HIGHLIGHTDISABLECOLOR=rgba(57,19,139,170) -PRIMARYCOLOR=rgba(65,67,80,240) -PRIMARYDISABLECOLOR=rgba(65,67,80,180) -SECONDARYCOLOR=rgba(74,65,120,200) -SECONDARYDISABLECOLOR=rgba(71,65,120,100) -TEXTCOLOR=white -TEXTDISABLECOLOR=darkgrey -TEXTHIGHLIGHTCOLOR=white
\ No newline at end of file diff --git a/src-qt5/core/libLumina/colors/Lumina-Red.qss.colors b/src-qt5/core/libLumina/colors/Lumina-Red.qss.colors deleted file mode 100644 index f73bdb75..00000000 --- a/src-qt5/core/libLumina/colors/Lumina-Red.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(255,244,245,200) -ACCENTDISABLECOLOR=rgba(167,166,166,200) -ALTBASECOLOR=rgb(63,61,61) -BASECOLOR=rgb(93,92,92) -HIGHLIGHTCOLOR=rgba(175,9,9,170) -HIGHLIGHTDISABLECOLOR=rgba(154,20,20,170) -PRIMARYCOLOR=rgba(80,66,66,240) -PRIMARYDISABLECOLOR=rgba(80,66,66,180) -SECONDARYCOLOR=rgba(120,22,23,200) -SECONDARYDISABLECOLOR=rgba(120,22,23,100) -TEXTCOLOR=white -TEXTDISABLECOLOR=darkgrey -TEXTHIGHLIGHTCOLOR=white
\ No newline at end of file diff --git a/src-qt5/core/libLumina/colors/PCBSD10-Default.qss.colors b/src-qt5/core/libLumina/colors/PCBSD10-Default.qss.colors deleted file mode 100644 index efcea51d..00000000 --- a/src-qt5/core/libLumina/colors/PCBSD10-Default.qss.colors +++ /dev/null @@ -1,13 +0,0 @@ -ACCENTCOLOR=rgba(182,186,191,200) -ACCENTDISABLECOLOR=rgba(190,190,191,200) -ALTBASECOLOR=rgb(241,241,241) -BASECOLOR=rgb(247,246,244) -HIGHLIGHTCOLOR=rgb(129,184,243) -HIGHLIGHTDISABLECOLOR=rgba(129,184,243,150) -PRIMARYCOLOR=rgba(224,236,238,200) -PRIMARYDISABLECOLOR=rgba(234,237,238,100) -SECONDARYCOLOR=rgba(200,222,243,200) -SECONDARYDISABLECOLOR=rgba(200,222,243,100) -TEXTCOLOR=black -TEXTDISABLECOLOR=grey -TEXTHIGHLIGHTCOLOR=black diff --git a/src-qt5/core/libLumina/colors/Solarized-Dark.qss.colors b/src-qt5/core/libLumina/colors/Solarized-Dark.qss.colors deleted file mode 100644 index d4f0f1c9..00000000 --- a/src-qt5/core/libLumina/colors/Solarized-Dark.qss.colors +++ /dev/null @@ -1,16 +0,0 @@ -# Solarized is a theme created by Ethan Schoonover -# See the project site at http://ethanschoonover.com/solarized -# Or see the source at https://github.com/altercation/solarized -ACCENTCOLOR=rgb(181,137,0) -ACCENTDISABLECOLOR=rgb(181,137,0) -ALTBASECOLOR=rgb(0,43,54) -BASECOLOR=rgb(0,43,54) -HIGHLIGHTCOLOR=rgb(7,54,66) -HIGHLIGHTDISABLECOLOR=rgb(7,53,66) -PRIMARYCOLOR=rgb(0,43,54) -PRIMARYDISABLECOLOR=rgb(7,54,66) -SECONDARYCOLOR=rgb(0,43,54) -SECONDARYDISABLECOLOR=rgb(7,54,66) -TEXTCOLOR=rgb(131,148,150) -TEXTDISABLECOLOR=rgb(88,110,117) -TEXTHIGHLIGHTCOLOR=rgb(147,161,161) diff --git a/src-qt5/core/libLumina/colors/Solarized-Light.qss.colors b/src-qt5/core/libLumina/colors/Solarized-Light.qss.colors deleted file mode 100644 index fead1915..00000000 --- a/src-qt5/core/libLumina/colors/Solarized-Light.qss.colors +++ /dev/null @@ -1,16 +0,0 @@ -# Solarized is a theme created by Ethan Schoonover -# See the project site at http://ethanschoonover.com/solarized -# Or see the source at https://github.com/altercation/solarized -ACCENTCOLOR=rgb(38,139,210) -ACCENTDISABLECOLOR=rgb(38,139,210) -ALTBASECOLOR=rgb(253,246,227) -BASECOLOR=rgb(253,246,227) -HIGHLIGHTCOLOR=rgb(238,232,213) -HIGHLIGHTDISABLECOLOR=rgb(238,232,213) -PRIMARYCOLOR=rgb(253,246,227) -PRIMARYDISABLECOLOR=rgb(238,232,213) -SECONDARYCOLOR=rgb(253,246,227) -SECONDARYDISABLECOLOR=rgb(238,232,213) -TEXTCOLOR=rgb(131,148,150) -TEXTDISABLECOLOR=rgb(147,161,161) -TEXTHIGHLIGHTCOLOR=rgb(88,110,117) diff --git a/src-qt5/core/libLumina/libLumina.pro b/src-qt5/core/libLumina/libLumina.pro deleted file mode 100644 index 7f9e4203..00000000 --- a/src-qt5/core/libLumina/libLumina.pro +++ /dev/null @@ -1,65 +0,0 @@ -include("$${PWD}/../../OS-detect.pri") - -QT += core network widgets x11extras multimedia concurrent svg - -define -#Setup any special defines (qmake -> C++) -GIT_VERSION=$$system(git describe --always) -!isEmpty(GIT_VERSION){ - DEFINES += GIT_VERSION='"\\\"$${GIT_VERSION}\\\""' -} -DEFINES += BUILD_DATE='"\\\"$$system(date)\\\""' - -TARGET=LuminaUtils - -target.path = $${L_LIBDIR} - -DESTDIR= $$_PRO_FILE_PWD_/ - -TEMPLATE = lib -LANGUAGE = C++ -VERSION = 1 - -HEADERS += LuminaXDG.h \ - LuminaUtils.h \ - LuminaX11.h \ - LuminaThemes.h \ - LuminaOS.h \ - LuminaSingleApplication.h - -SOURCES += LuminaXDG.cpp \ - LuminaUtils.cpp \ - LuminaX11.cpp \ - LuminaThemes.cpp \ - LuminaSingleApplication.cpp - -# Also load the OS template as available for -# LuminaOS support functions (or fall back to generic one) -exists($${PWD}/LuminaOS-$${LINUX_DISTRO}.cpp){ - SOURCES += LuminaOS-$${LINUX_DISTRO}.cpp -}else:exists($${PWD}/LuminaOS-$${OS}.cpp){ - SOURCES += LuminaOS-$${OS}.cpp -}else{ - SOURCES += LuminaOS-template.cpp -} - -LIBS += -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lXdamage - -include.path=$${L_INCLUDEDIR} -include.files=LuminaXDG.h \ - LuminaUtils.h \ - LuminaX11.h \ - LuminaThemes.h \ - LuminaOS.h \ - LuminaSingleApplication.h - -colors.path=$${L_SHAREDIR}/lumina-desktop/colors -colors.files=colors/*.qss.colors - -themes.path=$${L_SHAREDIR}/lumina-desktop/themes/ -themes.files=themes/*.qss.template - -#quickplugins.path=$${L_SHAREDIR}/lumina-desktop/quickplugins/ -#quickplugins.files=quickplugins/* - -INSTALLS += target include colors themes diff --git a/src-qt5/core/libLumina/quickplugins/quick-sample.qml b/src-qt5/core/libLumina/quickplugins/quick-sample.qml deleted file mode 100644 index 18b10d77..00000000 --- a/src-qt5/core/libLumina/quickplugins/quick-sample.qml +++ /dev/null @@ -1,12 +0,0 @@ -// Plugin-Name=Sample -// Plugin-Description=A simple example for QtQuick/QML plugins -// Plugin-Icon=preferences-plugin -// Created: Ken Moore (ken@pcbsd.org) May 2015 - -import QtQuick.Controls 1.3 - -Label { - text: "Sample" - color: "blue" - font.bold: true -}
\ No newline at end of file diff --git a/src-qt5/core/libLumina/themes/Glass.qss.template b/src-qt5/core/libLumina/themes/Glass.qss.template deleted file mode 100644 index d594d25e..00000000 --- a/src-qt5/core/libLumina/themes/Glass.qss.template +++ /dev/null @@ -1,539 +0,0 @@ -/* ALL THE TEMPLATE WIDGETS */ -INHERITS=None - -/* ALL THE WIDGETS WITH THE BASE COLOR */ -QMainWindow, QMenu, QDialog, QMessageBox{ - background: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 %%BASECOLOR%%, stop:1 %%ALTBASECOLOR%%); - color: %%TEXTCOLOR%%; - border: 1px solid %%ACCENTDISABLECOLOR%%; - border-radius: 3px; -} - -/* ALL THE WIDGETS WITH AN ALTERNATE BASE COLOR */ -QLineEdit, QTextEdit, QTextBrowser, QPlainTextEdit, QSpinBox, QDateEdit, QDateTimeEdit, QTimeEdit, QDoubleSpinBox{ - background: %%ALTBASECOLOR%%; - color: %%TEXTCOLOR%%; - border-color: %%ACCENTDISABLECOLOR%%; - selection-background-color: %%HIGHLIGHTCOLOR%%; - selection-color: %%TEXTHIGHLIGHTCOLOR%%; -} - -/* PAGES OF CONTAINER WIDGETS */ -QStackedWidget .QWidget{ - background: transparent; - color: %%TEXTCOLOR%%; - border: none; -} - -QToolBox::tab{ - color: %%TEXTCOLOR%%; -} - -/* MENU WIDGETS */ -QMenuBar, QMenuBar::item,QToolBar{ - background: transparent; - border: none; - color: %%TEXTCOLOR%%; -} - -QStatusBar{ - background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 transparent, stop: 0.5 %%SECONDARYCOLOR%%); - border: none; - color: %%TEXTCOLOR%%; -} -QToolBar:top{ - border-bottom: 1px solid %%ACCENTCOLOR%%; -} -QToolBar:bottom{ - border-top: 1px solid %%ACCENTCOLOR%%; -} -QToolBar:left{ - border-right: 1px solid %%ACCENTCOLOR%%; -} -QToolBar:right{ - border-left: 1px solid %%ACCENTCOLOR%%; -} - -QMenuBar::item{ - background: transparent; /*Use the menu bar color*/ - padding-left: 4px; - padding-right: 2px; -} - -QMenuBar::item:selected, QMenuBar::item:pressed, QMenu::item:selected{ -background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); -color: %%TEXTHIGHLIGHTCOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -} -QMenuBar::item:disabled{ - color: %%TEXTDISABLECOLOR%%; -} - -/*QMenu::item{ - border: 2px solid #808080; -}*/ - -QMenu::item{ - background: transparent; - border: 1px solid transparent; - color: %%TEXTCOLOR%%; - padding: 4px 30px 4px 20px; - margin-left: 3px; - margin-right: 3px; -} - -/* TAB WIDGETS */ -/*QTabBar{ - Custom Font settings need to be here and NOT in the ::tab fields, - otherwise it will break auto-scaling of the tab sizes to fit the text -}*/ -/* Transparency does not work on main pages within tabwidgets*/ -QTabWidget QStackedWidget .QWidget{ - background: rgb(230,230,230); - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; -} -QTabWidget{ - color: black; - border: none; -} -QTabWidget QLabel{ - color: black; -} -QTabBar::tab { - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%SECONDARYDISABLECOLOR%%, stop: 1 %%ALTBASECOLOR%%); - border: 1px solid %%ACCENTCOLOR%%; - padding: 2px; - color: %%TEXTCOLOR%%; -} -QTabBar::tab:top{ - border-top-left-radius: 4px; - border-top-right-radius: 4px; - max-width: 100em; - min-width: 0em; -} -QTabBar::tab:bottom{ - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - max-width: 100em; - min-width: 0em; -} -/* left/right tab indicators appear to be reversed in Qt*/ -QTabBar::tab:right{ - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - max-height: 100em; - min-height: 0em; -} -QTabBar::tab:left{ - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - max-height: 100em; - min-height: 0em; -} -QTabBar::tab:selected{ - background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 rgb(230,230,230)); - border-bottom: none; -} -QTabBar::tab:hover { - background: %%HIGHLIGHTCOLOR%%; - border: 1px solid %%ACCENTDISABLECOLOR%%; - } - -QTabBar::tab:!selected:top { - margin-top: 4px; -} -QTabBar::tab:!selected:bottom{ - margin-bottom: 4px; -} -QTabBar::tab:!selected:right{ - margin-left: 4px; -} -QTabBar::tab:!selected:left{ - margin-right: 4px; -} - -/* FRAME WIDGETS */ -QToolTip{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%BASECOLOR%%, stop: 1 %%ALTBASECOLOR%%); - border-radius: 3px; - border: 1px solid %%ACCENTCOLOR%%; - padding: 1px; - color: %%TEXTCOLOR%%; -} - -QLabel{ - background: transparent; - border: none; - color: %%TEXTCOLOR%%; -} -QAbstractButton::disabled{ - color: %%TEXTDISABLECOLOR%%; -} - -/* GROUP BOX */ -QGroupBox{ - background-color: transparent; - border-color: %%ACCENTCOLOR%%; - border-radius: 5px; - margin-top: 2ex; - font-weight: bold; -} -QGroupBox::title{ - subcontrol-origin: margin; - subcontrol-position: top center; - padding: 0 3px; - background: transparent; - /*border: none;*/ - color: %%TEXTCOLOR%%; -} - -/* COMBO BOX */ -QComboBox{ - /*border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; - padding: 1px 18px 1px 3px;*/ - color: %%TEXTCOLOR%%; - background: %%ALTBASECOLOR%%; - selection-background-color: %%HIGHLIGHTCOLOR%%; - } - - -/* VIEW WIDGETS */ -QTreeView, QListView{ - background: %%ALTBASECOLOR%%; - alternate-background-color: %%BASECOLOR%%; - /*selection-background-color: %%SECONDARYCOLOR%%;*/ - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; - /*show-decoration-selected: 1;*/ - color: %%TEXTCOLOR%%; - selection-color: %%TEXTCOLOR%%; -} - -QTreeView:focus, QListView:focus{ - border: 1px solid %%HIGHLIGHTDISABLECOLOR%%; -} - -/* -QTreeView::item and QListView::item unneccessary: -Already set though parentage and causes usage errors if set manually -*/ - -/*QTreeView::item:selected, QListView::item:selected{ - background: %%SECONDARYDISABLECOLOR%%; - border-color: %%ACCENTCOLOR%%; - color: %%TEXTCOLOR%%; -}*/ - -QTreeView::item:hover, QListView::item:hover{ - background: %%HIGHLIGHTDISABLECOLOR%%; -} -QTreeView::item:selected:hover, QListView::item:selected:hover{ - background: %%HIGHLIGHTDISABLECOLOR%%; -} -QTreeView::item:selected, QListView::item:selected{ - background: %%SECONDARYDISABLECOLOR%%; -} -QTreeView::item:selected:focus, QListView::item:selected:focus{ - background: %%SECONDARYCOLOR%%; -} -QHeaderView{ - background: %%HIGHLIGHTDISABLECOLOR%%; - color: %%TEXTHIGHLIGHTCOLOR%%; - border: none; - border-top-left-radius: 3px; /*match the list/tree view widgets*/ - border-top-right-radius: 3px; /*match the list/tree view widgets*/ -} -QHeaderView::section{ - background: %%HIGHLIGHTDISABLECOLOR%%; /*QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%PRIMARYDISABLECOLOR%%, stop: 1 %%PRIMARYCOLOR%%);*/ - color: %%TEXTHIGHLIGHTCOLOR%%; - border-color: %%ACCENTCOLOR%%; - padding: 1px; - padding-left: 4px; -} -QHeaderView::section:hover{ - background: %%PRIMARYCOLOR%%; - border-color: %%ACCENTDISABLECOLOR%%; - color: %%TEXTCOLOR%%; -} - -/* SCROLLBARS (NOTE: Changing 1 subcontrol means you have to change all of them)*/ -QScrollBar{ - background:%%ALTBASECOLOR%%; -} -QScrollBar:horizontal{ - margin: 0px 0px 0px 0px; -} -QScrollBar:vertical{ - margin: 0px 0px 0px 0px; -} -QScrollBar::handle{ - background: %%SECONDARYCOLOR%%; - border: 1px solid transparent; - border-radius: 7px; -} -QScrollBar::handle:hover, QScrollBar::add-line:hover, QScrollBar::sub-line:hover{ - background: %%SECONDARYDISABLECOLOR%%; -} -QScrollBar::add-line{ -subcontrol-origin: none; -} -QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical{ -height: 0px; -} -QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal{ -width: 0px; -} -QScrollBar::sub-line{ -subcontrol-origin: none; -} - -/* SLIDERS */ -QSlider::groove:horizontal { -border: 1px solid %%ACCENTCOLOR%%; -background: %%ALTBASECOLOR%%; -height: 10px; -border-radius: 3px; -} -QSlider::groove:vertical { -border: 1px solid %%ACCENTCOLOR%%; -background: %%ALTBASECOLOR%%; -width: 10px; -border-radius: 3px; -} -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, - stop: 0 %%HIGHLIGHTCOLOR%%, stop: 1 %%HIGHLIGHTDISABLECOLOR%%); -border: 1px solid %%ACCENTCOLOR%%; -height: 10px; -border-radius: 3px; -} -QSlider::sub-page:vertical { -background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, - stop: 0 %%HIGHLIGHTCOLOR%%, stop: 1 %%HIGHLIGHTDISABLECOLOR%%); -border: 1px solid %%ACCENTCOLOR%%; -width: 10px; -border-radius: 3px; -} -QSlider::add-page:horizontal{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -height: 10px; -border-radius: 3px; -} -QSlider::add-page:vertical{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -width: 10px; -border-radius: 3px; -} -QSlider::handle:horizontal{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -width: 13px; -border-radius: 4px; -} -QSlider::handle:vertical{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -height: 13px; -border-radius: 4px; -} -QSlider::handle:horizontal:hover, QSlider::handle:vertical:hover{ -border: 1px solid %%ACCENTDISABLECOLOR%%; -/*background: %%HIGHLIGHTCOLOR%%;*/ -} - -QSlider::sub-page:horizontal:disabled { -background: %%ACCENTDISABLECOLOR%%; -border-color: %%ACCENTCOLOR%%; -} - -QSlider::add-page:horizontal:disabled { -background: %%ACCENTDISABLECOLOR%%; -border-color: %%ACCENTCOLOR%%; -} - -QSlider::handle:horizontal:disabled { -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -} - -/* BUTTONS */ -QPushButton{ - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%SECONDARYDISABLECOLOR%%, stop: 1 %%SECONDARYCOLOR%%); - padding: 2px; - padding-right: 4px; - color: %%TEXTCOLOR%%; - } - -QToolButton{ /* Assume a flat button for every toolbutton by default*/ - color: %%TEXTCOLOR%%; - border: 1px solid transparent; - border-radius: 3px; - background-color: transparent; - padding: 1px; -} - - QPushButton:pressed, QPushButton:open, QPushButton:selected, QPushButton:checked, QPushButton:on, QToolButton:pressed, QToolButton:open, QToolButton:selected, QToolButton:checked, QToolButton:on{ - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); - margin-top: 2px; - } - -QPushButton:flat, QToolButton:flat{ - background-color: transparent; - border: 1px solid transparent; /* no border for a flat button */ -} - -QPushButton:hover, QToolButton:hover{ - border: 1px solid %%ACCENTCOLOR%%; - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); - color: %%TEXTHIGHLIGHTCOLOR%%; -} -QRadioButton, QCheckBox{ - padding: 2px; - border: 1px solid transparent; - border-radius: 3px; - color: %%TEXTCOLOR%%; -} -QRadioButton::hover, QCheckBox:hover{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); - border: 1px solid %%ACCENTCOLOR%%; - color: %%TEXTHIGHLIGHTCOLOR%%; -} -QRadioButton::indicator, QCheckBox::indicator, QGroupBox::indicator{ - border: 1px solid %%TEXTCOLOR%%; -} -QRadioButton::indicator{ - border-radius: 7px; -} -QRadioButton::indicator:checked{ - background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:1, fx:0.5, fy:0.5, stop:0 %%TEXTCOLOR%%, stop:0.25 %%TEXTCOLOR%%, stop:0.25001 transparent); -} -QCheckBox::indicator:checked, QGroupBox::indicator:checked{ - padding: 1px; - background-origin: content; - background-clip: content; - background: %%TEXTCOLOR%%; -} -QCheckBox::indicator:indeterminate, QGroupBox::indicator:indeterminate{ - padding: 1px; - background-origin: content; - background-clip: content; - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0.49 transparent, stop: 0.5 %%TEXTCOLOR%%); -} - -/* PROGRESSBAR */ -QProgressBar{ - background-color: %%ALTBASECOLOR%%; - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 5px; - color: %%TEXTCOLOR%%; - text-align: center; - padding: 1px; -} - QProgressBar::chunk { - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTCOLOR%%, stop: 1 %%HIGHLIGHTDISABLECOLOR%%); - /*border: 1px solid %%ACCENTDISABLECOLOR%%;*/ - border-radius: 5px; - } -QProgressBar::chunk:vertical{ - margin-left: 2px; - margin-right: 2px; -} -QProgressBar::chunk:horizontal{ - margin-top: 2px; - margin-bottom: 2px; -} - -QWidget#LuminaBootSplash{ - background: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(234, 236, 243, 30), stop:1 rgba(229, 229, 229, 70)); - border-radius: 5px; -} - -LDPlugin#applauncher{ - background-color: transparent; - border: none; -} -LDPlugin#applauncher QToolButton, LDPlugin, LDPlugin#desktopview QListWidget::item{ - background-color: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(234, 236, 243, 30), stop:1 rgba(229, 229, 229, 70)); - border-width: 3px; - border-style: solid; - border-radius: 5px; - border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - color: white; -} - -LDPlugin#applauncher QToolButton:hover, LDPlugin#desktopview QListWidget::item:hover{ - background-color: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(234, 236, 243, 100), stop:1 rgba(229, 229, 229, 150)); - border-width: 3px; - border-style: solid; - border-radius: 5px; - border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - color: %%TEXTHIGHLIGHTCOLOR%%; -} -QWidget#LuminaPanelColor{ - background: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(234, 236, 243, 60), stop:1 rgba(229, 229, 229, 110)); - border-radius: 3px; -} -/*Special taskmanager window buttons: based on window state*/ -LTBWidget{ - border: 1px solid transparent; - border-radius: 3px; -} -LTBWidget::menu-indicator{ image: none; } /*disable the menu arrow*/ -LTBWidget#WindowVisible{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 %%PRIMARYCOLOR%%, stop: 1 transparent); -} -LTBWidget#WindowInvisible{ - background: transparent; -} -LTBWidget#WindowActive{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 transparent); -} -LTBWidget#WindowAttention{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 %%HIGHLIGHTCOLOR%%, stop: 1 transparent); -} -LTBWidget:hover, LTBWidget#WindowVisible:hover, LTBWidget#WindowInvisible:hover, LTBWidget#WindowActive:hover, LTBWidget#WindowAttention:hover, QToolButton:hover{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 %%HIGHLIGHTCOLOR%%, stop: 1 transparent); - color: %%TEXTHIGHLIGHTCOLOR%%; - border-width: 1px; - border-style: solid; - border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); - border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255, 255, 255, 30), stop:0.724868 rgba(255, 255, 255, 60), stop:1 rgba(255, 255, 255, 10)); -} -/* CALENDER WIDGET */ - /* (This is a special hack since there is no official support for stylesheets for this widget) */ - QCalendarWidget QWidget#qt_calendar_navigationbar{ - background-color: %%ALTBASECOLOR%%; - } -QCalendarWidget QWidget{ - background-color: %%BASECOLOR%%; - alternate-background-color: rgba(255, 255, 255, 50); - color: %%TEXTCOLOR%%; -} -QCalendarWidget QAbstractButton{ - background-color: transparent; -} -QCalendarWidget QAbstractButton::menu-indicator{ - image: none; -} -QCalendarWidget QAbstractItemView{ - selection-background-color: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(234, 236, 243, 20), stop:1 rgba(229, 229, 229, 100)); - selection-color: %%TEXTHIGHLIGHTCOLOR%%; -} -QCalendarWidget QWidget#qt_calendar_calendarview{ - background-color: rgb(220,220,220); - border: none; -} diff --git a/src-qt5/core/libLumina/themes/Lumina-default.qss.template b/src-qt5/core/libLumina/themes/Lumina-default.qss.template deleted file mode 100644 index 9f03d4ae..00000000 --- a/src-qt5/core/libLumina/themes/Lumina-default.qss.template +++ /dev/null @@ -1,494 +0,0 @@ -/* ALL THE TEMPLATE WIDGETS */ -INHERITS=None - -/* ALL THE WIDGETS WITH THE BASE COLOR */ -QMainWindow, QMenu, QDialog, QMessageBox{ - background: %%BASECOLOR%%; - color: %%TEXTCOLOR%%; -} - -/* ALL THE WIDGETS WITH AN ALTERNATE BASE COLOR */ -QLineEdit, QTextEdit, QTextBrowser, QPlainTextEdit, QSpinBox, QDateEdit, QDateTimeEdit, QTimeEdit, QDoubleSpinBox{ - background: %%ALTBASECOLOR%%; - color: %%TEXTCOLOR%%; - border-color: %%ACCENTDISABLECOLOR%%; - selection-background-color: %%HIGHLIGHTCOLOR%%; - selection-color: %%TEXTHIGHLIGHTCOLOR%%; - -} - -/* PAGES OF CONTAINER WIDGETS */ -QStackedWidget .QWidget, QTabWidget .QWidget{ - background: %%ALTBASECOLOR%%; - color: %%TEXTCOLOR%%; - border: none; -} -QToolBox::tab{ - color: %%TEXTCOLOR%%; -} - -/* MENU WIDGETS */ -QMenuBar, QMenuBar::item,QToolBar{ - background: %%SECONDARYCOLOR%%; - border: none; - color: %%TEXTCOLOR%%; -} - -QStatusBar{ - background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 transparent, stop: 0.5 %%SECONDARYCOLOR%%); - border: none; - color: %%TEXTCOLOR%%; -} -QToolBar:top{ - border-bottom: 1px solid %%ACCENTCOLOR%%; -} -QToolBar:bottom{ - border-top: 1px solid %%ACCENTCOLOR%%; -} -QToolBar:left{ - border-right: 1px solid %%ACCENTCOLOR%%; -} -QToolBar:right{ - border-left: 1px solid %%ACCENTCOLOR%%; -} - -QMenuBar::item{ - background: transparent; /*Use the menu bar color*/ - padding-left: 4px; - padding-right: 2px; -} - -QMenuBar::item:selected, QMenuBar::item:pressed, QMenu::item:selected{ -background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); -color: %%TEXTHIGHLIGHTCOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -} -QMenuBar::item:disabled{ - color: %%TEXTDISABLECOLOR%%; -} - -QMenu::item{ - border: 2px solid #808080; -} - -QMenu::item{ - background: transparent; - border: 1px solid transparent; - color: %%TEXTCOLOR%%; - padding: 4px 30px 4px 20px; - margin-left: 3px; - margin-right: 3px; -} - -/* TAB WIDGETS */ -/*QTabBar{ - Custom Font settings need to be here and NOT in the ::tab fields, - otherwise it will break auto-scaling of the tab sizes to fit the text -}*/ -QTabBar::tab { - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%SECONDARYDISABLECOLOR%%, stop: 1 %%SECONDARYCOLOR%%); - border: 1px solid %%ACCENTCOLOR%%; - padding: 2px; - color: %%TEXTCOLOR%%; -} -QTabBar::tab:top{ - border-top-left-radius: 4px; - border-top-right-radius: 4px; - max-width: 100em; - min-width: 0em; -} -QTabBar::tab:bottom{ - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - max-width: 100em; - min-width: 0em; -} -/* left/right tab indicators appear to be reversed in Qt*/ -QTabBar::tab:right{ - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - max-height: 100em; - min-height: 0em; -} -QTabBar::tab:left{ - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - max-height: 100em; - min-height: 0em; -} -QTabBar::tab:selected{ - background: %%HIGHLIGHTDISABLECOLOR%%; -} -QTabBar::tab:hover { - background: %%HIGHLIGHTCOLOR%%; - border: 1px solid %%ACCENTDISABLECOLOR%%; - } - -QTabBar::tab:!selected:top { - margin-top: 4px; -} -QTabBar::tab:!selected:bottom{ - margin-bottom: 4px; -} -QTabBar::tab:!selected:right{ - margin-left: 4px; -} -QTabBar::tab:!selected:left{ - margin-right: 4px; -} - -/* FRAME WIDGETS */ -QToolTip{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%BASECOLOR%%, stop: 1 %%ALTBASECOLOR%%); - border-radius: 3px; - border: 1px solid %%ACCENTCOLOR%%; - padding: 1px; - color: %%TEXTCOLOR%%; -} - -QLabel{ - background: transparent; - border: none; - color: %%TEXTCOLOR%%; -} -QAbstractButton::disabled{ - color: %%TEXTDISABLECOLOR%%; -} - -/* GROUP BOX */ -QGroupBox{ - background-color: transparent; - border-color: %%ACCENTCOLOR%%; - border-radius: 5px; - margin-top: 2ex; - font-weight: bold; -} -QGroupBox::title{ - subcontrol-origin: margin; - subcontrol-position: top center; - padding: 0 3px; - background: transparent; - /*border: none;*/ - color: %%TEXTCOLOR%%; -} - -/* COMBO BOX */ -QComboBox{ - /*border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; - padding: 1px 18px 1px 3px;*/ - color: %%TEXTCOLOR%%; - background: %%ALTBASECOLOR%%; - selection-background-color: %%HIGHLIGHTCOLOR%%; - } - - -/* VIEW WIDGETS */ -QTreeView, QListView{ - background: %%ALTBASECOLOR%%; - alternate-background-color: %%BASECOLOR%%; - /*selection-background-color: %%SECONDARYCOLOR%%;*/ - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; - /*show-decoration-selected: 1;*/ - color: %%TEXTCOLOR%%; - selection-color: %%TEXTCOLOR%%; -} - -QTreeView:focus, QListView:focus{ - border: 1px solid %%HIGHLIGHTDISABLECOLOR%%; -} - -/* -QTreeView::item and QListView::item unneccessary: -Already set though parentage and causes usage errors if set manually -*/ - -/*QTreeView::item:selected, QListView::item:selected{ - background: %%SECONDARYDISABLECOLOR%%; - border-color: %%ACCENTCOLOR%%; - color: %%TEXTCOLOR%%; -}*/ - -QTreeView::item:hover, QListView::item:hover{ - background: %%HIGHLIGHTDISABLECOLOR%%; -} -QTreeView::item:selected:hover, QListView::item:selected:hover{ - background: %%HIGHLIGHTDISABLECOLOR%%; -} -QTreeView::item:selected, QListView::item:selected{ - background: %%SECONDARYDISABLECOLOR%%; -} -QTreeView::item:selected:focus, QListView::item:selected:focus{ - background: %%SECONDARYCOLOR%%; -} -QHeaderView{ - background: %%HIGHLIGHTDISABLECOLOR%%; - color: %%TEXTHIGHLIGHTCOLOR%%; - border: none; - border-top-left-radius: 3px; /*match the list/tree view widgets*/ - border-top-right-radius: 3px; /*match the list/tree view widgets*/ -} -QHeaderView::section{ - background: %%HIGHLIGHTDISABLECOLOR%%; /*QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%PRIMARYDISABLECOLOR%%, stop: 1 %%PRIMARYCOLOR%%);*/ - color: %%TEXTHIGHLIGHTCOLOR%%; - border-color: %%ACCENTCOLOR%%; - padding: 1px; - padding-left: 4px; -} -QHeaderView::section:hover{ - background: %%PRIMARYCOLOR%%; - border-color: %%ACCENTDISABLECOLOR%%; - color: %%TEXTCOLOR%%; -} - -/* SCROLLBARS (NOTE: Changing 1 subcontrol means you have to change all of them)*/ -QScrollBar{ - background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 %%SECONDARYCOLOR%%, stop: 1 %%SECONDARYDISABLECOLOR%%); - /*border: 1px solid %%ACCENTCOLOR%%;*/ -} -QScrollBar:horizontal{ - margin: 0px 20px 0px 20px; -} -QScrollBar:vertical{ - margin: 20px 0px 20px 0px; -} -QScrollBar::sub-page, QScrollBar::add-page{ - background: %%BASECOLOR%%; - border: 1px solid %%ACCENTCOLOR%%; -} -QScrollBar::sub-page:vertical{ - border-bottom: none; -} -QScrollBar::add-page:vertical{ - border-top: none; -} -QScrollBar::sub-page:horizontal{ - border-right: none; -} -QScrollBar::add-page:horizontal{ - border-left: none; -} -QScrollBar::handle{ - background: QLinearGradient(x1: 0, y1: -0.3, x2: 0, y2: 1.3, stop: 0 %%BASECOLOR%%, stop: 0.5 %%SECONDARYCOLOR%%, stop: 1 %%BASECOLOR%%); - border: 1px solid %%ACCENTCOLOR%%; -} -QScrollBar::handle:hover, QScrollBar::add-line:hover, QScrollBar::sub-line:hover{ - background: %%HIGHLIGHTCOLOR%%; -} -QScrollBar::add-line{ - background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 %%SECONDARYDISABLECOLOR%%, stop: 1 %%SECONDARYCOLOR%%); - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; -subcontrol-position: bottom right; -subcontrol-origin: margin; -} -QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical{ -height: 20px; -} -QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal{ -width: 20px; -} -QScrollBar::sub-line{ - background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 %%SECONDARYCOLOR%%, stop: 1 %%SECONDARYDISABLECOLOR%%); - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; -subcontrol-position: top left; -subcontrol-origin: margin; -height: 20px; -} -/* SLIDERS */ -QSlider::groove:horizontal { -border: 1px solid %%ACCENTCOLOR%%; -background: %%ALTBASECOLOR%%; -height: 10px; -border-radius: 3px; -} -QSlider::groove:vertical { -border: 1px solid %%ACCENTCOLOR%%; -background: %%ALTBASECOLOR%%; -width: 10px; -border-radius: 3px; -} -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, - stop: 0 %%HIGHLIGHTCOLOR%%, stop: 1 %%HIGHLIGHTDISABLECOLOR%%); -border: 1px solid %%ACCENTCOLOR%%; -height: 10px; -border-radius: 3px; -} -QSlider::sub-page:vertical { -background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, - stop: 0 %%HIGHLIGHTCOLOR%%, stop: 1 %%HIGHLIGHTDISABLECOLOR%%); -border: 1px solid %%ACCENTCOLOR%%; -width: 10px; -border-radius: 3px; -} -QSlider::add-page:horizontal{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -height: 10px; -border-radius: 3px; -} -QSlider::add-page:vertical{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -width: 10px; -border-radius: 3px; -} -QSlider::handle:horizontal{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -width: 13px; -border-radius: 4px; -} -QSlider::handle:vertical{ -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -height: 13px; -border-radius: 4px; -} -QSlider::handle:horizontal:hover, QSlider::handle:vertical:hover{ -border: 1px solid %%ACCENTDISABLECOLOR%%; -/*background: %%HIGHLIGHTCOLOR%%;*/ -} - -QSlider::sub-page:horizontal:disabled { -background: %%ACCENTDISABLECOLOR%%; -border-color: %%ACCENTCOLOR%%; -} - -QSlider::add-page:horizontal:disabled { -background: %%ACCENTDISABLECOLOR%%; -border-color: %%ACCENTCOLOR%%; -} - -QSlider::handle:horizontal:disabled { -background: %%ALTBASECOLOR%%; -border: 1px solid %%ACCENTCOLOR%%; -} - -/* BUTTONS */ -QPushButton{ - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%SECONDARYDISABLECOLOR%%, stop: 1 %%SECONDARYCOLOR%%); - padding: 2px; - padding-right: 4px; - color: %%TEXTCOLOR%%; - } - -QToolButton{ /* Assume a flat button for every toolbutton by default*/ - color: %%TEXTCOLOR%%; - border: 1px solid transparent; - border-radius: 3px; - background-color: transparent; - padding: 1px; -} - - QPushButton:pressed, QPushButton:open, QPushButton:selected, QPushButton:checked, QPushButton:on, QToolButton:pressed, QToolButton:open, QToolButton:selected, QToolButton:checked, QToolButton:on{ - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); - margin-top: 2px; - } - -QPushButton:flat, QToolButton:flat{ - background-color: transparent; - border: 1px solid transparent; /* no border for a flat button */ -} - -QPushButton:hover, QToolButton:hover{ - border: 1px solid %%ACCENTCOLOR%%; - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); - color: %%TEXTHIGHLIGHTCOLOR%%; -} -QRadioButton, QCheckBox{ - padding: 2px; - border: 1px solid transparent; - border-radius: 3px; - color: %%TEXTCOLOR%%; -} -QRadioButton::hover, QCheckBox:hover{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%); - border: 1px solid %%ACCENTCOLOR%%; - color: %%TEXTHIGHLIGHTCOLOR%%; -} -QRadioButton::indicator, QCheckBox::indicator, QGroupBox::indicator{ - border: 1px solid %%TEXTCOLOR%%; -} -QRadioButton::indicator{ - border-radius: 7px; -} -QRadioButton::indicator:checked{ - background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:1, fx:0.5, fy:0.5, stop:0 %%TEXTCOLOR%%, stop:0.25 %%TEXTCOLOR%%, stop:0.25001 transparent); -} -QCheckBox::indicator:checked, QGroupBox::indicator:checked{ - padding: 1px; - background-origin: content; - background-clip: content; - background: %%TEXTCOLOR%%; -} -QCheckBox::indicator:indeterminate, QGroupBox::indicator:indeterminate{ - padding: 1px; - background-origin: content; - background-clip: content; - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0.49 transparent, stop: 0.5 %%TEXTCOLOR%%); -} - -/* PROGRESSBAR */ -QProgressBar{ - background-color: %%ALTBASECOLOR%%; - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 5px; - color: %%TEXTCOLOR%%; - text-align: center; - padding: 1px; -} - QProgressBar::chunk { - background-color: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%HIGHLIGHTCOLOR%%, stop: 1 %%HIGHLIGHTDISABLECOLOR%%); - /*border: 1px solid %%ACCENTDISABLECOLOR%%;*/ - border-radius: 5px; - } -QProgressBar::chunk:vertical{ - margin-left: 2px; - margin-right: 2px; -} -QProgressBar::chunk:horizontal{ - margin-top: 2px; - margin-bottom: 2px; -} - - /* SPINBOX */ -/*QAbstractSpinBox{ - background-color: %%ALTBASECOLOR%%; - border: 1px solid %%ACCENTCOLOR%%; - border-radius: 3px; -} -QAbstractSpinBox:disabled{ - color: %%ACCENTDISABLECOLOR%%; -}*/ -/*QAbstractSpinBox::down-button{ - subcontrol-origin: border; - subcontrol-position: left; - width: 16px; - border-width: 1px; -} -QAbstractSpinBox::up-button{ - subcontrol-origin: border; - subcontrol-position: right; - width: 16px; - border-width: 1px; -}*/ -/* -QAbstractSpinBox::down-arrow{ - border-image: url(":/trolltech/styles/commonstyle/images/left-16.png"); - width: 16px; - height: 16px; -} -QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::down-arrow:off, QAbstractSpinBox::up-arrow:off{ - border-image: url(:/none); -} -QAbstractSpinBox::up-arrow{ - border-image: url(":/trolltech/styles/commonstyle/images/right-16.png"); - width: 16px; - height: 16px; -}*/ diff --git a/src-qt5/core/libLumina/themes/None.qss.template b/src-qt5/core/libLumina/themes/None.qss.template deleted file mode 100644 index 7d923b1e..00000000 --- a/src-qt5/core/libLumina/themes/None.qss.template +++ /dev/null @@ -1,118 +0,0 @@ -/* This is a blank stylesheet to disable the Lumina Themes almost entirely*/ -QWidget{ - font-family: %%FONT%%; - font-size: %%FONTSIZE%%; -} -/* Set the panel appearance for this theme (unless manually customized) */ -QWidget#LuminaPanelColor{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 %%PRIMARYCOLOR%%, stop: 1 %%PRIMARYDISABLECOLOR%%); - border-radius: 5px; -} -QWidget#LuminaBootSplash{ - background: %%BASECOLOR%%; - border-radius: 5px; -} - -/* Set the default canvas appearance for Lumina desktop plugins*/ -/* Default to a non-transparent background for all desktop plugins*/ -LDPlugin{ - background: %%BASECOLOR%%; - border-radius: 5px; -} -/* Now specify which plugins should have a transparent background */ -LDPlugin#applauncher, LDPlugin#desktopview{ - background: transparent; - border-radius: 5px; -} - -LDPlugin#applauncher QToolButton{ -background: transparent; - border: none; - border-radius: 5px; - color: white; -} -LDPlugin#applauncher QToolButton:hover{ - background: %%PRIMARYDISABLECOLOR%%; - border: none; - border-radius: 5px; - color: %%TEXTHIGHLIGHTCOLOR%%; -} - -LDPlugin#desktopview QListWidget{ - background: transparent; - border: 1px solid transparent; -} -LDPlugin#desktopview QListWidget::item{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 transparent, - stop: 0.7 transparent, - stop: 1.0 %%PRIMARYDISABLECOLOR%%); - border-radius: 5px; - color: %%TEXTCOLOR%%; -} - -LDPlugin#desktopview QListWidget::item:hover{ - background: %%PRIMARYDISABLECOLOR%%; - border-radius: 5px; - color: %%TEXTHIGHLIGHTCOLOR%%; -} -/*For the special widgets on the user button*/ -UserItemWidget, ItemWidget{ - background: transparent; - border-radius: 3px; -} -UserItemWidget:hover, ItemWidget:hover{ - background: %%HIGHLIGHTCOLOR%%; - color: %%TEXTHIGHLIGHTCOLOR%%; -} - -/*Special taskmanager window buttons: based on window state*/ -LTBWidget{ - border: 1px solid transparent; - border-radius: 3px; -} -LTBWidget::menu-indicator{ image: none; } /*disable the menu arrow*/ -LTBWidget#WindowVisible{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.3 %%SECONDARYCOLOR%%, stop: 1 transparent); -} -LTBWidget#WindowInvisible{ - /* Primary color is used for the panel appearance, so use that to make it disappear*/ - background: transparent; -} -LTBWidget#WindowActive{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.3 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 transparent); -} -LTBWidget#WindowAttention{ - background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.3 %%HIGHLIGHTCOLOR%%, stop: 1 transparent); -} -LTBWidget:hover, LTBWidget#WindowVisible:hover, LTBWidget#WindowInvisible:hover, LTBWidget#WindowActive:hover, LTBWidget#WindowAttention:hover{ - background: %%HIGHLIGHTCOLOR%%; - color: %%TEXTHIGHLIGHTCOLOR%%; - border: 1px solid %%ACCENTCOLOR%%; -} - -/* CALENDER WIDGET */ - /* (This is a special hack since there is no official support for stylesheets for this widget) */ - QCalendarWidget QWidget#qt_calendar_navigationbar{ - background-color: %%ALTBASECOLOR%%; - } -QCalendarWidget QWidget{ - background-color: %%BASECOLOR%%; - alternate-background-color: %%HIGHLIGHTDISABLECOLOR%%; - color: %%TEXTCOLOR%%; -} -QCalendarWidget QAbstractButton{ - background-color: transparent; -} -QCalendarWidget QAbstractButton::menu-indicator{ - image: none; -} -QCalendarWidget QAbstractItemView{ - background-color: %%SECONDARYCOLOR%%; - selection-background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 %%HIGHLIGHTDISABLECOLOR%%, stop: 1 %%HIGHLIGHTCOLOR%%);; - selection-color: %%TEXTHIGHLIGHTCOLOR%%; -} -QCalendarWidget QWidget#qt_calendar_calendarview{ - background-color: %%ALTBASECOLOR%%; - border: none; -}
\ No newline at end of file |