diff options
Diffstat (limited to 'src-qt5/core/libLumina')
-rw-r--r-- | src-qt5/core/libLumina/LuminaUtils.cpp | 5 | ||||
-rw-r--r-- | src-qt5/core/libLumina/LuminaXDG.cpp | 691 | ||||
-rw-r--r-- | src-qt5/core/libLumina/LuminaXDG.h | 56 | ||||
-rw-r--r-- | src-qt5/core/libLumina/libLumina.pro | 5 | ||||
-rw-r--r-- | src-qt5/core/libLumina/xtrafiles/globs2 | 991 |
5 files changed, 1575 insertions, 173 deletions
diff --git a/src-qt5/core/libLumina/LuminaUtils.cpp b/src-qt5/core/libLumina/LuminaUtils.cpp index 1ab3faac..dd4c75c4 100644 --- a/src-qt5/core/libLumina/LuminaUtils.cpp +++ b/src-qt5/core/libLumina/LuminaUtils.cpp @@ -159,9 +159,8 @@ QString LUtils::GenerateOpenTerminalExec(QString term, QString dirpath){ //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"; } + 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 diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index 48185a38..96f77ff9 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -15,11 +15,398 @@ static QStringList mimeglobs; static qint64 mimechecktime; +//============================= +// XDGDesktop CLASS +//============================= +XDGDesktop::XDGDesktop(QString file, QObject *parent) : QObject(parent){ + isHidden=false; + useTerminal=false; + startupNotify=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 +421,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 +436,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 +502,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,11 +521,10 @@ 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 @@ -167,12 +565,12 @@ QString LFileInfo::iconfile(){ // -- Check if this is an XDG desktop file bool LFileInfo::isDesktopFile(){ - return (!desk.filePath.isEmpty()); + 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,17 +586,17 @@ bool LFileInfo::isAVFile(){ //==== LXDG Functions ==== -XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){ +/*XDGDesktop *LXDG::loadDesktopFile(QString filePath, bool& ok, QObject *parent){ //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 + XDGDesktop *DF = new XDGDesktop(parent); + 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 @@ -218,7 +616,7 @@ XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){ 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(); } + 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; } @@ -234,13 +632,12 @@ XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){ 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; } + 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 @@ -248,89 +645,81 @@ XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){ } //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; } + 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; } + 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; } + 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=="TryExec") && (DF->tryexec.isEmpty()) && insection) { DF->tryexec = val; } else if(var=="Exec"){ - if(insection && DF.exec.isEmpty() ){ DF.exec = val; } + 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=="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); } + 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=="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 + 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(); + file.clear(); //done with contents of file //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(", ")+")"); - //} + if( !DF->showInList.isEmpty() && !DF->showInList.contains("Lumina", Qt::CaseInsensitive) ){ + 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) + 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() ){ + 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; + 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){ +/*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; @@ -442,9 +831,9 @@ bool LXDG::saveDesktopFile(XDGDesktop dFile, bool merge){ //Now save the file return LUtils::writeFile(dFile.filePath, info, true); -} +}*/ -bool LXDG::checkValidity(XDGDesktop dFile, bool showAll){ +/*bool LXDG::checkValidity(XDGDesktop dFile, bool showAll){ bool ok=true; bool DEBUG = false; if(DEBUG){ qDebug() << "[LXDG] Check File validity:" << dFile.name << dFile.filePath; } @@ -476,7 +865,7 @@ bool LXDG::checkValidity(XDGDesktop dFile, bool showAll){ else if(dFile.name.isEmpty()){ ok = false; } } return ok; -} +}*/ bool LXDG::checkExec(QString exec){ //Return true(good) or false(bad) @@ -510,40 +899,43 @@ QStringList LXDG::systemApplicationDirs(){ return out; } -XDGDesktopList* LXDG::systemAppsList(){ - static XDGDesktopList *sysapps = new XDGDesktopList(0,true); //set this to automatically update as needed +/*XDGDesktopList* LXDG::systemAppsList(){ + static XDGDesktopList *sysapps = 0; + if(sysapps == 0){ qDebug() << "Generating new apps list"; 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); -} +/*QList<XDGDesktop*> LXDG::systemDesktopFiles(bool showAll, bool showHidden){ + //If this is going to be used regularly, it is better to use a custom instance of an XDGDesktopList() which self-updates instead. + // Since this function will need to re-read the entire system app registry every time. + XDGDesktopList sysapps; + sysapps.updateList(); + return sysapps.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,23 +971,23 @@ 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){ +/*QString LXDG::getDesktopExec(XDGDesktop app, QString ActionID){ //Generate the executable line for the application QString out; QString exec = app.exec; @@ -633,7 +1025,7 @@ QString LXDG::getDesktopExec(XDGDesktop app, QString ActionID){ } if(out.contains("%k")){ out.replace("%k", "\'"+app.filePath+"\'"); } return out; -} +}*/ void LXDG::setEnvironmentVars(){ //Set the default XDG environment variables if not already set @@ -1107,19 +1499,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 +1523,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 +1553,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 +1576,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 +1621,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..dd9d1c67 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 @@ -64,10 +66,19 @@ public: QList<XDGDesktopAction> actions; //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 +91,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 +104,7 @@ public slots: private: QFileSystemWatcher *watcher; QTimer *synctimer; + bool keepsynced; private slots: void watcherChanged(); @@ -107,7 +119,7 @@ signals: class LFileInfo : public QFileInfo{ private: QString mime, icon; - XDGDesktop desk; + XDGDesktop *desk; void loadExtraInfo(); @@ -115,7 +127,9 @@ public: //Couple overloaded contructors LFileInfo(QString filepath); LFileInfo(QFileInfo info); - ~LFileInfo(){} + ~LFileInfo(){ + desk->deleteLater(); + } //Functions for accessing the extra information // -- Return the mimetype for the file @@ -142,25 +156,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 +205,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/libLumina.pro b/src-qt5/core/libLumina/libLumina.pro index 7f9e4203..2786b875 100644 --- a/src-qt5/core/libLumina/libLumina.pro +++ b/src-qt5/core/libLumina/libLumina.pro @@ -62,4 +62,7 @@ themes.files=themes/*.qss.template #quickplugins.path=$${L_SHAREDIR}/lumina-desktop/quickplugins/ #quickplugins.files=quickplugins/* -INSTALLS += target include colors themes +globs.path=$${L_SHAREDIR}/lumina-desktop +globs.files=xtrafiles/globs2 + +INSTALLS += target include colors themes globs diff --git a/src-qt5/core/libLumina/xtrafiles/globs2 b/src-qt5/core/libLumina/xtrafiles/globs2 new file mode 100644 index 00000000..0a783316 --- /dev/null +++ b/src-qt5/core/libLumina/xtrafiles/globs2 @@ -0,0 +1,991 @@ +# Fallback "globs2" file from the FreeDesktop mimetype database (9/23/16) +# This is only used if the official database cannot be found on the system +80:application/x-cd-image:*.iso +80:application/x-doom-wad:*.wad +50:text/x-vala:*.vala +50:application/x-nes-rom:*.nez +50:audio/ac3:*.ac3 +50:application/x-mswrite:*.wri +50:application/smil+xml:*.smil +50:text/x-verilog:*.v +50:application/x-qpress:*.qp +50:image/x-exr:*.exr +50:application/x-compress:*.z +50:image/x-jng:*.jng +50:application/oda:*.oda +50:application/vnd.oasis.opendocument.database:*.odb +50:application/vnd.sun.xml.base:*.odb +50:application/vnd.oasis.opendocument.chart:*.odc +50:text/vtt:*.vtt +50:application/x-xz-compressed-tar:*.txz +50:application/vnd.oasis.opendocument.formula:*.odf +50:application/vnd.oasis.opendocument.formula:*.odf +50:application/vnd.oasis.opendocument.graphics:*.odg +50:application/vnd.oasis.opendocument.graphics:*.odg +50:text/x-ldif:*.ldif +50:application/vnd.oasis.opendocument.image:*.odi +50:image/jp2:*.jp2 +50:application/x-oleo:*.oleo +50:application/oxps:*.xps +50:application/vnd.oasis.opendocument.text-master:*.odm +50:application/vnd.oasis.opendocument.text-master:*.odm +50:application/x-ruby:*.rb +50:audio/vnd.rn-realaudio:*.ra +50:application/x-mimearchive:*.mht +50:application/vnd.oasis.opendocument.presentation:*.odp +50:application/vnd.oasis.opendocument.presentation:*.odp +50:application/x-raw-disk-image-xz-compressed:*.raw-disk-image.xz +50:application/vnd.oasis.opendocument.spreadsheet:*.ods +50:application/vnd.oasis.opendocument.spreadsheet:*.ods +50:application/vnd.oasis.opendocument.text:*.odt +50:application/vnd.oasis.opendocument.text:*.odt +50:image/x-portable-bitmap:*.pbm +50:application/x-egon:*.egon +50:application/x-font-pcf:*.pcf.z +50:application/x-xliff:*.xliff +50:application/vnd.rn-realmedia:*.rm +50:application/x-abiword:*.abw +50:image/vnd.rn-realpix:*.rp +50:image/x-sigma-x3f:*.x3f +50:video/webm:*.webm +50:text/rust:*.rs +50:text/vnd.rn-realtext:*.rt +50:image/webp:*.webp +50:application/x-cpio:*.cpio +50:audio/midi:*.mid +50:application/x-mif:*.mif +50:video/vnd.rn-realvideo:*.rv +50:application/vnd.google-earth.kml+xml:*.kml +50:image/x-3ds:*.3ds +50:image/x-photo-cd:*.pcd +50:application/x-pc-engine-rom:*.pce +50:application/x-font-pcf:*.pcf +50:application/x-cisco-vpn-settings:*.pcf +50:model/vrml:*.wrl +50:text/x-fortran:*.f95 +50:text/plain:*.txt +50:image/x-xpixmap:*.xpm +50:application/vnd.hp-pcl:*.pcl +50:application/x-trash:*.bak +50:application/vnd.openxmlformats-officedocument.presentationml.template:*.potx +50:application/vnd.openxmlformats-officedocument.presentationml.template:*.potx +50:application/x-sms-rom:*.sg +50:application/x-shellscript:*.sh +50:model/vrml:*.vrml +50:text/vcard:*.vcard +50:image/x-skencil:*.sk +50:image/x-pict:*.pct +50:video/3gpp2:*.3g2 +50:text/x-vala:*.vapi +50:application/x-sharedlib:*.so +50:application/x-tzo:*.tzo +50:video/x-javafx:*.fxm +50:image/jpeg:*.jpe +50:audio/x-aifc:*.aifc +50:application/x-lzma-compressed-tar:*.tar.lzma +50:x-epoc/x-sisx-app:*.sisx +50:audio/x-aiff:*.aiff +50:audio/x-aifc:*.aiffc +50:image/jp2:*.jpf +50:application/x-hdf:*.hdf4 +50:application/x-hdf:*.hdf5 +50:application/x-aportisdoc:*.pdb +50:application/vnd.palm:*.pdb +50:application/x-aportisdoc:*.pdc +50:application/x-profile:gmon.out +50:application/x-jbuilder-project:*.jpr +50:application/pdf:*.pdf +50:application/x-bzpdf:*.pdf.bz2 +50:application/x-theme:*.theme +50:image/jpeg:*.jpg +50:application/x-raw-disk-image-xz-compressed:*.img.xz +50:application/x-jbuilder-project:*.jpx +50:image/jp2:*.jpx +50:text/x-svsrc:*.sv +50:image/x-quicktime:*.qtif +50:image/x-kodak-k25:*.k25 +50:text/x-scheme:*.ss +50:application/vnd.openxmlformats-officedocument.presentationml.presentation:*.pptx +50:application/vnd.openxmlformats-officedocument.presentationml.presentation:*.pptx +50:application/x-ace:*.ace +50:image/vnd.zbrush.pcx:*.pcx +50:text/x-adasrc:*.ads +50:text/x-tcl:*.tk +50:text/x-changelog:changelog +50:audio/flac:*.flac +50:text/x-adasrc:*.adb +50:text/html:*.htm +50:text/x-google-video-pointer:*.gvp +50:text/troff:*.tr +50:audio/x-matroska:*.mka +50:text/vnd.trolltech.linguist:*.ts +50:video/mp2t:*.ts +50:application/x-cb7:*.cb7 +50:text/x-vhdl:*.vhdl +50:audio/ogg:*.oga +50:audio/x-vorbis+ogg:*.oga +50:audio/x-flac+ogg:*.oga +50:audio/x-speex+ogg:*.oga +50:application/xslt+xml:*.xsl +50:application/x-saturn-rom:*.iso +50:application/x-wii-rom:*.iso +50:application/x-gamecube-rom:*.iso +50:application/atom+xml:*.atom +50:video/3gpp:*.3ga +50:application/x-kontour:*.kon +50:audio/ogg:*.ogg +50:video/ogg:*.ogg +50:audio/x-vorbis+ogg:*.ogg +50:audio/x-flac+ogg:*.ogg +50:audio/x-speex+ogg:*.ogg +50:video/x-theora+ogg:*.ogg +50:image/x-pentax-pef:*.pef +50:application/vnd.ms-cab-compressed:*.cab +50:text/markdown:*.mkd +50:application/rdf+xml:*.rdfs +50:application/x-zoo:*.zoo +50:video/x-ogm+ogg:*.ogm +50:text/x-rpm-spec:*.spec +50:application/x-x509-ca-cert:*.pem +50:video/3gpp2:*.3gp2 +50:application/x-xpinstall:*.xpi +50:video/x-matroska:*.mkv +50:application/ram:*.ram +50:application/x-designer:*.ui +50:application/x-gtk-builder:*.ui +50:audio/x-wavpack-correction:*.wvc +50:video/ogg:*.ogv +50:application/vnd.tcpdump.pcap:*.cap +50:application/ogg:*.ogx +50:application/x-rar:*.rar +50:application/x-xbel:*.xbel +50:application/jrd+json:*.jrd +50:application/vnd.ms-tnef:*.tnef +50:image/x-panasonic-raw:*.raw +50:video/3gpp:*.3gp +50:audio/vnd.rn-realaudio:*.rax +50:text/x-python:*.wsgi +50:application/x-7z-compressed:*.7z +50:audio/x-wavpack:*.wvp +50:image/x-cmu-raster:*.ras +50:application/x-font-type1:*.pfa +50:application/x-font-type1:*.pfb +50:application/x-kpovmodeler:*.kpm +50:text/x-ocaml:*.mli +50:image/x-fuji-raf:*.raf +50:application/ld+json:*.jsonld +50:audio/x-ms-asx:*.wvx +50:application/x-kpresenter:*.kpr +50:application/x-font-bdf:*.bdf +50:application/x-cd-image:*.iso9660 +50:application/x-kpresenter:*.kpt +50:text/x-eiffel:*.e +50:application/x-font-afm:*.afm +50:text/x-nfo:*.nfo +50:image/x-compressed-xcf:*.xcf.bz2 +50:text/x-cobol:*.cbl +50:video/mp2t:*.bdm +50:video/quicktime:*.moov +50:text/x-texinfo:*.texi +50:application/x-wwf:*.wwf +50:application/x-cbr:*.cbr +50:application/pkcs12:*.pfx +50:application/metalink+xml:*.metalink +50:application/x-cbt:*.cbt +50:video/mpeg:[0-9][0-9][0-9].vdr +50:application/x-perl:*.perl +50:application/vnd.mozilla.xul+xml:*.xul +50:application/x-cbz:*.cbz +50:text/x-log:*.log +50:application/x-smaf:*.mmf +50:application/javascript:*.jsm +50:text/x-meson:meson_options.txt +50:application/x-gba-rom:*.agb +50:application/x-hwt:*.hwt +50:text/x-iptables:*.iptables +50:application/mathml+xml:*.mml +50:application/oxps:*.oxps +50:video/mp2t:*.bdmv +50:video/3gpp:*.3gpp +50:application/x-docbook+xml:*.docbook +50:audio/x-mod:*.m15 +50:application/x-chess-pgn:*.pgn +50:audio/x-mo3:*.mo3 +50:application/x-bcpio:*.bcpio +50:application/pgp-encrypted:*.pgp +50:application/pgp-keys:*.pgp +50:application/pgp-signature:*.pgp +50:application/x-bzip-compressed-tar:*.tar.bz +50:application/x-amipro:*.sam +50:application/vnd.google-earth.kmz:*.kmz +50:video/quicktime:*.qt +50:image/x-portable-graymap:*.pgm +50:application/x-krita:*.kra +50:application/x-dar:*.dar +50:application/vnd.wordperfect:*.wp +50:image/vnd.wap.wbmp:*.wbmp +50:application/x-spss-sav:*.sav +50:text/x-scons:sconstruct +50:video/x-msvideo:*.divx +50:audio/x-wavpack:*.wv +50:application/xhtml+xml:*.xhtml +50:video/x-mng:*.mng +50:text/x-uuencode:*.uue +50:image/x-pict:*.pict1 +50:image/x-pict:*.pict2 +50:image/x-bzeps:*.eps.bz2 +50:application/x-n64-rom:*.z64 +50:audio/x-musepack:*.mp+ +50:text/x-c++hdr:*.hxx +50:application/rdf+xml:*.rdf +50:application/x-netcdf:*.cdf +50:application/vnd.rn-realmedia:*.rmvb +50:application/x-dbf:*.dbf +50:audio/mp2:*.mp2 +50:video/mpeg:*.mp2 +50:application/vnd.lotus-1-2-3:*.123 +50:application/x-php:*.php +50:application/x-font-pcf:*.pcf.gz +50:audio/mpeg:*.mp3 +50:video/mp4:*.mp4 +50:text/x-python:*.py +50:audio/x-minipsf:*.minipsf +50:audio/x-xm:*.xm +50:application/vnd.corel-draw:*.cdr +50:audio/x-xi:*.xi +50:image/x-xwindowdump:*.xwd +50:application/x-desktop:*.desktop +50:application/x-bzip-compressed-tar:*.tb2 +50:text/x-tex:*.latex +50:text/x-moc:*.moc +50:audio/x-mod:*.mod +50:application/vnd.openxmlformats-officedocument.presentationml.slideshow:*.ppsx +50:application/x-docbook+xml:*.dbk +50:text/x-mof:*.mof +50:application/x-xz:*.xz +50:application/vnd.ms-excel.sheet.binary.macroEnabled.12:*.xlsb +50:application/vnd.ms-excel.sheet.binary.macroenabled.12:*.xlsb +50:application/x-kspread:*.ksp +50:audio/x-aiff:*.aif +50:text/markdown:*.markdown +50:text/vcard:*.gcrd +50:application/x-php:*.php3 +50:application/x-php:*.php4 +50:application/x-php:*.php5 +50:text/x-reject:*.rej +50:application/vnd.ms-excel.sheet.macroEnabled.12:*.xlsm +50:application/vnd.ms-excel.sheet.macroenabled.12:*.xlsm +50:video/mp2t:*.m2ts +50:text/x-ms-regedit:*.reg +50:application/vnd.openxmlformats-officedocument.wordprocessingml.document:*.docx +50:application/vnd.openxmlformats-officedocument.wordprocessingml.document:*.docx +50:text/x-dcl:*.dcl +50:application/dicom:*.dcm +50:video/vnd.mpegurl:*.m1u +50:text/x-scheme:*.scm +50:application/x-qtiplot:*.qti.gz +50:application/pkix-cert:*.cer +50:image/x-kodak-dcr:*.dcr +50:application/x-tar:*.tar +50:text/x-patch:*.patch +50:text/x-scala:*.scala +50:image/vnd.djvu:*.djvu +50:audio/x-musepack:*.mpc +50:video/quicktime:*.mov +50:video/mpeg:*.mpe +50:application/x-tarz:*.taz +50:application/x-trash:*.old +50:video/mpeg:*.mpg +50:video/mp2t:*.mpl +50:application/vnd.stardivision.draw:*.sda +50:application/vnd.stardivision.calc:*.sdc +50:text/x-mrml:*.mrml +50:application/vnd.stardivision.impress:*.sdd +50:audio/x-musepack:*.mpp +50:application/vnd.ms-excel.template.macroEnabled.12:*.xltm +50:application/vnd.ms-excel.template.macroenabled.12:*.xltm +50:video/mp4:*.lrv +50:video/mp2t:*.m2t +50:image/x-gzeps:*.epsf.gz +50:application/x-lrzip:*.lrz +50:video/3gpp2:*.3gpp2 +50:image/jpeg:*.jpeg +50:application/mbox:*.mbox +50:application/vnd.stardivision.impress:*.sdp +50:application/sdp:*.sdp +50:audio/x-mpegurl:*.m3u8 +50:application/vnd.apple.mpegurl:*.m3u8 +50:application/vnd.stardivision.chart:*.sds +50:image/x-dds:*.dds +50:application/x-kugar:*.kud +50:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:*.xlsx +50:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:*.xlsx +50:application/vnd.stardivision.writer:*.sdw +50:application/x-fictionbook+xml:*.fb2 +50:application/x-xzpdf:*.pdf.xz +50:text/x-copying:copying +50:application/x-bzip-compressed-tar:*.tbz +50:application/zlib:*.zz +50:application/x-lrzip-compressed-tar:*.tar.lrz +50:text/x-bibtex:*.bib +50:image/x-rgb:*.rgb +50:application/x-gzpostscript:*.ps.gz +50:application/x-gameboy-rom:*.cgb +50:application/x-php:*.phps +50:application/vnd.debian.binary-package:*.deb +50:application/x-qw:*.qif +50:image/x-quicktime:*.qif +50:audio/x-mpegurl:*.m3u +50:application/vnd.apple.mpegurl:*.m3u +50:application/vnd.openxmlformats-officedocument.spreadsheetml.template:*.xltx +50:application/vnd.openxmlformats-officedocument.spreadsheetml.template:*.xltx +50:text/x-c++src:*.c++ +50:application/x-ccmx:*.ccmx +50:application/vnd.coffeescript:*.coffee +50:application/octet-stream:*.bin +50:application/x-saturn-rom:*.bin +50:application/smil+xml:*.kino +50:application/pgp-keys:*.pkr +50:application/vnd.ms-visio.stencil.macroEnabled.main+xml:*.vssm +50:image/cgm:*.cgm +50:text/x-mup:*.not +50:text/x-tcl:*.tcl +50:audio/mp4:*.m4a +50:application/x-x509-ca-cert:*.der +50:audio/x-m4b:*.m4b +50:application/x-pagemaker:*.pm6 +50:text/x-meson:meson.build +50:application/x-sami:*.sami +50:application/vnd.ms-visio.stencil.main+xml:*.vssx +50:audio/x-iriver-pla:*.pla +50:text/x-mrml:*.mrl +50:application/vnd.nintendo.snes.rom:*.sfc +50:application/xml:*.xsd +50:video/mp4:*.m4v +50:video/mp2t:*.mpls +50:application/x-planperfect:*.pln +50:text/x-tex:*.ltx +50:image/x-minolta-mrw:*.mrw +50:application/metalink4+xml:*.meta4 +50:application/vnd.ms-powerpoint.addin.macroEnabled.12:*.ppam +50:application/vnd.ms-visio.template.macroEnabled.main+xml:*.vstm +50:application/x-compressed-tar:*.tar.gz +50:audio/x-scpls:*.pls +50:application/vnd.ms-htmlhelp:*.chm +50:application/x-hwp:*.hwp +50:application/x-abiword:*.abw.gz +50:application/x-alz:*.alz +50:application/x-kword:*.kwd +50:text/x-lua:*.lua +50:application/vnd.ms-visio.template.main+xml:*.vstx +50:video/vnd.mpegurl:*.m4u +50:text/x-ooc:*.ooc +50:application/x-msi:*.msi +50:application/x-kexiproject-sqlite2:*.kexi +50:application/x-kexiproject-sqlite3:*.kexi +50:video/x-anim:*.anim[1-9j] +50:application/x-pagemaker:*.pmd +50:application/x-abiword:*.zabw +50:application/x-gameboy-rom:*.sgb +50:application/x-kword:*.kwt +50:application/x-go-sgf:*.sgf +50:application/pkcs10:*.p10 +50:image/x-sgi:*.sgi +50:application/pkcs12:*.p12 +50:application/x-blender:*.blender +50:application/vnd.stardivision.writer:*.sgl +50:application/x-msx-rom:*.msx +50:application/x-dia-shape:*.shape +50:application/x-blender:*.blend +50:application/x-blender:*.blend +50:application/x-mimearchive:*.mhtml +50:audio/midi:*.midi +50:application/x-java-jnlp-file:*.jnlp +50:text/x-cmake:cmakelists.txt +50:audio/x-amzxml:*.amz +50:image/x-tga:*.tpic +50:audio/AMR:*.amr +50:text/x-makefile:makefile +50:text/x-scons:sconscript.* +50:text/x-tex:*.tex +50:application/vnd.oasis.opendocument.graphics-flat-xml:*.fodg +50:application/vnd.oasis.opendocument.graphics-flat-xml:*.fodg +50:text/sgml:*.sgm +50:application/x-amiga-disk-format:*.adf +50:image/x-msod:*.msod +50:audio/x-mod:*.mtm +50:image/png:*.png +50:application/vnd.oasis.opendocument.presentation-flat-xml:*.fodp +50:application/vnd.oasis.opendocument.presentation-flat-xml:*.fodp +50:application/x-navi-animation:*.ani +50:application/vnd.oasis.opendocument.spreadsheet-flat-xml:*.fods +50:application/vnd.oasis.opendocument.spreadsheet-flat-xml:*.fods +50:application/vnd.oasis.opendocument.text-flat-xml:*.fodt +50:application/vnd.oasis.opendocument.text-flat-xml:*.fodt +50:application/x-n64-rom:*.n64 +50:application/x-ustar:*.ustar +50:application/x-gameboy-rom:*.gbc +50:application/x-gba-rom:*.gba +50:application/x-java-pack200:*.pack +50:application/dicom:dicomdir +50:application/x-shar:*.shar +50:application/x-shorten:*.shn +50:application/x-genesis-rom:*.32x +50:image/x-portable-anymap:*.pnm +50:application/x-gzdvi:*.dvi.gz +50:application/annodex:*.anx +50:text/html:*.html +50:video/mp2t:*.mts +50:text/x-authors:authors +50:text/x-install:install +50:application/x-quattropro:*.wb1 +50:application/x-quattropro:*.wb2 +50:application/x-quattropro:*.wb3 +50:application/x-gnucash:*.gnucash +50:application/x-perl:*.pod +50:application/x-source-rpm:*.src.rpm +50:image/x-lwo:*.lwo +50:application/x-dia-diagram:*.dia +50:application/vnd.lotus-wordpro:*.lwp +50:application/x-lrzip-compressed-tar:*.tlrz +50:application/x-partial-download:*.wkdownload +50:application/x-glade:*.glade +50:application/pgp-signature:*.sig +50:text/x-qml:*.qml +50:image/x-tga:*.tga +50:audio/prs.sid:*.sid +50:application/x-trash:*.sik +50:application/x-spss-por:*.por +50:application/x-wii-wad:*.wad +50:application/vnd.ms-powerpoint:*.pot +50:text/x-gettext-translation-template:*.pot +50:image/x-lws:*.lws +50:application/x-zip-compressed-fb2:*.fb2.zip +50:text/vcard:*.vcf +50:application/vnd.symbian.install:*.sis +50:application/x-stuffit:*.sit +50:application/x-e-theme:*.etheme +50:application/sieve:*.siv +50:image/bmp:*.bmp +50:application/x-nes-rom:*.unif +50:image/x-skencil:*.sk1 +50:image/openraster:*.ora +50:text/vcard:*.vct +50:application/x-compressed-tar:*.tgz +50:application/x-netshow-channel:*.nsc +50:audio/x-wav:*.wav +50:image/x-olympus-orf:*.orf +50:audio/x-ms-asx:*.wax +50:audio/x-ape:*.ape +50:image/x-lwo:*.lwob +50:text/calendar:*.vcs +50:image/rle:*.rle +50:application/x-siag:*.siag +50:application/vnd.android.package-archive:*.apk +50:image/x-portable-pixmap:*.ppm +50:application/x-lz4:*.lz4 +50:image/x-applix-graphics:*.ag +50:application/illustrator:*.ai +50:application/vnd.ms-powerpoint:*.pps +50:application/vnd.ms-powerpoint:*.ppt +50:application/vnd.ms-powerpoint:*.ppt +50:video/x-nsv:*.nsv +50:application/x-perl:*.al +50:image/x-tga:*.vda +50:text/x-tex:*.cls +50:application/x-archive:*.ar +50:application/vnd.ms-powerpoint:*.ppz +50:application/x-applix-spreadsheet:*.as +50:application/vnd.tcpdump.pcap:*.pcap +50:audio/basic:*.au +50:application/x-applix-word:*.aw +50:image/vnd.djvu:*.djv +50:application/vnd.palm:*.pqa +50:application/xslt+xml:*.xslt +50:application/x-bittorrent:*.torrent +50:image/x-bzeps:*.epsi.bz2 +50:video/quicktime:*.qtvr +50:text/x-mup:*.mup +50:application/x-t602:*.602 +50:application/vnd.rn-realmedia:*.rmj +50:image/tiff:*.tif +50:application/x-lyx:*.lyx +50:application/x-gedcom:*.ged +50:application/vnd.rn-realmedia:*.rmm +50:application/x-gnucash:*.xac +50:text/x-eiffel:*.eif +50:application/x-sv4cpio:*.sv4cpio +50:application/vnd.rn-realmedia:*.rms +50:application/pgp-keys:*.skr +50:application/x-tar:*.gem +50:application/x-genesis-rom:*.gen +50:application/vnd.ms-works:*.wcm +50:application/x-yaml:*.yaml +50:application/vnd.ms-word.template.macroEnabled.12:*.dotm +50:application/vnd.ms-word.template.macroenabled.12:*.dotm +50:application/x-lha:*.lzh +50:application/mxf:*.mxf +50:application/vnd.oasis.opendocument.chart-template:*.otc +50:application/x-mobipocket-ebook:*.prc +50:application/vnd.palm:*.prc +50:application/vnd.oasis.opendocument.formula-template:*.otf +50:application/x-font-otf:*.otf +50:application/vnd.oasis.opendocument.graphics-template:*.otg +50:application/vnd.oasis.opendocument.graphics-template:*.otg +50:application/vnd.oasis.opendocument.text-web:*.oth +50:application/vnd.oasis.opendocument.text-web:*.oth +50:application/relax-ng-compact-syntax:*.rnc +50:application/x-lzop:*.lzo +50:text/x-makefile:gnumakefile +50:application/x-bzip:*.bz +50:application/x-arj:*.arj +50:application/x-spss-sav:*.zsav +50:text/x-c++src:*.cc +50:application/vnd.oasis.opendocument.presentation-template:*.otp +50:application/vnd.oasis.opendocument.presentation-template:*.otp +50:image/fits:*.fits +50:application/vnd.ms-works:*.wdb +50:application/vnd.oasis.opendocument.spreadsheet-template:*.ots +50:application/vnd.oasis.opendocument.spreadsheet-template:*.ots +50:application/vnd.oasis.opendocument.text-template:*.ott +50:application/vnd.oasis.opendocument.text-template:*.ott +50:application/x-partial-download:*.crdownload +50:application/x-tzo:*.tar.lzo +50:application/x-hdf:*.hdf +50:application/x-tarz:*.tar.z +50:application/vnd.rn-realmedia:*.rmx +50:image/x-sony-arw:*.arw +50:image/svg+xml-compressed:*.svgz +50:text/x-csharp:*.cs +50:text/spreadsheet:*.slk +50:image/x-icns:*.icns +50:image/x-xbitmap:*.xbm +50:video/vnd.mpegurl:*.mxu +50:application/xml:*.xbl +50:application/xml:*.rng +50:application/x-pagemaker:*.p65 +50:text/x-opml+xml:*.opml +50:text/plain:*.asc +50:image/vnd.adobe.photoshop:*.psd +50:application/x-font-linux-psf:*.psf +50:audio/x-psf:*.psf +50:text/x-cobol:*.cob +50:application/vnd.ms-asf:*.asf +50:application/vnd.nintendo.snes.rom:*.smc +50:application/vnd.stardivision.mail:*.smd +50:application/x-genesis-rom:*.smd +50:application/x-dc-rom:*.dc +50:application/vnd.stardivision.math:*.smf +50:application/x-apple-diskimage:*.dmg +50:application/smil+xml:*.smi +50:application/x-sami:*.smi +50:text/x-dsrc:*.di +50:application/x-asp:*.asp +50:application/x-gedcom:*.gedcom +50:application/smil+xml:*.sml +50:text/x-ssa:*.ass +50:image/x-xfig:*.fig +50:image/x-tga:*.icb +50:application/vnd.tcpdump.pcap:*.dmp +50:application/x-pocket-word:*.psw +50:application/x-sms-rom:*.sms +50:audio/x-ms-asx:*.asx +50:image/x-xcf:*.xcf +50:text/vnd.sun.j2me.app-descriptor:*.jad +50:video/dv:*.dv +50:application/vnd.openxmlformats-officedocument.wordprocessingml.template:*.dotx +50:application/vnd.openxmlformats-officedocument.wordprocessingml.template:*.dotx +50:image/vnd.microsoft.icon:*.ico +50:application/x-ica:*.ica +50:application/vnd.iccprofile:*.icc +50:text/calendar:*.ics +50:application/x-java-archive:*.jar +50:application/x-gnumeric:*.gnumeric +50:application/vnd.iccprofile:*.icm +50:application/x-sv4crc:*.sv4crc +50:audio/basic:*.snd +50:application/x-lzma:*.lzma +50:application/x-x509-ca-cert:*.cert +50:image/x-adobe-dng:*.dng +50:video/mp2t:*.cpi +50:text/x-vhdl:*.vhd +50:application/x-rpm:*.rpm +50:application/x-bzpostscript:*.ps.bz2 +50:text/x-emacs-lisp:*.el +50:application/xspf+xml:*.xspf +50:text/x-c++src:*.cpp +50:application/vnd.oasis.opendocument.text-master-template:*.otm +50:image/x-canon-cr2:*.cr2 +50:application/x-gnuplot:*.gnuplot +50:application/ecmascript:*.es +50:image/fax-g3:*.g3 +50:text/x-idl:*.idl +50:application/x-pkcs7-certificates:*.p7b +50:application/pkcs7-mime:*.p7c +50:application/andrew-inset:*.ez +50:application/x-desktop:*.kdelnk +50:application/x-lzma-compressed-tar:*.tlz +50:application/vnd.ms-publisher:*.pub +50:text/x-xslfo:*.xslfo +50:application/x-core:core:cs +50:application/x-core:core +50:application/x-trig:*.trig +50:application/pkcs7-mime:*.p7m +50:application/msword:*.doc +50:application/msword:*.doc +50:application/vnd.ms-word:*.doc +50:application/rdf+xml:*.owl +50:text/cache-manifest:*.manifest +50:application/pkcs7-signature:*.p7s +50:image/x-emf:*.emf +50:application/x-fluid:*.fl +50:image/gif:*.gif +50:message/rfc822:*.eml +50:application/owl+xml:*.owx +50:image/ief:*.ief +50:text/x-c++hdr:*.h++ +50:text/x-xslfo:*.fo +50:application/vnd.emusic-emusic_package:*.emp +50:application/msword-template:*.dot +50:text/vnd.graphviz:*.dot +50:application/x-hdf:*.h4 +50:application/x-hdf:*.h5 +50:application/x-nzb:*.nzb +50:text/x-uil:*.uil +50:video/vnd.vivo:*.viv +50:application/vnd.debian.binary-package:*.udeb +50:audio/midi:*.kar +50:video/x-msvideo:*.avf +50:text/csv-schema:*.csvs +50:application/x-pkcs7-certificates:*.spc +50:application/x-font-speedo:*.spd +50:application/x-qtiplot:*.qti +50:application/vnd.ms-excel.addin.macroEnabled.12:*.xlam +50:application/x-tex-gf:*.gf +50:application/vnd.ms-tnef:*.tnf +50:application/x-quicktime-media-link:*.qtl +50:text/x-patch:*.diff +50:application/pkix-crl:*.crl +50:application/vnd.openofficeorg.extension:*.oxt +50:application/vnd.openofficeorg.extension:*.oxt +50:application/x-source-rpm:*.spm +50:application/x-sms-rom:*.gg +50:application/vnd.adobe.flash.movie:*.spl +50:application/x-bzdvi:*.dvi.bz2 +50:application/x-gnuplot:*.gp +50:application/x-gameboy-rom:*.gb +50:application/x-x509-ca-cert:*.crt +50:image/x-sony-sr2:*.sr2 +50:application/x-gz-font-linux-psf:*.psf.gz +50:image/x-canon-crw:*.crw +50:image/x-ilbm:*.iff +50:audio/x-speex:*.spx +50:audio/x-mod:*.ult +50:audio/x-mod:*.669 +50:video/x-flv:*.flv +50:application/x-kivio:*.flw +50:text/vnd.graphviz:*.gv +50:application/gzip:*.gz +50:application/pkix-pkipath:*.pkipath +50:application/vnd.palm:*.oprc +50:audio/AMR-WB:*.awb +50:text/x-genie:*.gs:cs +50:text/x-genie:*.gs +50:video/x-flic:*.flc +50:text/x-go:*.go +50:application/x-cdrdao-toc:*.toc +50:application/x-awk:*.awk +50:application/x-csh:*.csh +50:audio/x-s3m:*.s3m +50:text/x-c++hdr:*.hh +50:application/xml-external-parsed-entity:*.ent +50:application/sql:*.sql +50:image/x-gzeps:*.eps.gz +50:text/x-texinfo:*.texinfo +50:video/x-msvideo:*.avi +50:application/rss+xml:*.rss +50:application/x-ufraw:*.ufraw +50:text/css:*.css +50:text/x-c++hdr:*.hp +50:application/x-ms-wim:*.wim +50:text/csv:*.csv +50:text/x-haskell:*.hs +50:application/x-mobipocket-ebook:*.mobi +50:application/vnd.lotus-1-2-3:*.wk1 +50:audio/annodex:*.axa +50:application/vnd.lotus-1-2-3:*.wk3 +50:application/vnd.lotus-1-2-3:*.wk4 +50:application/x-wais-source:*.src +50:application/rtf:*.rtf +50:image/x-sony-srf:*.srf +50:image/x-ilbm:*.ilbm +50:audio/x-mpegurl:*.vlc +50:application/x-nes-rom:*.unf +50:application/x-smaf:*.smaf +50:audio/x-mod:*.uni +50:video/x-flic:*.fli +50:text/sgml:*.sgml +50:video/annodex:*.axv +50:image/x-kodak-kdc:*.kdc +50:text/x-txt2tags:*.t2t +50:application/x-subrip:*.srt +50:audio/x-it:*.it +50:image/x-eps:*.eps +50:application/x-gzpdf:*.pdf.gz +50:image/x-eps:*.epsf +50:text/richtext:*.rtx +50:image/x-eps:*.epsi +50:application/x-java-jce-keystore:*.jceks +50:application/x-python-bytecode:*.pyc +50:image/x-ilbm:*.lbm +50:video/vnd.vivo:*.vivo +50:text/x-ssa:*.ssa +50:application/x-cue:*.cue +50:audio/vnd.dts.hd:*.dtshd +50:application/x-python-bytecode:*.pyo +50:application/x-windows-themepack:*.themepack +50:video/x-sgi-movie:*.movie +50:text/x-cmake:*.cmake +50:text/x-dsl:*.dsl +50:application/x-trash:*% +50:application/vnd.ms-powerpoint.slide.macroEnabled.12:*.sldm +50:image/x-panasonic-raw2:*.rw2 +50:application/gml+xml:*.gml +50:application/javascript:*.js +50:application/x-markaby:*.mab +50:application/x-gettext-translation:*.gmo +50:image/x-win-bitmap:*.cur +50:text/x-fortran:*.for +50:application/vnd.lotus-1-2-3:*.wks +50:application/vnd.ms-works:*.wks +50:text/x-python:*.pyx +50:application/vnd.openxmlformats-officedocument.presentationml.slide:*.sldx +50:text/x-makefile:*.mak +50:application/x-troff-man:*.man +50:message/x-gnu-rmail:rmail +50:application/vnd.sun.xml.calc.template:*.stc +50:application/vnd.sun.xml.calc.template:*.stc +50:application/vnd.sun.xml.draw.template:*.std +50:application/vnd.sun.xml.draw.template:*.std +50:application/xml-dtd:*.dtd +50:application/x-iwork-keynote-sffkey:*.key +50:application/vnd.sun.xml.impress.template:*.sti +50:application/vnd.sun.xml.impress.template:*.sti +50:application/x-gnucash:*.gnc +50:application/x-abiword:*.abw.crashed +50:application/x-kchart:*.chrt +50:audio/prs.sid:*.psid +50:application/gnunet-directory:*.gnd +50:audio/ogg:*.opus +50:audio/x-opus+ogg:*.opus +50:audio/x-stm:*.stm +50:application/x-bzip:*.bz2 +50:text/x-erlang:*.erl +50:application/epub+zip:*.epub +50:application/x-java-keystore:*.ks +50:video/vnd.rn-realvideo:*.rvx +50:application/x-m4:*.m4 +50:application/vnd.sun.xml.writer.template:*.stw +50:application/vnd.sun.xml.writer.template:*.stw +50:text/x-tex:*.sty +50:audio/vnd.dts:*.dts +50:application/json:*.json +50:text/x-tex:*.dtx +50:application/x-kformula:*.kfo +50:application/json-patch+json:*.json-patch +50:application/x-bzip-compressed-tar:*.tar.bz2 +50:application/x-java:*.class +50:application/x-shared-library-la:*.la +50:text/x-microdvd:*.sub +50:text/x-mpsub:*.sub +50:text/x-subviewer:*.sub +50:application/font-woff:*.woff +50:image/x-macpaint:*.pntg +50:application/winhlp:*.hlp +50:image/tiff:*.tiff +50:audio/x-ms-wma:*.wma +50:text/x-qml:*.qmlproject +50:video/mpeg:*.vob +50:application/vnd.ms-visio.drawing.macroEnabled.main+xml:*.vsdm +50:text/troff:*.roff +50:image/x-sun-raster:*.sun +50:audio/x-voc:*.voc +50:image/x-wmf:*.wmf +50:text/x-scons:sconscript +50:application/x-tar:*.gtar +50:text/vnd.wap.wml:*.wml +50:application/x-par2:*.par2 +50:application/x-par2:*.par2 +50:application/x-cpio-compressed:*.cpio.gz +50:application/vnd.ms-visio.drawing.main+xml:*.vsdx +50:application/vnd.stardivision.writer:*.vor +50:image/x-compressed-xcf:*.xcf.gz +50:text/x-lilypond:*.ly +50:application/x-lzip:*.lz +50:audio/x-psflib:*.psflib +50:video/x-ms-wmv:*.wmv +50:audio/x-ms-asx:*.wmx +50:application/x-it87:*.it87 +50:text/tab-separated-values:*.tsv +50:audio/mp4:*.f4a +50:audio/x-m4b:*.f4b +50:audio/x-tta:*.tta +50:application/x-trash:*~ +50:application/x-font-ttf:*.ttc +50:image/svg+xml:*.svg +50:application/x-kexi-connectiondata:*.kexic +50:application/x-font-ttf:*.ttf +50:application/x-dvi:*.dvi +50:application/vnd.ms-excel:*.xla +50:text/x-java:*.java +50:application/vnd.ms-excel:*.xlc +50:application/vnd.ms-excel:*.xld +50:application/pgp-encrypted:*.gpg +50:application/pgp-keys:*.gpg +50:application/pgp-signature:*.gpg +50:application/x-xliff:*.xlf +50:application/x-gettext-translation:*.mo +50:text/x-modelica:*.mo +50:text/x-svhdr:*.svh +50:application/x-mswinurl:*.url +50:image/x-gzeps:*.epsi.gz +50:application/vnd.ms-access:*.mdb +50:application/vnd.ms-excel:*.xll +50:application/vnd.ms-excel:*.xlm +50:application/vnd.ms-tnef:winmail.dat +50:application/x-kexiproject-shortcut:*.kexis +50:application/x-font-ttx:*.ttx +50:application/x-raw-disk-image:*.raw-disk-image +50:application/vnd.ms-works:*.xlr +50:application/vnd.ms-excel:*.xls +50:application/vnd.ms-excel:*.xls +50:application/vnd.wordperfect:*.wp4 +50:application/vnd.wordperfect:*.wp5 +50:application/vnd.wordperfect:*.wp6 +50:application/vnd.ms-excel:*.xlt +50:application/vnd.ms-excel:*.xlw +50:text/turtle:*.ttl +50:application/mathematica:*.nb +50:application/x-netcdf:*.nc +50:video/mp4:*.f4v +50:application/vnd.adobe.flash.movie:*.swf +50:text/x-makefile:*.mk +50:image/vnd.dwg:*.dwg +50:text/x-setext:*.etx +50:application/x-genesis-rom:*.mdx +50:application/vnd.ms-powerpoint.template.macroEnabled.12:*.potm +50:application/vnd.ms-powerpoint.template.macroenabled.12:*.potm +50:application/x-xz-compressed-tar:*.tar.xz +50:application/x-ms-wim:*.swm +50:video/mpeg:*.mpeg +50:text/x-credits:credits +50:text/x-iMelody:*.ime +50:audio/x-xmf:*.xmf +50:application/x-raw-disk-image:*.img +50:text/x-xmi:*.xmi +50:text/spreadsheet:*.sylk +50:application/x-partial-download:*.part +50:application/xml:*.xml +50:audio/x-mod:*.med +50:text/vnd.wap.wmlscript:*.wmls +50:image/x-bzeps:*.epsf.bz2 +50:application/x-killustrator:*.kil +50:application/pkcs8:*.p8 +50:application/zip:*.zip +50:image/vnd.ms-modi:*.mdi +50:application/x-java-keystore:*.jks +50:text/x-c++src:*.cxx +50:text/x-iMelody:*.imy +50:application/vnd.sun.xml.calc:*.sxc +50:application/vnd.sun.xml.calc:*.sxc +50:application/vnd.sun.xml.draw:*.sxd +50:application/vnd.sun.xml.draw:*.sxd +50:application/x-java-keystore:cacerts +50:application/vnd.sun.xml.writer.global:*.sxg +50:application/vnd.sun.xml.writer.global:*.sxg +50:application/x-graphite:*.gra +50:application/vnd.sun.xml.impress:*.sxi +50:application/vnd.sun.xml.impress:*.sxi +50:video/x-matroska-3d:*.mk3d +50:application/vnd.wordperfect:*.wpd +50:application/vnd.sun.xml.math:*.sxm +50:application/vnd.sun.xml.math:*.sxm +50:application/vnd.ms-powerpoint.slideshow.macroEnabled.12:*.ppsm +50:application/x-wpg:*.wpg +50:application/x-gnuplot:*.gplt +50:image/vnd.dxf:*.dxf +50:application/x-lha:*.lha +50:model/vrml:*.vrm +50:application/vnd.ms-wpl:*.wpl +50:audio/mpeg:*.mpga +50:application/vnd.sun.xml.writer:*.sxw +50:application/vnd.sun.xml.writer:*.sxw +50:application/vnd.wordperfect:*.wpp +50:application/x-n64-rom:*.v64 +50:text/x-c++hdr:*.hpp +50:application/vnd.ms-works:*.wps +50:text/plain:*,v +50:text/markdown:*.md +50:text/x-tex:*.ins +50:text/x-troff-ms:*.ms +50:application/x-tgif:*.obj +50:text/x-c++src:*.C:cs +50:text/x-c++src:*.C +50:text/x-literate-haskell:*.lhs +50:image/x-pict:*.pict +50:text/x-ocaml:*.ml +50:text/x-troff-mm:*.mm +50:application/x-nintendo-ds-rom:*.nds +50:application/x-bzip-compressed-tar:*.tbz2 +50:text/x-qml:*.qmltypes +50:application/x-lhz:*.lhz +50:application/vnd.visio:*.vsd +50:application/x-tex-pk:*.pk +50:application/x-font-type1:*.gsf +50:application/x-perl:*.pl +50:application/x-perl:*.pl +50:application/x-perl:*.pm +50:application/x-pagemaker:*.pm +50:application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm +50:application/vnd.ms-powerpoint.presentation.macroenabled.12:*.pptm +50:text/x-gettext-translation:*.po +50:application/vnd.hp-hpgl:*.hpgl +50:audio/x-gsm:*.gsm +50:application/postscript:*.ps +50:text/x-fortran:*.f90 +50:application/vnd.ms-word.document.macroEnabled.12:*.docm +50:application/vnd.ms-word.document.macroenabled.12:*.docm +50:application/x-yaml:*.yml +50:application/vnd.visio:*.vss +50:application/vnd.visio:*.vst +50:image/x-tga:*.vst +50:application/x-karbon:*.karbon +50:image/x-nikon-nef:*.nef +50:application/vnd.visio:*.vsw +50:application/x-archive:*.a +50:audio/aac:*.aac +50:text/x-csrc:*.c:cs +50:text/x-csrc:*.c +50:application/x-pw:*.pw +50:application/x-magicpoint:*.mgp +50:text/x-ocl:*.ocl +50:application/x-pak:*.pak +50:text/x-chdr:*.h +50:text/x-dsrc:*.d +50:application/x-nes-rom:*.nes +50:application/x-ms-dos-executable:*.exe +50:text/x-objcsrc:*.m +50:text/x-matlab:*.m +50:text/x-troff-me:*.me +50:application/x-object:*.o +50:text/x-fortran:*.f +50:text/x-pascal:*.p +50:text/x-pascal:*.pas +50:video/mp2t:*.clpi +10:application/x-perl:*.t +10:text/troff:*.t +10:text/x-readme:readme* +10:application/pgp-encrypted:*.asc +10:application/pgp-keys:*.asc +10:application/pgp-signature:*.asc +10:text/x-makefile:makefile.* |