aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core')
-rw-r--r--src-qt5/core/libLumina/LuminaOS-Debian.cpp2
-rw-r--r--src-qt5/core/libLumina/LuminaOS-DragonFly.cpp6
-rw-r--r--src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp7
-rw-r--r--src-qt5/core/libLumina/LuminaOS-Gentoo.cpp2
-rw-r--r--src-qt5/core/libLumina/LuminaOS-Linux.cpp2
-rw-r--r--src-qt5/core/libLumina/LuminaOS-NetBSD.cpp8
-rw-r--r--src-qt5/core/libLumina/LuminaOS-OpenBSD.cpp2
-rw-r--r--src-qt5/core/libLumina/LuminaOS-kFreeBSD.cpp2
-rw-r--r--src-qt5/core/libLumina/LuminaOS-template.cpp4
-rw-r--r--src-qt5/core/libLumina/LuminaOS.h3
-rw-r--r--src-qt5/core/libLumina/LuminaUtils.cpp77
-rw-r--r--src-qt5/core/libLumina/LuminaUtils.h5
-rw-r--r--src-qt5/core/libLumina/LuminaX11.h14
-rw-r--r--src-qt5/core/libLumina/LuminaXDG.cpp34
-rw-r--r--src-qt5/core/lumina-desktop/AppMenu.cpp2
-rw-r--r--src-qt5/core/lumina-desktop/LDesktop.cpp2
-rw-r--r--src-qt5/core/lumina-desktop/LWinInfo.cpp4
-rw-r--r--src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf52
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/NewDP.h3
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/calendar/CalendarPlugin.h1
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/desktop-plugins.pri11
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp363
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.h72
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.ui545
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp275
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h101
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/appmenu/LAppMenuPlugin.cpp3
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp3
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp8
-rw-r--r--src-qt5/core/lumina-open/LFileDialog.cpp8
-rw-r--r--src-qt5/core/lumina-open/main.cpp6
-rw-r--r--src-qt5/core/lumina-session/main.cpp4
32 files changed, 1565 insertions, 66 deletions
diff --git a/src-qt5/core/libLumina/LuminaOS-Debian.cpp b/src-qt5/core/libLumina/LuminaOS-Debian.cpp
index 75aad108..cb8e9cdd 100644
--- a/src-qt5/core/libLumina/LuminaOS-Debian.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-Debian.cpp
@@ -24,6 +24,8 @@ QString LOS::SysPrefix(){ return "/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return LOS::AppPrefix() + "/share/applications/synaptic.desktop"; } //graphical app/pkg manager
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){ return QStringList(); }
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
diff --git a/src-qt5/core/libLumina/LuminaOS-DragonFly.cpp b/src-qt5/core/libLumina/LuminaOS-DragonFly.cpp
index b98a36ee..919c88e5 100644
--- a/src-qt5/core/libLumina/LuminaOS-DragonFly.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-DragonFly.cpp
@@ -74,6 +74,12 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return ""; } //graphical app/pkg manager
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){
+ QStringList feeds;
+ feeds << "DragonFly BSD Feed::::http://www.dragonflybsd.org/recentchanges/index.rss";
+ return feeds;
+}
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
diff --git a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp
index fb405cb5..6f03767b 100644
--- a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp
@@ -26,6 +26,13 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return "/usr/local/share/applications/pccontrol.desktop"; } //system control panel
QString LOS::AppStoreShortcut(){ return "/usr/local/share/applications/appcafe.desktop"; } //graphical app/pkg manager
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){
+ QStringList feeds;
+ feeds << "FreeBSD News Feed::::https://www.freebsd.org/news/rss.xml";
+ feeds << "PC-BSD News Feed::::https://blog.pcbsd.org/?feed=rss2";
+ return feeds;
+ }
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
diff --git a/src-qt5/core/libLumina/LuminaOS-Gentoo.cpp b/src-qt5/core/libLumina/LuminaOS-Gentoo.cpp
index e3d5fe56..3a9c7320 100644
--- a/src-qt5/core/libLumina/LuminaOS-Gentoo.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-Gentoo.cpp
@@ -24,6 +24,8 @@ QString LOS::SysPrefix(){ return "/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return LOS::AppPrefix() + "/share/applications/porthole.desktop"; } //graphical app/pkg manager
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){ return QStringList(); }
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
diff --git a/src-qt5/core/libLumina/LuminaOS-Linux.cpp b/src-qt5/core/libLumina/LuminaOS-Linux.cpp
index 5939c9d1..c40cbd60 100644
--- a/src-qt5/core/libLumina/LuminaOS-Linux.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-Linux.cpp
@@ -24,6 +24,8 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return ""; } //graphical app/pkg manager
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){ return QStringList(); }
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
diff --git a/src-qt5/core/libLumina/LuminaOS-NetBSD.cpp b/src-qt5/core/libLumina/LuminaOS-NetBSD.cpp
index 866ccc5c..e1152527 100644
--- a/src-qt5/core/libLumina/LuminaOS-NetBSD.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-NetBSD.cpp
@@ -20,7 +20,13 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return ""; } //graphical app/pkg manager
-
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){
+ QStringList feeds;
+ feeds << "NetBSD News::::http://www.netbsd.org/changes/rss-netbsd.xml";
+ return feeds;
+}
+
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
//Returns: QStringList[<type>::::<filesystem>::::<path>]
diff --git a/src-qt5/core/libLumina/LuminaOS-OpenBSD.cpp b/src-qt5/core/libLumina/LuminaOS-OpenBSD.cpp
index c0fdafd4..30a02078 100644
--- a/src-qt5/core/libLumina/LuminaOS-OpenBSD.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-OpenBSD.cpp
@@ -23,6 +23,8 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return ""; } //graphical app/pkg manager
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){ return QStringList(); }
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
diff --git a/src-qt5/core/libLumina/LuminaOS-kFreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-kFreeBSD.cpp
index 4fe62686..8414db1a 100644
--- a/src-qt5/core/libLumina/LuminaOS-kFreeBSD.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-kFreeBSD.cpp
@@ -28,6 +28,8 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return ""; } //graphical app/pkg manager
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){ return QStringList(); }
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
diff --git a/src-qt5/core/libLumina/LuminaOS-template.cpp b/src-qt5/core/libLumina/LuminaOS-template.cpp
index 5969bf3a..7aea0edd 100644
--- a/src-qt5/core/libLumina/LuminaOS-template.cpp
+++ b/src-qt5/core/libLumina/LuminaOS-template.cpp
@@ -20,7 +20,9 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system
//OS-specific application shortcuts (*.desktop files)
QString LOS::ControlPanelShortcut(){ return ""; } //system control panel
QString LOS::AppStoreShortcut(){ return ""; } //graphical app/pkg manager
-
+//OS-specific RSS feeds (Format: QStringList[ <name>::::<url> ]; )
+QStringList LOS::RSSFeeds(){ return QStringList(); }
+
// ==== ExternalDevicePaths() ====
QStringList LOS::ExternalDevicePaths(){
//Returns: QStringList[<type>::::<filesystem>::::<path>]
diff --git a/src-qt5/core/libLumina/LuminaOS.h b/src-qt5/core/libLumina/LuminaOS.h
index c305277a..a18f2909 100644
--- a/src-qt5/core/libLumina/LuminaOS.h
+++ b/src-qt5/core/libLumina/LuminaOS.h
@@ -34,6 +34,9 @@ public:
static QString ControlPanelShortcut();
static QString AppStoreShortcut();
+ //OS-specific RSS feeds
+ static QStringList RSSFeeds(); //Return Format: QStringList[ <name>::::<url> ];
+
//Scan for mounted external devices
static QStringList ExternalDevicePaths(); //Returns: QStringList[<type>::::<filesystem>::::<path>]
//Note: <type> = [USB, HDRIVE, DVD, SDCARD, UNKNOWN]
diff --git a/src-qt5/core/libLumina/LuminaUtils.cpp b/src-qt5/core/libLumina/LuminaUtils.cpp
index 12dcf0be..4911b9fa 100644
--- a/src-qt5/core/libLumina/LuminaUtils.cpp
+++ b/src-qt5/core/libLumina/LuminaUtils.cpp
@@ -211,6 +211,23 @@ QString LUtils::PathToAbsolute(QString path){
}
return path;
}
+QString LUtils::AppToAbsolute(QString path){
+ if(path.startsWith("/") || QFile::exists(path)){ return path; }
+ if(path.endsWith(".desktop")){
+ //Look in the XDG dirs
+ QStringList dirs = LXDG::systemApplicationDirs();
+ for(int i=0; i<dirs.length(); i++){
+ if(QFile::exists(dirs[i]+"/"+path)){ return (dirs[i]+"/"+path); }
+ }
+ }else{
+ //Look on $PATH for the binary
+ QStringList paths = QString(getenv("PATH")).split(":");
+ for(int i=0; i<paths.length(); i++){
+ if(QFile::exists(paths[i]+"/"+path)){ return (paths[i]+"/"+path); }
+ }
+ }
+ return path;
+}
QStringList LUtils::imageExtensions(bool wildcards){
//Note that all the image extensions are lowercase!!
@@ -472,6 +489,7 @@ QStringList LUtils::listFavorites(){
if(lastRead.isNull() || lastRead<QFileInfo(QDir::homePath()+"/.lumina/favorites/fav.list").lastModified()){
fav = LUtils::readFile(QDir::homePath()+"/.lumina/favorites/fav.list");
fav.removeAll(""); //remove any empty lines
+ fav.removeDuplicates();
lastRead = cur;
if(fav.isEmpty()){
//Make sure the favorites dir exists, and create it if necessary
@@ -484,6 +502,7 @@ QStringList LUtils::listFavorites(){
}
bool LUtils::saveFavorites(QStringList list){
+ list.removeDuplicates();
bool ok = LUtils::writeFile(QDir::homePath()+"/.lumina/favorites/fav.list", list, true);
if(ok){ fav = list; } //also save internally in case of rapid write/read of the file
return ok;
@@ -576,7 +595,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){
}
}
//Now setup the default "desktopsettings.conf" and "sessionsettings.conf" files
- QStringList deskset, sesset, lopenset;
+ QStringList deskset, sesset;//, lopenset;
// -- SESSION SETTINGS --
QStringList tmp = sysDefaults.filter("session_");
@@ -593,38 +612,71 @@ void LUtils::LoadSystemDefaults(bool skipOS){
if(var.contains(".")){ var.replace(".","_"); }
//Now parse the variable and put the value in the proper file
+ if(var.contains("_default_")){ val = AppToAbsolute(val); } //got an application/binary
//Special handling for values which need to exist first
if(var.endsWith("_ifexists") ){
var = var.remove("_ifexists"); //remove this flag from the variable
//Check if the value exists (absolute path only)
if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist
}
+
//Parse/save the value
- QString loset, sset; //temporary strings
+ QString sset; //temporary strings
if(var=="session_enablenumlock"){ sset = "EnableNumlock="+ istrue; }
else if(var=="session_playloginaudio"){ sset = "PlayStartupAudio="+istrue; }
else if(var=="session_playlogoutaudio"){ sset = "PlayLogoutAudio="+istrue; }
- else if(var=="session_default_terminal"){ sset = "default-terminal="+val; }
- else if(var=="session_default_filemanager"){
- sset = "default-filemanager="+val;
- loset = "directory="+val;
+ else if(var=="session_default_terminal"){
+ LXDG::setDefaultAppForMime("application/terminal", val);
+ //sset = "default-terminal="+val;
+ }else if(var=="session_default_filemanager"){
+ LXDG::setDefaultAppForMime("inode/directory", val);
+ //sset = "default-filemanager="+val;
+ //loset = "directory="+val;
+ }else if(var=="session_default_webbrowser"){
+ //loset = "webbrowser="+val;
+ LXDG::setDefaultAppForMime("x-scheme-handler/http", val);
+ LXDG::setDefaultAppForMime("x-scheme-handler/https", val);
+ }else if(var=="session_default_email"){
+ LXDG::setDefaultAppForMime("application/email",val);
+ //loset = "email="+val;
}
- else if(var=="session_default_webbrowser"){ loset = "webbrowser="+val; }
- else if(var=="session_default_email"){ loset = "email="+val; }
//Put the line into the file (overwriting any previous assignment as necessary)
- if(!loset.isEmpty()){
+ /*if(!loset.isEmpty()){
int index = lopenset.indexOf(QRegExp(loset.section("=",0,0)+"=*", Qt::CaseSensitive, QRegExp::Wildcard));
qDebug() << "loset line:" << loset << index << lopenset;
if(index<0){ lopenset << loset; } //new line
else{ lopenset[index] = loset; } //overwrite the other line
- }
+ }*/
if(!sset.isEmpty()){
int index = sesset.indexOf(QRegExp(sset.section("=",0,0)+"=*", Qt::CaseSensitive, QRegExp::Wildcard));
if(index<0){ sesset << sset; } //new line
else{ sesset[index] = sset; } //overwrite the other line
}
}
- if(!lopenset.isEmpty()){ lopenset.prepend("[default]"); } //the session options exist within this set
+ //if(!lopenset.isEmpty()){ lopenset.prepend("[default]"); } //the session options exist within this set
+
+ // -- MIMETYPE DEFAULTS --
+ tmp = sysDefaults.filter("mime_default_");
+ for(int i=0; i<tmp.length(); i++){
+ if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; }
+ QString var = tmp[i].section("=",0,0).toLower().simplified();
+ QString val = tmp[i].section("=",1,1).section("#",0,0).simplified();
+ if(val.isEmpty()){ continue; }
+ QString istrue = (val.toLower()=="true") ? "true": "false";
+ //Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while
+ if(var.contains(".")){ var.replace(".","_"); }
+ //Now parse the variable and put the value in the proper file
+ val = AppToAbsolute(val);
+ //Special handling for values which need to exist first
+ if(var.endsWith("_ifexists") ){
+ var = var.remove("_ifexists"); //remove this flag from the variable
+ //Check if the value exists (absolute path only)
+ if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist
+ }
+ //Now turn this variable into the mimetype only
+ var = var.section("_default_",1,-1);
+ LXDG::setDefaultAppForMime(var, val);
+ }
// -- DESKTOP SETTINGS --
//(only works for the primary desktop at the moment)
@@ -710,6 +762,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){
if(var.contains(".")){ var.replace(".","_"); }
//Now parse the variable and put the value in the proper file
qDebug() << "Favorite entry:" << var << val;
+ val = AppToAbsolute(val); //turn any relative files into absolute
if(var=="favorites_add_ifexists" && QFile::exists(val)){ qDebug() << " - Exists/Adding:"; LUtils::addFavorite(val); }
else if(var=="favorites_add"){ qDebug() << " - Adding:"; LUtils::addFavorite(val); }
else if(var=="favorites_remove"){ qDebug() << " - Removing:"; LUtils::removeFavorite(val); }
@@ -780,7 +833,7 @@ void LUtils::LoadSystemDefaults(bool skipOS){
if(setTheme){ LTHEME::setCurrentSettings( themesettings[0], themesettings[1], themesettings[2], themesettings[3], themesettings[4]); }
LUtils::writeFile(setdir+"/sessionsettings.conf", sesset, true);
LUtils::writeFile(setdir+"/desktopsettings.conf", deskset, true);
- LUtils::writeFile(setdir+"/lumina-open.conf", lopenset, true);
+ //LUtils::writeFile(setdir+"/lumina-open.conf", lopenset, true);
}
bool LUtils::checkUserFiles(QString lastversion){
diff --git a/src-qt5/core/libLumina/LuminaUtils.h b/src-qt5/core/libLumina/LuminaUtils.h
index 32109244..e07363ca 100644
--- a/src-qt5/core/libLumina/LuminaUtils.h
+++ b/src-qt5/core/libLumina/LuminaUtils.h
@@ -54,8 +54,9 @@ public:
static QStringList listSubDirectories(QString dir, bool recursive = true);
//Convert an input file/dir path to an absolute file path
- static QString PathToAbsolute(QString path);
-
+ static QString PathToAbsolute(QString path); //This is primarily for CLI usage (relative paths)
+ static QString AppToAbsolute(QString path); //This is for looking up a binary/ *.desktop path
+
//Get the list of all file extensions which Qt can read (lowercase)
static QStringList imageExtensions(bool wildcards = false);
diff --git a/src-qt5/core/libLumina/LuminaX11.h b/src-qt5/core/libLumina/LuminaX11.h
index b0a5d588..b7310abd 100644
--- a/src-qt5/core/libLumina/LuminaX11.h
+++ b/src-qt5/core/libLumina/LuminaX11.h
@@ -69,6 +69,14 @@ public:
}
};
+//simple data structure for passing around the XRANDR information
+/*class monitor_info{
+public:
+ QString ID;
+ bool active;
+ QRect geometry;
+};*/
+
//XCB Library replacement for LX11 (Qt5 uses XCB instead of XLib)
class LXCB{
@@ -393,6 +401,12 @@ public:
WId WM_Get_CM_Owner();
void WM_Set_CM_Owner(WId win);
+ //============
+ // RANDR Functions (directly reading changing monitor outputs)
+ //============
+ //QList<monitor_info> RR_List_Monitors();
+ //void RR_Set_Monitors(QList<monitor_info> monitors);
+
private:
QList<xcb_atom_t> ATOMS;
QStringList atoms;
diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp
index bfca4f71..8f6ada37 100644
--- a/src-qt5/core/libLumina/LuminaXDG.cpp
+++ b/src-qt5/core/libLumina/LuminaXDG.cpp
@@ -854,20 +854,27 @@ QString LXDG::findDefaultAppForMime(QString mime){
//Now go through all the files in order of priority until a default is found
QString cdefault;
- QStringList white; //lists to keep track of during the search (black unused at the moment)
for(int i=0; i<dirs.length() && cdefault.isEmpty(); i++){
if(!QFile::exists(dirs[i])){ continue; }
QStringList info = LUtils::readFile(dirs[i]);
if(info.isEmpty()){ continue; }
- QString workdir = dirs[i].section("/",0,-1); //just the directory
+ QStringList white; //lists to keep track of during the search (black unused at the moment)
+ QString workdir = dirs[i].section("/",0,-2); //just the directory
+ // qDebug() << "Check File:" << mime << dirs[i] << workdir;
int def = info.indexOf("[Default Applications]"); //find this line to start on
if(def>=0){
for(int d=def+1; d<info.length(); d++){
+ //qDebug() << "Check Line:" << info[d];
if(info[d].startsWith("[")){ break; } //starting a new section now - finished with defaults
- if(info[d].contains(mime+"=")){
- white << info[d].section("=",1,50).split(";");
- break;
- }
+ if(info[d].contains(mime+"=") ){
+ white = info[d].section("=",1,-1).split(";") + white; //exact mime match - put at front of list
+ break; //already found exact match
+ }else if(info[d].contains("*") && info[d].contains("=") ){
+ QRegExp rg(info[d].section("=",0,0), Qt::CaseSensitive, QRegExp::WildcardUnix);
+ if(rg.exactMatch(mime)){
+ white << info[d].section("=",1,-1).split(";"); //partial mime match - put at end of list
+ }
+ }
}
}
// Now check for any white-listed files in this work dir
@@ -884,19 +891,10 @@ QString LXDG::findDefaultAppForMime(QString mime){
else if( QFile::exists(workdir+"/"+white[w]) ){ cdefault=workdir+"/"+white[w]; break; }
//Now go through the XDG DATA dirs and see if the file is in there
else{
- QStringList xdirs;
- xdirs << QString(getenv("XDG_DATA_HOME"))+"/applications/";
- tmp = QString(getenv("XDG_DATA_DIRS")).split(":");
- for(int t=0; t<tmp.length(); t++){ xdirs << tmp[t]+"/applications/"; }
- //Now scan these dirs
- bool found = false;
- //qDebug() << "Scan dirs:" << white[w] << xdirs;
- for(int x=0; x<xdirs.length() && !found; x++){
- if(QFile::exists(xdirs[x]+white[w])){cdefault=xdirs[x]+white[w]; found = true; }
- }
- if(found){ break; }
+ white[w] = LUtils::AppToAbsolute(white[w]);
+ if(QFile::exists(white[w])){ cdefault = white[w]; }
}
- }
+ }
/* WRITTEN BUT UNUSED CODE FOR MIMETYPE ASSOCIATIONS
//Skip using this because it is simply an alternate/unsupported standard that conflicts with
the current mimetype database standards. It is better/faster to parse 1 or 2 database glob files
diff --git a/src-qt5/core/lumina-desktop/AppMenu.cpp b/src-qt5/core/lumina-desktop/AppMenu.cpp
index 14af988a..0b8aeace 100644
--- a/src-qt5/core/lumina-desktop/AppMenu.cpp
+++ b/src-qt5/core/lumina-desktop/AppMenu.cpp
@@ -32,6 +32,7 @@ QHash<QString, QList<XDGDesktop> >* AppMenu::currentAppHash(){
// PRIVATE
//===========
void AppMenu::updateAppList(){
+ watcher->removePaths(watcher->directories());
//Make sure the title/icon are updated as well (in case of locale/icon change)
this->setTitle(tr("Applications"));
this->setIcon( LXDG::findIcon("system-run","") );
@@ -111,6 +112,7 @@ void AppMenu::updateAppList(){
}
this->addMenu(menu);
}
+ watcher->addPaths(LXDG::systemApplicationDirs());
emit AppMenuUpdated();
}
diff --git a/src-qt5/core/lumina-desktop/LDesktop.cpp b/src-qt5/core/lumina-desktop/LDesktop.cpp
index 113b7efc..11d99581 100644
--- a/src-qt5/core/lumina-desktop/LDesktop.cpp
+++ b/src-qt5/core/lumina-desktop/LDesktop.cpp
@@ -104,7 +104,7 @@ void LDesktop::SystemLogout(){
void LDesktop::SystemTerminal(){
LSession::handle()->sessionSettings()->sync(); //make sure it is up to date
- QString term = LSession::handle()->sessionSettings()->value("default-terminal","xterm").toString();
+ QString term = LXDG::findDefaultAppForMime("application/terminal"); //LSession::handle()->sessionSettings()->value("default-terminal","xterm").toString();
if(term.endsWith(".desktop")){ term = "lumina-open \""+term+"\""; }
LSession::LaunchApplication(term);
}
diff --git a/src-qt5/core/lumina-desktop/LWinInfo.cpp b/src-qt5/core/lumina-desktop/LWinInfo.cpp
index 3ff0c2d7..6a6cea0b 100644
--- a/src-qt5/core/lumina-desktop/LWinInfo.cpp
+++ b/src-qt5/core/lumina-desktop/LWinInfo.cpp
@@ -21,7 +21,7 @@ QString LWinInfo::text(){
if(nm.simplified().isEmpty()){ nm = LSession::handle()->XCB->OldWindowIconName(window); }
if(nm.simplified().isEmpty()){ nm = LSession::handle()->XCB->OldWindowName(window); }
//Make sure that the text is a reasonable size (40 char limit)
- if(nm.length()>40){ nm = nm.left(40)+"..."; }
+ //if(nm.length()>40){ nm = nm.left(40)+"..."; }
return nm;
}
@@ -45,4 +45,4 @@ LXCB::WINDOWVISIBILITY LWinInfo::status(bool update){
cstate = LSession::handle()->XCB->WindowState(window);
}
return cstate;
-} \ No newline at end of file
+}
diff --git a/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf b/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf
index 2c973adb..251e8309 100644
--- a/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf
+++ b/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf
@@ -6,12 +6,12 @@
# system corresponding to the XDG mime-type specifications for default applications
# See Here for specifications: http://www.freedesktop.org/wiki/Specifications/mime-apps-spec/
-# Possible Desktop Plugins (Lumina version 0.8.7):
-# calendar, applauncher[::absolute path to *.desktop file], desktopview, notepad, audioplayer
-# Possible Panel Plugins (Lumina version 0.8.7):
+# Possible Desktop Plugins (Lumina version 0.9.1):
+# calendar, applauncher[::absolute path to *.desktop file], desktopview, notepad, audioplayer, rssreader
+# Possible Panel Plugins (Lumina version 0.9.1):
# userbutton, desktopbar, spacer, desktopswitcher, battery, clock, systemdashboard, systemstart
# taskmanager[-nogroups], systemtray, homebutton, appmenu, applauncher[::absolute path to *.desktop file]
-# Possible Menu Plugins (Lumina version 0.8.7):
+# Possible Menu Plugins (Lumina version 0.9.1):
# terminal, filemanager, applications, line, settings, windowlist, app::<absolute path to *.desktop file>
#GENERAL SESSION SETTINGS
@@ -22,32 +22,50 @@ session_playlogoutaudio=true #[true/false] Play the audio chimes on log out
# DEFAULT UTILITIES
# Provide the full path to *.desktop file, or a binary name which exists on PATH
# *.desktop files provide better support for input formats, and are recommended
-#session_default_terminal=xterm
-#session_default_filemanager=lumina-fm
-#session_default_webbrowser=/usr/local/share/applications/firefox.desktop
-#session_default_email=/usr/local/share/applications/thunderbird.desktop
+#Note: the last "ifexists" entry has the highest priority for each session utility
+session_default_terminal_ifexists=xterm.desktop
+session_default_terminal_ifexists=lumina-terminal.desktop
+session_default_filemanager=lumina-fm.desktop
+session_default_webbrowser_ifexists=chromium-browser.desktop
+session_default_webbrowser_ifexists=firefox.desktop
+session_default_webbrowser_ifexists=qupzilla.desktop
+session_default_email_ifexists=trojita.desktop
+
+#DEFAULT UTILITIES FOR INDIVIDUAL MIME TYPES
+# Format: mime_default_<mimetype>[_ifexists]=<*.desktop file>
+mime_default_text/*_ifexists=lumina-textedit.desktop
+mime_default_audio/*_ifexists=vlc.desktop
+mime_default_video/*_ifexists=vlc.desktop
+mime_default_application/zip_ifexists=peazip.desktop
+mime_default_application/x-compressed-tar_ifexists=peazip.desktop
+mime_default_application/x-bzip-compressed-tar_ifexists=peazip.desktop
+mime_default_application/x-lrzip-compressed-tar_ifexists=peazip.desktop
+mime_default_application/x-lzma-compressed-tar_ifexists=peazip.desktop
+mime_default_application/x-xz-compressed-tar_ifexists=peazip.desktop
+mime_default_application/x-tar_ifexists=peazip.desktop
+
#THEME SETTINGS
-#theme.themefile=<file path> #Absolute path to the theme template file to use (disable for Lumina-Default)
+theme_themefile=Glass #Name of the theme to use (disable for Lumina-Default)
theme_colorfile=Black #Name of the color spec file to use for theming
theme_iconset=oxygen #Name of the icon theme to use
theme_font=Arial #Name of the font family to use
theme_fontsize=10pt #Default size of the fonts to use on the desktop (can also use a percentage of the screen height (<number>%) )
#DESKTOP SETTINGS (used for the primary screen in multi-screen setups)
-desktop_visiblepanels=1 #[0/1/2] The number of panels visible by default
+desktop_visiblepanels=1 #[0 - 12] The number of panels visible by default
#desktop.backgroundfiles= #list of absolute file paths for image files (disable for Lumina default)
desktop_backgroundrotateminutes=5 #[positive integer] number of minutes between background rotations (if multiple files)
-desktop_plugins= #list of plugins to be shown on the desktop by default
+desktop_plugins=rssreader #list of plugins to be shown on the desktop by default
desktop_generate_icons=true #[true/false] Auto-generate launchers for ~/Desktop items
#PANEL SETTINGS (preface with panel1.<setting> or panel2.<setting>, depending on the number of panels you have visible by default)
-panel1_location=top #[top/bottom/left/right] Screen edge the panel should be on
+panel1_location=bottom #[top/bottom/left/right] Screen edge the panel should be on
panel1_pixelsize=4%H #number of pixels wide/high the panel should be (or <number>%[W/H] for a percentage of the screen width/height)
panel1_autohide=false #[true/false] Have the panel become visible on mouse-over
panel1_plugins=systemstart, taskmanager-nogroups, spacer, systemtray, clock #list of plugins for the panel
panel1_pinlocation=center #[left/center/right] Note:[left/right] corresponds to [top/bottom] for vertical panels
-panel1_edgepercent=90 #[1->100] percentage of the screen edge to use
+panel1_edgepercent=99 #[1->100] percentage of the screen edge to use
#MENU SETTINGS (right-click menu)
menu_plugins=terminal, filemanager, applications, line, settings #list of menu plugins to show
@@ -56,3 +74,11 @@ menu_plugins=terminal, filemanager, applications, line, settings #list of menu p
#favorites_add=<file/dir path> #Create a favorites entry for this file/dir
#favorites_remove=<file/dir path> #Remove a favorites entry for this file/dir
#favorites_add_ifexists=<file/dir path> #Create a favorites entry for this file/dir if the file/dir exists
+favorites_add_ifexists=firefox.desktop
+favorites_add_ifexists=chromium-browser.desktop
+favorites_add_ifexists=qupzilla.desktop
+favorites_add_ifexists=thunderbird.desktop
+favorites_add_ifexists=trojita.desktop
+favorites_add_ifexists=smplayer.desktop
+favorites_add_ifexists=vlc.desktop
+favorites_add_ifexists=pithos.desktop
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/NewDP.h b/src-qt5/core/lumina-desktop/desktop-plugins/NewDP.h
index a12341bb..e28b8c61 100644
--- a/src-qt5/core/lumina-desktop/desktop-plugins/NewDP.h
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/NewDP.h
@@ -22,6 +22,7 @@
#include "systemmonitor/MonitorWidget.h"
//#include "quickcontainer/QuickDPlugin.h"
//#include "messagecenter/MessageCenter.h"
+#include "rssreader/RSSFeedPlugin.h"
class NewDP{
public:
@@ -48,6 +49,8 @@ public:
//plug = new MessageCenterPlugin(parent, plugin);
//}else if(plugin.section("---",0,0).startsWith("quick-") && LUtils::validQuickPlugin(plugin.section("---",0,0)) ){
//plug = new QuickDPlugin(parent, plugin);
+ }else if(plugin.section("---",0,0)=="rssreader"){
+ plug = new RSSFeedPlugin(parent, plugin);
}else{
qWarning() << "Invalid Desktop Plugin:"<<plugin << " -- Ignored";
}
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/calendar/CalendarPlugin.h b/src-qt5/core/lumina-desktop/desktop-plugins/calendar/CalendarPlugin.h
index b3a6a8d7..abb138f7 100644
--- a/src-qt5/core/lumina-desktop/desktop-plugins/calendar/CalendarPlugin.h
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/calendar/CalendarPlugin.h
@@ -31,6 +31,7 @@ public:
timer = new QTimer(this);
timer->setInterval(1800000); //30 minute refresh timer
timer->start();
+ connect(timer, SIGNAL(timeout()), this, SLOT(updateDate()) );
QTimer::singleShot(0,this, SLOT(updateDate()) );
connect(this, SIGNAL(PluginResized()), this, SLOT(UpdateCalendarSize()));
}
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/desktop-plugins.pri b/src-qt5/core/lumina-desktop/desktop-plugins/desktop-plugins.pri
index 5a631b52..8376316a 100644
--- a/src-qt5/core/lumina-desktop/desktop-plugins/desktop-plugins.pri
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/desktop-plugins.pri
@@ -2,7 +2,9 @@ SOURCES += $$PWD/applauncher/AppLauncherPlugin.cpp \
$$PWD/desktopview/DesktopViewPlugin.cpp \
$$PWD/notepad/NotepadPlugin.cpp \
$$PWD/audioplayer/PlayerWidget.cpp \
- $$PWD/systemmonitor/MonitorWidget.cpp
+ $$PWD/systemmonitor/MonitorWidget.cpp \
+ $$PWD/rssreader/RSSFeedPlugin.cpp \
+ $$PWD/rssreader/RSSObjects.cpp
# $$PWD/messagecenter/MessageCenter.cpp
HEADERS += $$PWD/calendar/CalendarPlugin.h \
@@ -11,9 +13,12 @@ HEADERS += $$PWD/calendar/CalendarPlugin.h \
$$PWD/desktopview/DesktopViewPlugin.h \
$$PWD/notepad/NotepadPlugin.h \
$$PWD/audioplayer/PlayerWidget.h \
- $$PWD/systemmonitor/MonitorWidget.h
+ $$PWD/systemmonitor/MonitorWidget.h \
+ $$PWD/rssreader/RSSFeedPlugin.h \
+ $$PWD/rssreader/RSSObjects.h
# $$PWD/quickcontainer/QuickDPlugin.h
# $$PWD/messagecenter/MessageCenter.h
FORMS += $$PWD/audioplayer/PlayerWidget.ui \
- $$PWD/systemmonitor/MonitorWidget.ui \ No newline at end of file
+ $$PWD/systemmonitor/MonitorWidget.ui \
+ $$PWD/rssreader/RSSFeedPlugin.ui
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp
new file mode 100644
index 00000000..23c1ca01
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp
@@ -0,0 +1,363 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RSSFeedPlugin.h"
+#include "ui_RSSFeedPlugin.h"
+
+#include <LuminaXDG.h>
+#include "LSession.h"
+#include <LuminaUtils.h>
+#include <QDir>
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QtConcurrent>
+
+RSSFeedPlugin::RSSFeedPlugin(QWidget* parent, QString ID) : LDPlugin(parent, ID), ui(new Ui::RSSFeedPlugin()){
+ ui->setupUi(this);
+ //Load the global settings
+ setprefix = "rssreader/"; //this structure/prefix should be used for *all* plugins of this type
+ RSS = new RSSReader(this, setprefix);
+
+ //Create the options menu
+ optionsMenu = new QMenu(this);
+ ui->tool_options->setMenu(optionsMenu);
+ presetMenu = new QMenu(this);
+ ui->tool_add_preset->setMenu(presetMenu);
+
+ //Setup any signal/slot connections
+ connect(ui->push_back1, SIGNAL(clicked()), this, SLOT(backToFeeds()) );
+ connect(ui->push_back2, SIGNAL(clicked()), this, SLOT(backToFeeds()) );
+ connect(ui->push_back3, SIGNAL(clicked()), this, SLOT(backToFeeds()) );
+ connect(ui->push_save_settings, SIGNAL(clicked()), this, SLOT(saveSettings()) );
+ connect(RSS, SIGNAL(rssChanged(QString)), this, SLOT(RSSItemChanged(QString)) );
+ connect(RSS, SIGNAL(newChannelsAvailable()), this, SLOT(UpdateFeedList()));
+ connect(ui->tool_gotosite, SIGNAL(clicked()), this, SLOT(openFeedPage()) );
+ connect(ui->push_rm_feed, SIGNAL(clicked()), this, SLOT(removeFeed()) );
+ connect(ui->push_add_url, SIGNAL(clicked()), this, SLOT(addNewFeed()) );
+ connect(ui->combo_feed, SIGNAL(currentIndexChanged(int)), this, SLOT(currentFeedChanged()) );
+
+ connect(presetMenu, SIGNAL(triggered(QAction*)), this, SLOT(loadPreset(QAction*)) );
+
+ updateOptionsMenu();
+ QTimer::singleShot(0,this, SLOT(ThemeChange()) );
+ //qDebug() << " - Done with init";
+ QStringList feeds;
+ if( !LSession::handle()->DesktopPluginSettings()->contains(setprefix+"currentfeeds") ){
+ //First-time run of the plugin - automatically load the default feeds
+ feeds = LOS::RSSFeeds();
+ for(int i=0; i<feeds.length(); i++){ feeds[i] = feeds[i].section("::::",1,-1); } //just need url right now
+ feeds << "http://lumina-desktop.org/?feed=rss2"; //Lumina Desktop blog feed
+ LSession::handle()->DesktopPluginSettings()->setValue(setprefix+"currentfeeds", feeds);
+ }else{
+ feeds = LSession::handle()->DesktopPluginSettings()->value(setprefix+"currentfeeds",QStringList()).toStringList();
+ }
+ RSS->addUrls(feeds);
+ backToFeeds(); //always load the first page
+}
+
+RSSFeedPlugin::~RSSFeedPlugin(){
+
+}
+
+//================
+// PRIVATE
+//================
+void RSSFeedPlugin::updateOptionsMenu(){
+ optionsMenu->clear();
+ optionsMenu->addAction(LXDG::findIcon("list-add",""), tr("Add RSS Feed"), this, SLOT(openFeedNew()) );
+ optionsMenu->addAction(LXDG::findIcon("help-about",""), tr("View Feed Details"), this, SLOT(openFeedInfo()) );
+ optionsMenu->addAction(LXDG::findIcon("configure",""), tr("Settings"), this, SLOT(openSettings()) );
+ optionsMenu->addSeparator();
+ optionsMenu->addAction(LXDG::findIcon("download",""), tr("Update Feeds Now"), this, SLOT(resyncFeeds()) );
+
+ presetMenu->clear();
+ QStringList feeds = LOS::RSSFeeds();
+ feeds << tr("Lumina Desktop RSS")+"::::http://lumina-desktop.org/?feed=rss2";
+ feeds.sort();
+ for(int i=0; i<feeds.length(); i++){
+ QAction *tmp = presetMenu->addAction(feeds[i].section("::::",0,0) );
+ tmp->setWhatsThis( feeds[i].section("::::",1,-1) );
+ }
+}
+
+void RSSFeedPlugin::checkFeedNotify(){
+ bool notify = false;
+ for(int i=0; i<ui->combo_feed->count() && !notify; i++){
+ if( !ui->combo_feed->itemData(i, Qt::WhatsThisRole).toString().isEmpty()){ notify = true; }
+ }
+ QString style;
+ if(notify){ style = "QComboBox{ background-color: rgba(255,0,0,120); }"; }
+ ui->combo_feed->setStyleSheet(style);
+}
+
+//Simplification functions for loading feed info onto widgets
+void RSSFeedPlugin::updateFeed(QString ID){
+ //Now clear/update the feed viewer (HTML)
+ ui->text_feed->clear();
+ if(ID.isEmpty()){ return; } //nothing to show
+
+ //Save the datetime this feed was read
+ LSession::handle()->DesktopPluginSettings()->setValue(setprefix+"feedReads/"+ID, QDateTime::currentDateTime() );
+ //Get the color to use for hyperlinks (need to specify in html)
+ QString color = ui->text_feed->palette().text().color().name(); //keep the hyperlinks the same color as the main text (different formatting still applies)
+ QString html;
+ RSSchannel data = RSS->dataForID(ID);
+ ui->label_lastupdate->setText( data.lastsync.toString(Qt::DefaultLocaleShortDate) );
+ // - generate the html
+ // html.append("<ul style=\"margin-left: 3px;\">\n");
+ for(int i=0; i<data.items.length(); i++){
+ //html.append("<li>");
+ html.append("<h4><a href=\""+data.items[i].link+"\" style=\"color: "+color+";\">"+data.items[i].title+"</a></h4>");
+ if(!data.items[i].pubdate.isNull() || !data.items[i].author.isEmpty()){
+ html.append("<i>(");
+ if(!data.items[i].pubdate.isNull()){ html.append(data.items[i].pubdate.toString(Qt::DefaultLocaleShortDate)); }
+ if(!data.items[i].author.isEmpty()){
+ if(!html.endsWith("(")){ html.append(", "); } //spacing between date/author
+ if(!data.items[i].author_email.isEmpty()){ html.append("<a href=\"mailto:"+data.items[i].author_email+"\" style=\"color: "+color+";\">"+data.items[i].author+"</a>"); }
+ else{ html.append(data.items[i].author); }
+ }
+ html.append(")</i><br>");
+ }
+ html.append(data.items[i].description);
+ //html.append("</li>\n");
+ if(i+1 < data.items.length()){ html.append("<br>"); }
+ }
+ //html.append("</ul>\n");
+ // - load that html into the viewer
+ ui->text_feed->setHtml(html);
+}
+
+void RSSFeedPlugin::updateFeedInfo(QString ID){
+ ui->page_feed_info->setWhatsThis(ID);
+ ui->text_feed_info->clear();
+ if(ID.isEmpty()){ return; }
+ //Get the color to use for hyperlinks (need to specify in html)
+ QString color = ui->text_feed->palette().text().color().name(); //keep the hyperlinks the same color as the main text (different formatting still applies)
+ QString html;
+ RSSchannel data = RSS->dataForID(ID);
+ // - generate the html
+ // <a href=\""+LINK+"\" style=\"color: "+color+";\">"+TEXT+"</a>
+ html.append( QString(tr("Feed URL: %1")).arg("<a href=\""+data.originalURL+"\" style=\"color: "+color+";\">"+data.originalURL+"</a>") +"<br><hr>");
+ html.append( QString(tr("Title: %1")).arg(data.title) +"<br>");
+ html.append( QString(tr("Description: %1")).arg(data.description) +"<br>");
+ html.append( QString(tr("Website: %1")).arg("<a href=\""+data.link+"\" style=\"color: "+color+";\">"+data.link+"</a>") +"<br><hr>");
+ if(!data.lastBuildDate.isNull()){ html.append( QString(tr("Last Build Date: %1")).arg(data.lastBuildDate.toString(Qt::DefaultLocaleShortDate)) +"<br>"); }
+ html.append( QString(tr("Last Sync: %1")).arg(data.lastsync.toString(Qt::DefaultLocaleShortDate)) +"<br>");
+ html.append( QString(tr("Next Sync: %1")).arg(data.nextsync.toString(Qt::DefaultLocaleShortDate)) +"<br>");
+ // - load that html into the viewer
+ ui->text_feed_info->setHtml(html);
+}
+
+//================
+// PRIVATE SLOTS
+//================
+void RSSFeedPlugin::loadIcons(){
+ ui->tool_options->setIcon( LXDG::findIcon("configure","") );
+ ui->tool_gotosite->setIcon( LXDG::findIcon("applications-internet","") );
+ ui->push_back1->setIcon( LXDG::findIcon("go-previous","") );
+ ui->push_back2->setIcon( LXDG::findIcon("go-previous","") );
+ ui->push_back3->setIcon( LXDG::findIcon("go-previous","") );
+ ui->push_rm_feed->setIcon( LXDG::findIcon("list-remove","") );
+ ui->push_add_url->setIcon( LXDG::findIcon("list-add","") );
+ ui->push_save_settings->setIcon( LXDG::findIcon("document-save","") );
+ ui->tool_add_preset->setIcon( LXDG::findIcon("bookmark-new-list","") );
+}
+
+//GUI slots
+// - Page management
+void RSSFeedPlugin::backToFeeds(){
+ ui->stackedWidget->setCurrentWidget(ui->page_feed);
+}
+
+void RSSFeedPlugin::openFeedInfo(){
+ QString ID = ui->combo_feed->currentData().toString();
+ if(ID.isEmpty()){ return; }
+ updateFeedInfo(ID);
+ ui->stackedWidget->setCurrentWidget(ui->page_feed_info);
+
+}
+
+void RSSFeedPlugin::openFeedNew(){
+ ui->line_new_url->setText("");
+ ui->stackedWidget->setCurrentWidget(ui->page_new_feed);
+}
+
+void RSSFeedPlugin::openSettings(){
+ //Sync the widget with the current settings
+ QSettings *set = LSession::handle()->DesktopPluginSettings();
+
+ ui->check_manual_sync->setChecked( set->value(setprefix+"manual_sync_only", false).toBool() );
+ int DI = set->value(setprefix+"default_interval_minutes", 60).toInt();
+ if(DI<1){ DI = 60; }
+ if( (DI%60) == 0 ){DI = DI/60; ui->combo_sync_units->setCurrentIndex(1); } //hourly setting
+ else{ ui->combo_sync_units->setCurrentIndex(1); } //minutes setting
+ ui->spin_synctime->setValue(DI);
+
+ //Now show the page
+ ui->stackedWidget->setCurrentWidget(ui->page_settings);
+}
+
+// - Feed Management
+void RSSFeedPlugin::addNewFeed(){
+ if(ui->line_new_url->text().isEmpty()){ return; } //nothing to add
+ //Validate the URL
+ QUrl url(ui->line_new_url->text());
+ if(!url.isValid()){
+ ui->line_new_url->setFocus();
+ return;
+ }
+ //Add the URL to the settings file for next login
+ QStringList feeds = LSession::handle()->DesktopPluginSettings()->value(setprefix+"currentfeeds",QStringList()).toStringList();
+ feeds << url.toString();
+ LSession::handle()->DesktopPluginSettings()->setValue(setprefix+"currentfeeds", feeds);
+
+ //Set this URL as the current selection
+ ui->combo_feed->setWhatsThis(url.toString()); //hidden field - will trigger an update in a moment
+ //Add the URL to the backend
+ RSS->addUrls(QStringList() << url.toString());
+ //UpdateFeedList(); //now re-load the feeds which are available
+
+ //Now go back to the main page
+ backToFeeds();
+}
+
+void RSSFeedPlugin::loadPreset(QAction *act){
+ ui->line_new_url->setText( act->whatsThis() );
+}
+
+void RSSFeedPlugin::removeFeed(){
+ QString ID = ui->page_feed_info->whatsThis();
+ if(ID.isEmpty()){ return; }
+ //Remove from the RSS feed object
+ RSSchannel info = RSS->dataForID(ID);
+ RSS->removeUrl(ID);
+ //Remove the URL from the settings file for next login
+ QStringList feeds = LSession::handle()->DesktopPluginSettings()->value(setprefix+"currentfeeds",QStringList()).toStringList();
+ feeds.removeAll(info.originalURL);
+ LSession::handle()->DesktopPluginSettings()->setValue(setprefix+"currentfeeds", feeds);
+ LSession::handle()->DesktopPluginSettings()->remove(setprefix+"feedReads/"+ID);
+ //Now go back to the main page
+ backToFeeds();
+}
+
+void RSSFeedPlugin::resyncFeeds(){
+ RSS->addUrls( LSession::handle()->DesktopPluginSettings()->value(setprefix+"currentfeeds",QStringList()).toStringList() );
+ RSS->syncNow();
+}
+
+// - Feed Interactions
+void RSSFeedPlugin::currentFeedChanged(){
+ QString ID = ui->combo_feed->currentData().toString();
+ //Remove the "unread" color/flag from the feed
+ ui->combo_feed->setItemData( ui->combo_feed->currentIndex(), QBrush(Qt::transparent) , Qt::BackgroundRole);
+ ui->combo_feed->setItemData( ui->combo_feed->currentIndex(), "", Qt::WhatsThisRole);
+ checkFeedNotify();
+ updateFeed(ID);
+}
+
+void RSSFeedPlugin::openFeedPage(){ //Open main website for feed
+ QString ID = ui->combo_feed->currentData().toString();
+ //Find the data associated with this feed
+ RSSchannel data = RSS->dataForID(ID);
+ QString url = data.link;
+ //qDebug() << "Open Feed Page:" << url;
+ //Now launch the browser
+ if(!url.isEmpty()){
+ LSession::LaunchApplication("lumina-open \""+url+"\"");
+ }
+}
+
+void RSSFeedPlugin::saveSettings(){
+ QSettings *set = LSession::handle()->DesktopPluginSettings();
+ set->setValue(setprefix+"manual_sync_only", ui->check_manual_sync->isChecked() );
+ int DI = ui->spin_synctime->value();
+ if(ui->combo_sync_units->currentIndex()==1){ DI = DI*60; } //convert from hours to minutes
+ set->setValue(setprefix+"default_interval_minutes", DI);
+ set->sync();
+
+ //Now go back to the feeds
+ backToFeeds();
+}
+
+//Feed Object interactions
+void RSSFeedPlugin::UpdateFeedList(){
+
+ QString activate = ui->combo_feed->whatsThis();
+ if(!activate.isEmpty()){ ui->combo_feed->setWhatsThis(""); }
+ if(activate.isEmpty()){ activate = ui->combo_feed->currentData().toString(); } // keep current item selected
+ //Now get/list all the available feeds
+ QStringList IDS = RSS->channels(); //this is pre-sorted by title of the feed
+ //qDebug() << "Update RSS Feed List:" << IDS << activate;
+ for(int i=0; i<IDS.length(); i++){
+ bool newitem = false;
+ if(ui->combo_feed->count()<=i){ newitem = true; }
+ else{
+ QString cid = ui->combo_feed->itemData(i).toString();
+ if(IDS[i]!=cid){
+ if(IDS.contains(cid)){ newitem = true; } //this item is just out of order
+ else{ ui->combo_feed->removeItem(i); } //item no longer is valid
+ }
+ }
+ if(newitem){
+ //Need to add a new item at this point in the menu
+ RSSchannel info = RSS->dataForID(IDS[i]);
+ if(info.title.isEmpty()){
+ //invalid/empty channel
+ ui->combo_feed->insertItem(i, IDS[i], IDS[i]); //just show the URL
+ }else{
+ ui->combo_feed->insertItem(i, info.icon, info.title, IDS[i]);
+ }
+ }
+ }
+ //Remove any extra items on the end of the list
+ for(int i=IDS.length(); i<ui->combo_feed->count(); i++){
+ ui->combo_feed->removeItem(i); i--;
+ }
+ //Now activate the proper item as needed
+ if(IDS.contains(activate)){
+ ui->combo_feed->setCurrentIndex( IDS.indexOf(activate) );
+ }
+ checkFeedNotify();
+}
+
+void RSSFeedPlugin::RSSItemChanged(QString ID){
+ for(int i=0; i<ui->combo_feed->count(); i++){
+ if(ui->combo_feed->itemData(i).toString()!=ID){ continue; }
+ RSSchannel info = RSS->dataForID(ID);
+ if(info.title.isEmpty()){
+ ui->combo_feed->setItemText(i, ID);
+ ui->combo_feed->setItemIcon(i, LXDG::findIcon("dialog-cancel","") );
+ }else{
+ ui->combo_feed->setItemText(i, info.title);
+ ui->combo_feed->setItemIcon(i, info.icon );
+ QColor color(Qt::transparent);
+ if( info.lastBuildDate > LSession::handle()->DesktopPluginSettings()->value(setprefix+"feedReads/"+ID,QDateTime()).toDateTime() ){
+ color = QColor(255,10,10,100); //semi-transparent red
+ ui->combo_feed->setItemData(i, "notify", Qt::WhatsThisRole);
+ }else{
+ ui->combo_feed->setItemData(i, "", Qt::WhatsThisRole);
+ }
+ ui->combo_feed->setItemData(i, QBrush(color) , Qt::BackgroundRole);
+ }
+ }
+ if(ID == ui->combo_feed->currentData().toString()){
+ currentFeedChanged(); //re-load the current feed
+ }else{
+ checkFeedNotify();
+ }
+}
+
+//==================
+// PUBLIC SLOTS
+//==================
+void RSSFeedPlugin::LocaleChange(){
+ ui->retranslateUi(this);
+ updateOptionsMenu();
+}
+void RSSFeedPlugin::ThemeChange(){
+ QTimer::singleShot(0,this, SLOT(loadIcons()));
+ updateOptionsMenu();
+}
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.h b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.h
new file mode 100644
index 00000000..68b36760
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.h
@@ -0,0 +1,72 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This plugin is a simple RSS feed reader for the desktop
+//===========================================
+#ifndef _LUMINA_DESKTOP_RSS_FEEDER_PLUGIN_H
+#define _LUMINA_DESKTOP_RSS_FEEDER_PLUGIN_H
+
+#include <QTimer>
+#include "../LDPlugin.h"
+
+#include "RSSObjects.h"
+
+namespace Ui{
+ class RSSFeedPlugin;
+};
+
+class RSSFeedPlugin : public LDPlugin{
+ Q_OBJECT
+public:
+ RSSFeedPlugin(QWidget* parent, QString ID);
+ ~RSSFeedPlugin();
+
+ virtual QSize defaultPluginSize(){
+ // The returned QSize is in grid points (typically 100 or 200 pixels square)
+ return QSize(3,3);
+ }
+private:
+ Ui::RSSFeedPlugin *ui;
+ QMenu *optionsMenu, *presetMenu;
+ QString setprefix; //settings prefix
+ RSSReader *RSS;
+
+ void updateOptionsMenu();
+ void checkFeedNotify(); //check if unread feeds are available and change the styling a bit as needed
+
+ //Simplification functions for loading feed info onto widgets
+ void updateFeed(QString ID);
+ void updateFeedInfo(QString ID);
+
+private slots:
+ void loadIcons();
+
+ //GUI slots
+ // - Page management
+ void backToFeeds();
+ void openFeedInfo();
+ void openFeedNew();
+ void openSettings();
+ // - Feed Management
+ void addNewFeed(); // the "add" button (current url in widget on page)
+ void loadPreset(QAction*); //the add-preset menu
+ void removeFeed(); // the "remove" button (current feed for page)
+ void resyncFeeds();
+ // - Feed Interactions
+ void currentFeedChanged();
+ void openFeedPage(); //Open the website in a browser
+ void saveSettings();
+
+ //Feed Object interactions
+ void UpdateFeedList();
+ void RSSItemChanged(QString ID);
+
+public slots:
+ void LocaleChange();
+ void ThemeChange();
+
+};
+#endif
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.ui b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.ui
new file mode 100644
index 00000000..45dac405
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.ui
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RSSFeedPlugin</class>
+ <widget class="QWidget" name="RSSFeedPlugin">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>238</width>
+ <height>278</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="stackedWidget">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="page_feed">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="combo_feed"/>
+ </item>
+ <item>
+ <widget class="QToolButton" name="tool_options">
+ <property name="toolTip">
+ <string>View Options</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_lastupdate">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="tool_gotosite">
+ <property name="toolTip">
+ <string>Open Website</string>
+ </property>
+ <property name="text">
+ <string>More</string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::NoArrow</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTextBrowser" name="text_feed">
+ <property name="undoRedoEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="html">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ <property name="openLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_feed_info">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>5</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QPushButton" name="push_back1">
+ <property name="text">
+ <string>Back to Feeds</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Feed Information</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTextBrowser" name="text_feed_info">
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <widget class="QPushButton" name="push_rm_feed">
+ <property name="text">
+ <string>Remove Feed</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_new_feed">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QPushButton" name="push_back2">
+ <property name="text">
+ <string>Back to Feeds</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>New Feed Subscription</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>RSS URL</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_10">
+ <item>
+ <widget class="QLineEdit" name="line_new_url"/>
+ </item>
+ <item>
+ <widget class="QToolButton" name="tool_add_preset">
+ <property name="toolTip">
+ <string>Load a preset RSS Feed</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="push_add_url">
+ <property name="text">
+ <string>Add to Feeds</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_settings">
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QPushButton" name="push_back3">
+ <property name="text">
+ <string>Back to Feeds</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Feed Reader Settings</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="check_manual_sync">
+ <property name="text">
+ <string>Manual Sync Only</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_4">
+ <property name="toolTip">
+ <string>Some RSS feeds may request custom update intervals instead of using this setting</string>
+ </property>
+ <property name="title">
+ <string>Default Sync Interval</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="spin_synctime">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>60</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="combo_sync_units">
+ <property name="currentText">
+ <string>Hour(s)</string>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Minutes</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Hour(s)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="push_save_settings">
+ <property name="text">
+ <string>Save Settings</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp
new file mode 100644
index 00000000..654a005d
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp
@@ -0,0 +1,275 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RSSObjects.h"
+#include <QNetworkRequest>
+#include <QXmlStreamReader>
+
+#include "LSession.h"
+
+//============
+// PUBLIC
+//============
+RSSReader::RSSReader(QObject *parent, QString settingsPrefix) : QObject(parent){
+ NMAN = new QNetworkAccessManager(this);
+ connect(NMAN, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)) );
+ connect(NMAN, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(sslErrors(QNetworkReply*, const QList<QSslError>&)) );
+
+ setprefix = settingsPrefix;
+ syncTimer = new QTimer(this);
+ syncTimer->setInterval(300000); //5 minutes
+ connect(syncTimer, SIGNAL(timeout()), this, SLOT(checkTimes()));
+ syncTimer->start();
+}
+
+RSSReader::~RSSReader(){
+
+}
+
+//Information retrieval
+QStringList RSSReader::channels(){
+ QStringList urls = hash.keys();
+ QStringList ids;
+ //sort all the channels by title before output
+ for(int i=0; i<urls.length(); i++){
+ QString title = hash[urls[i]].title;
+ if(title.isEmpty()){ title = "ZZZ"; } //put currently-invalid ones at the end of the list
+ ids << title+" : "+urls[i];
+ }
+ ids.sort();
+ //Now strip off all the titles again to just get the IDs
+ for(int i=0; i<ids.length(); i++){
+ ids[i] = ids[i].section(" : ",-1);
+ }
+ return ids;
+}
+
+RSSchannel RSSReader::dataForID(QString ID){
+ if(hash.contains(ID)){ return hash[ID]; }
+ else{ return RSSchannel(); }
+}
+
+//Initial setup
+void RSSReader::addUrls(QStringList urls){
+ //qDebug() << "Add URLS:" << urls;
+ QStringList known = hash.keys();
+ int orig = known.length();
+ for(int i=0; i<orig; i++){ known << hash[known[i]].originalURL; }
+ for(int i=0; i<urls.length(); i++){
+ //Note: Make sure we get the complete URL form for accurate comparison later
+ QString url = QUrl(urls[i]).toString();
+ if(known.contains(url)){ continue; } //already handled
+ RSSchannel blank;
+ blank.originalURL = url;
+ hash.insert(url, blank); //put the empty struct into the hash for now
+ requestRSS(url); //startup the initial request for this url
+ }
+ emit newChannelsAvailable();
+}
+
+void RSSReader::removeUrl(QString ID){
+ if(hash.contains(ID)){ hash.remove(ID); }
+ emit newChannelsAvailable();
+}
+
+//=================
+// PUBLIC SLOTS
+//=================
+void RSSReader::syncNow(){
+ QStringList urls = hash.keys();
+ for(int i=0; i<urls.length(); i++){
+ requestRSS(urls[i]);
+ }
+}
+
+//=================
+// PRIVATE
+//=================
+void RSSReader::requestRSS(QString url){
+ if(!outstandingURLS.contains(url)){
+ //qDebug() << "Request URL:" << url;
+ NMAN->get( QNetworkRequest( QUrl(url) ) );
+ outstandingURLS << url;
+ }
+}
+
+//RSS parsing functions
+RSSchannel RSSReader::readRSS(QByteArray bytes){
+ //Note: We could expand this later to support multiple "channel"s per Feed
+ // but it seems like there is normally only one channel anyway
+ //qDebug() << "Read RSS:" << bytes.left(100);
+ QXmlStreamReader xml(bytes);
+ RSSchannel rssinfo;
+ //qDebug() << "Can Read XML Stream:" << !xml.hasError();
+ if(xml.readNextStartElement()){
+ //qDebug() << " - RSS Element:" << xml.name();
+ if(xml.name() == "rss" && (xml.attributes().value("version") =="2.0" || xml.attributes().value("version") =="0.91") ){
+ while(xml.readNextStartElement()){
+ //qDebug() << " - RSS Element:" << xml.name();
+ if(xml.name()=="channel"){ rssinfo = readRSSChannel(&xml); }
+ else{ xml.skipCurrentElement(); }
+ }
+ }
+ }
+ if(xml.hasError()){ qDebug() << " - XML Read Error:" << xml.errorString() << "\n" << bytes; }
+ return rssinfo;
+}
+RSSchannel RSSReader::readRSSChannel(QXmlStreamReader *rss){
+ RSSchannel info;
+ info.timetolive = -1;
+ while(rss->readNextStartElement()){
+ //qDebug() << " - RSS Element (channel):" <<rss->name();
+ if(rss->name()=="item"){ info.items << readRSSItem(rss); }
+ else if(rss->name()=="title"){ info.title = rss->readElementText(); }
+ else if(rss->name()=="link"){
+ QString txt = rss->readElementText();
+ if(!txt.isEmpty()){ info.link = txt; }
+ }
+ else if(rss->name()=="description"){ info.description = rss->readElementText(); }
+ else if(rss->name()=="lastBuildDate"){ info.lastBuildDate = RSSDateTime(rss->readElementText()); }
+ else if(rss->name()=="pubDate"){ info.lastPubDate = RSSDateTime(rss->readElementText()); }
+ else if(rss->name()=="image"){ readRSSImage(&info, rss); }
+ //else if(rss->name()=="skipHours"){ info.link = rss->readElementText(); }
+ //else if(rss->name()=="skipDays"){ info.link = rss->readElementText(); }
+ else if(rss->name()=="ttl"){ info.timetolive = rss->readElementText().toInt(); }
+ else{ rss->skipCurrentElement(); }
+ }
+ return info;
+}
+
+RSSitem RSSReader::readRSSItem(QXmlStreamReader *rss){
+ RSSitem item;
+ while(rss->readNextStartElement()){
+ //qDebug() << " - RSS Element (Item):" << rss->name();
+ if(rss->name()=="title"){ item.title = rss->readElementText(); }
+ else if(rss->name()=="link"){ item.link = rss->readElementText(); }
+ else if(rss->name()=="description"){ item.description = rss->readElementText(); }
+ else if(rss->name()=="comments"){ item.comments_url = rss->readElementText(); }
+ else if(rss->name()=="author"){
+ //Special handling - this field can contain both email and name
+ QString raw = rss->readElementText();
+ if(raw.contains("@")){
+ item.author_email = raw.split(" ").filter("@").first();
+ item.author = raw.remove(item.author_email).remove("(").remove(")").simplified(); //the name is often put within parentheses after the email
+ }else{ item.author = raw; }
+ }
+ else if(rss->name()=="guid"){ item.guid = rss->readElementText(); }
+ else if(rss->name()=="pubDate"){ item.pubdate = RSSDateTime(rss->readElementText()); }
+ else{ rss->skipCurrentElement(); }
+ }
+ return item;
+}
+
+void RSSReader::readRSSImage(RSSchannel *item, QXmlStreamReader *rss){
+ while(rss->readNextStartElement()){
+ //qDebug() << " - RSS Element (Image):" << rss->name();
+ if(rss->name()=="url"){ item->icon_url = rss->readElementText(); }
+ else if(rss->name()=="title"){ item->icon_title = rss->readElementText(); }
+ else if(rss->name()=="link"){ item->icon_link = rss->readElementText(); }
+ else if(rss->name()=="width"){ item->icon_size.setWidth(rss->readElementText().toInt()); }
+ else if(rss->name()=="height"){ item->icon_size.setHeight(rss->readElementText().toInt()); }
+ else if(rss->name()=="description"){ item->icon_description = rss->readElementText(); }
+ }
+ //Go ahead and kick off the request for the icon
+ if(!item->icon_url.isEmpty()){ requestRSS(item->icon_url); }
+}
+
+QDateTime RSSReader::RSSDateTime(QString datetime){
+ return QDateTime::fromString(datetime, Qt::RFC2822Date);
+}
+
+//=================
+// PRIVATE SLOTS
+//=================
+void RSSReader::replyFinished(QNetworkReply *reply){
+ QString url = reply->request().url().toString();
+ //qDebug() << "Got Reply:" << url;
+ QByteArray data = reply->readAll();
+ outstandingURLS.removeAll(url);
+ if(data.isEmpty()){
+ //qDebug() << "No data returned:" << url;
+ //see if the URL can be adjusted for known issues
+ bool handled = false;
+ QUrl redirecturl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ if(redirecturl.isValid() && (redirecturl.toString() != url )){
+ //New URL redirect - make the change and send a new request
+ QString newurl = redirecturl.toString();
+ //qDebug() << " - Redirect to:" << newurl;
+ if(hash.contains(url) && !hash.contains(newurl)){
+ hash.insert(newurl, hash.take(url) ); //just move the data over to the new url
+ requestRSS(newurl);
+ emit newChannelsAvailable();
+ handled = true;
+ }
+ }
+ if(!handled && hash.contains(url) ){
+ emit rssChanged(url);
+ }
+ return;
+ }
+
+ if(!hash.contains(url)){
+ //qDebug() << " - hash does not contain URL:" << url;
+ //URL removed from list while a request was outstanding?
+ //Could also be an icon fetch response
+ QStringList keys = hash.keys();
+ for(int i=0; i<keys.length(); i++){
+ //qDebug() << " - Check for icon URL:" << hash[keys[i]].icon_url;
+ if(hash[keys[i]].icon_url.toLower() == url.toLower()){ //needs to be case-insensitive
+ //Icon fetch response
+ RSSchannel info = hash[keys[i]];
+ QImage img = QImage::fromData(data);
+ info.icon = QIcon( QPixmap::fromImage(img) );
+ //qDebug() << "Got Icon response:" << url << info.icon;
+ hash.insert(keys[i], info); //insert back into the hash
+ emit rssChanged(keys[i]);
+ break;
+ }
+ }
+ reply->deleteLater();
+ }else{
+ //RSS reply
+ RSSchannel info = readRSS(data); //QNetworkReply can be used as QIODevice
+ reply->deleteLater(); //clean up
+ //Validate the info and announce any changes
+ if(info.title.isEmpty() || info.link.isEmpty() || info.description.isEmpty()){
+ qDebug() << "Missing XML Information:" << url << info.title << info.link << info.description;
+ return;
+ } //bad info/read
+ //Update the bookkeeping elements of the info
+ if(info.timetolive<=0){ info.timetolive = LSession::handle()->DesktopPluginSettings()->value(setprefix+"default_interval_minutes", 60).toInt(); }
+ if(info.timetolive <=0){ info.timetolive = 60; } //error in integer conversion from settings?
+ info.lastsync = QDateTime::currentDateTime(); info.nextsync = info.lastsync.addSecs(info.timetolive * 60);
+ //Now see if anything changed and save the info into the hash
+ bool changed = (hash[url].lastBuildDate.isNull() || (hash[url].lastBuildDate < info.lastBuildDate) );
+ bool newinfo = false;
+ if(changed){ newinfo = hash[url].title.isEmpty(); } //no previous info from this URL
+ info.originalURL = hash[url].originalURL; //make sure this info gets preserved across updates
+ hash.insert(url, info);
+ if(newinfo){ emit newChannelsAvailable(); } //new channel
+ else if(changed){ emit rssChanged(url); } //update to existing channel
+ }
+}
+
+void RSSReader::sslErrors(QNetworkReply *reply, const QList<QSslError> &errors){
+ int ok = 0;
+ qDebug() << "SSL Errors Detected (RSS Reader):" << reply->url();
+ for(int i=0; i<errors.length(); i++){
+ if(errors[i].error()==QSslError::SelfSignedCertificate || errors[i].error()==QSslError::SelfSignedCertificateInChain){ ok++; }
+ else{ qDebug() << "Unhandled SSL Error:" << errors[i].errorString(); }
+ }
+ if(ok==errors.length()){ qDebug() << " - Permitted:" << reply->url(); reply->ignoreSslErrors(); }
+ else{ qDebug() << " - Denied:" << reply->url(); }
+}
+
+void RSSReader::checkTimes(){
+ if(LSession::handle()->DesktopPluginSettings()->value(setprefix+"manual_sync_only", false).toBool()){ return; }
+ QStringList urls = hash.keys();
+ QDateTime cdt = QDateTime::currentDateTime();
+ for(int i=0; i<urls.length(); i++){
+ if(hash[urls[i]].nextsync < cdt){ requestRSS(urls[i]); }
+ }
+}
diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h
new file mode 100644
index 00000000..c0e72e18
--- /dev/null
+++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h
@@ -0,0 +1,101 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2016, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_RSS_READER_PLUGIN_OBJECT_H
+#define _LUMINA_DESKTOP_RSS_READER_PLUGIN_OBJECT_H
+
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QString>
+#include <QDateTime>
+#include <QList>
+#include <QIcon>
+#include <QTimer>
+#include <QXmlStreamReader> //Contained in the Qt "core" module - don't need the full "xml" module for this
+#include <QSslError>
+
+struct RSSitem{
+ //Required Fields
+ QString title, link, description;
+
+ //Optional Fields
+ QString comments_url, author_email, author, guid;
+ QDateTime pubdate; //when the item was published
+ //IGNORED INFO from RSS2 spec: "category", "source", "enclosure"
+};
+
+struct RSSchannel{
+ //Required fields
+ QString title, link, description;
+
+ //Optional Fields
+ QDateTime lastBuildDate, lastPubDate; //last build/publish dates
+ // - channel refresh information
+ int timetolive; //in minutes - time until next sync should be performed
+ //QList<int> skiphours;
+ //QStringList skipdays;
+ // - icon info
+ QIcon icon;
+ QString icon_url, icon_title, icon_link, icon_description;
+ QSize icon_size;
+ //All items within this channel
+ QList<RSSitem> items;
+
+ //Optional RSS2 elements ignored:
+ // "cloud", "textInput", "rating", "language", "copyright", "managingEditor", "webMaster",
+ // "category", "generator", "docs"
+
+ //Internal data for bookkeeping
+ QDateTime lastsync, nextsync;
+ QString originalURL; //in case it was redirected to some "fixed" url later
+};
+
+class RSSReader : public QObject{
+ Q_OBJECT
+public:
+ RSSReader(QObject *parent, QString settingsPrefix);
+ ~RSSReader();
+
+ //Information retrieval
+ QStringList channels(); //returns all ID's
+ RSSchannel dataForID(QString ID);
+
+ //Initial setup
+ void addUrls(QStringList urls);
+ void removeUrl(QString ID);
+
+public slots:
+ void syncNow(); //not generally needed
+
+private:
+ //Internal data objects
+ QHash<QString, RSSchannel> hash; // ID/data
+ QString setprefix;
+ QTimer *syncTimer;
+ QNetworkAccessManager *NMAN;
+ QStringList outstandingURLS;
+
+ //Network request function
+ void requestRSS(QString url);
+
+ //RSS parsing functions
+ RSSchannel readRSS(QByteArray bytes);
+ RSSchannel readRSSChannel(QXmlStreamReader *rss);
+ RSSitem readRSSItem(QXmlStreamReader *rss);
+ void readRSSImage(RSSchannel *item, QXmlStreamReader *rss);
+ QDateTime RSSDateTime(QString datetime);
+
+private slots:
+ void replyFinished(QNetworkReply *reply);
+ void sslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
+ void checkTimes();
+
+signals:
+ void rssChanged(QString); //ID
+ void newChannelsAvailable();
+};
+
+#endif
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 318d03fa..7c9b7ab0 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/appmenu/LAppMenuPlugin.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/appmenu/LAppMenuPlugin.cpp
@@ -34,7 +34,7 @@ void LAppMenuPlugin::updateButtonVisuals(){
button->setToolTip( tr("Quickly launch applications or open files"));
button->setText( tr("Applications") );
//Use the PC-BSD icon by default (or the Lumina icon for non-PC-BSD systems)
- button->setIcon( LXDG::findIcon("pcbsd","Lumina-DE") );
+ button->setIcon( LXDG::findIcon("start-here-lumina","Lumina-DE") );
}
// ========================
@@ -131,4 +131,3 @@ void LAppMenuPlugin::UpdateMenu(){
tmpact->setWhatsThis("internal::logout");
}
-
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp
index e08ef1c8..d57846e2 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp
@@ -42,7 +42,7 @@ LStartButtonPlugin::~LStartButtonPlugin(){
void LStartButtonPlugin::updateButtonVisuals(){
button->setToolTip(tr(""));
button->setText( SYSTEM::user() );
- button->setIcon( LXDG::findIcon("pcbsd","Lumina-DE") ); //force icon refresh
+ button->setIcon( LXDG::findIcon("start-here-lumina","Lumina-DE") ); //force icon refresh
}
void LStartButtonPlugin::updateQuickLaunch(QStringList apps){
@@ -117,4 +117,3 @@ void LStartButtonPlugin::openMenu(){
void LStartButtonPlugin::closeMenu(){
menu->hide();
}
-
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
index a67ef5d6..7e2e53de 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
@@ -122,8 +122,12 @@ void LTaskButton::UpdateButton(){
//single window
this->setPopupMode(QToolButton::DelayedPopup);
this->setMenu(actMenu);
- if(showText){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( WINLIST[0].text()); }
- else if(noicon){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( cname ); }
+ if(showText){
+ QString txt = WINLIST[0].text();
+ if(txt.length()>30){ txt.truncate(27); txt.append("..."); }
+ else if(txt.length()<30){ txt = txt.leftJustified(30, ' '); }
+ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText(txt);
+ }else if(noicon){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( cname ); }
else{ this->setToolButtonStyle(Qt::ToolButtonIconOnly); this->setText(""); }
this->setToolTip(WINLIST[0].text());
}else if(WINLIST.length() > 1){
diff --git a/src-qt5/core/lumina-open/LFileDialog.cpp b/src-qt5/core/lumina-open/LFileDialog.cpp
index c0417935..9ec94bf5 100644
--- a/src-qt5/core/lumina-open/LFileDialog.cpp
+++ b/src-qt5/core/lumina-open/LFileDialog.cpp
@@ -15,8 +15,8 @@ LFileDialog::LFileDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LFileDia
appExec.clear();
appPath.clear();
appFile.clear();
- QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, QDir::homePath()+"/.lumina");
- settings = new QSettings("LuminaDE", "lumina-open",this);
+ //QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, QDir::homePath()+"/.lumina");
+ settings = new QSettings("lumina-desktop", "lumina-open", this);
//Connect the signals/slots
connect(ui->combo_apps, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()) );
connect(ui->radio_rec, SIGNAL(toggled(bool)), this, SLOT(radioChanged()) );
@@ -46,6 +46,7 @@ void LFileDialog::setFileInfo(QString filename, QString extension, bool isFile){
//static functions
QString LFileDialog::getDefaultApp(QString extension){
+ qDebug() << "Get Default App:" << extension;
QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, QDir::homePath()+"/.lumina");
if(extension.contains("/")){
return LXDG::findDefaultAppForMime(extension);
@@ -66,7 +67,7 @@ void LFileDialog::setDefaultApp(QString extension, QString appFile){
}else{
QSettings("LuminaDE", "lumina-open").setValue("default/"+extension,appFile);
}
- }
+ }
}
// -----------
@@ -283,4 +284,3 @@ void LFileDialog::on_tool_findBin_clicked(){
void LFileDialog::on_line_bin_textChanged(){
updateUI();
}
-
diff --git a/src-qt5/core/lumina-open/main.cpp b/src-qt5/core/lumina-open/main.cpp
index a323e075..7a7fef19 100644
--- a/src-qt5/core/lumina-open/main.cpp
+++ b/src-qt5/core/lumina-open/main.cpp
@@ -101,6 +101,7 @@ QString cmdFromUser(int argc, char **argv, QString inFile, QString extension, QS
//qDebug() << "Matches:" << matches;
for(int i=0; i<matches.length(); i++){
defApp = LXDG::findDefaultAppForMime(matches[i]);
+ //qDebug() << "MimeType:" << matches[i] << defApp;
if(!defApp.isEmpty()){ extension = matches[i]; break; }
else if(i+1==matches.length()){ extension = matches[0]; }
}
@@ -226,6 +227,7 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat
//Now check what type of file this is
if(QFile::exists(inFile)){ isFile=true; }
else if(QFile::exists(QDir::currentPath()+"/"+inFile)){isFile=true; inFile = QDir::currentPath()+"/"+inFile;} //account for relative paths
+ else if(inFile.startsWith("mailto:")){ isUrl= true; }
else if(QUrl(inFile).isValid() && !inFile.startsWith("/") ){ isUrl=true; }
if( !isFile && !isUrl ){ ShowErrorDialog( argc, argv, QString(QObject::tr("Invalid file or URL: %1")).arg(inFile) ); }
//Determing the type of file (extension)
@@ -239,7 +241,7 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat
else if(info.isExecutable() && extension.isEmpty()){ extension="binary"; }
else if(extension!="desktop"){ extension="mimetype"; } //flag to check for mimetype default based on file
}
- else if(isUrl && inFile.startsWith("mailto:")){ extension = "email"; }
+ else if(isUrl && inFile.startsWith("mailto:")){ extension = "application/email"; }
else if(isUrl && inFile.contains("://") ){ extension = "x-scheme-handler/"+inFile.section("://",0,0); }
else if(isUrl && inFile.startsWith("www.")){ extension = "x-scheme-handler/http"; inFile.prepend("http://"); } //this catches partial (but still valid) URL's ("www.<something>" for instance)
//qDebug() << "Input:" << inFile << isFile << isUrl << extension;
@@ -314,7 +316,7 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat
cmd.replace("%F","\""+inFile+"\"");
}else if( (cmd.contains("%U") || cmd.contains("%u")) ){
//Apply any special field replacements for the desired format
- if(!inFile.contains("://")){ inFile.prepend("file://"); } //local file - add the extra flag
+ if(!inFile.contains("://") && !isUrl){ inFile.prepend("file://"); } //local file - add the extra flag
inFile.replace(" ", "%20");
//Now replace the field codes
cmd.replace("%u","\""+inFile+"\"");
diff --git a/src-qt5/core/lumina-session/main.cpp b/src-qt5/core/lumina-session/main.cpp
index 8f89e95c..27eaf537 100644
--- a/src-qt5/core/lumina-session/main.cpp
+++ b/src-qt5/core/lumina-session/main.cpp
@@ -40,7 +40,9 @@ int main(int argc, char ** argv)
//Start X11 if needed
//Configure X11 monitors if needed
-
+ if(LUtils::isValidBinary("lumina-xconfig")){
+ QProcess::execute("lumina-xconfig --reset-monitors");
+ }
//Startup the session
QCoreApplication a(argc, argv);
LSession sess;
bgstack15