aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/LUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina/LUtils.cpp')
-rw-r--r--src-qt5/core/libLumina/LUtils.cpp436
1 files changed, 436 insertions, 0 deletions
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;
+}
bgstack15