diff options
5 files changed, 109 insertions, 30 deletions
diff --git a/src-qt5/core/libLumina/LIconCache.cpp b/src-qt5/core/libLumina/LIconCache.cpp index 3ce17439..cf2204a1 100644 --- a/src-qt5/core/libLumina/LIconCache.cpp +++ b/src-qt5/core/libLumina/LIconCache.cpp @@ -14,7 +14,7 @@ #include <QtConcurrent> LIconCache::LIconCache(QObject *parent) : QObject(parent){ - + connect(this, SIGNAL(InternalIconLoaded(QString, QDateTime, QByteArray*)), this, SLOT(IconLoaded(QString, QDateTime, QByteArray*)) ); } LIconCache::~LIconCache(){ @@ -45,7 +45,8 @@ bool LIconCache::isLoaded(QString icon){ } QString LIconCache::findFile(QString icon){ -//Get the currently-set theme + if(icon.isEmpty()){ return ""; } + //Get the currently-set theme QString cTheme = QIcon::themeName(); if(cTheme.isEmpty()){ QIcon::setThemeName("material-design-light"); @@ -91,6 +92,7 @@ QString LIconCache::findFile(QString icon){ } //If still no icon found, look for any image format in the "pixmaps" directory if(QFile::exists(LOS::AppPrefix()+"share/pixmaps/"+icon)){ + if(QFileInfo(LOS::AppPrefix()+"share/pixmaps/"+icon).isDir()){ return ""; } return (LOS::AppPrefix()+"share/pixmaps/"+icon); }else{ //Need to scan for any close match in the directory @@ -112,7 +114,8 @@ QString LIconCache::findFile(QString icon){ void LIconCache::loadIcon(QAbstractButton *button, QString icon, bool noThumb){ //See if the icon has already been loaded into the HASH - if(HASH.contains(icon)){ + bool needload = !HASH.contains(icon); + if(!needload){ if(!noThumb && !HASH[icon].thumbnail.isNull()){ button->setIcon( HASH[icon].thumbnail ); return; } else if(!HASH[icon].icon.isNull()){ button->setIcon( HASH[icon].icon ); return; } } @@ -122,12 +125,29 @@ void LIconCache::loadIcon(QAbstractButton *button, QString icon, bool noThumb){ else { idata = createData(icon); } idata.pendingButtons << button; //save this button for later HASH.insert(icon, idata); - QtConcurrent::run(this, &LIconCache::ReadFile, this, icon, idata.fullpath); + if(needload){ QtConcurrent::run(this, &LIconCache::ReadFile, this, icon, idata.fullpath); } +} + +void LIconCache::loadIcon(QAction *action, QString icon, bool noThumb){ + //See if the icon has already been loaded into the HASH + bool needload = !HASH.contains(icon); + if(!needload){ + if(!noThumb && !HASH[icon].thumbnail.isNull()){ action->setIcon( HASH[icon].thumbnail ); return; } + else if(!HASH[icon].icon.isNull()){ action->setIcon( HASH[icon].icon ); return; } + } + //Need to load the icon + icon_data idata; + if(HASH.contains(icon)){ idata = HASH.value(icon); } + else { idata = createData(icon); } + idata.pendingActions << action; //save this button for later + HASH.insert(icon, idata); + if(needload){ QtConcurrent::run(this, &LIconCache::ReadFile, this, icon, idata.fullpath); } } void LIconCache::loadIcon(QLabel *label, QString icon, bool noThumb){ //See if the icon has already been loaded into the HASH - if(HASH.contains(icon)){ + bool needload = !HASH.contains(icon); + if(!needload){ if(!noThumb && !HASH[icon].thumbnail.isNull()){ label->setPixmap( HASH[icon].thumbnail.pixmap(label->sizeHint()) ); return; } else if(!HASH[icon].icon.isNull()){ label->setPixmap( HASH[icon].icon.pixmap(label->sizeHint()) ); return; } } @@ -137,7 +157,7 @@ void LIconCache::loadIcon(QLabel *label, QString icon, bool noThumb){ else { idata = createData(icon); } idata.pendingLabels << label; //save this QLabel for later HASH.insert(icon, idata); - QtConcurrent::run(this, &LIconCache::ReadFile, this, icon, idata.fullpath); + if(needload){ QtConcurrent::run(this, &LIconCache::ReadFile, this, icon, idata.fullpath); } } void LIconCache::clearIconTheme(){ @@ -223,6 +243,7 @@ QStringList LIconCache::getIconThemeDepChain(QString theme, QStringList paths){ } void LIconCache::ReadFile(LIconCache *obj, QString id, QString path){ + qDebug() << "Start Reading File:" << id << path; QByteArray *BA = new QByteArray(); QDateTime cdt = QDateTime::currentDateTime(); QFile file(path); @@ -235,6 +256,7 @@ void LIconCache::ReadFile(LIconCache *obj, QString id, QString path){ // === PRIVATE SLOTS === void LIconCache::IconLoaded(QString id, QDateTime sync, QByteArray *data){ + qDebug() << "Icon Loaded:" << id << HASH.contains(id); QPixmap pix; bool ok = pix.loadFromData(*data); delete data; //no longer used - free this up diff --git a/src-qt5/core/libLumina/LIconCache.h b/src-qt5/core/libLumina/LIconCache.h index d89ddd70..4a8f3442 100644 --- a/src-qt5/core/libLumina/LIconCache.h +++ b/src-qt5/core/libLumina/LIconCache.h @@ -16,6 +16,7 @@ #include <QDateTime> #include <QAbstractButton> #include <QLabel> +#include <QAction> //Data structure for saving the icon/information internally struct icon_data{ @@ -23,6 +24,7 @@ struct icon_data{ QDateTime lastread; QList<QLabel*> pendingLabels; QList<QAbstractButton*> pendingButtons; + QList<QAction*> pendingActions; QIcon icon; QIcon thumbnail; }; @@ -40,7 +42,8 @@ public: //Special loading routines for QLabel and QAbstractButton (pushbutton, toolbutton, etc) void loadIcon(QAbstractButton *button, QString icon, bool noThumb = false); void loadIcon(QLabel *label, QString icon, bool noThumb = false); - + void loadIcon(QAction *action, QString icon, bool noThumb = false); + QIcon loadIcon(QString icon, bool noThumb = false); //generic loading routine - does not background the loading of icons when not in the cache void clearIconTheme(); //use when the icon theme changes to refresh all requested icons diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index d03ab4d3..d125b27a 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -17,6 +17,7 @@ #include <LuminaX11.h> #include <LUtils.h> #include <ExternalProcess.h> +#include <LIconCache.h> #include <unistd.h> //for usleep() usage @@ -25,6 +26,7 @@ #endif XCBEventFilter *evFilter = 0; +LIconCache *ICONS = 0; LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lumina-desktop"){ if(this->isPrimaryProcess()){ @@ -47,6 +49,7 @@ LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lu lastActiveWin = 0; cleansession = true; TrayStopping = false; + ICONS = new LIconCache(this); screenTimer = new QTimer(this); screenTimer->setSingleShot(true); screenTimer->setInterval(50); diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp b/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp index 266025c5..61293b46 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp +++ b/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp @@ -3,9 +3,13 @@ #include "OutlineToolButton.h" #include <QClipboard> +#include <LIconCache.h> + #define OUTMARGIN 10 //special margin for fonts due to the outlining effect from the OutlineToolbutton +extern LIconCache *ICONS; AppLauncherPlugin::AppLauncherPlugin(QWidget* parent, QString ID) : LDPlugin(parent, ID){ + connect(ICONS, SIGNAL(IconAvailable(QString)), this, SLOT(iconLoaded(QString)) ); QVBoxLayout *lay = new QVBoxLayout(); inputDLG = 0; this->setLayout(lay); @@ -42,31 +46,38 @@ void AppLauncherPlugin::loadButton(){ //qDebug() << "Default Application Launcher:" << def << path; bool ok = QFile::exists(path); if(!ok){ emit RemovePlugin(this->ID()); return;} - int icosize = this->height()-4 - 2.2*button->fontMetrics().height(); + icosize = this->height()-4 - 2.2*button->fontMetrics().height(); button->setFixedSize( this->width()-4, this->height()-4); button->setIconSize( QSize(icosize,icosize) ); button->setToolTip(""); QString txt; + iconID.clear(); if(path.endsWith(".desktop") && ok){ XDGDesktop file(path); ok = !file.name.isEmpty(); if(!ok){ button->setWhatsThis(""); - button->setIcon( QIcon(LXDG::findIcon("quickopen-file","").pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); + iconID = "quickopen-file"; + //button->setIcon( QIcon(LXDG::findIcon("quickopen-file","").pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); txt = tr("Click to Set"); if(!watcher->files().isEmpty()){ watcher->removePaths(watcher->files()); } }else{ button->setWhatsThis(file.filePath); - button->setIcon( QIcon(LXDG::findIcon(file.icon,"system-run").pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); + if(ICONS->exists(file.icon)){ iconID = file.icon; } + else{ iconID = "system-run"; } + //button->setIcon( QIcon(LXDG::findIcon(file.icon,"system-run").pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); if(!file.comment.isEmpty()){button->setToolTip(file.comment); } txt = file.name; //Put the simple Open action first (no open-with for .desktop files) - this->contextMenu()->addAction(button->icon(), QString(tr("Launch %1")).arg(file.name), this, SLOT(buttonClicked()) ); + QAction *tmp = this->contextMenu()->addAction( QString(tr("Launch %1")).arg(file.name), this, SLOT(buttonClicked()) ); + ICONS->loadIcon(tmp, file.icon); //See if there are any "actions" listed for this file, and put them in the context menu as needed. if(!file.actions.isEmpty()){ for(int i=0; i<file.actions.length(); i++){ - QAction *tmp = this->contextMenu()->addAction( file.actions[i].name ); - tmp->setIcon( LXDG::findIcon(file.actions[i].icon,"quickopen-file") ); + tmp = this->contextMenu()->addAction( file.actions[i].name ); + if(ICONS->exists(file.actions[i].icon)){ ICONS->loadIcon(tmp, file.actions[i].icon); } + else{ ICONS->loadIcon(tmp, "quickopen-file"); } + //tmp->setIcon( LXDG::findIcon(file.actions[i].icon,"quickopen-file") ); tmp->setWhatsThis( file.actions[i].ID ); } } @@ -75,53 +86,73 @@ void AppLauncherPlugin::loadButton(){ } }else if(ok){ button->setWhatsThis(info.absoluteFilePath()); + QString iconame; if(info.isDir()){ if(path.startsWith("/media/")){ + iconame = "drive-removable-media"; //Could add device ID parsing here to determine what "type" of device it is - will be OS-specific though - button->setIcon( LXDG::findIcon("drive-removable-media","") ); + //button->setIcon( LXDG::findIcon("drive-removable-media","") ); } - else{ button->setIcon( LXDG::findIcon("folder","") ); } + else{ iconame = "folder"; } //button->setIcon( LXDG::findIcon("folder","") ); }else if(LUtils::imageExtensions().contains(info.suffix().toLower()) ){ - QPixmap pix; - if(pix.load(path)){ button->setIcon( QIcon(pix.scaled(256,256)) ); } //max size for thumbnails in memory - else{ button->setIcon( LXDG::findIcon("dialog-cancel","") ); } + iconame = info.absoluteFilePath(); + //QPixmap pix; + //if(pix.load(path)){ button->setIcon( QIcon(pix.scaled(256,256)) ); } //max size for thumbnails in memory + //else{ iconame = "dialog-cancel"; } //button->setIcon( LXDG::findIcon("dialog-cancel","") ); }else{ - button->setIcon( QIcon(LXDG::findMimeIcon(path).pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); + iconame = LXDG::findAppMimeForFile(path).replace("/","-"); + //button->setIcon( QIcon(LXDG::findMimeIcon(path).pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); } + if(!iconame.isEmpty()){ iconID = iconame; } txt = info.fileName(); if(!watcher->files().isEmpty()){ watcher->removePaths(watcher->files()); } watcher->addPath(path); //make sure to update this shortcut if the file changes }else{ //InValid File button->setWhatsThis(""); - button->setIcon( QIcon(LXDG::findIcon("quickopen","dialog-cancel").pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); + + iconID = "quickopen"; + //button->setIcon( QIcon(LXDG::findIcon("quickopen","dialog-cancel").pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); button->setText( tr("Click to Set") ); if(!watcher->files().isEmpty()){ watcher->removePaths(watcher->files()); } } + if(!iconID.isEmpty()){ + bool updatenow = ICONS->isLoaded(iconID); + ICONS->loadIcon(button, iconID); + if(updatenow){ iconLoaded(iconID); } //will not get a signal - already loaded right now + } //Now adjust the context menu for the button as needed + QAction *tmp = 0; if(this->contextMenu()->isEmpty()){ - this->contextMenu()->addAction(LXDG::findIcon("document-open",""), tr("Open"), this, SLOT(buttonClicked()) ); - this->contextMenu()->addAction(LXDG::findIcon("document-preview",""), tr("Open With"), this, SLOT(openWith()) ); + tmp = this->contextMenu()->addAction( tr("Open"), this, SLOT(buttonClicked()) ); + ICONS->loadIcon(tmp, "document-open"); + this->contextMenu()->addAction( tr("Open With"), this, SLOT(openWith()) ); + ICONS->loadIcon(tmp, "document-preview"); } - this->contextMenu()->addAction(LXDG::findIcon("document-properties",""), tr("View Properties"), this, SLOT(fileProperties()) ); + tmp = this->contextMenu()->addAction( tr("View Properties"), this, SLOT(fileProperties()) ); + ICONS->loadIcon(tmp, "document-properties"); this->contextMenu()->addSection(tr("File Operations")); if(!path.endsWith(".desktop")){ - this->contextMenu()->addAction(LXDG::findIcon("edit-rename","edit-new"), tr("Rename"), this, SLOT(fileRename()) ); + tmp = this->contextMenu()->addAction( tr("Rename"), this, SLOT(fileRename()) ); + ICONS->loadIcon(tmp, "edit-rename"); } - this->contextMenu()->addAction(LXDG::findIcon("edit-copy",""), tr("Copy"), this, SLOT(fileCopy()) ); + tmp = this->contextMenu()->addAction( tr("Copy"), this, SLOT(fileCopy()) ); + ICONS->loadIcon(tmp, "edit-copy"); if(info.isWritable() || (info.isSymLink() && QFileInfo(info.absolutePath()).isWritable() ) ){ - this->contextMenu()->addAction(LXDG::findIcon("edit-cut",""), tr("Cut"), this, SLOT(fileCut()) ); - this->contextMenu()->addAction(LXDG::findIcon("document-close",""), tr("Delete"), this, SLOT(fileDelete()) ); + tmp = this->contextMenu()->addAction( tr("Cut"), this, SLOT(fileCut()) ); + ICONS->loadIcon(tmp, "edit-cut"); + tmp = this->contextMenu()->addAction( tr("Delete"), this, SLOT(fileDelete()) ); + ICONS->loadIcon(tmp, "document-close"); } //If the file is a symlink, put the overlay on the icon - if(info.isSymLink()){ + /*if(info.isSymLink()){ QImage img = button->icon().pixmap(QSize(icosize,icosize)).toImage(); int oSize = icosize/3; //overlay size - QPixmap overlay = LXDG::findIcon("emblem-symbolic-link").pixmap(oSize,oSize).scaled(oSize,oSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmap overlay = ICONS->loadIcon("emblem-symbolic-link").pixmap(oSize,oSize).scaled(oSize,oSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPainter painter(&img); painter.drawPixmap(icosize-oSize,icosize-oSize,overlay); //put it in the bottom-right corner button->setIcon( QIcon(QPixmap::fromImage(img)) ); - } + }*/ //Now adjust the visible text as necessary based on font/grid sizing if(button->toolTip().isEmpty()){ button->setToolTip(txt); } //Double check that the visual icon size matches the requested size - otherwise upscale the icon @@ -183,6 +214,22 @@ void AppLauncherPlugin::buttonClicked(bool openwith){ } +void AppLauncherPlugin::iconLoaded(QString ico){ + if(ico == iconID){ + //Reload/scale the icon as needed + QPixmap pix = button->icon().pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation); + if(QFileInfo(button->whatsThis()).isSymLink()){ + QImage img = pix.toImage(); + int oSize = icosize/3; //overlay size + QPixmap overlay = ICONS->loadIcon("emblem-symbolic-link").pixmap(oSize,oSize).scaled(oSize,oSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPainter painter(&img); + painter.drawPixmap(icosize-oSize,icosize-oSize,overlay); //put it in the bottom-right corner + pix = QPixmap::fromImage(img); + } + button->setIcon( QIcon(pix) ); + } +} + void AppLauncherPlugin::actionTriggered(QAction *act){ if(act->whatsThis().isEmpty()){ return; } QString path = button->whatsThis(); diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h b/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h index b1e3fc85..34a75ce8 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h +++ b/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h @@ -36,10 +36,14 @@ private: QFileSystemWatcher *watcher; //QMenu *menu; QInputDialog *inputDLG; + QString iconID; + int icosize; private slots: void loadButton(); void buttonClicked(bool openwith = false); + void iconLoaded(QString); + //void openContextMenu(); //void increaseIconSize(); |