aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp
diff options
context:
space:
mode:
authorKen Moore <moorekou@gmail.com>2016-06-02 14:33:14 -0400
committerKen Moore <moorekou@gmail.com>2016-06-02 14:33:14 -0400
commit24c03502bfcbd544ddd7f884d3c6ec0094f498b6 (patch)
treeae169c6cf09a2ab9c14d0ac7ce243d167d5fdd78 /src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp
parentAdd the new RSS reader to the known plugins in lumina-config. (diff)
downloadlumina-24c03502bfcbd544ddd7f884d3c6ec0094f498b6.tar.gz
lumina-24c03502bfcbd544ddd7f884d3c6ec0094f498b6.tar.bz2
lumina-24c03502bfcbd544ddd7f884d3c6ec0094f498b6.zip
Rename/move the new RSS reader plugin to "rssreader" in the backend/source tree, update luminaDesktop.conf to include this plugin as well as other quick out-of-box shortcuts.
Diffstat (limited to 'src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp')
-rw-r--r--src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp363
1 files changed, 363 insertions, 0 deletions
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();
+}
bgstack15