diff options
41 files changed, 900 insertions, 570 deletions
diff --git a/src-qt5/core-utils/lumina-config/AppDialog.h b/src-qt5/core-utils/lumina-config/AppDialog.h index 392dbe4d..ea7615e2 100644 --- a/src-qt5/core-utils/lumina-config/AppDialog.h +++ b/src-qt5/core-utils/lumina-config/AppDialog.h @@ -9,13 +9,7 @@ #ifndef _LUMINA_FILE_MANAGER_APP_SELECT_DIALOG_H #define _LUMINA_FILE_MANAGER_APP_SELECT_DIALOG_H -#include <QDialog> -#include <QString> -#include <QList> -#include <QPoint> -#include <QDesktopWidget> -#include <QCursor> -#include <LuminaXDG.h> +#include "globals.h" #include "ui_AppDialog.h" @@ -27,16 +21,15 @@ class AppDialog : public QDialog{ Q_OBJECT private: Ui::AppDialog *ui; - QList<XDGDesktop> APPS; public: - AppDialog(QWidget *parent = 0, QList<XDGDesktop> applist = QList<XDGDesktop>()) : QDialog(parent), ui(new Ui::AppDialog){ + AppDialog(QWidget *parent = 0) : QDialog(parent), ui(new Ui::AppDialog){ ui->setupUi(this); //load the designer file - APPS = applist; //save this for later appreset = false; ui->comboBox->clear(); + QList<XDGDesktop*> APPS = LXDG::sortDesktopNames(APPSLIST->apps(false,false)); //Don't show all/hidden for(int i=0; i<APPS.length(); i++){ - ui->comboBox->addItem( LXDG::findIcon(APPS[i].icon,"application-x-executable"), APPS[i].name ); + ui->comboBox->addItem( LXDG::findIcon(APPS[i]->icon,"application-x-executable"), APPS[i]->name, APPS[i]->filePath); } this->setWindowIcon( LXDG::findIcon("system-search","") ); if(parent!=0){ @@ -56,13 +49,14 @@ public: ui->buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); } } - XDGDesktop appselected; //selected application (empty template for cancelled/reset) + + QString appselected; //selected application bool appreset; //Did the user select to reset to defaults? private slots: void on_buttonBox_accepted(){ - appselected = APPS[ ui->comboBox->currentIndex() ]; + appselected = ui->comboBox->currentData().toString(); this->close(); } void on_buttonBox_rejected(){ diff --git a/src-qt5/core-utils/lumina-config/PanelWidget.cpp b/src-qt5/core-utils/lumina-config/PanelWidget.cpp index 7132dcf8..8b38f407 100644 --- a/src-qt5/core-utils/lumina-config/PanelWidget.cpp +++ b/src-qt5/core-utils/lumina-config/PanelWidget.cpp @@ -59,9 +59,8 @@ void PanelWidget::LoadSettings(QSettings *settings, int Dnum, int Pnum){ for(int i=0; i<plugs.length(); i++){ QString pid = plugs[i].section("---",0,0); if(pid.startsWith("applauncher")){ - bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(pid.section("::",1,1),ok); - if(ok){ + XDGDesktop desk(pid.section("::",1,1)); + if(desk.type!=XDGDesktop::BAD){ //still need to allow invalid apps QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(desk.icon,""), desk.name ); it->setWhatsThis(plugs[i]); //make sure to preserve the entire plugin ID (is the unique version) ui->list_plugins->addItem(it); @@ -121,17 +120,15 @@ void PanelWidget::reloadColorSample(){ ui->label_color_sample->setStyleSheet("background: "+ui->label_color_sample->whatsThis()); } -XDGDesktop PanelWidget::getSysApp(bool allowreset){ - AppDialog dlg(this, LXDG::sortDesktopNames( LXDG::systemDesktopFiles() ) ); +QString PanelWidget::getSysApp(bool allowreset){ + AppDialog dlg(this); dlg.allowReset(allowreset); dlg.exec(); - XDGDesktop desk; if(dlg.appreset && allowreset){ - desk.filePath = "reset"; //special internal flag + return "reset"; }else{ - desk = dlg.appselected; + return dlg.appselected; } - return desk; } QString PanelWidget::getColorStyle(QString current, bool allowTransparency){ @@ -183,10 +180,11 @@ void PanelWidget::on_tool_addplugin_clicked(){ QString pan = dlg.plugID; //getNewPanelPlugin(); if(pan == "applauncher"){ //Prompt for the application to add - XDGDesktop app =getSysApp(); - if(app.filePath.isEmpty()){ return; } //cancelled - pan.append("::"+app.filePath); - QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(app.icon,""), app.name); + QString app =getSysApp(); + if(app.isEmpty()){ return; } //cancelled + pan.append("::"+app); + XDGDesktop desk(app); + QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(desk.icon,""), desk.name); it->setWhatsThis(pan); ui->list_plugins->addItem(it); ui->list_plugins->setCurrentItem(it); diff --git a/src-qt5/core-utils/lumina-config/PanelWidget.h b/src-qt5/core-utils/lumina-config/PanelWidget.h index 3f3cb360..f4e67c2d 100644 --- a/src-qt5/core-utils/lumina-config/PanelWidget.h +++ b/src-qt5/core-utils/lumina-config/PanelWidget.h @@ -39,7 +39,7 @@ private: int dnum, pnum; void reloadColorSample(); - XDGDesktop getSysApp(bool allowreset = false); + QString getSysApp(bool allowreset = false); QString getColorStyle(QString current, bool allowTransparency = true); private slots: void on_tool_rm_clicked(); diff --git a/src-qt5/core-utils/lumina-config/globals.h b/src-qt5/core-utils/lumina-config/globals.h index c96aaaa3..2a863bda 100644 --- a/src-qt5/core-utils/lumina-config/globals.h +++ b/src-qt5/core-utils/lumina-config/globals.h @@ -22,6 +22,9 @@ #include <QMessageBox> #include <QShortcut> #include <QImageReader> +#include <QDialog> +#include <QPoint> +#include <QCursor> //Now the Lumina Library classes #include <LuminaXDG.h> @@ -31,3 +34,6 @@ #include <LuminaThemes.h> #endif + +//Now the global class for available system applications +extern XDGDesktopList *APPSLIST; diff --git a/src-qt5/core-utils/lumina-config/main.cpp b/src-qt5/core-utils/lumina-config/main.cpp index 856570c0..8df7db48 100644 --- a/src-qt5/core-utils/lumina-config/main.cpp +++ b/src-qt5/core-utils/lumina-config/main.cpp @@ -10,6 +10,9 @@ #include <LuminaUtils.h> #include <LuminaThemes.h> #include <LuminaSingleApplication.h> +#include <LuminaXDG.h> + +XDGDesktopList *APPSLIST = 0; int main(int argc, char ** argv) { diff --git a/src-qt5/core-utils/lumina-config/mainWindow.cpp b/src-qt5/core-utils/lumina-config/mainWindow.cpp index 5f465199..d6ada8f5 100644 --- a/src-qt5/core-utils/lumina-config/mainWindow.cpp +++ b/src-qt5/core-utils/lumina-config/mainWindow.cpp @@ -15,6 +15,8 @@ //============= mainWindow::mainWindow() : QMainWindow(), ui(new Ui::mainWindow()){ ui->setupUi(this); + APPSLIST = new XDGDesktopList(this, true); //keep this up to date while the app is open + QTimer::singleShot(100, APPSLIST, SLOT(updateList())); //don't let this hold up the initial application loading cpage = "somerandomjunktostartwith"; //Need to insert a spacer action in the toolbar QWidget *tmp = new QWidget(this); diff --git a/src-qt5/core-utils/lumina-config/pages/page_autostart.cpp b/src-qt5/core-utils/lumina-config/pages/page_autostart.cpp index b7c52fb7..371791e9 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_autostart.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_autostart.cpp @@ -32,19 +32,19 @@ page_autostart::~page_autostart(){ // PUBLIC SLOTS //================ void page_autostart::SaveSettings(){ - QList<XDGDesktop> STARTAPPS = LXDG::findAutoStartFiles(true); //also want invalid/disabled items + QList<XDGDesktop*> STARTAPPS = LXDG::findAutoStartFiles(true); //also want invalid/disabled items //bool newstartapps = false; for(int i=0; i<ui->list_session_start->count(); i++){ QString file = ui->list_session_start->item(i)->whatsThis(); bool enabled = ui->list_session_start->item(i)->checkState()==Qt::Checked; bool found = false; for(int i=0; i<STARTAPPS.length(); i++){ - if(STARTAPPS[i].filePath==file){ + if(STARTAPPS[i]->filePath==file){ found = true; - if(enabled != !STARTAPPS[i].isHidden){ + if(enabled != !STARTAPPS[i]->isHidden){ //value is different - qDebug() << "Setting Autostart:" << enabled << STARTAPPS[i].filePath; - LXDG::setAutoStarted(enabled, STARTAPPS[i]); + qDebug() << "Setting Autostart:" << enabled << STARTAPPS[i]->filePath; + STARTAPPS[i]->setAutoStarted(enabled); } break; } @@ -55,25 +55,29 @@ void page_autostart::SaveSettings(){ LXDG::setAutoStarted(enabled, file); //newstartapps = true; } - } + } //end loop over GUI items + //Now cleanup all the STARTAPPS data + for(int i=0; STARTAPPS.length(); i++){ STARTAPPS[i]->deleteLater(); } } void page_autostart::LoadSettings(int){ emit HasPendingChanges(false); emit ChangePageTitle( tr("Startup Services") ); - QList<XDGDesktop> STARTAPPS = LXDG::findAutoStartFiles(true); //also want invalid/disabled items + QList<XDGDesktop*> STARTAPPS = LXDG::findAutoStartFiles(true); //also want invalid/disabled items //qDebug() << "StartApps:"; ui->list_session_start->clear(); for(int i=0; i<STARTAPPS.length(); i++){ //qDebug() << STARTAPPS[i].filePath +" -> " +STARTAPPS[i].name << STARTAPPS[i].isHidden; - if( !LXDG::checkValidity(STARTAPPS[i],false) || !QFile::exists(STARTAPPS[i].filePath) ){ continue; } - QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(STARTAPPS[i].icon,"application-x-executable"), STARTAPPS[i].name ); - it->setWhatsThis(STARTAPPS[i].filePath); //keep the file location - it->setToolTip(STARTAPPS[i].comment); - if(STARTAPPS[i].isHidden){ it->setCheckState( Qt::Unchecked); } + if( !STARTAPPS[i]->isValid() || !QFile::exists(STARTAPPS[i]->filePath) ){ continue; } + QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(STARTAPPS[i]->icon,"application-x-executable"), STARTAPPS[i]->name ); + it->setWhatsThis(STARTAPPS[i]->filePath); //keep the file location + it->setToolTip(STARTAPPS[i]->comment); + if(STARTAPPS[i]->isHidden){ it->setCheckState( Qt::Unchecked); } else{it->setCheckState( Qt::Checked); } ui->list_session_start->addItem(it); } + //Now cleanup all the STARTAPPS data + for(int i=0; STARTAPPS.length(); i++){ STARTAPPS[i]->deleteLater(); } } void page_autostart::updateIcons(){ @@ -85,17 +89,15 @@ void page_autostart::updateIcons(){ //================= // PRIVATE //================= -XDGDesktop page_autostart::getSysApp(bool allowreset){ - AppDialog dlg(this, LXDG::sortDesktopNames( LXDG::systemDesktopFiles() ) ); +QString page_autostart::getSysApp(bool allowreset){ + AppDialog dlg(this); dlg.allowReset(allowreset); dlg.exec(); - XDGDesktop desk; if(dlg.appreset && allowreset){ - desk.filePath = "reset"; //special internal flag + return "reset"; }else{ - desk = dlg.appselected; + return dlg.appselected; } - return desk; } //================= @@ -109,8 +111,9 @@ void page_autostart::rmsessionstartitem(){ void page_autostart::addsessionstartapp(){ //Prompt for the application to start - XDGDesktop desk = getSysApp(false); //no reset - if(desk.filePath.isEmpty()){ return; } //cancelled + QString app = getSysApp(false); //no reset + if(app.isEmpty()){ return; } //cancelled + XDGDesktop desk(app); QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(desk.icon,""), desk.name ); it->setWhatsThis(desk.filePath); it->setToolTip(desk.comment); diff --git a/src-qt5/core-utils/lumina-config/pages/page_autostart.h b/src-qt5/core-utils/lumina-config/pages/page_autostart.h index 88f1ef94..60868598 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_autostart.h +++ b/src-qt5/core-utils/lumina-config/pages/page_autostart.h @@ -27,7 +27,7 @@ public slots: private: Ui::page_autostart *ui; - XDGDesktop getSysApp(bool allowreset); + QString getSysApp(bool allowreset); private slots: void rmsessionstartitem(); diff --git a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp index e55beba6..b2a0896c 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp @@ -48,9 +48,8 @@ void page_defaultapps::LoadSettings(int){ if(tmp.isEmpty()){ tmp = "lumina-fm"; } if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ + XDGDesktop file(tmp); + if(file.type == XDGDesktop::BAD){ //Might be a binary - just print out the raw "path" ui->tool_default_filemanager->setText(tmp.section("/",-1)); ui->tool_default_filemanager->setIcon( LXDG::findIcon("application-x-executable","") ); @@ -70,9 +69,8 @@ void page_defaultapps::LoadSettings(int){ tmp =LXDG::findDefaultAppForMime("application/terminal"); //sessionsettings->value("default-terminal", "xterm").toString(); if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ + XDGDesktop file(tmp); + if(file.type == XDGDesktop::BAD){ //Might be a binary - just print out the raw "path" ui->tool_default_terminal->setText(tmp.section("/",-1)); ui->tool_default_terminal->setIcon( LXDG::findIcon("application-x-executable","") ); @@ -92,9 +90,8 @@ void page_defaultapps::LoadSettings(int){ tmp = LXDG::findDefaultAppForMime("x-scheme-handler/http"); //appsettings->value("default/webbrowser", "").toString(); if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ + XDGDesktop file(tmp); + if(file.type == XDGDesktop::BAD){ //Might be a binary - just print out the raw "path" ui->tool_default_webbrowser->setText(tmp.section("/",-1)); ui->tool_default_webbrowser->setIcon( LXDG::findIcon("application-x-executable","") ); @@ -114,9 +111,8 @@ void page_defaultapps::LoadSettings(int){ tmp = LXDG::findDefaultAppForMime("application/email"); //appsettings->value("default/email", "").toString(); if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ + XDGDesktop file(tmp); + if(file.type == XDGDesktop::BAD){ //Might be a binary - just print out the raw "path" ui->tool_default_email->setText(tmp.section("/",-1)); ui->tool_default_email->setIcon( LXDG::findIcon("application-x-executable","") ); @@ -165,9 +161,8 @@ void page_defaultapps::LoadSettings(int){ //Now load the default (if there is one) it->setWhatsThis(1,def); //save for later if(def.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(def, ok); - if(!ok || file.filePath.isEmpty()){ + XDGDesktop file(def); + if(file.type == XDGDesktop::BAD){ //Might be a binary - just print out the raw "path" it->setText(1,def.section("/",-1)); it->setIcon(1, LXDG::findIcon("application-x-executable","") ); @@ -199,150 +194,80 @@ void page_defaultapps::updateIcons(){ //================= // PRIVATE //================= -XDGDesktop page_defaultapps::getSysApp(bool allowreset){ - AppDialog dlg(this, LXDG::sortDesktopNames( LXDG::systemDesktopFiles() ) ); +QString page_defaultapps::getSysApp(bool allowreset){ + AppDialog dlg(this); dlg.allowReset(allowreset); dlg.exec(); - XDGDesktop desk; if(dlg.appreset && allowreset){ - desk.filePath = "reset"; //special internal flag + return "reset"; }else{ - desk = dlg.appselected; + return dlg.appselected; } - return desk; } -//================= -// PRIVATE SLOTS -//================= -void page_defaultapps::changeDefaultBrowser(){ - //Prompt for the new app - XDGDesktop desk = getSysApp(true); - if(desk.filePath.isEmpty()){ return; }//nothing selected - if(desk.filePath=="reset"){ - desk.filePath=""; - } - //save the new app setting and adjust the button appearance - //appsettings->setValue("default/webbrowser", desk.filePath); - LXDG::setDefaultAppForMime("x-scheme-handler/http", desk.filePath.section("/",-1)); - LXDG::setDefaultAppForMime("x-scheme-handler/https", desk.filePath.section("/",-1)); - QString tmp = desk.filePath; - if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ +void page_defaultapps::updateDefaultButton(QToolButton *button, QString app){ + if(app.endsWith(".desktop")){ + XDGDesktop file(app); + if(file.type == XDGDesktop::BAD){ //Might be a binary - just print out the raw "path" - ui->tool_default_webbrowser->setText(tmp.section("/",-1)); - ui->tool_default_webbrowser->setIcon( LXDG::findIcon("application-x-executable","") ); + button->setText(app.section("/",-1)); + button->setIcon( LXDG::findIcon("application-x-executable","") ); }else{ - ui->tool_default_webbrowser->setText(desk.name); - ui->tool_default_webbrowser->setIcon(LXDG::findIcon(desk.icon,"") ); + button->setText(file.name); + button->setIcon(LXDG::findIcon(file.icon,"") ); } - }else if(tmp.isEmpty()){ - ui->tool_default_webbrowser->setText(tr("Click to Set")); - ui->tool_default_webbrowser->setIcon( LXDG::findIcon("system-help","") ); + }else if(app.isEmpty()){ + button->setText(tr("Click to Set")); + button->setIcon( LXDG::findIcon("system-help","") ); }else{ //Might be a binary - just print out the raw "path" - ui->tool_default_webbrowser->setText(tmp.section("/",-1)); - ui->tool_default_webbrowser->setIcon( LXDG::findIcon("application-x-executable","") ); + button->setText(app.section("/",-1)); + button->setIcon( LXDG::findIcon("application-x-executable","") ); } } +//================= +// PRIVATE SLOTS +//================= +void page_defaultapps::changeDefaultBrowser(){ + //Prompt for the new app + QString app = getSysApp(true); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app.clear(); } + //save the new app setting and adjust the button appearance + LXDG::setDefaultAppForMime("x-scheme-handler/http", app.section("/",-1)); + LXDG::setDefaultAppForMime("x-scheme-handler/https", app.section("/",-1)); + updateDefaultButton(ui->tool_default_webbrowser, app); +} + void page_defaultapps::changeDefaultEmail(){ //Prompt for the new app - XDGDesktop desk = getSysApp(true); //allow reset to default - if(desk.filePath.isEmpty()){ return; }//nothing selected - if(desk.filePath=="reset"){ - desk.filePath=""; - } + QString app = getSysApp(true); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app.clear(); } //save the new app setting and adjust the button appearance - LXDG::setDefaultAppForMime("application/email",desk.filePath); - // appsettings->setValue("default/email", desk.filePath); - QString tmp = desk.filePath; - if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ - //Might be a binary - just print out the raw "path" - ui->tool_default_email->setText(tmp.section("/",-1)); - ui->tool_default_email->setIcon( LXDG::findIcon("application-x-executable","") ); - }else{ - ui->tool_default_email->setText(file.name); - ui->tool_default_email->setIcon(LXDG::findIcon(file.icon,"") ); - } - }else if(tmp.isEmpty()){ - ui->tool_default_email->setText(tr("Click to Set")); - ui->tool_default_email->setIcon( LXDG::findIcon("system-help","") ); - }else{ - //Might be a binary - just print out the raw "path" - ui->tool_default_email->setText(tmp.section("/",-1)); - ui->tool_default_email->setIcon( LXDG::findIcon("application-x-executable","") ); - } + LXDG::setDefaultAppForMime("application/email",app.section("/",-1)); + updateDefaultButton(ui->tool_default_email, app); } void page_defaultapps::changeDefaultFileManager(){ //Prompt for the new app - XDGDesktop desk = getSysApp(true); - if(desk.filePath.isEmpty()){ return; }//nothing selected - if(desk.filePath=="reset"){ - desk.filePath="lumina-fm"; - } + QString app = getSysApp(true); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app = "lumina-fm"; } //save the new app setting and adjust the button appearance - //appsettings->setValue("default/directory", desk.filePath); - //sessionsettings->setValue("default-filemanager", desk.filePath); - LXDG::setDefaultAppForMime("inode/directory", desk.filePath.section("/",-1)); - QString tmp = desk.filePath; - if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ - //Might be a binary - just print out the raw "path" - ui->tool_default_filemanager->setText(tmp.section("/",-1)); - ui->tool_default_filemanager->setIcon( LXDG::findIcon("application-x-executable","") ); - }else{ - ui->tool_default_filemanager->setText(file.name); - ui->tool_default_filemanager->setIcon(LXDG::findIcon(file.icon,"") ); - } - }else if(tmp.isEmpty()){ - ui->tool_default_filemanager->setText(tr("Click to Set")); - ui->tool_default_filemanager->setIcon( LXDG::findIcon("system-help","") ); - }else{ - //Might be a binary - just print out the raw "path" - ui->tool_default_filemanager->setText(tmp.section("/",-1)); - ui->tool_default_filemanager->setIcon( LXDG::findIcon("application-x-executable","") ); - } + LXDG::setDefaultAppForMime("inode/directory", app.section("/",-1)); + updateDefaultButton(ui->tool_default_filemanager, app); } void page_defaultapps::changeDefaultTerminal(){ //Prompt for the new app - XDGDesktop desk = getSysApp(true); - if(desk.filePath.isEmpty()){ return; }//nothing selected - if(desk.filePath=="reset"){ - desk.filePath="xterm"; - } + QString app = getSysApp(true); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app = "xterm"; } //save the new app setting and adjust the button appearance - LXDG::setDefaultAppForMime("application/terminal",desk.filePath); - //sessionsettings->setValue("default-terminal", desk.filePath); - QString tmp = desk.filePath; - if(tmp.endsWith(".desktop")){ - bool ok = false; - XDGDesktop file = LXDG::loadDesktopFile(tmp, ok); - if(!ok || file.filePath.isEmpty()){ - //Might be a binary - just print out the raw "path" - ui->tool_default_terminal->setText(tmp.section("/",-1)); - ui->tool_default_terminal->setIcon( LXDG::findIcon("application-x-executable","") ); - }else{ - ui->tool_default_terminal->setText(file.name); - ui->tool_default_terminal->setIcon(LXDG::findIcon(file.icon,"") ); - } - }else if(tmp.isEmpty()){ - ui->tool_default_terminal->setText(tr("Click to Set")); - ui->tool_default_terminal->setIcon( LXDG::findIcon("system-help","") ); - }else{ - //Might be a binary - just print out the raw "path" - ui->tool_default_terminal->setText(tmp.section("/",-1)); - ui->tool_default_terminal->setIcon( LXDG::findIcon("application-x-executable","") ); - } + LXDG::setDefaultAppForMime("application/terminal", app.section("/",-1) ); + updateDefaultButton(ui->tool_default_terminal, app); } void page_defaultapps::cleardefaultitem(){ @@ -374,14 +299,15 @@ void page_defaultapps::setdefaultitem(){ } if(list.isEmpty()){ list << it; } //just do the current item //Prompt for which application to use - XDGDesktop desk = getSysApp(false); //no "reset" option - if(desk.filePath.isEmpty()){ return; }//nothing selected + QString app = getSysApp(false); //no "reset" option + if(app.isEmpty()){ return; }//nothing selected //Now set the items for(int i=0; i<list.length(); i++){ //Set it in the back end - LXDG::setDefaultAppForMime(list[i]->whatsThis(0), desk.filePath); + LXDG::setDefaultAppForMime(list[i]->whatsThis(0), app.section("/",-1)); //Set it in the UI - list[i]->setWhatsThis(1,desk.filePath); //app path + XDGDesktop desk(app); + list[i]->setWhatsThis(1,app); //app path list[i]->setIcon(1,LXDG::findIcon(desk.icon,"")); //reset the icon list[i]->setText(1,desk.name); //reset the name } diff --git a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h index afe99d4b..f80ea1ab 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h +++ b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h @@ -27,7 +27,9 @@ public slots: private: Ui::page_defaultapps *ui; - XDGDesktop getSysApp(bool allowreset); + QString getSysApp(bool allowreset); + + void updateDefaultButton(QToolButton *button, QString app); private slots: //Simple defaults tab diff --git a/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.cpp b/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.cpp index 7a52959a..fdcde804 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.cpp @@ -69,9 +69,8 @@ void page_interface_desktop::LoadSettings(int screennum){ dplugs[i] = dplugs[i].section("---",0,0); } if(dplugs[i].startsWith("applauncher::")){ - bool ok = false; - XDGDesktop app = LXDG::loadDesktopFile(dplugs[i].section("::",1,50), ok); - if(!ok){ continue; } //invalid for some reason + XDGDesktop app(dplugs[i].section("::",1,50)); + if(app.type == XDGDesktop::BAD){ continue; } //invalid for some reason //Now fill the item with the necessary info it->setText(app.name); it->setIcon(LXDG::findIcon(app.icon,"") ); @@ -97,17 +96,15 @@ void page_interface_desktop::updateIcons(){ //================= // PRIVATE //================= -XDGDesktop page_interface_desktop::getSysApp(bool allowreset){ - AppDialog dlg(this, LXDG::sortDesktopNames( LXDG::systemDesktopFiles() ) ); +QString page_interface_desktop::getSysApp(bool allowreset){ + AppDialog dlg(this); dlg.allowReset(allowreset); dlg.exec(); - XDGDesktop desk; if(dlg.appreset && allowreset){ - desk.filePath = "reset"; //special internal flag + return "reset"; }else{ - desk = dlg.appselected; + return dlg.appselected; } - return desk; } //================= @@ -122,14 +119,15 @@ void page_interface_desktop::deskplugadded(){ QListWidgetItem *it = new QListWidgetItem(); if(newplug=="applauncher"){ //Prompt for the application to add - XDGDesktop app = getSysApp(); - if(app.filePath.isEmpty()){ return; } //cancelled - newplug.append("::"+app.filePath); + QString app = getSysApp(); + if(app.isEmpty()){ return; } //cancelled + newplug.append("::"+app); + XDGDesktop desk(app); //Now fill the item with the necessary info it->setWhatsThis(newplug); - it->setText(app.name); - it->setIcon(LXDG::findIcon(app.icon,"") ); - it->setToolTip(app.comment); + it->setText(desk.name); + it->setIcon(LXDG::findIcon(desk.icon,"") ); + it->setToolTip(desk.comment); }else{ //Load the info for this plugin LPI info = PINFO->desktopPluginInfo(newplug); diff --git a/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.h b/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.h index e212182a..cfeb7f8c 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.h +++ b/src-qt5/core-utils/lumina-config/pages/page_interface_desktop.h @@ -33,7 +33,7 @@ private: LPlugins *PINFO; //Get an application on the system - XDGDesktop getSysApp(bool allowreset = false); + QString getSysApp(bool allowreset = false); private slots: void deskplugadded(); diff --git a/src-qt5/core-utils/lumina-config/pages/page_interface_menu.cpp b/src-qt5/core-utils/lumina-config/pages/page_interface_menu.cpp index d211d380..370980d2 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_interface_menu.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_interface_menu.cpp @@ -53,9 +53,8 @@ QStringList items = settings.value("menu/itemlist", QStringList() ).toStringList ui->list_menu->clear(); for(int i=0; i<items.length(); i++){ if(items[i].startsWith("app::::")){ - bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(items[i].section("::::",1,1), ok); - if(!ok){ continue; } //invalid application file (no longer installed?) + XDGDesktop desk(items[i].section("::::",1,1)); + if(desk.type == XDGDesktop::BAD){ continue; } //invalid application file (no longer installed?) QListWidgetItem *item = new QListWidgetItem(); item->setWhatsThis( items[i] ); item->setIcon( LXDG::findIcon(desk.icon) ); @@ -99,17 +98,15 @@ void page_interface_menu::updateIcons(){ //================= // PRIVATE //================= -XDGDesktop page_interface_menu::getSysApp(bool allowreset){ - AppDialog dlg(this, LXDG::sortDesktopNames( LXDG::systemDesktopFiles() ) ); +QString page_interface_menu::getSysApp(bool allowreset){ + AppDialog dlg(this); dlg.allowReset(allowreset); dlg.exec(); - XDGDesktop desk; if(dlg.appreset && allowreset){ - desk.filePath = "reset"; //special internal flag + return "reset"; }else{ - desk = dlg.appselected; + return dlg.appselected; } - return desk; } //================= @@ -127,9 +124,10 @@ void page_interface_menu::addmenuplugin(){ if(info.ID=="app"){ //Need to prompt for the exact application to add to the menu // Note: whatsThis() format: "app::::< *.desktop file path >" - XDGDesktop desk = getSysApp(); - if(desk.filePath.isEmpty()){ return; }//nothing selected + QString app = getSysApp(); + if(app.isEmpty()){ return; }//nothing selected //Create the item for the list + XDGDesktop desk(app); it = new QListWidgetItem(LXDG::findIcon(desk.icon,""), desk.name ); it->setWhatsThis(info.ID+"::::"+desk.filePath); it->setToolTip( desk.comment ); diff --git a/src-qt5/core-utils/lumina-config/pages/page_interface_menu.h b/src-qt5/core-utils/lumina-config/pages/page_interface_menu.h index f2a53007..16f80385 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_interface_menu.h +++ b/src-qt5/core-utils/lumina-config/pages/page_interface_menu.h @@ -29,7 +29,7 @@ private: Ui::page_interface_menu *ui; LPlugins *PINFO; //Get an application on the system - XDGDesktop getSysApp(bool allowreset = false); + QString getSysApp(bool allowreset = false); private slots: void addmenuplugin(); diff --git a/src-qt5/core-utils/lumina-search/MainUI.cpp b/src-qt5/core-utils/lumina-search/MainUI.cpp index 99b04b2b..93ee7411 100644 --- a/src-qt5/core-utils/lumina-search/MainUI.cpp +++ b/src-qt5/core-utils/lumina-search/MainUI.cpp @@ -169,8 +169,8 @@ void MainUI::foundSearchItem(QString path){ //Now setup the visuals if(path.simplified().endsWith(".desktop")){ bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(path,ok); - if( !ok || !LXDG::checkValidity(desk) ){delete it; return; } //invalid file + XDGDesktop desk(path); + if( !desk.isValid() ){delete it; return; } //invalid file it->setText(desk.name); it->setIcon( LXDG::findIcon(desk.icon, "application-x-desktop") ); }else{ diff --git a/src-qt5/core-utils/lumina-search/Worker.cpp b/src-qt5/core-utils/lumina-search/Worker.cpp index b414a72f..025bcc1e 100644 --- a/src-qt5/core-utils/lumina-search/Worker.cpp +++ b/src-qt5/core-utils/lumina-search/Worker.cpp @@ -6,11 +6,13 @@ Worker::Worker(QObject *parent) : QObject(parent){ //Get the list of all applications and save them in an easily-searchable form - QList<XDGDesktop> apps = LXDG::systemDesktopFiles(); + QList<XDGDesktop*> apps = LXDG::systemDesktopFiles(); for(int i=0; i<apps.length(); i++){ - applist << ":::1:::"+apps[i].name+":::2:::"+apps[i].genericName+":::3:::"+apps[i].comment+":::4:::"+apps[i].filePath; + applist << ":::1:::"+apps[i]->name+":::2:::"+apps[i]->genericName+":::3:::"+apps[i]->comment+":::4:::"+apps[i]->filePath; } stopsearch = false; + //Clean up all the apps structures + for(int i=0; i<apps.length(); i++){ apps[i]->deleteLater(); } } Worker::~Worker(){ @@ -108,4 +110,4 @@ void Worker::beginsearch(){ } emit SearchUpdate( tr("Search Finished") ); emit SearchDone(); -}
\ No newline at end of file +} 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 36b05676..0e33f254 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -15,10 +15,396 @@ 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){ @@ -35,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(){ @@ -54,19 +442,21 @@ void XDGDesktopList::updateList(){ 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) - found << files[path].name; //keep track of which files were already found + found << files[path]->name; //keep track of which files were already found ok=true; }else{ ok=false; - if(files.contains(path)){ appschanged = true; files.remove(path); } - XDGDesktop dFile = LXDG::loadDesktopFile(path,ok); //will change the "ok" variable as needed - if(ok){ + 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; + found << dFile->name; + }else{ + dFile->deleteLater(); //bad file - discard it } } oldkeys.removeAll(path); //make sure this key does not get cleaned up later @@ -80,25 +470,28 @@ void XDGDesktopList::updateList(){ //Now go through and cleanup any old keys where the associated file does not exist anymore for(int i=0; i<oldkeys.length(); i++){ //qDebug() << "Removing file from internal map:" << oldkeys[i]; - files.remove(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() << "Auto App List Update:" << lastCheck << "Changes:" << appschanged << "Files:" << files.count(); + 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(); } } -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( showHidden || !files[keys[i]].isHidden ){ //this is faster than the "checkValidity()" function below - so always filter here first - if( LXDG::checkValidity(files[keys[i]], showAll) ){ + 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]]; } } @@ -109,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"; @@ -127,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 @@ -172,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) @@ -193,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 @@ -223,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; } @@ -242,9 +635,9 @@ XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){ //------------------- 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 @@ -252,70 +645,70 @@ 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.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) ){ - 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; } } @@ -324,9 +717,9 @@ XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){ //Return the structure 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; @@ -438,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; } @@ -472,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) @@ -506,40 +899,43 @@ QStringList LXDG::systemApplicationDirs(){ return out; } -XDGDesktopList* LXDG::systemAppsList(){ +/*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 - return systemAppsList()->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)); } @@ -575,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; @@ -629,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 @@ -1109,13 +1505,13 @@ QStringList LXDG::loadMimeFileGlobs2(){ } //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++){ @@ -1123,23 +1519,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{ @@ -1153,18 +1549,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); @@ -1177,12 +1572,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); @@ -1222,18 +1617,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 5c012b9a..f2b1e3e2 100644 --- a/src-qt5/core/libLumina/LuminaXDG.h +++ b/src-qt5/core/libLumina/LuminaXDG.h @@ -46,8 +46,9 @@ struct XDGDesktopAction{ // ====================== // FreeDesktop Desktop Entry Framework (data structure) // ====================== -struct XDGDesktop{ -//public: +class XDGDesktop : public QObject{ + Q_OBJECT +public: enum XDGDesktopType { BAD, APP, LINK, DIR }; //Admin variables @@ -66,14 +67,18 @@ struct XDGDesktop{ //Type 2 (LINK) variables QString url; - //Constructor/destructor - XDGDesktop(){} - ~XDGDesktop(){ - actions.clear(); - showInList.clear(); notShowInList.clear(); actionList.clear(); mimeList.clear(); catList.clear(); keyList.clear(); - name.clear(); genericName.clear(); comment.clear(); icon.clear(); - exec.clear(); tryexec.clear(); path.clear(); startupWM.clear(); url.clear(); - } + //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); }; // ======================== @@ -86,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 @@ -114,7 +119,7 @@ signals: class LFileInfo : public QFileInfo{ private: QString mime, icon; - XDGDesktop desk; + XDGDesktop *desk; void loadExtraInfo(); @@ -122,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 @@ -149,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 @@ -198,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/lumina-desktop/AppMenu.cpp b/src-qt5/core/lumina-desktop/AppMenu.cpp index cbf71e62..798d8b6d 100644 --- a/src-qt5/core/lumina-desktop/AppMenu.cpp +++ b/src-qt5/core/lumina-desktop/AppMenu.cpp @@ -11,6 +11,7 @@ AppMenu::AppMenu(QWidget* parent) : QMenu(parent){ appstorelink = LOS::AppStoreShortcut(); //Default application "store" to display (AppCafe in TrueOS) controlpanellink = LOS::ControlPanelShortcut(); //Default control panel + sysApps = new XDGDesktopList(this, true); //have this one automatically keep in sync APPS.clear(); //watcher = new QFileSystemWatcher(this); //connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(watcherUpdate()) ); @@ -24,7 +25,7 @@ AppMenu::~AppMenu(){ } -QHash<QString, QList<XDGDesktop> >* AppMenu::currentAppHash(){ +QHash<QString, QList<XDGDesktop*> >* AppMenu::currentAppHash(){ return &APPS; } @@ -38,8 +39,7 @@ void AppMenu::updateAppList(){ this->setIcon( LXDG::findIcon("system-run","") ); //Now update the lists this->clear(); - APPS.clear(); - XDGDesktopList *sysApps = LXDG:: systemAppsList(); + APPS.clear(); //NOTE: Don't delete these pointers - the pointers are managed by the sysApps class and these are just references to them //qDebug() << "New Apps List:"; if(LSession::handle()->sessionSettings()->value("AutomaticDesktopAppLinks",true).toBool() && !lastHashUpdate.isNull() ){ QString desktop = QDir::homePath()+"/"+tr("Desktop")+"/"; //translated desktop folder @@ -60,8 +60,8 @@ void AppMenu::updateAppList(){ } tmp = sysApps->newApps; for(int i=0; i<tmp.length() && !desktop.isEmpty(); i++){ - XDGDesktop desk = sysApps->files.value(tmp[i]); - if(desk.isHidden || !LXDG::checkValidity(desk, false) ){ continue; } //skip this one + XDGDesktop *desk = sysApps->files.value(tmp[i]); + if(desk->isHidden || !desk->isValid(false) ){ continue; } //skip this one //qDebug() << "New App: " << tmp[i] << desk.filePath << "Hidden:" << desk.isHidden; //Create a new symlink for this file if one does not exist QString filename = tmp[i].section("/",-1); @@ -69,23 +69,22 @@ void AppMenu::updateAppList(){ if(!QFile::exists(desktop+filename) ){ QFile::link(tmp[i], desktop+filename); } } } - QList<XDGDesktop> allfiles = sysApps->apps(false,false); //only valid, non-hidden apps + QList<XDGDesktop*> allfiles = sysApps->apps(false,false); //only valid, non-hidden apps APPS = LXDG::sortDesktopCats(allfiles); APPS.insert("All", LXDG::sortDesktopNames(allfiles)); lastHashUpdate = QDateTime::currentDateTime(); //Now fill the menu - bool ok; //for checking inputs //Add link to the file manager //this->addAction( LXDG::findIcon("user-home", ""), tr("Browse Files"), this, SLOT(launchFileManager()) ); //--Look for the app store - XDGDesktop store = LXDG::loadDesktopFile(appstorelink, ok); - if(ok){ + XDGDesktop store(appstorelink); + if(store.isValid()){ this->addAction( LXDG::findIcon(store.icon, ""), tr("Manage Applications"), this, SLOT(launchStore()) ); } //--Look for the control panel - store = LXDG::loadDesktopFile(controlpanellink, ok); - if(ok){ - this->addAction( LXDG::findIcon(store.icon, ""), tr("Control Panel"), this, SLOT(launchControlPanel()) ); + XDGDesktop controlp(controlpanellink); + if(controlp.isValid()){ + this->addAction( LXDG::findIcon(controlp.icon, ""), tr("Control Panel"), this, SLOT(launchControlPanel()) ); } this->addSeparator(); //--Now create the sub-menus @@ -112,29 +111,29 @@ void AppMenu::updateAppList(){ QMenu *menu = new QMenu(name, this); menu->setIcon(LXDG::findIcon(icon,"")); connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(launchApp(QAction*)) ); - QList<XDGDesktop> appL = APPS.value(cats[i]); + QList<XDGDesktop*> appL = APPS.value(cats[i]); for( int a=0; a<appL.length(); a++){ - if(appL[a].actions.isEmpty()){ + if(appL[a]->actions.isEmpty()){ //Just a single entry point - no extra actions - QAction *act = new QAction(LXDG::findIcon(appL[a].icon, ""), appL[a].name, this); - act->setToolTip(appL[a].comment); - act->setWhatsThis(appL[a].filePath); + QAction *act = new QAction(LXDG::findIcon(appL[a]->icon, ""), appL[a]->name, this); + act->setToolTip(appL[a]->comment); + act->setWhatsThis(appL[a]->filePath); menu->addAction(act); }else{ //This app has additional actions - make this a sub menu // - first the main menu/action - QMenu *submenu = new QMenu(appL[a].name, this); - submenu->setIcon( LXDG::findIcon(appL[a].icon,"") ); + QMenu *submenu = new QMenu(appL[a]->name, this); + submenu->setIcon( LXDG::findIcon(appL[a]->icon,"") ); //This is the normal behavior - not a special sub-action (although it needs to be at the top of the new menu) - QAction *act = new QAction(LXDG::findIcon(appL[a].icon, ""), appL[a].name, this); - act->setToolTip(appL[a].comment); - act->setWhatsThis(appL[a].filePath); + QAction *act = new QAction(LXDG::findIcon(appL[a]->icon, ""), appL[a]->name, this); + act->setToolTip(appL[a]->comment); + act->setWhatsThis(appL[a]->filePath); submenu->addAction(act); //Now add entries for every sub-action listed - for(int sa=0; sa<appL[a].actions.length(); sa++){ - QAction *sact = new QAction(LXDG::findIcon(appL[a].actions[sa].icon, appL[a].icon), appL[a].actions[sa].name, this); - sact->setToolTip(appL[a].comment); - sact->setWhatsThis("-action \""+appL[a].actions[sa].ID+"\" \""+appL[a].filePath+"\""); + for(int sa=0; sa<appL[a]->actions.length(); sa++){ + QAction *sact = new QAction(LXDG::findIcon(appL[a]->actions[sa].icon, appL[a]->icon), appL[a]->actions[sa].name, this); + sact->setToolTip(appL[a]->comment); + sact->setWhatsThis("-action \""+appL[a]->actions[sa].ID+"\" \""+appL[a]->filePath+"\""); submenu->addAction(sact); } menu->addMenu(submenu); @@ -151,7 +150,8 @@ void AppMenu::updateAppList(){ //================= void AppMenu::start(){ //Setup the watcher - connect(LXDG:: systemAppsList(), SIGNAL(appsUpdated()), this, SLOT(watcherUpdate()) ); + connect(sysApps, SIGNAL(appsUpdated()), this, SLOT(watcherUpdate()) ); + sysApps->updateList(); //Now fill the menu the first time updateAppList(); } diff --git a/src-qt5/core/lumina-desktop/AppMenu.h b/src-qt5/core/lumina-desktop/AppMenu.h index 7584de07..5baaab7a 100644 --- a/src-qt5/core/lumina-desktop/AppMenu.h +++ b/src-qt5/core/lumina-desktop/AppMenu.h @@ -31,14 +31,15 @@ public: AppMenu(QWidget *parent = 0); ~AppMenu(); - QHash<QString, QList<XDGDesktop> > *currentAppHash(); + QHash<QString, QList<XDGDesktop*> > *currentAppHash(); QDateTime lastHashUpdate; private: //QFileSystemWatcher *watcher; QString appstorelink, controlpanellink; QList<QMenu> MLIST; - QHash<QString, QList<XDGDesktop> > APPS; + XDGDesktopList *sysApps; + QHash<QString, QList<XDGDesktop*> > APPS; void updateAppList(); //completely update the menu lists diff --git a/src-qt5/core/lumina-desktop/LDesktop.cpp b/src-qt5/core/lumina-desktop/LDesktop.cpp index e3d946d4..f1b73bc0 100644 --- a/src-qt5/core/lumina-desktop/LDesktop.cpp +++ b/src-qt5/core/lumina-desktop/LDesktop.cpp @@ -280,9 +280,8 @@ void LDesktop::UpdateMenu(bool fast){ else if(items[i].startsWith("app::::") && items[i].endsWith(".desktop")){ //Custom *.desktop application QString file = items[i].section("::::",1,1).simplified(); - bool ok = false; - XDGDesktop xdgf = LXDG::loadDesktopFile(file, ok); - if(ok){ + XDGDesktop xdgf(file);// = LXDG::loadDesktopFile(file, ok); + if(xdgf.type!=XDGDesktop::BAD){ deskMenu->addAction( LXDG::findIcon(xdgf.icon,""), xdgf.name)->setWhatsThis(file); }else{ qDebug() << "Could not load application file:" << file; diff --git a/src-qt5/core/lumina-desktop/SettingsMenu.cpp b/src-qt5/core/lumina-desktop/SettingsMenu.cpp index 10ada2cf..80ef3042 100644 --- a/src-qt5/core/lumina-desktop/SettingsMenu.cpp +++ b/src-qt5/core/lumina-desktop/SettingsMenu.cpp @@ -45,9 +45,8 @@ void SettingsMenu::UpdateMenu(){ QString CONTROLPANEL = LOS::ControlPanelShortcut(); if(QFile::exists(CONTROLPANEL) && !CONTROLPANEL.isEmpty()){ //Now load the info - bool ok = false; - XDGDesktop cpan = LXDG::loadDesktopFile(CONTROLPANEL, ok); - if(ok){ + XDGDesktop cpan(CONTROLPANEL); + if(cpan.isValid()){ act = new QAction( LXDG::findIcon(cpan.icon,""), tr("Control Panel"), this); act->setWhatsThis("lumina-open \""+CONTROLPANEL+"\""); this->addAction(act); 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 8c7af5e9..bd8e79db 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp +++ b/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp @@ -38,8 +38,9 @@ void AppLauncherPlugin::loadButton(){ button->setIconSize( QSize(icosize,icosize) ); QString txt; if(path.endsWith(".desktop") && ok){ - XDGDesktop file = LXDG::loadDesktopFile(path, ok); - if(path.isEmpty() || !QFile::exists(path) || !ok){ + XDGDesktop file(path); + ok = file.isValid(); + if(!ok){ button->setWhatsThis(""); button->setIcon( QIcon(LXDG::findIcon("quickopen-file","").pixmap(QSize(icosize,icosize)).scaledToHeight(icosize, Qt::SmoothTransformation) ) ); txt = tr("Click to Set"); @@ -125,13 +126,13 @@ void AppLauncherPlugin::buttonClicked(){ QString path = button->whatsThis(); if(path.isEmpty() || !QFile::exists(path) ){ //prompt for the user to select an application - QList<XDGDesktop> apps = LXDG::sortDesktopNames( LXDG::systemDesktopFiles() ); + QList<XDGDesktop*> apps = LXDG::sortDesktopNames( LXDG::systemDesktopFiles() ); QStringList names; - for(int i=0; i<apps.length(); i++){ names << apps[i].name; } + for(int i=0; i<apps.length(); i++){ names << apps[i]->name; } bool ok = false; QString app = QInputDialog::getItem(this, tr("Select Application"), tr("Name:"), names, 0, false, &ok); if(!ok || names.indexOf(app)<0){ return; } //cancelled - this->saveSetting("applicationpath", apps[ names.indexOf(app) ].filePath); + this->saveSetting("applicationpath", apps[ names.indexOf(app) ]->filePath); QTimer::singleShot(0,this, SLOT(loadButton())); }else{ LSession::LaunchApplication("lumina-open \""+path+"\""); diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/desktopview/DesktopViewPlugin.cpp b/src-qt5/core/lumina-desktop/desktop-plugins/desktopview/DesktopViewPlugin.cpp index 01e174e9..90f3374b 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/desktopview/DesktopViewPlugin.cpp +++ b/src-qt5/core/lumina-desktop/desktop-plugins/desktopview/DesktopViewPlugin.cpp @@ -149,9 +149,8 @@ void DesktopViewPlugin::updateContents(){ it->setIcon( LXDG::findIcon("folder","") ); txt = files[i].fileName(); }else if(files[i].suffix() == "desktop" ){ - bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(files[i].absoluteFilePath(), ok); - if(ok){ + XDGDesktop desk(files[i].absoluteFilePath()); + if(desk.isValid()){ it->setIcon( LXDG::findIcon(desk.icon,"unknown") ); if(desk.name.isEmpty()){ txt = files[i].fileName(); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp index 321970ed..05b7981f 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp @@ -31,9 +31,8 @@ void AppLaunchButtonPlugin::updateButtonVisuals(){ QIcon icon; QString tooltip = tr("Click to assign an application"); if(appfile.endsWith(".desktop")){ - bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(appfile,ok); - if(ok){ + XDGDesktop desk(appfile); + if(desk.isValid()){ icon = LXDG::findIcon(desk.icon, "unknown"); tooltip = QString(tr("Launch %1")).arg(desk.name); }else{ @@ -56,13 +55,13 @@ void AppLaunchButtonPlugin::updateButtonVisuals(){ void AppLaunchButtonPlugin::AppClicked(){ if(appfile.isEmpty()){ //No App File selected - QList<XDGDesktop> apps = LSession::handle()->applicationMenu()->currentAppHash()->value("All"); + QList<XDGDesktop*> apps = LSession::handle()->applicationMenu()->currentAppHash()->value("All"); QStringList names; - for(int i=0; i<apps.length(); i++){ names << apps[i].name; } + for(int i=0; i<apps.length(); i++){ names << apps[i]->name; } bool ok = false; QString app = QInputDialog::getItem(this, tr("Select Application"), tr("Name:"), names, 0, false, &ok); if(!ok || names.indexOf(app)<0){ return; } //cancelled - appfile = apps[ names.indexOf(app) ].filePath; + appfile = apps[ names.indexOf(app) ]->filePath; //Still need to find a way to set this value persistently // --- perhaps replace the plugin in the desktop settings file with the new path? // --- "applauncher::broken---<something>" -> "applauncher::fixed---<something>" ? @@ -71,4 +70,3 @@ void AppLaunchButtonPlugin::AppClicked(){ LSession::LaunchApplication("lumina-open \""+appfile+"\""); } } - diff --git a/src-qt5/core/lumina-desktop/panel-plugins/appmenu/LAppMenuPlugin.cpp b/src-qt5/core/lumina-desktop/panel-plugins/appmenu/LAppMenuPlugin.cpp index 5d20e3ec..e3be55c2 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/appmenu/LAppMenuPlugin.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/appmenu/LAppMenuPlugin.cpp @@ -62,23 +62,22 @@ void LAppMenuPlugin::LaunchItem(QAction* item){ void LAppMenuPlugin::UpdateMenu(){ mainmenu->clear(); - QHash<QString, QList<XDGDesktop> > *HASH = LSession::handle()->applicationMenu()->currentAppHash(); + QHash<QString, QList<XDGDesktop*> > *HASH = LSession::handle()->applicationMenu()->currentAppHash(); //Now Re-create the menu (orignally copied from the AppMenu class) - bool ok; //for checking inputs //Add link to the file manager QAction *tmpact = mainmenu->addAction( LXDG::findIcon("user-home", ""), tr("Browse Files") ); tmpact->setWhatsThis("\""+QDir::homePath()+"\""); //--Look for the app store - XDGDesktop store = LXDG::loadDesktopFile(LOS::AppStoreShortcut(), ok); - if(ok){ + XDGDesktop store(LOS::AppStoreShortcut()); + if(store.isValid()){ tmpact = mainmenu->addAction( LXDG::findIcon(store.icon, ""), tr("Install Applications") ); tmpact->setWhatsThis("\""+store.filePath+"\""); } //--Look for the control panel - store = LXDG::loadDesktopFile(LOS::ControlPanelShortcut(), ok); - if(ok){ - tmpact = mainmenu->addAction( LXDG::findIcon(store.icon, ""), tr("Control Panel") ); - tmpact->setWhatsThis("\""+store.filePath+"\""); + XDGDesktop controlp(LOS::ControlPanelShortcut()); + if(controlp.isValid()){ + tmpact = mainmenu->addAction( LXDG::findIcon(controlp.icon, ""), tr("Control Panel") ); + tmpact->setWhatsThis("\""+controlp.filePath+"\""); } mainmenu->addSeparator(); //--Now create the sub-menus @@ -104,29 +103,29 @@ void LAppMenuPlugin::UpdateMenu(){ QMenu *menu = new QMenu(name, this); menu->setIcon(LXDG::findIcon(icon,"")); - QList<XDGDesktop> appL = HASH->value(cats[i]); + QList<XDGDesktop*> appL = HASH->value(cats[i]); for( int a=0; a<appL.length(); a++){ - if(appL[a].actions.isEmpty()){ + if(appL[a]->actions.isEmpty()){ //Just a single entry point - no extra actions - QAction *act = new QAction(LXDG::findIcon(appL[a].icon, ""), appL[a].name, menu); - act->setToolTip(appL[a].comment); - act->setWhatsThis("\""+appL[a].filePath+"\""); + QAction *act = new QAction(LXDG::findIcon(appL[a]->icon, ""), appL[a]->name, menu); + act->setToolTip(appL[a]->comment); + act->setWhatsThis("\""+appL[a]->filePath+"\""); menu->addAction(act); }else{ //This app has additional actions - make this a sub menu // - first the main menu/action - QMenu *submenu = new QMenu(appL[a].name, menu); - submenu->setIcon( LXDG::findIcon(appL[a].icon,"") ); + QMenu *submenu = new QMenu(appL[a]->name, menu); + submenu->setIcon( LXDG::findIcon(appL[a]->icon,"") ); //This is the normal behavior - not a special sub-action (although it needs to be at the top of the new menu) - QAction *act = new QAction(LXDG::findIcon(appL[a].icon, ""), appL[a].name, submenu); - act->setToolTip(appL[a].comment); - act->setWhatsThis(appL[a].filePath); + QAction *act = new QAction(LXDG::findIcon(appL[a]->icon, ""), appL[a]->name, submenu); + act->setToolTip(appL[a]->comment); + act->setWhatsThis(appL[a]->filePath); submenu->addAction(act); //Now add entries for every sub-action listed - for(int sa=0; sa<appL[a].actions.length(); sa++){ - QAction *sact = new QAction(LXDG::findIcon(appL[a].actions[sa].icon, appL[a].icon), appL[a].actions[sa].name, this); - sact->setToolTip(appL[a].comment); - sact->setWhatsThis("-action \""+appL[a].actions[sa].ID+"\" \""+appL[a].filePath+"\""); + for(int sa=0; sa<appL[a]->actions.length(); sa++){ + QAction *sact = new QAction(LXDG::findIcon(appL[a]->actions[sa].icon, appL[a]->icon), appL[a]->actions[sa].name, this); + sact->setToolTip(appL[a]->comment); + sact->setWhatsThis("-action \""+appL[a]->actions[sa].ID+"\" \""+appL[a]->filePath+"\""); submenu->addAction(sact); } menu->addMenu(submenu); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/desktopbar/LDeskBar.cpp b/src-qt5/core/lumina-desktop/panel-plugins/desktopbar/LDeskBar.cpp index 48bbface..9903d4fd 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/desktopbar/LDeskBar.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/desktopbar/LDeskBar.cpp @@ -130,11 +130,9 @@ void LDeskBarPlugin::updateFiles(){ if(type=="app"){ //Add it to appM bool ok = false; - XDGDesktop df = LXDG::loadDesktopFile(path, ok); - if(ok){ - if( LXDG::checkValidity(df) && !df.isHidden ){ + XDGDesktop df(path); + if(df.isValid() && !df.isHidden){ appM->addAction( newAction(df.filePath, df.name, LXDG::findIcon(df.icon, ":/images/default-application.png")) ); - } } }else if(type=="dir"){ //Add it to dirM diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp index 3a0493a3..48d9623a 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp @@ -16,8 +16,8 @@ ItemWidget::ItemWidget(QWidget *parent, QString itemPath, QString type, bool gob bool inHome = type.endsWith("-home"); //internal code if(inHome){ type = type.remove("-home"); } if(itemPath.endsWith(".desktop") || type=="app"){ - XDGDesktop item = LXDG::loadDesktopFile(itemPath, gooditem); - if(gooditem){ gooditem = LXDG::checkValidity(item); } + XDGDesktop item(itemPath, this); + gooditem = item.isValid(); //qDebug() << "Good Item:" << gooditem << itemPath; if(gooditem){ icon->setPixmap( LXDG::findIcon(item.icon, "preferences-system-windows-actions").pixmap(32,32) ); @@ -26,7 +26,7 @@ ItemWidget::ItemWidget(QWidget *parent, QString itemPath, QString type, bool gob if(!item.genericName.isEmpty() && item.name!=item.genericName){ text.append("<br><i> -- "+item.genericName+"</i>"); } name->setText(text); name->setToolTip(item.comment); - setupActions(item); + setupActions(&item); }else{ return; } @@ -89,13 +89,14 @@ ItemWidget::ItemWidget(QWidget *parent, QString itemPath, QString type, bool gob } // - Application constructor -ItemWidget::ItemWidget(QWidget *parent, XDGDesktop item) : QFrame(parent){ +ItemWidget::ItemWidget(QWidget *parent, XDGDesktop *item) : QFrame(parent){ + if(item==0){ return; } createWidget(); isDirectory = false; - if(LUtils::isFavorite(item.filePath)){ - linkPath = item.filePath; + if(LUtils::isFavorite(item->filePath)){ + linkPath = item->filePath; isShortcut=true; - }else if( item.filePath.section("/",0,-2)==QDir::homePath()+"/Desktop" ){ + }else if( item->filePath.section("/",0,-2)==QDir::homePath()+"/Desktop" ){ isShortcut = true; }else{ isShortcut = false; @@ -104,14 +105,14 @@ ItemWidget::ItemWidget(QWidget *parent, XDGDesktop item) : QFrame(parent){ name->setToolTip(icon->whatsThis()); //also allow the user to see the full shortcut path } //Now fill it appropriately - icon->setPixmap( LXDG::findIcon(item.icon,"preferences-system-windows-actions").pixmap(64,64) ); - text = item.name; - if(!item.genericName.isEmpty() && item.name!=item.genericName){ text.append("<br><i> -- "+item.genericName+"</i>"); } + icon->setPixmap( LXDG::findIcon(item->icon,"preferences-system-windows-actions").pixmap(64,64) ); + text = item->name; + if(!item->genericName.isEmpty() && item->name!=item->genericName){ text.append("<br><i> -- "+item->genericName+"</i>"); } name->setText(text); - name->setToolTip(item.comment); - this->setWhatsThis(item.name); - icon->setWhatsThis(item.filePath); - iconPath = item.icon; + name->setToolTip(item->comment); + this->setWhatsThis(item->name); + icon->setWhatsThis(item->filePath); + iconPath = item->icon; //Now setup the buttons appropriately setupContextMenu(); setupActions(item); @@ -176,14 +177,14 @@ void ItemWidget::setupContextMenu(){ } } -void ItemWidget::setupActions(XDGDesktop app){ - if(app.actions.isEmpty()){ actButton->setVisible(false); return; } +void ItemWidget::setupActions(XDGDesktop *app){ + if(app==0 || app->actions.isEmpty()){ actButton->setVisible(false); return; } //Actions Available - go ahead and list them all actButton->setMenu( new QMenu(this) ); - for(int i=0; i<app.actions.length(); i++){ - QAction *act = new QAction(LXDG::findIcon(app.actions[i].icon, app.icon), app.actions[i].name, this); - act->setToolTip(app.actions[i].ID); - act->setWhatsThis(app.actions[i].ID); + for(int i=0; i<app->actions.length(); i++){ + QAction *act = new QAction(LXDG::findIcon(app->actions[i].icon, app->icon), app->actions[i].name, this); + act->setToolTip(app->actions[i].ID); + act->setWhatsThis(app->actions[i].ID); actButton->menu()->addAction(act); } connect(actButton->menu(), SIGNAL(triggered(QAction*)), this, SLOT(actionClicked(QAction*)) ); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.h b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.h index 8190de43..365b434f 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.h +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.h @@ -32,7 +32,7 @@ public: // - Favorites (path/type) ItemWidget(QWidget *parent=0, QString itemPath="", QString type="unknown", bool goback=false); // - Generic Apps - ItemWidget(QWidget *parent=0, XDGDesktop item= XDGDesktop()); + ItemWidget(QWidget *parent=0, XDGDesktop *item= 0); // - Categories //ItemWidget(QWidget *parent=0, QString cat=""); @@ -53,7 +53,7 @@ private: void createWidget(); //void setupButton(bool disable = false); void setupContextMenu(); - void setupActions(XDGDesktop); + void setupActions(XDGDesktop*); void updateItems(); //update the text/icon to match sizes diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp index 60a313e8..ae61760b 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp @@ -23,7 +23,6 @@ StartMenu::StartMenu(QWidget *parent) : QWidget(parent), ui(new Ui::StartMenu){ searchTimer->setInterval(300); //~1/3 second searchTimer->setSingleShot(true); connect(searchTimer, SIGNAL(timeout()), this, SLOT(startSearch()) ); - sysapps = LSession::handle()->applicationMenu()->currentAppHash(); connect(LSession::handle()->applicationMenu(), SIGNAL(AppMenuUpdated()), this, SLOT(UpdateApps()) ); //Need to load the last used setting of the application list QString state = LSession::handle()->DesktopPluginSettings()->value("panelPlugs/systemstart/showcategories", "partial").toString(); @@ -72,9 +71,8 @@ void StartMenu::UpdateAll(){ if(QFile::exists(tmp)){ ui->tool_launch_controlpanel->setWhatsThis(tmp); //Now read the file to see which icon to use - bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(tmp, ok); - if(ok && LXDG::checkValidity(desk)){ + XDGDesktop desk(tmp); + if(desk.isValid()){ ui->tool_launch_controlpanel->setIcon(LXDG::findIcon(desk.icon,"preferences-other")); }else{ ui->tool_launch_controlpanel->setVisible(false); } }else{ ui->tool_launch_controlpanel->setVisible(false); } @@ -83,9 +81,8 @@ void StartMenu::UpdateAll(){ if(QFile::exists(tmp)){ ui->tool_launch_store->setWhatsThis(tmp); //Now read the file to see which icon to use - bool ok = false; - XDGDesktop desk = LXDG::loadDesktopFile(tmp, ok); - if(ok && LXDG::checkValidity(desk)){ + XDGDesktop desk(tmp); + if(desk.isValid()){ ui->tool_launch_store->setIcon(LXDG::findIcon(desk.icon,"utilities-file-archiver")); }else{ ui->tool_launch_store->setVisible(false); } }else{ ui->tool_launch_store->setVisible(false); } @@ -158,8 +155,14 @@ void StartMenu::UpdateQuickLaunch(QString path, bool keep){ // ========================== // PRIVATE FUNCTIONS // ========================== +void StartMenu::deleteChildren(QObject *obj){ +for(int i=0; i<obj->children().count(); i++){ obj->children().at(i)->deleteLater(); } +} + void StartMenu::ClearScrollArea(QScrollArea *area){ - area->takeWidget()->deleteLater(); + QWidget *old = area->takeWidget(); + deleteChildren(old); //make sure we *fully* delete these items to save memory + old->deleteLater(); area->setWidget( new QWidget() ); //create a new widget in the scroll area area->widget()->setContentsMargins(0,0,0,0); QVBoxLayout *layout = new QVBoxLayout; @@ -216,18 +219,18 @@ void StartMenu::do_search(QString search, bool force){ QStringList found; //syntax: [<sorter>::::<mimetype>::::<filepath>] QString tmp = search; if(LUtils::isValidBinary(tmp)){ found << "0::::application/x-executable::::"+tmp; } - QList<XDGDesktop> apps = sysapps->value("All"); + QList<XDGDesktop*> apps = LSession::handle()->applicationMenu()->currentAppHash()->value("All"); for(int i=0; i<apps.length(); i++){ int priority = -1; - if(apps[i].name.toLower()==search.toLower()){ priority = 10; } - else if(apps[i].name.startsWith(search, Qt::CaseInsensitive)){ priority = 15; } - else if(apps[i].name.contains(search, Qt::CaseInsensitive)){ priority = 19; } - else if(apps[i].genericName.contains(search, Qt::CaseInsensitive)){ priority = 20; } - else if(apps[i].comment.contains(search, Qt::CaseInsensitive)){ priority = 30; } + if(apps[i]->name.toLower()==search.toLower()){ priority = 10; } + else if(apps[i]->name.startsWith(search, Qt::CaseInsensitive)){ priority = 15; } + else if(apps[i]->name.contains(search, Qt::CaseInsensitive)){ priority = 19; } + else if(apps[i]->genericName.contains(search, Qt::CaseInsensitive)){ priority = 20; } + else if(apps[i]->comment.contains(search, Qt::CaseInsensitive)){ priority = 30; } //Can add other filters here later if(priority>0){ - found << QString::number(priority)+"::::app::::"+apps[i].filePath; + found << QString::number(priority)+"::::app::::"+apps[i]->filePath; } } found.sort(Qt::CaseInsensitive); //sort by priority/type (lower numbers are higher on list) @@ -238,10 +241,8 @@ void StartMenu::do_search(QString search, bool force){ if(topsearch.isEmpty()){ topsearch = found[i].section("::::",2,-1); } ItemWidget *it = 0; if( found[i].section("::::",2,-1).endsWith(".desktop")){ - bool ok = false; - XDGDesktop item = LXDG::loadDesktopFile(found[i].section("::::",2,-1), ok); - if(ok){ ok = LXDG::checkValidity(item); } - if(ok){ it = new ItemWidget(ui->scroll_favs->widget(), item); } + XDGDesktop item(found[i].section("::::",2,-1)); + if(item.isValid()){ it = new ItemWidget(ui->scroll_favs->widget(), &item); } }else{ it = new ItemWidget(ui->scroll_favs->widget(), found[i].section("::::",2,-1), found[i].section("::::",1,1) ); } @@ -308,11 +309,11 @@ void StartMenu::UpdateApps(){ //qDebug() << " - Partially Checked"; //Show a single page of apps, but still divided up by categories CCat.clear(); - QStringList cats = sysapps->keys(); + QStringList cats = LSession::handle()->applicationMenu()->currentAppHash()->keys(); cats.sort(); cats.removeAll("All"); for(int c=0; c<cats.length(); c++){ - QList<XDGDesktop> apps = sysapps->value(cats[c]); + QList<XDGDesktop*> apps = LSession::handle()->applicationMenu()->currentAppHash()->value(cats[c]); if(apps.isEmpty()){ continue; } //Add the category label to the scroll QLabel *catlabel = new QLabel("<b>"+cats[c]+"</b>",ui->scroll_apps->widget()); @@ -335,7 +336,7 @@ void StartMenu::UpdateApps(){ //Only show categories to start with - and have the user click-into a cat to see apps if(CCat.isEmpty()){ //No cat selected yet - show cats only - QStringList cats = sysapps->keys(); + QStringList cats = LSession::handle()->applicationMenu()->currentAppHash()->keys(); cats.sort(); cats.removeAll("All"); //This is not a "real" category for(int c=0; c<cats.length(); c++){ @@ -352,7 +353,7 @@ void StartMenu::UpdateApps(){ ui->scroll_apps->widget()->layout()->addWidget(it); connect(it, SIGNAL(RunItem(QString)), this, SLOT(LaunchItem(QString)) ); //Show apps for this cat - QList<XDGDesktop> apps = sysapps->value(CCat); + QList<XDGDesktop*> apps = LSession::handle()->applicationMenu()->currentAppHash()->value(CCat); for(int i=0; i<apps.length(); i++){ //qDebug() << " - App:" << apps[i].name; ItemWidget *it = new ItemWidget(ui->scroll_apps->widget(), apps[i] ); @@ -368,7 +369,7 @@ void StartMenu::UpdateApps(){ }else{ //qDebug() << " - Not Checked"; //No categories at all - just alphabetize all the apps - QList<XDGDesktop> apps = sysapps->value("All"); + QList<XDGDesktop*> apps = LSession::handle()->applicationMenu()->currentAppHash()->value("All"); CCat.clear(); //Now add all the apps for this category for(int i=0; i<apps.length(); i++){ @@ -431,10 +432,8 @@ void StartMenu::UpdateFavs(){ if( !QFile::exists(tmp[i].section("::::",2,-1)) ){ continue; } //invalid favorite - skip it ItemWidget *it = 0; if( tmp[i].section("::::",2,-1).endsWith(".desktop")){ - bool ok = false; - XDGDesktop item = LXDG::loadDesktopFile(tmp[i].section("::::",2,-1), ok); - if(ok){ ok = LXDG::checkValidity(item); } - if(ok){ it = new ItemWidget(ui->scroll_favs->widget(), item); } + XDGDesktop item(tmp[i].section("::::",2,-1)); + if(item.isValid()){ it = new ItemWidget(ui->scroll_favs->widget(), &item); } }else{ it = new ItemWidget(ui->scroll_favs->widget(), tmp[i].section("::::",2,-1), tmp[i].section("::::",1,1) ); } diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h index 9a629cc2..af7bd136 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h @@ -32,12 +32,12 @@ public slots: private: Ui::StartMenu *ui; - QHash<QString, QList<XDGDesktop> > *sysapps; QStringList favs; QString CCat, CSearch, topsearch; //current category/search QTimer *searchTimer; //Simple utility functions + void deleteChildren(QObject *obj); //recursive function void ClearScrollArea(QScrollArea *area); void SortScrollArea(QScrollArea *area); void do_search(QString search, bool force); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp index 1d32440a..a1dfe956 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.cpp @@ -15,12 +15,11 @@ UserItemWidget::UserItemWidget(QWidget *parent, QString itemPath, QString type, bool inHome = type.endsWith("-home"); //internal code if(inHome){ type = type.remove("-home"); } if(itemPath.endsWith(".desktop") || type=="app"){ - bool ok = false; - XDGDesktop item = LXDG::loadDesktopFile(itemPath, ok); - if(ok && LXDG::checkValidity(item) ){ + XDGDesktop item(itemPath); + if( item.isValid() ){ icon->setPixmap( LXDG::findIcon(item.icon, "preferences-system-windows-actions").pixmap(32,32) ); name->setText( this->fontMetrics().elidedText(item.name, Qt::ElideRight, TEXTCUTOFF) ); - setupActions(item); + setupActions(&item); }else{ gooditem = false; return; @@ -63,22 +62,23 @@ UserItemWidget::UserItemWidget(QWidget *parent, QString itemPath, QString type, setupButton(goback); } -UserItemWidget::UserItemWidget(QWidget *parent, XDGDesktop item) : QFrame(parent){ +UserItemWidget::UserItemWidget(QWidget *parent, XDGDesktop *item) : QFrame(parent){ + if(item==0){ return; } createWidget(); isDirectory = false; - if(LUtils::isFavorite(item.filePath)){ - linkPath = item.filePath; + if(LUtils::isFavorite(item->filePath)){ + linkPath = item->filePath; isShortcut=true; - }else if( item.filePath.section("/",0,-2)==QDir::homePath()+"/Desktop" ){ + }else if( item->filePath.section("/",0,-2)==QDir::homePath()+"/Desktop" ){ isShortcut = true; }else{ isShortcut = false; } //Now fill it appropriately - icon->setPixmap( LXDG::findIcon(item.icon,"preferences-system-windows-actions").pixmap(32,32) ); - name->setText( this->fontMetrics().elidedText(item.name, Qt::ElideRight, TEXTCUTOFF) ); + icon->setPixmap( LXDG::findIcon(item->icon,"preferences-system-windows-actions").pixmap(32,32) ); + name->setText( this->fontMetrics().elidedText(item->name, Qt::ElideRight, TEXTCUTOFF) ); this->setWhatsThis(name->text()); - icon->setWhatsThis(item.filePath); + icon->setWhatsThis(item->filePath); //Now setup the buttons appropriately setupButton(); setupActions(item); @@ -152,14 +152,14 @@ void UserItemWidget::setupButton(bool disable){ } } -void UserItemWidget::setupActions(XDGDesktop app){ - if(app.actions.isEmpty()){ actButton->setVisible(false); return; } +void UserItemWidget::setupActions(XDGDesktop *app){ + if(app==0 || app->actions.isEmpty()){ actButton->setVisible(false); return; } //Actions Available - go ahead and list them all actButton->setMenu( new QMenu(this) ); - for(int i=0; i<app.actions.length(); i++){ - QAction *act = new QAction(LXDG::findIcon(app.actions[i].icon, app.icon), app.actions[i].name, this); - act->setToolTip(app.actions[i].ID); - act->setWhatsThis(app.actions[i].ID); + for(int i=0; i<app->actions.length(); i++){ + QAction *act = new QAction(LXDG::findIcon(app->actions[i].icon, app->icon), app->actions[i].name, this); + act->setToolTip(app->actions[i].ID); + act->setWhatsThis(app->actions[i].ID); actButton->menu()->addAction(act); } connect(actButton->menu(), SIGNAL(triggered(QAction*)), this, SLOT(actionClicked(QAction*)) ); @@ -201,4 +201,4 @@ void UserItemWidget::actionClicked(QAction *act){ if(!linkPath.isEmpty()){ cmd = cmd.arg(linkPath); } else{ cmd = cmd.arg(icon->whatsThis()); } emit RunItem(cmd); -}
\ No newline at end of file +} diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.h b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.h index 2251344c..0b212f10 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.h +++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserItemWidget.h @@ -28,7 +28,7 @@ class UserItemWidget : public QFrame{ Q_OBJECT public: UserItemWidget(QWidget *parent=0, QString itemPath="", QString type="unknown", bool goback=false); - UserItemWidget(QWidget *parent=0, XDGDesktop item= XDGDesktop()); + UserItemWidget(QWidget *parent=0, XDGDesktop *item= 0); ~UserItemWidget(); bool gooditem; @@ -41,7 +41,7 @@ private: void createWidget(); void setupButton(bool disable = false); - void setupActions(XDGDesktop); + void setupActions(XDGDesktop*); private slots: void buttonClicked(); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp index c7d8109c..fb58c7f6 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.cpp @@ -130,8 +130,8 @@ void UserWidget::UpdateAll(){ QString APPSTORE = LOS::AppStoreShortcut(); if(QFile::exists(APPSTORE) && !APPSTORE.isEmpty()){ //Now load the info - bool ok = false; - XDGDesktop store = LXDG::loadDesktopFile(APPSTORE, ok); + XDGDesktop store(APPSTORE); + bool ok = store.isValid(); if(ok){ ui->tool_app_store->setIcon( LXDG::findIcon(store.icon, "") ); ui->tool_app_store->setText( store.name ); @@ -143,8 +143,8 @@ void UserWidget::UpdateAll(){ QString CONTROLPANEL = LOS::ControlPanelShortcut(); if(QFile::exists(CONTROLPANEL) && !CONTROLPANEL.isEmpty()){ //Now load the info - bool ok = false; - XDGDesktop cpan = LXDG::loadDesktopFile(CONTROLPANEL, ok); + XDGDesktop cpan(CONTROLPANEL); + bool ok = cpan.isValid(); if(ok){ ui->tool_controlpanel->setIcon( LXDG::findIcon(cpan.icon, "") ); } @@ -307,7 +307,7 @@ void UserWidget::updateAppCategories(){ void UserWidget::updateApps(){ if(ui->combo_app_cats->currentIndex() < 0){ return; } //no cat QString cat = ui->combo_app_cats->itemData( ui->combo_app_cats->currentIndex() ).toString(); - QList<XDGDesktop> items = sysapps->value(cat); + QList<XDGDesktop*> items = sysapps->value(cat); ClearScrollArea(ui->scroll_apps); for(int i=0; i<items.length(); i++){ UserItemWidget *it = new UserItemWidget(ui->scroll_apps->widget(), items[i]); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h index af9408dd..8b03c489 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h +++ b/src-qt5/core/lumina-desktop/panel-plugins/userbutton/UserWidget.h @@ -42,7 +42,7 @@ public slots: private: Ui::UserWidget *ui; - QHash<QString, QList<XDGDesktop> > *sysapps; + QHash<QString, QList<XDGDesktop*> > *sysapps; QDateTime lastUpdate, lastHomeUpdate; QStringList favs; QFileInfoList homefiles; diff --git a/src-qt5/core/lumina-open/LFileDialog.cpp b/src-qt5/core/lumina-open/LFileDialog.cpp index fbcf007f..a0fef17c 100644 --- a/src-qt5/core/lumina-open/LFileDialog.cpp +++ b/src-qt5/core/lumina-open/LFileDialog.cpp @@ -158,17 +158,21 @@ void LFileDialog::updateUI(){ void LFileDialog::generateAppList(bool shownetwork){ //Now load the preferred applications + XDGDesktopList applist; + applist.updateList(); PREFAPPS = getPreferredApplications(); + //qDebug() << "Preferred Apps:" << PREFAPPS; ui->combo_rec->clear(); //Now get the application mimetype for the file extension (if available) QStringList mimetypes = LXDG::findAppMimeForFile(filePath, true).split("::::"); //use all mimetypes + mimetypes.removeDuplicates(); //Now add all the detected applications - QHash< QString, QList<XDGDesktop> > hash = LXDG::sortDesktopCats( LXDG::systemDesktopFiles(false,true) ); + QHash< QString, QList<XDGDesktop*> > hash = LXDG::sortDesktopCats( applist.apps(false,true) ); QStringList cat = hash.keys(); cat.sort(); //sort alphabetically ui->combo_apps->clear(); for(int c=0; c<cat.length(); c++){ - QList<XDGDesktop> app = hash[cat[c]]; + QList<XDGDesktop*> app = hash[cat[c]]; if(app.length()<1){ continue; } if(ui->combo_apps->count() >1){ ui->combo_apps->insertSeparator(ui->combo_apps->count()); } ui->combo_apps->addItem(translateCat(cat[c])); @@ -176,17 +180,19 @@ void LFileDialog::generateAppList(bool shownetwork){ for(int a=0; a<app.length(); a++){ if(shownetwork && (cat[c].toLower()=="network" || cat[c].toLower()=="utility") ){ //Need to show preferred internet applications - look for ones that handle URL's - if(app[a].exec.contains("%u") || app[a].exec.contains("%U")){ - PREFAPPS << app[a].filePath; + if(app[a]->exec.contains("%u") || app[a]->exec.contains("%U")){ + //qDebug() << "Add to Preferred Apps:" << app[a]->filePath; + PREFAPPS << app[a]->filePath; } } - ui->combo_apps->addItem(LXDG::findIcon(app[a].icon, "application-x-desktop"), app[a].name, app[a].filePath); + ui->combo_apps->addItem(LXDG::findIcon(app[a]->icon, "application-x-desktop"), app[a]->name, app[a]->filePath); //Check to see if this app matches the mime type if(!mimetypes.isEmpty()){ - QStringList tmp = mimetypes; tmp << app[a].mimeList; + QStringList tmp = mimetypes; tmp << app[a]->mimeList; if(tmp.removeDuplicates() > 0 ){ // also put this app in the preferred list - PREFAPPS.append(app[a].filePath); + //qDebug() << "Mimetype match:" << mimetypes << app[a]->mimeList; + PREFAPPS.append(app[a]->filePath); //If this is the first preferred app found - select this app initially if(ui->combo_apps->currentIndex()<=0){ ui->combo_apps->setCurrentIndex(ui->combo_apps->count()-1); } } @@ -197,9 +203,8 @@ void LFileDialog::generateAppList(bool shownetwork){ //Now add all the preferred applications PREFAPPS.removeDuplicates(); for(int i=0; i<PREFAPPS.length(); i++){ - bool ok = false; - XDGDesktop dFile = LXDG::loadDesktopFile(PREFAPPS[i], ok); - if( LXDG::checkValidity(dFile) && ok ){ + XDGDesktop dFile(PREFAPPS[i]); + if( dFile.isValid() ){ ui->combo_rec->addItem( LXDG::findIcon(dFile.icon, "application-x-desktop"), dFile.name); if(i==0){ ui->combo_rec->setCurrentIndex(0); } //make sure the first item is selected }else{ @@ -242,19 +247,17 @@ void LFileDialog::on_tool_ok_clicked(){ appExec = ui->line_bin->text(); }else if(ui->radio_rec->isChecked()){ //application selected - bool ok = false; - XDGDesktop app = LXDG::loadDesktopFile(PREFAPPS[ui->combo_rec->currentIndex()], ok); + XDGDesktop app(PREFAPPS[ui->combo_rec->currentIndex()]); //Set the output variables - appExec = LXDG::getDesktopExec(app); + appExec = app.getDesktopExec(); appPath = app.path; appFile = app.filePath; setPreferredApplication(app.filePath); //bump this to the top of the preferred list for next time }else{ //application selected - bool ok = false; - XDGDesktop app = LXDG::loadDesktopFile(ui->combo_apps->currentData().toString(), ok); + XDGDesktop app(ui->combo_apps->currentData().toString()); //Set the output variables - appExec = LXDG::getDesktopExec(app); + appExec = app.getDesktopExec(); appPath = app.path; appFile = app.filePath; setPreferredApplication(app.filePath); //save this app to this extension as a recommendation diff --git a/src-qt5/core/lumina-open/main.cpp b/src-qt5/core/lumina-open/main.cpp index 756bef25..68d2575b 100644 --- a/src-qt5/core/lumina-open/main.cpp +++ b/src-qt5/core/lumina-open/main.cpp @@ -80,17 +80,19 @@ void showOSD(int argc, char **argv, QString message){ } void LaunchAutoStart(){ - QList<XDGDesktop> xdgapps = LXDG::findAutoStartFiles(); + QList<XDGDesktop*> xdgapps = LXDG::findAutoStartFiles(); for(int i=0; i<xdgapps.length(); i++){ //Generate command and clean up any stray "Exec" field codes (should not be any here) - QString cmd = LXDG::getDesktopExec(xdgapps[i]); + QString cmd = xdgapps[i]->getDesktopExec(); if(cmd.contains("%")){cmd = cmd.remove("%U").remove("%u").remove("%F").remove("%f").remove("%i").remove("%c").remove("%k").simplified(); } //Now run the command if(!cmd.isEmpty()){ - qDebug() << " - Auto-Starting File:" << xdgapps[i].filePath; + qDebug() << " - Auto-Starting File:" << xdgapps[i]->filePath; QProcess::startDetached(cmd); } } + //make sure we clean up all the xdgapps structures + for(int i=0; i<xdgapps.length(); i++){ xdgapps[i]->deleteLater(); } } QString cmdFromUser(int argc, char **argv, QString inFile, QString extension, QString& path, bool showDLG=false){ @@ -109,11 +111,10 @@ QString cmdFromUser(int argc, char **argv, QString inFile, QString extension, QS }else{ defApp = LFileDialog::getDefaultApp(extension); } //qDebug() << "extension:" << extension << "defApp:" << defApp; if( !defApp.isEmpty() && !showDLG ){ - bool ok = false; if(defApp.endsWith(".desktop")){ - XDGDesktop DF = LXDG::loadDesktopFile(defApp, ok); - if(ok){ - QString exec = LXDG::getDesktopExec(DF); + XDGDesktop DF(defApp); + if(DF.isValid()){ + QString exec = DF.getDesktopExec(); if(!exec.isEmpty()){ qDebug() << "[lumina-open] Using default application:" << DF.name << "File:" << inFile; if(!DF.path.isEmpty()){ path = DF.path; } @@ -258,15 +259,14 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat QString cmd; bool useInputFile = false; if(extension=="desktop" && !showDLG){ - bool ok = false; - XDGDesktop DF = LXDG::loadDesktopFile(inFile, ok); - if(!ok){ + XDGDesktop DF(inFile); + if(!DF.isValid()){ ShowErrorDialog( argc, argv, QString(QObject::tr("File could not be opened: %1")).arg(inFile) ); } switch(DF.type){ case XDGDesktop::APP: if(!DF.exec.isEmpty()){ - cmd = LXDG::getDesktopExec(DF,ActionID); + cmd = DF.getDesktopExec(ActionID); if(!DF.path.isEmpty()){ path = DF.path; } watch = DF.startupNotify || !DF.filePath.contains("/xdg/autostart/"); }else{ diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index 56b72a3c..2656b855 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -241,27 +241,27 @@ void MainUI::on_push_save_clicked(){ INFO.setFile(filePath); INFO.XDG()->filePath = filePath; } - XDGDesktop XDG = *INFO.XDG(); + XDGDesktop *XDG = INFO.XDG(); //Now change the structure - XDG.name = ui->line_xdg_name->text(); - XDG.genericName = ui->line_xdg_name->text().toLower(); - XDG.comment = ui->line_xdg_comment->text(); - XDG.icon = ui->push_xdg_getIcon->whatsThis(); + XDG->name = ui->line_xdg_name->text(); + XDG->genericName = ui->line_xdg_name->text().toLower(); + XDG->comment = ui->line_xdg_comment->text(); + XDG->icon = ui->push_xdg_getIcon->whatsThis(); //Now do the type-specific fields - if(XDG.type==XDGDesktop::APP){ - XDG.exec = ui->line_xdg_command->text(); - XDG.tryexec = ui->line_xdg_command->text().section(" ",0,0); //use the first word/binary for the existance check - XDG.path = ui->line_xdg_wdir->text(); //working dir/path - XDG.useTerminal = ui->check_xdg_useTerminal->isChecked(); - XDG.startupNotify = ui->check_xdg_startupNotify->isChecked(); - }else if(XDG.type==XDGDesktop::LINK){ - XDG.url = ui->line_xdg_wdir->text(); //we re-used this field + if(XDG->type == XDGDesktop::APP){ + XDG->exec = ui->line_xdg_command->text(); + XDG->tryexec = ui->line_xdg_command->text().section(" ",0,0); //use the first word/binary for the existance check + XDG->path = ui->line_xdg_wdir->text(); //working dir/path + XDG->useTerminal = ui->check_xdg_useTerminal->isChecked(); + XDG->startupNotify = ui->check_xdg_startupNotify->isChecked(); + }else if(XDG->type==XDGDesktop::LINK){ + XDG->url = ui->line_xdg_wdir->text(); //we re-used this field } //Clear any info which this utility does not support at the moment - XDG.actionList.clear(); - XDG.actions.clear(); + XDG->actionList.clear(); + XDG->actions.clear(); //Now save the structure to file - bool saved = LXDG::saveDesktopFile( XDG, true); //Try to merge the file/structure as necessary + bool saved = XDG->saveDesktopFile(true); //Try to merge the file/structure as necessary qDebug() << "File Saved:" << saved; ui->push_save->setEnabled( !saved ); if(saved){ diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index 65349d3e..e17ab439 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -35,12 +35,12 @@ public slots: private: Ui::MainUI *ui; bool canwrite; - bool terminate_thread; //flag for terminating the GetDirSize task + bool terminate_thread; //flag for terminating the GetDirSize task void ReloadAppIcon(); - void GetDirSize(const QString dirname) const; //function to get folder size + void GetDirSize(const QString dirname) const; //function to get folder size signals: - void folder_size_changed(quint64 size, quint64 files, quint64 folders, bool finished) const; //Signal for updating the folder size asynchronously + void folder_size_changed(quint64 size, quint64 files, quint64 folders, bool finished) const; //Signal for updating the folder size asynchronously private slots: //Initialization functions diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp index a23c9aec..b8b4da0b 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp @@ -94,7 +94,7 @@ void DirWidget::ChangeDir(QString dirpath){ } void DirWidget::setDirCompleter(QCompleter *comp){ - line_dir->setCompleter(comp); + //line_dir->setCompleter(comp); } QString DirWidget::id(){ |