diff options
author | Ken Moore <ken@ixsystems.com> | 2017-05-26 11:18:24 -0400 |
---|---|---|
committer | Ken Moore <ken@ixsystems.com> | 2017-05-26 11:18:24 -0400 |
commit | b1fff33e839f9fd5c967552ecba3ff31f2b060aa (patch) | |
tree | 64e4982ddad051975b82ad7005448a4150a3d9fb /src-qt5 | |
parent | Oops - forgot to include the changes to the LIconCache files in that last com... (diff) | |
download | lumina-b1fff33e839f9fd5c967552ecba3ff31f2b060aa.tar.gz lumina-b1fff33e839f9fd5c967552ecba3ff31f2b060aa.tar.bz2 lumina-b1fff33e839f9fd5c967552ecba3ff31f2b060aa.zip |
Get the new Icon Cache system implemented and turned on for the desktop "applauncher" plugins. This seems to be working quite well, and now we just need to start using this for all the other pieces of the desktop.
Diffstat (limited to 'src-qt5')
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(); |