diff options
Diffstat (limited to 'src-qt5/core/libLumina/LuminaXDG.cpp')
-rw-r--r-- | src-qt5/core/libLumina/LuminaXDG.cpp | 176 |
1 files changed, 135 insertions, 41 deletions
diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index 01b3305e..ab1000ab 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -44,7 +44,7 @@ void XDGDesktop::sync(){ //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 + QString slang = lang.section("_",0,0); //short lang code //Now start looping over the information XDGDesktopAction CDA; //current desktop action bool insection=false; @@ -53,14 +53,14 @@ void XDGDesktop::sync(){ 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){ + 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 ")){ + 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; @@ -73,26 +73,26 @@ void XDGDesktop::sync(){ var = var.section("[",0,0).simplified(); //remove the localization QString val = line.section("=",1,50).simplified(); //------------------- - if(var=="Name"){ + 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; } + if(loc==slang){ name = val;} //short locale code + else if(loc==lang){ name = val;} + else if(name.isEmpty() && loc.isEmpty()){ /*qDebug() << "Empty" << val;*/ 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; } + else if(loc == lang){ CDA.name = val; } } //hasName = true; - }else if(var=="GenericName" && insection){ + }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){ + }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"){ + }else if(var=="Icon"){ if(insection){ if(icon.isEmpty() && loc.isEmpty()){ icon = val; } else if(icon.isEmpty() && loc==slang){ icon = val; } //short locale code @@ -107,7 +107,7 @@ void XDGDesktop::sync(){ 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"); } @@ -117,7 +117,7 @@ void XDGDesktop::sync(){ 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){ + else if(var=="Keywords" && insection){ if(keyList.isEmpty() && loc.isEmpty()){ keyList = val.split(";",QString::SkipEmptyParts); } else if(loc == lang){ keyList = val.split(";",QString::SkipEmptyParts); } } @@ -136,7 +136,7 @@ void XDGDesktop::sync(){ 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(", ")+")"); + 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/")){ @@ -164,7 +164,7 @@ bool XDGDesktop::isValid(bool showAll){ //if(DEBUG){ qDebug() << "[LXDG] Check File validity:" << dFile.name << dFile.filePath; } switch (type){ case XDGDesktop::BAD: - ok=false; + ok=false; //if(DEBUG){ qDebug() << " - Bad file type"; } break; case XDGDesktop::APP: @@ -182,7 +182,7 @@ bool XDGDesktop::isValid(bool showAll){ break; default: ok=false; - //if(DEBUG){ qDebug() << " - Unknown file type"; } + //if(DEBUG){ qDebug() << " - Unknown file type"; } } if(!showAll){ QString cdesk = getenv("XDG_CURRENT_DESKTOP"); @@ -206,7 +206,7 @@ QString XDGDesktop::getDesktopExec(QString ActionID){ } } } - + if(out.isEmpty()){ return ""; } else if(useTerminal){ //Get the currently default terminal @@ -222,7 +222,7 @@ QString XDGDesktop::getDesktopExec(QString ActionID){ } //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(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)+"\""); } @@ -250,17 +250,17 @@ QString XDGDesktop::generateExec(QStringList inputfiles, QString ActionID){ } } //Now to the exec replacements as needed - if(exec.contains("%f")){ + if(exec.contains("%f")){ if(inputfiles.isEmpty()){ exec.replace("%f",""); } else{ exec.replace("%f", "\""+inputfiles.first()+"\""); } //Note: can only take one input - }else if(exec.contains("%F")){ + }else if(exec.contains("%F")){ if(inputfiles.isEmpty()){ exec.replace("%F",""); } else{ exec.replace("%F", "\""+inputfiles.join("\" \"")+"\""); } } - if(exec.contains("%u")){ + if(exec.contains("%u")){ if(inputfiles.isEmpty()){ exec.replace("%u",""); } else{ exec.replace("%u", "\""+inputfiles.first()+"\""); } //Note: can only take one input - }else if(exec.contains("%U")){ + }else if(exec.contains("%U")){ if(inputfiles.isEmpty()){ exec.replace("%U",""); } else{ exec.replace("%U", "\""+inputfiles.join("\" \"")+"\""); } } @@ -281,7 +281,7 @@ bool XDGDesktop::saveDesktopFile(bool merge){ 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; + bool clearName, clearComment, clearGName; QString tmp = ""; if(!info.filter("Name=").isEmpty()){ tmp = info.filter("Name=").first().section("=",1,50); } clearName=(tmp!=name); @@ -294,13 +294,13 @@ bool XDGDesktop::saveDesktopFile(bool merge){ //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; + if(info[i]=="[Desktop Entry]"){ + insection = true; continue; - }else if(info[i].startsWith("[")){ + }else if(info[i].startsWith("[")){ if(insection){ insertloc = i; } //save this location for later insertions - insection = false; - continue; + insection = false; + continue; } if(!insection || info[i].isEmpty() || info[i].section("#",0,0).simplified().isEmpty()){ continue; } QString var = info[i].section("=",0,0); @@ -331,25 +331,25 @@ bool XDGDesktop::saveDesktopFile(bool merge){ 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"){ + else if(var=="Hidden"){ if(!autofile){ info.removeAt(i); i--; continue; } else{ info[i] = var+"="+(isHidden ? "true": "false"); isHidden=false;} - }else if(var=="NoDisplay"){ + }else if(var=="NoDisplay"){ if(autofile){ info.removeAt(i); i--; continue; } else{ info[i] = var+"="+(isHidden ? "true": "false"); isHidden=false;} - }else if(var=="Terminal"){ + }else if(var=="Terminal"){ info[i] = var+"="+(useTerminal ? "true": "false"); useTerminal=false; - }else if(var=="StartupNotify"){ + }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 + //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"; @@ -357,7 +357,7 @@ bool XDGDesktop::saveDesktopFile(bool merge){ 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); } @@ -379,7 +379,7 @@ bool XDGDesktop::saveDesktopFile(bool merge){ 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); } @@ -409,7 +409,7 @@ bool XDGDesktop::setAutoStarted(bool autostart){ } } //Make sure the user-autostart dir is specified, and clean the app structure as necessary - if( !filePath.startsWith(upath) && autostart){ + 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+"\""; @@ -444,6 +444,39 @@ bool XDGDesktop::setAutoStarted(bool autostart){ return saved; } +void XDGDesktop::addToMenu(QMenu *topmenu){ + if(!this->isValid()){ return; } + if(actions.isEmpty()){ + //Just a single entry point - no extra actions + QAction *act = new QAction(this->name, topmenu); + act->setIcon(LXDG::findIcon(this->icon, "")); + act->setToolTip(this->comment); + act->setWhatsThis(this->filePath); + topmenu->addAction(act); + }else{ + //This app has additional actions - make this a sub menu + // - first the main menu/action + QMenu *submenu = new QMenu(this->name, topmenu); + submenu->setIcon( LXDG::findIcon(this->icon,"") ); + //This is the normal behavior - not a special sub-action (although it needs to be at the top of the new menu) + QAction *act = new QAction(this->name, submenu); + act->setIcon(LXDG::findIcon(this->icon, "")); + act->setToolTip(this->comment); + act->setWhatsThis(this->filePath); + submenu->addAction(act); + //Now add entries for every sub-action listed + for(int sa=0; sa<this->actions.length(); sa++){ + QAction *sact = new QAction( this->actions[sa].name, this); + sact->setIcon(LXDG::findIcon( this->actions[sa].icon, this->icon)); + sact->setToolTip(this->comment); + sact->setWhatsThis("-action \""+this->actions[sa].ID+"\" \""+this->filePath+"\""); + submenu->addAction(sact); + } + topmenu->addMenu(submenu); + } +} + + //====XDGDesktopList Functions ==== XDGDesktopList::XDGDesktopList(QObject *parent, bool watchdirs) : QObject(parent){ synctimer = new QTimer(this); //interval set automatically based on changes/interactions @@ -462,6 +495,14 @@ XDGDesktopList::~XDGDesktopList(){ //nothing special to do here } +XDGDesktopList* XDGDesktopList::instance(){ + static XDGDesktopList *APPLIST = 0; + if(APPLIST==0){ + APPLIST = new XDGDesktopList(0, true); + } + return APPLIST; +} + void XDGDesktopList::watcherChanged(){ if(synctimer->isActive()){ synctimer->stop(); } synctimer->setInterval(1000); //1 second delay before check kicks off @@ -484,7 +525,7 @@ void XDGDesktopList::updateList(){ 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) found << files[path]->name; //keep track of which files were already found }else{ @@ -503,7 +544,7 @@ void XDGDesktopList::updateList(){ } //end loop over apps } //end loop over appDirs //Save the extra info to the internal lists - if(!firstrun){ + if(!firstrun){ removedApps = oldkeys;//files which were removed newApps = newfiles; //files which were added } @@ -539,6 +580,52 @@ QList<XDGDesktop*> XDGDesktopList::apps(bool showAll, bool showHidden){ return out; } +XDGDesktop* XDGDesktopList::findAppFile(QString filename){ + QStringList keys = files.keys().filter(filename); + QString chk = filename.section("/",-1); + for(int i=0; i<keys.length(); i++){ + if(keys[i] == filename || keys[i].endsWith("/"+chk)){ return files[keys[i]]; } + } + //No matches + return 0; +} + +void XDGDesktopList::populateMenu(QMenu *topmenu, bool byCategory){ + topmenu->clear(); + if(byCategory){ + QHash<QString, QList<XDGDesktop*> > APPS = LXDG::sortDesktopCats( this->apps(false,false) ); + QStringList cats = APPS.keys(); + cats.sort(); //make sure they are alphabetical + for(int i=0; i<cats.length(); i++){ + //Make sure they are translated and have the right icons + QString name, icon; + if(cats[i]=="All"){continue; } //skip this listing for the menu + else if(cats[i] == "Multimedia"){ name = tr("Multimedia"); icon = "applications-multimedia"; } + else if(cats[i] == "Development"){ name = tr("Development"); icon = "applications-development"; } + else if(cats[i] == "Education"){ name = tr("Education"); icon = "applications-education"; } + else if(cats[i] == "Game"){ name = tr("Games"); icon = "applications-games"; } + else if(cats[i] == "Graphics"){ name = tr("Graphics"); icon = "applications-graphics"; } + else if(cats[i] == "Network"){ name = tr("Network"); icon = "applications-internet"; } + else if(cats[i] == "Office"){ name = tr("Office"); icon = "applications-office"; } + else if(cats[i] == "Science"){ name = tr("Science"); icon = "applications-science"; } + else if(cats[i] == "Settings"){ name = tr("Settings"); icon = "preferences-system"; } + else if(cats[i] == "System"){ name = tr("System"); icon = "applications-system"; } + else if(cats[i] == "Utility"){ name = tr("Utility"); icon = "applications-utilities"; } + else if(cats[i] == "Wine"){ name = tr("Wine"); icon = "wine"; } + else{ name = tr("Unsorted"); icon = "applications-other"; } + + QMenu *menu = new QMenu(name, topmenu); + menu->setIcon(LXDG::findIcon(icon,"")); + QList<XDGDesktop*> appL = APPS.value(cats[i]); + for( int a=0; a<appL.length(); a++){ appL[a]->addToMenu(menu); } + topmenu->addMenu(menu); + } //end loop over cats + }else{ + QList<XDGDesktop*> APPS = this->apps(false, false); + for(int i=0; i<APPS.length(); i++){ APPS[i]->addToMenu(topmenu); } + } +} + //==== LFileInfo Functions ==== //Need some extra information not usually available by a QFileInfo void LFileInfo::loadExtraInfo(){ @@ -617,7 +704,14 @@ XDGDesktop* LFileInfo::XDG(){ return desk; } -// -- Check if this is a readable image file (for thumbnail support) +// -- Check if this is a readable video file (for thumbnail support) +bool LFileInfo::isVideo(){ + if(!mime.startsWith("video/")){ return false; } + //Check the hardcoded list of known supported video formats to see if the thumbnail can be generated + return ( !LUtils::videoExtensions().filter(this->suffix().toLower()).isEmpty() ); +} + +// -- Check if this is a readable image file bool LFileInfo::isImage(){ if(!mime.startsWith("image/")){ return false; } //quick return for non-image files //Check the Qt subsystems to see if this image file can be read |