aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina')
-rw-r--r--src-qt5/core/libLumina/LuminaUtils.cpp5
-rw-r--r--src-qt5/core/libLumina/LuminaXDG.cpp691
-rw-r--r--src-qt5/core/libLumina/LuminaXDG.h56
-rw-r--r--src-qt5/core/libLumina/libLumina.pro5
-rw-r--r--src-qt5/core/libLumina/xtrafiles/globs2991
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.*
bgstack15