aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2017-05-22 15:56:26 -0400
committerKen Moore <ken@ixsystems.com>2017-05-22 15:56:26 -0400
commitf2935bff1e1817ff7dc27de6ef428ebe405599de (patch)
tree425a46c683d8e391f5dedb2b045fdb54b2f7a381 /src-qt5/core
parentMerge branch 'master' of github.com:trueos/lumina (diff)
downloadlumina-f2935bff1e1817ff7dc27de6ef428ebe405599de.tar.gz
lumina-f2935bff1e1817ff7dc27de6ef428ebe405599de.tar.bz2
lumina-f2935bff1e1817ff7dc27de6ef428ebe405599de.zip
Commit my WIP on the new icon cache/loading systems for Lumina.
Diffstat (limited to 'src-qt5/core')
-rw-r--r--src-qt5/core/libLumina/LIconCache.cpp201
-rw-r--r--src-qt5/core/libLumina/LIconCache.h56
-rw-r--r--src-qt5/core/libLumina/LIconCache.pri7
3 files changed, 264 insertions, 0 deletions
diff --git a/src-qt5/core/libLumina/LIconCache.cpp b/src-qt5/core/libLumina/LIconCache.cpp
new file mode 100644
index 00000000..8ff4a8d7
--- /dev/null
+++ b/src-qt5/core/libLumina/LIconCache.cpp
@@ -0,0 +1,201 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LIconCache.h"
+
+#include <LuminaOS.h>
+
+LIconCache::LIconCache(QObject *parent = 0{
+
+}
+
+LIconCache::~LIconCache(){
+
+
+}
+
+// === PUBLIC ===
+//Icon Checks
+bool LIconCache::exists(QString icon){
+ if(HASH.contains(icon){ return true; } //already
+ else if(!icon.startsWith("/")){
+ //relative path to file (from icon theme?)
+ QString path = findFile(QString icon);
+ if(!path.isEmpty() && QFile::exists(path)){ return true; }
+ }else{
+ //absolute path to file
+ return QFile::exists(icon);
+ }
+ return false;
+}
+
+bool LIconCache::isLoaded(QString icon){
+ if(HASH.contains(icon){
+ return !HASH[icon].icon.isNull();
+ }
+ return false;
+}
+
+QString LIconCache::findFile(QString icon){
+//Get the currently-set theme
+ QString cTheme = QIcon::themeName();
+ if(cTheme.isEmpty()){
+ QIcon::setThemeName("material-design-light");
+ cTheme = "material-design-light";
+ }
+ //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" "material-design-light" 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;
+ QStringList themedeps = getIconThemeDepChain(cTheme, paths);
+ for(int i=0; i<paths.length(); i++){
+ theme << getChildIconDirs( paths[i]+cTheme);
+ for(int j=0; j<themedeps.length(); j++){ theme << getChildIconDirs(paths[i]+themedeps[j]); }
+ oxy << getChildIconDirs(paths[i]+"material-design-light"); //Lumina base icon set
+ fall << getChildIconDirs(paths[i]+"hicolor"); //XDG fallback (apps add to this)
+ }
+ //Now load all the icon theme dependencies in order (Theme1 -> Theme2 -> Theme3 -> Fallback)
+
+ //fall << LOS::AppPrefix()+"share/pixmaps"; //always use this as well as a final fallback
+ QDir::setSearchPaths("icontheme", theme);
+ QDir::setSearchPaths("default", oxy);
+ QDir::setSearchPaths("fallback", fall);
+ //qDebug() << "Setting Icon Search Paths:" << "\nicontheme:" << theme << "\nmaterial-design-light:" << oxy << "\nfallback:" << fall;
+ }
+ //Find the icon in the search paths
+ QIcon ico;
+ QStringList srch; srch << "icontheme" << "default" << "fallback";
+ for(int i=0; i<srch.length() && ico.isNull(); i++){
+ if(QFile::exists(srch[i]+":"+iconName+".svg") && !iconName.contains("libreoffice") ){
+ return QFile(srch[i]+":"+iconName+".svg").absoluteFilePath();
+ }else if(QFile::exists(srch[i]+":"+iconName+".png")){
+ return QFile(srch[i]+":"+iconName+".png").absoluteFilePath();
+ }
+ }
+ //If still no icon found, look for any image format in the "pixmaps" directory
+ if(QFile::exists(LOS::AppPrefix()+"share/pixmaps/"+iconName)){
+ return QFile(LOS::AppPrefix()+"share/pixmaps/"+iconName).absoluteFilePath();
+ }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()) ){
+ return pix.absoluteFilePath(found[i]);
+ }
+ }
+ }
+ return ""; //no file found
+}
+
+
+void LIconCache::loadIcon(QAbstractButton *button, QString icon, bool noThumb = false){
+ //See if the icon has already been loaded into the HASH
+ if(HASH.contains(icon)){
+ if(!noThumb && !HASH[icon].thumbnail.isNull()){ button->setIcon( HASH[icon].thumbnail ); return; }
+ else if(!HASH[icon].icon.isNull()){ button->setIcon( HASH[icon].icon ); return; }
+ }
+ //Need to load the icon
+ icon_data idata;
+ if(HASH.contains(icon)){ idata = HASH.value(icon); }
+ else { idata = icon_data createData(QString icon); }
+ idata.pendingButtons << button; //save this button for later
+ HASH.insert(icon, idata);
+ QtConcurrent::run(this, &LIconCache::ReadFile, this, icon, idata.fullpath);
+}
+
+void LIconCache::loadIcon(QLabel *label, QString icon, bool noThumb = false){
+ //See if the icon has already been loaded into the HASH
+ if(HASH.contains(icon)){
+ if(!noThumb && !HASH[icon].thumbnail.isNull()){ button->setIcon( HASH[icon].thumbnail ); return; }
+ else if(!HASH[icon].icon.isNull()){ button->setIcon( HASH[icon].icon ); return; }
+ }
+ //Need to load the icon
+ icon_data idata;
+ if(HASH.contains(icon)){ idata = HASH.value(icon); }
+ else { idata = icon_data createData(QString icon); }
+ idata.pendingLabels << label; //save this QLabel for later
+ HASH.insert(icon, idata);
+ QtConcurrent::run(this, &LIconCache::ReadFile, this, icon, idata.fullpath);
+}
+
+
+// === PRIVATE ===
+icon_data LIconCache::createData(QString icon){
+ icon_data idat;
+ //Find the real path of the icon
+ if(icon.startsWith("/")){ idat.fullpath = icon; } //already full path
+ else{
+ idat.fullpath = findFile(icon);
+ }
+ return idat;
+}
+
+QStringList LIconCache::getChildIconDirs(QString path){
+//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);
+ 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 if(dirs[i].at(0).isNumber()){dirs[i].prepend( QString::number(10-dirs[i].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++){
+ img.clear();
+ img = getChildIconDirs(D.absoluteFilePath(dirs[i])); //re-use the old list variable
+ if(img.length() > 0){ out << img; }
+ }
+ return out;
+}
+
+QStringList LXDG::getIconThemeDepChain(QString theme, QStringList paths){
+ QStringList results;
+ for(int i=0; i<paths.length(); i++){
+ if( QFile::exists(paths[i]+theme+"/index.theme") ){
+ QStringList deps = LUtils::readFile(paths[i]+theme+"/index.theme").filter("Inherits=");
+ if(!deps.isEmpty()){
+ deps = deps.first().section("=",1,-1).split(";",QString::SkipEmptyParts);
+ for(int j=0; j<deps.length(); j++){
+ results << deps[j] << getIconThemeDepChain(deps[j],paths);
+ }
+ }
+ break; //found primary theme index file - stop here
+ }
+ }
+ return results;
+}
+
+void LIconCache::ReadFile(LIconCache *obj, QString id, QString path){
+
+}
+
+// === PRIVATE SLOTS ===
+void LIconCache::IconLoaded(QString id, QDateTime sync, QByteArray *data){
+
+}
diff --git a/src-qt5/core/libLumina/LIconCache.h b/src-qt5/core/libLumina/LIconCache.h
new file mode 100644
index 00000000..08726399
--- /dev/null
+++ b/src-qt5/core/libLumina/LIconCache.h
@@ -0,0 +1,56 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This is a simple class for loading/serving icon files
+// from the icon theme or local filesystem
+//===========================================
+#include <QHash>
+#include <QIcon>
+#include <QPixmap>
+#include <QFileSystemWatcher>
+#include <QString>
+#include <QFile>
+#include <QDateTime>
+
+//Data structure for saving the icon/information internally
+struct icon_data{
+ QString fullpath;
+ QDateTime lastread;
+ QList<QLabel*> pendingLabels;
+ QList<QAbstractButton*> pendingButtons;
+ QIcon icon;
+ QIcon thumbnail;
+};
+
+class LIconCache : public QObject{
+ Q_OBJECT
+public:
+ LIconCache(QObject *parent = 0);
+ ~LIconCache();
+ //Icon Checks
+ bool exists(QString icon);
+ bool isLoaded(QString icon);
+ QString findFile(QString icon); //find the full path of a given file/name (searching the current Icon theme)
+
+ void loadIcon(QAbstractButton *button, QString icon, bool noThumb = false);
+ void loadIcon(QLabel *label, QString icon, bool noThumb = false);
+
+private:
+ QHash<QString, icon_data> HASH;
+ QFileSystemWatcher *WATCHER;
+
+ icon_data createData(QString icon);
+ QStringList getChildIconDirs(QString path); //recursive function to find directories with icons in them
+
+ static void ReadFile(LIconCache *obj, QString id, QString path);
+
+private slots:
+ void IconLoaded(QString id, QDateTime sync, QByteArray *data);
+
+signals:
+ void InternalIconLoaded(QString, QDateTime, QByteArray*); //INTERNAL SIGNAL - DO NOT USE in other classes/objects
+ void IconAvailable(QString); //way for classes to listen/reload icons as they change
+};
diff --git a/src-qt5/core/libLumina/LIconCache.pri b/src-qt5/core/libLumina/LIconCache.pri
new file mode 100644
index 00000000..f1f58f16
--- /dev/null
+++ b/src-qt5/core/libLumina/LIconCache.pri
@@ -0,0 +1,7 @@
+HEADERS *= $${PWD}/LIconCache.h
+SOURCES *= $${PWD}/LIconCache.cpp
+
+INCLUDEPATH *= ${PWD}
+
+#Now the other dependendies of it
+#include(LUtils.pri)
bgstack15