diff options
author | Ken Moore <moorekou@gmail.com> | 2015-11-10 12:37:12 -0500 |
---|---|---|
committer | Ken Moore <moorekou@gmail.com> | 2015-11-10 12:37:12 -0500 |
commit | df1b1ce03827d8efae1fa1124a504fd972eb40dc (patch) | |
tree | 8c26ff37d4eaf66c46f6e25261665e780d9bf412 | |
parent | Adjust the user validation routine a bit in lumina-checkpass: (diff) | |
download | lumina-df1b1ce03827d8efae1fa1124a504fd972eb40dc.tar.gz lumina-df1b1ce03827d8efae1fa1124a504fd972eb40dc.tar.bz2 lumina-df1b1ce03827d8efae1fa1124a504fd972eb40dc.zip |
Re-work how Lumina finds/loads icons from the current theme. This bypasses the QIcon::fromTheme() functionality completely, that way we get more detection/control over finding bad files and such (SVG files in particular).
-rw-r--r-- | libLumina/LuminaUtils.cpp | 7 | ||||
-rw-r--r-- | libLumina/LuminaUtils.h | 2 | ||||
-rw-r--r-- | libLumina/LuminaX11.h | 78 | ||||
-rw-r--r-- | libLumina/LuminaXDG.cpp | 129 | ||||
-rw-r--r-- | libLumina/libLumina.pro | 2 |
5 files changed, 174 insertions, 44 deletions
diff --git a/libLumina/LuminaUtils.cpp b/libLumina/LuminaUtils.cpp index 39e000a2..0e836748 100644 --- a/libLumina/LuminaUtils.cpp +++ b/libLumina/LuminaUtils.cpp @@ -199,12 +199,15 @@ QString LUtils::PathToAbsolute(QString path){ return path; } -QStringList LUtils::imageExtensions(){ +QStringList LUtils::imageExtensions(bool wildcards){ //Note that all the image extensions are lowercase!! static QStringList imgExtensions; if(imgExtensions.isEmpty()){ QList<QByteArray> fmt = QImageReader::supportedImageFormats(); - for(int i=0; i<fmt.length(); i++){ imgExtensions << QString::fromLocal8Bit(fmt[i]); } + for(int i=0; i<fmt.length(); i++){ + if(wildcards){ imgExtensions << "*."+QString::fromLocal8Bit(fmt[i]); } + else{ imgExtensions << QString::fromLocal8Bit(fmt[i]); } + } } return imgExtensions; } diff --git a/libLumina/LuminaUtils.h b/libLumina/LuminaUtils.h index bbb40c38..90b07962 100644 --- a/libLumina/LuminaUtils.h +++ b/libLumina/LuminaUtils.h @@ -56,7 +56,7 @@ public: static QString PathToAbsolute(QString path); //Get the list of all file extensions which Qt can read (lowercase) - static QStringList imageExtensions(); + static QStringList imageExtensions(bool wildcards = false); //Load a translation file for a Lumina Project static QTranslator* LoadTranslation(QApplication *app, QString appname, QString locale = "", QTranslator *cTrans = 0); diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h index 914ceaa2..779fae0e 100644 --- a/libLumina/LuminaX11.h +++ b/libLumina/LuminaX11.h @@ -144,8 +144,86 @@ public: void WM_ICCCM_SetProtocols(WId win, ICCCM_PROTOCOLS flags); //NET_WM Standards (newer standards) + + // -- ROOT WINDOW PROPERTIES + // _NET_SUPPORTED void WM_Set_Root_Supported(); //set the atom list of supported features on the root window + // _NET_CLIENT_LIST + + // _NET_NUMBER_OF_DESKTOPS + + // _NET_DESKTOP_GEOMETRY + + // _NET_DESKTOP_VIEWPORT + + // _NET_CURRENT_DESKTOP + + // _NET_DESKTOP_NAMES + + // _NET_ACTIVE_WINDOW + + // _NET_WORKAREA + + // _NET_SUPPORTING_WM_CHECK + + // _NET_VIRTUAL_ROOTS + + // _NET_DESKTOP_LAYOUT + + // _NET_SHOWING_DESKTOP + + // -- ROOT WINDOW MESSAGES + // _NET_CLOSE_WINDOW + + // _NET_MOVERESIZE_WINDOW + + // _NET_WM_MOVERESIZE + + // _NET_RESTACK_WINDOW + + // _NET_REQUEST_FRAME_EXTENTS + + // -- WINDOW PROPERTIES + // _NET_SUPPORTED void WM_Set_Window_Supported(WId win); //set the atom list of supported features on the given window + // _NET_WM_NAME + + // _NET_WM_VISIBLE_NAME + + // _NET_WM_ICON_NAME + + // _NET_WM_VISIBLE_ICON_NAME + + // _NET_WM_DESKTOP + + // _NET_WM_WINDOW_TYPE + + // _NET_WM_STATE + + // _NET_WM_ALLOWED_ACTIONS + + // _NET_WM_STRUT + + // _NET_WM_STRUT_PARTIAL + + // _NET_WM_ICON_GEOMETRY + + // _NET_WM_ICON + + // _NET_WM_PID + + // _NET_WM_HANDLED_ICONS + + // _NET_WM_USER_TIME + + // _NET_WM_USER_TIME_WINDOW + + // _NET_FRAME_EXTENTS + + // _NET_WM_OPAQUE_REGION + + // _NET_WM_BYPASS_COMPOSITOR + private: QList<xcb_atom_t> ATOMS; diff --git a/libLumina/LuminaXDG.cpp b/libLumina/LuminaXDG.cpp index b027f900..7003c976 100644 --- a/libLumina/LuminaXDG.cpp +++ b/libLumina/LuminaXDG.cpp @@ -9,6 +9,7 @@ #include "LuminaUtils.h" #include <QObject> #include <QMediaPlayer> +#include <QSvgRenderer> static QStringList mimeglobs; static qint64 mimechecktime; @@ -563,6 +564,9 @@ void LXDG::setEnvironmentVars(){ } QIcon LXDG::findIcon(QString iconName, QString fallback){ + //NOTE: This was re-written on 11/10/15 to avoid using the QIcon::fromTheme() framework + // -- Too many issues with SVG files and/or search paths with the built-in system + //Check if the icon is an absolute path and exists bool DEBUG =false; if(DEBUG){ qDebug() << "[LXDG] Find icon for:" << iconName; } @@ -575,53 +579,87 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){ } //Now try to find the icon from the theme if(DEBUG){ qDebug() << "[LXDG] Start search for icon"; } - //Check the default theme search paths - QStringList paths = QIcon::themeSearchPaths(); - if(paths.isEmpty()){ - //Set the XDG default icon theme search paths - paths << QDir::homePath()+"/.icons"; - QStringList xdd = QString(getenv("XDG_DATA_HOME")).split(":"); - xdd << QString(getenv("XDG_DATA_DIRS")).split(":"); - for(int i=0; i<xdd.length(); i++){ - paths << xdd[i]+"/icons"; - } - paths << LOS::AppPrefix()+"share/pixmaps"; - QIcon::setThemeSearchPaths(paths); - } - if(DEBUG){ qDebug() << "[LXDG] Icon search paths:" << paths; } - //Finding an icon from the current theme is already built into Qt, just use it + //Get the currently-set theme QString cTheme = QIcon::themeName(); if(cTheme.isEmpty()){ QIcon::setThemeName("oxygen"); cTheme = "oxygen"; } - if(DEBUG){ qDebug() << "[LXDG] Current theme:" << cTheme; } - //Try to load the icon from the current theme - QIcon ico = QIcon::fromTheme(iconName); - //Try to load the icon from /usr/local/share/pixmaps - if( ico.isNull() ){ - //qDebug() << "Could not find icon:" << iconName <<"In Theme:" << cTheme; - QDir base(LOS::AppPrefix()+"share/pixmaps"); - QStringList matches = base.entryList(QStringList() << "*"+iconName+"*", QDir::Files | QDir::NoDotAndDotDot, QDir::Name); - if( !matches.isEmpty() ){ - ico = QIcon(base.absoluteFilePath(matches[0])); //just use the first match - }else{ - //Fallback on a manual search over the default theme directories (hicolor, then oxygen) - if( QDir::searchPaths("fallbackicons").isEmpty() ){ - //Set the fallback search paths - QString sysbase = LOS::AppPrefix()+"share/icons/"; - QString localbase = QDir::homePath()+"/.local/share/icons/"; - QDir::setSearchPaths("fallbackicons", QStringList() << getChildIconDirs(localbase+"hicolor") << getChildIconDirs(localbase+"oxygen") << getChildIconDirs(sysbase+"hicolor") << getChildIconDirs(sysbase+"oxygen") ); + //Make sure the current search paths correspond to this theme + if( QDir::searchPaths("icontheme").filter("/"+cTheme+"/").isEmpty() ){ + //Need to reset search paths: setup the "icontheme" "oxygen" and "fallback" sets + // - Get all the base icon directories + QStringList paths; + paths << QDir::homePath()+"/.icons/"; //ordered by priority - local user dirs first + QStringList xdd = QString(getenv("XDG_DATA_HOME")).split(":"); + xdd << QString(getenv("XDG_DATA_DIRS")).split(":"); + for(int i=0; i<xdd.length(); i++){ + if(QFile::exists(xdd[i]+"/icons")){ paths << xdd[i]+"/icons/"; } + } + //Now load all the dirs into the search paths + QStringList theme, oxy, fall; + for(int i=0; i<paths.length(); i++){ + theme << getChildIconDirs( paths[i]+cTheme); + oxy << getChildIconDirs(paths[i]+"oxygen"); //Lumina base icon set + fall << getChildIconDirs(paths[i]+"hicolor"); //XDG fallback (apps add to this) + } + //fall << LOS::AppPrefix()+"share/pixmaps"; //always use this as well as a final fallback + QDir::setSearchPaths("icontheme", theme); + QDir::setSearchPaths("oxygen", oxy); + QDir::setSearchPaths("fallback", fall); + //qDebug() << "Setting Icon Search Paths:" << "\nicontheme:" << theme << "\noxygen:" << oxy << "\nfallback:" << fall; + } + //Find the icon in the search paths + QIcon ico; + QStringList srch; srch << "icontheme" << "oxygen" << "fallback"; + for(int i=0; i<srch.length() && ico.isNull(); i++){ + //Look for a svg first + if(QFile::exists(srch[i]+":"+iconName+".svg") ){ + //Temporary bypass for known bad icons (libreoffice only at the moment) + if( !iconName.startsWith("libreoffice") ){ + //Be careful about how an SVG is loaded - needs to render the image onto a paint device + QSvgRenderer svg; + if( svg.load(srch[i]+":"+iconName+".svg") ){ + ico.addFile(srch[i]+":"+iconName+".svg"); //could be loaded/parsed successfully + }else{ + qDebug() << "Found bad SVG file:" << iconName+".svg Theme:" << srch[i]; + } } - if(QFile::exists("fallbackicons:"+iconName+".png")){ - ico = QIcon("fallbackicons:"+iconName+".png"); + } + if(QFile::exists(srch[i]+":"+iconName+".png")){ + //simple PNG image - load directly into the QIcon structure + ico.addFile(srch[i]+":"+iconName+".png"); + } + + } + //If still no icon found, look for any image format inthe "pixmaps" directory + if(ico.isNull()){ + if(QFile::exists(LOS::AppPrefix()+"share/pixmaps/"+iconName)){ + ico.addFile(LOS::AppPrefix()+"share/pixmaps/"+iconName); + }else{ + //Need to scan for any close match in the directory + QDir pix(LOS::AppPrefix()+"share/pixmaps"); + QStringList formats = LUtils::imageExtensions(); + QStringList found = pix.entryList(QStringList() << iconName, QDir::Files, QDir::Unsorted); + if(found.isEmpty()){ found = pix.entryList(QStringList() << iconName+"*", QDir::Files, QDir::Unsorted); } + //qDebug() << "Found pixmaps:" << found << formats; + //Use the first one found that is a valid format + for(int i=0; i<found.length(); i++){ + if( formats.contains(found[i].section(".",-1).toLower()) ){ + ico.addFile( pix.absoluteFilePath(found[i]) ); + break; + } } + } } //Use the fallback icon if necessary if(ico.isNull() && !fallback.isEmpty()){ ico = LXDG::findIcon(fallback,""); } + if(ico.isNull()){ + qDebug() << "Could not find icon:" << iconName << fallback; + } //Return the icon return ico; } @@ -630,13 +668,24 @@ QStringList LXDG::getChildIconDirs(QString parent){ //This is a recursive function that returns the absolute path(s) of directories with *.png files QDir D(parent); QStringList out; - QStringList dirs = D.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); - QStringList pngs = D.entryList(QStringList() << "*.png", QDir::Files | QDir::NoDotAndDotDot, QDir::NoSort); - if(pngs.length() > 0){ out << D.absolutePath(); } + QStringList dirs = D.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + if(!dirs.isEmpty() && (dirs.contains("32x32") || dirs.contains("scalable")) ){ + //Need to sort these directories by image size + //qDebug() << " - Parent:" << parent << "Dirs:" << dirs; + for(int i=0; i<dirs.length(); i++){ + if(dirs[i].contains("x")){ dirs[i].prepend( QString::number(10-dirs[i].section("x",0,0).length())+QString::number(10-dirs[i].at(0).digitValue())+"::::"); } + else{ dirs[i].prepend( "0::::"); } + } + dirs.sort(); + for(int i=0; i<dirs.length(); i++){ dirs[i] = dirs[i].section("::::",1,50); } //chop the sorter off the front again + //qDebug() << "Sorted:" << dirs; + } + QStringList img = D.entryList(QStringList() << "*.png" << "*.svg", QDir::Files | QDir::NoDotAndDotDot, QDir::NoSort); + if(img.length() > 0){ out << D.absolutePath(); } for(int i=0; i<dirs.length(); i++){ - pngs.clear(); - pngs = getChildIconDirs(D.absoluteFilePath(dirs[i])); //re-use the old list variable - if(pngs.length() > 0){ out << pngs; } + img.clear(); + img = getChildIconDirs(D.absoluteFilePath(dirs[i])); //re-use the old list variable + if(img.length() > 0){ out << img; } } return out; } diff --git a/libLumina/libLumina.pro b/libLumina/libLumina.pro index 0a29325e..df8544d5 100644 --- a/libLumina/libLumina.pro +++ b/libLumina/libLumina.pro @@ -1,6 +1,6 @@ QT += core network -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets x11extras multimedia concurrent +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets x11extras multimedia concurrent svg TARGET=LuminaUtils |