work on discoverying feeds

This commit is contained in:
Martin Rotter 2023-10-17 15:23:36 +02:00
parent 075b249f23
commit e8090ce68c
23 changed files with 715 additions and 99 deletions

View File

@ -38,9 +38,9 @@ set(SOURCES
database/sqlitedriver.cpp database/sqlitedriver.cpp
database/sqlitedriver.h database/sqlitedriver.h
definitions/definitions.h definitions/definitions.h
definitions/typedefs.h
definitions/globals.cpp definitions/globals.cpp
definitions/globals.h definitions/globals.h
definitions/typedefs.h
dynamic-shortcuts/dynamicshortcuts.cpp dynamic-shortcuts/dynamicshortcuts.cpp
dynamic-shortcuts/dynamicshortcuts.h dynamic-shortcuts/dynamicshortcuts.h
dynamic-shortcuts/dynamicshortcutswidget.cpp dynamic-shortcuts/dynamicshortcutswidget.cpp
@ -49,20 +49,20 @@ set(SOURCES
dynamic-shortcuts/shortcutcatcher.h dynamic-shortcuts/shortcutcatcher.h
exceptions/applicationexception.cpp exceptions/applicationexception.cpp
exceptions/applicationexception.h exceptions/applicationexception.h
exceptions/feedrecognizedbutfailedexception.cpp
exceptions/feedrecognizedbutfailedexception.h
exceptions/feedfetchexception.cpp exceptions/feedfetchexception.cpp
exceptions/feedfetchexception.h exceptions/feedfetchexception.h
exceptions/feedrecognizedbutfailedexception.cpp
exceptions/feedrecognizedbutfailedexception.h
exceptions/filteringexception.cpp exceptions/filteringexception.cpp
exceptions/filteringexception.h exceptions/filteringexception.h
exceptions/ioexception.cpp exceptions/ioexception.cpp
exceptions/ioexception.h exceptions/ioexception.h
exceptions/networkexception.cpp exceptions/networkexception.cpp
exceptions/networkexception.h exceptions/networkexception.h
exceptions/scriptexception.cpp
exceptions/scriptexception.h
exceptions/processexception.cpp exceptions/processexception.cpp
exceptions/processexception.h exceptions/processexception.h
exceptions/scriptexception.cpp
exceptions/scriptexception.h
gui/dialogs/formabout.cpp gui/dialogs/formabout.cpp
gui/dialogs/formabout.h gui/dialogs/formabout.h
gui/dialogs/formaddaccount.cpp gui/dialogs/formaddaccount.cpp
@ -71,10 +71,10 @@ set(SOURCES
gui/dialogs/formbackupdatabasesettings.h gui/dialogs/formbackupdatabasesettings.h
gui/dialogs/formdatabasecleanup.cpp gui/dialogs/formdatabasecleanup.cpp
gui/dialogs/formdatabasecleanup.h gui/dialogs/formdatabasecleanup.h
gui/dialogs/formmain.cpp
gui/dialogs/formmain.h
gui/dialogs/formlog.cpp gui/dialogs/formlog.cpp
gui/dialogs/formlog.h gui/dialogs/formlog.h
gui/dialogs/formmain.cpp
gui/dialogs/formmain.h
gui/dialogs/formmessagefiltersmanager.cpp gui/dialogs/formmessagefiltersmanager.cpp
gui/dialogs/formmessagefiltersmanager.h gui/dialogs/formmessagefiltersmanager.h
gui/dialogs/formrestoredatabasesettings.cpp gui/dialogs/formrestoredatabasesettings.cpp
@ -97,14 +97,18 @@ set(SOURCES
gui/messagepreviewer.h gui/messagepreviewer.h
gui/messagesview.cpp gui/messagesview.cpp
gui/messagesview.h gui/messagesview.h
gui/notifications/articlelistnotification.cpp
gui/notifications/articlelistnotification.h
gui/notifications/basetoastnotification.cpp gui/notifications/basetoastnotification.cpp
gui/notifications/basetoastnotification.h gui/notifications/basetoastnotification.h
gui/notifications/notificationseditor.cpp gui/notifications/notificationseditor.cpp
gui/notifications/notificationseditor.h gui/notifications/notificationseditor.h
gui/notifications/singlenotificationeditor.cpp gui/notifications/singlenotificationeditor.cpp
gui/notifications/singlenotificationeditor.h gui/notifications/singlenotificationeditor.h
gui/notifications/articlelistnotification.cpp gui/notifications/toastnotification.cpp
gui/notifications/articlelistnotification.h gui/notifications/toastnotification.h
gui/notifications/toastnotificationsmanager.cpp
gui/notifications/toastnotificationsmanager.h
gui/reusable/baselineedit.cpp gui/reusable/baselineedit.cpp
gui/reusable/baselineedit.h gui/reusable/baselineedit.h
gui/reusable/basetreeview.cpp gui/reusable/basetreeview.cpp
@ -113,6 +117,8 @@ set(SOURCES
gui/reusable/colortoolbutton.h gui/reusable/colortoolbutton.h
gui/reusable/comboboxwithstatus.cpp gui/reusable/comboboxwithstatus.cpp
gui/reusable/comboboxwithstatus.h gui/reusable/comboboxwithstatus.h
gui/reusable/discoverfeedsbutton.cpp
gui/reusable/discoverfeedsbutton.h
gui/reusable/edittableview.cpp gui/reusable/edittableview.cpp
gui/reusable/edittableview.h gui/reusable/edittableview.h
gui/reusable/helpspoiler.cpp gui/reusable/helpspoiler.cpp
@ -125,6 +131,8 @@ set(SOURCES
gui/reusable/labelwithstatus.h gui/reusable/labelwithstatus.h
gui/reusable/lineeditwithstatus.cpp gui/reusable/lineeditwithstatus.cpp
gui/reusable/lineeditwithstatus.h gui/reusable/lineeditwithstatus.h
gui/reusable/locationlineedit.cpp
gui/reusable/locationlineedit.h
gui/reusable/messagecountspinbox.cpp gui/reusable/messagecountspinbox.cpp
gui/reusable/messagecountspinbox.h gui/reusable/messagecountspinbox.h
gui/reusable/networkproxydetails.cpp gui/reusable/networkproxydetails.cpp
@ -137,12 +145,12 @@ set(SOURCES
gui/reusable/progressbarwithtext.h gui/reusable/progressbarwithtext.h
gui/reusable/resizablestackedwidget.cpp gui/reusable/resizablestackedwidget.cpp
gui/reusable/resizablestackedwidget.h gui/reusable/resizablestackedwidget.h
gui/reusable/searchlineedit.cpp
gui/reusable/searchlineedit.h
gui/reusable/searchtextwidget.cpp gui/reusable/searchtextwidget.cpp
gui/reusable/searchtextwidget.h gui/reusable/searchtextwidget.h
gui/reusable/squeezelabel.cpp gui/reusable/squeezelabel.cpp
gui/reusable/squeezelabel.h gui/reusable/squeezelabel.h
gui/reusable/searchlineedit.cpp
gui/reusable/searchlineedit.h
gui/reusable/styleditemdelegatewithoutfocus.cpp gui/reusable/styleditemdelegatewithoutfocus.cpp
gui/reusable/styleditemdelegatewithoutfocus.h gui/reusable/styleditemdelegatewithoutfocus.h
gui/reusable/timespinbox.cpp gui/reusable/timespinbox.cpp
@ -151,6 +159,10 @@ set(SOURCES
gui/reusable/treeviewcolumnsmenu.h gui/reusable/treeviewcolumnsmenu.h
gui/reusable/widgetwithstatus.cpp gui/reusable/widgetwithstatus.cpp
gui/reusable/widgetwithstatus.h gui/reusable/widgetwithstatus.h
gui/richtexteditor/mrichtextedit.cpp
gui/richtexteditor/mrichtextedit.h
gui/richtexteditor/mtextedit.cpp
gui/richtexteditor/mtextedit.h
gui/settings/settingsbrowsermail.cpp gui/settings/settingsbrowsermail.cpp
gui/settings/settingsbrowsermail.h gui/settings/settingsbrowsermail.h
gui/settings/settingsdatabase.cpp gui/settings/settingsdatabase.cpp
@ -181,15 +193,6 @@ set(SOURCES
gui/tabcontent.h gui/tabcontent.h
gui/tabwidget.cpp gui/tabwidget.cpp
gui/tabwidget.h gui/tabwidget.h
gui/notifications/toastnotification.cpp
gui/notifications/toastnotification.h
gui/notifications/toastnotificationsmanager.cpp
gui/notifications/toastnotificationsmanager.h
gui/webviewers/webviewer.h
gui/richtexteditor/mrichtextedit.cpp
gui/richtexteditor/mrichtextedit.h
gui/richtexteditor/mtextedit.cpp
gui/richtexteditor/mtextedit.h
gui/toolbars/basetoolbar.cpp gui/toolbars/basetoolbar.cpp
gui/toolbars/basetoolbar.h gui/toolbars/basetoolbar.h
gui/toolbars/feedstoolbar.cpp gui/toolbars/feedstoolbar.cpp
@ -200,6 +203,9 @@ set(SOURCES
gui/toolbars/statusbar.h gui/toolbars/statusbar.h
gui/toolbars/toolbareditor.cpp gui/toolbars/toolbareditor.cpp
gui/toolbars/toolbareditor.h gui/toolbars/toolbareditor.h
gui/webbrowser.cpp
gui/webbrowser.h
gui/webviewers/webviewer.h
miscellaneous/application.cpp miscellaneous/application.cpp
miscellaneous/application.h miscellaneous/application.h
miscellaneous/autosaver.cpp miscellaneous/autosaver.cpp
@ -236,6 +242,14 @@ set(SOURCES
miscellaneous/templates.h miscellaneous/templates.h
miscellaneous/textfactory.cpp miscellaneous/textfactory.cpp
miscellaneous/textfactory.h miscellaneous/textfactory.h
network-web/adblock/adblockdialog.cpp
network-web/adblock/adblockdialog.h
network-web/adblock/adblockicon.cpp
network-web/adblock/adblockicon.h
network-web/adblock/adblockmanager.cpp
network-web/adblock/adblockmanager.h
network-web/adblock/adblockrequestinfo.cpp
network-web/adblock/adblockrequestinfo.h
network-web/basenetworkaccessmanager.cpp network-web/basenetworkaccessmanager.cpp
network-web/basenetworkaccessmanager.h network-web/basenetworkaccessmanager.h
network-web/cookiejar.cpp network-web/cookiejar.cpp
@ -244,6 +258,8 @@ set(SOURCES
network-web/downloader.h network-web/downloader.h
network-web/downloadmanager.cpp network-web/downloadmanager.cpp
network-web/downloadmanager.h network-web/downloadmanager.h
network-web/googlesuggest.cpp
network-web/googlesuggest.h
network-web/httpresponse.cpp network-web/httpresponse.cpp
network-web/httpresponse.h network-web/httpresponse.h
network-web/networkfactory.cpp network-web/networkfactory.cpp
@ -268,32 +284,32 @@ set(SOURCES
services/abstract/feed.h services/abstract/feed.h
services/abstract/gui/authenticationdetails.cpp services/abstract/gui/authenticationdetails.cpp
services/abstract/gui/authenticationdetails.h services/abstract/gui/authenticationdetails.h
services/abstract/gui/custommessagepreviewer.cpp
services/abstract/gui/custommessagepreviewer.h
services/abstract/gui/formaccountdetails.cpp services/abstract/gui/formaccountdetails.cpp
services/abstract/gui/formaccountdetails.h services/abstract/gui/formaccountdetails.h
services/abstract/gui/formcategorydetails.cpp
services/abstract/gui/formcategorydetails.h
services/abstract/gui/formfeeddetails.cpp
services/abstract/gui/formfeeddetails.h
services/abstract/gui/formaddeditlabel.cpp services/abstract/gui/formaddeditlabel.cpp
services/abstract/gui/formaddeditlabel.h services/abstract/gui/formaddeditlabel.h
services/abstract/gui/formaddeditprobe.cpp services/abstract/gui/formaddeditprobe.cpp
services/abstract/gui/formaddeditprobe.h services/abstract/gui/formaddeditprobe.h
services/abstract/gui/custommessagepreviewer.h services/abstract/gui/formcategorydetails.cpp
services/abstract/gui/custommessagepreviewer.cpp services/abstract/gui/formcategorydetails.h
services/abstract/gui/formfeeddetails.cpp
services/abstract/gui/formfeeddetails.h
services/abstract/importantnode.cpp services/abstract/importantnode.cpp
services/abstract/importantnode.h services/abstract/importantnode.h
services/abstract/label.cpp services/abstract/label.cpp
services/abstract/label.h services/abstract/label.h
services/abstract/labelsnode.cpp services/abstract/labelsnode.cpp
services/abstract/labelsnode.h services/abstract/labelsnode.h
services/abstract/search.cpp
services/abstract/search.h
services/abstract/searchsnode.cpp
services/abstract/searchsnode.h
services/abstract/recyclebin.cpp services/abstract/recyclebin.cpp
services/abstract/recyclebin.h services/abstract/recyclebin.h
services/abstract/rootitem.cpp services/abstract/rootitem.cpp
services/abstract/rootitem.h services/abstract/rootitem.h
services/abstract/search.cpp
services/abstract/search.h
services/abstract/searchsnode.cpp
services/abstract/searchsnode.h
services/abstract/serviceentrypoint.h services/abstract/serviceentrypoint.h
services/abstract/serviceroot.cpp services/abstract/serviceroot.cpp
services/abstract/serviceroot.h services/abstract/serviceroot.h
@ -317,6 +333,8 @@ set(SOURCES
services/gmail/gmailnetworkfactory.h services/gmail/gmailnetworkfactory.h
services/gmail/gmailserviceroot.cpp services/gmail/gmailserviceroot.cpp
services/gmail/gmailserviceroot.h services/gmail/gmailserviceroot.h
services/gmail/gui/emailpreviewer.cpp
services/gmail/gui/emailpreviewer.h
services/gmail/gui/emailrecipientcontrol.cpp services/gmail/gui/emailrecipientcontrol.cpp
services/gmail/gui/emailrecipientcontrol.h services/gmail/gui/emailrecipientcontrol.h
services/gmail/gui/formaddeditemail.cpp services/gmail/gui/formaddeditemail.cpp
@ -325,8 +343,6 @@ set(SOURCES
services/gmail/gui/formeditgmailaccount.h services/gmail/gui/formeditgmailaccount.h
services/gmail/gui/gmailaccountdetails.cpp services/gmail/gui/gmailaccountdetails.cpp
services/gmail/gui/gmailaccountdetails.h services/gmail/gui/gmailaccountdetails.h
services/gmail/gui/emailpreviewer.h
services/gmail/gui/emailpreviewer.cpp
services/greader/definitions.h services/greader/definitions.h
services/greader/greaderentrypoint.cpp services/greader/greaderentrypoint.cpp
services/greader/greaderentrypoint.h services/greader/greaderentrypoint.h
@ -367,6 +383,8 @@ set(SOURCES
services/reddit/redditsubscription.cpp services/reddit/redditsubscription.cpp
services/reddit/redditsubscription.h services/reddit/redditsubscription.h
services/standard/definitions.h services/standard/definitions.h
services/standard/gui/formdiscoverfeeds.cpp
services/standard/gui/formdiscoverfeeds.h
services/standard/gui/formeditstandardaccount.cpp services/standard/gui/formeditstandardaccount.cpp
services/standard/gui/formeditstandardaccount.h services/standard/gui/formeditstandardaccount.h
services/standard/gui/formstandardfeeddetails.cpp services/standard/gui/formstandardfeeddetails.cpp
@ -375,10 +393,10 @@ set(SOURCES
services/standard/gui/formstandardimportexport.h services/standard/gui/formstandardimportexport.h
services/standard/gui/standardfeeddetails.cpp services/standard/gui/standardfeeddetails.cpp
services/standard/gui/standardfeeddetails.h services/standard/gui/standardfeeddetails.h
services/standard/parsers/feedparser.cpp
services/standard/parsers/feedparser.h
services/standard/parsers/atomparser.cpp services/standard/parsers/atomparser.cpp
services/standard/parsers/atomparser.h services/standard/parsers/atomparser.h
services/standard/parsers/feedparser.cpp
services/standard/parsers/feedparser.h
services/standard/parsers/jsonparser.cpp services/standard/parsers/jsonparser.cpp
services/standard/parsers/jsonparser.h services/standard/parsers/jsonparser.h
services/standard/parsers/rdfparser.cpp services/standard/parsers/rdfparser.cpp
@ -417,22 +435,6 @@ set(SOURCES
services/tt-rss/ttrssserviceentrypoint.h services/tt-rss/ttrssserviceentrypoint.h
services/tt-rss/ttrssserviceroot.cpp services/tt-rss/ttrssserviceroot.cpp
services/tt-rss/ttrssserviceroot.h services/tt-rss/ttrssserviceroot.h
gui/reusable/discoverfeedsbutton.cpp
gui/reusable/discoverfeedsbutton.h
gui/reusable/locationlineedit.cpp
gui/reusable/locationlineedit.h
gui/webbrowser.cpp
gui/webbrowser.h
network-web/googlesuggest.cpp
network-web/googlesuggest.h
network-web/adblock/adblockdialog.cpp
network-web/adblock/adblockdialog.h
network-web/adblock/adblockicon.cpp
network-web/adblock/adblockicon.h
network-web/adblock/adblockmanager.cpp
network-web/adblock/adblockmanager.h
network-web/adblock/adblockrequestinfo.cpp
network-web/adblock/adblockrequestinfo.h
) )
set(UI_FILES set(UI_FILES
@ -440,21 +442,21 @@ set(UI_FILES
gui/dialogs/formaddaccount.ui gui/dialogs/formaddaccount.ui
gui/dialogs/formbackupdatabasesettings.ui gui/dialogs/formbackupdatabasesettings.ui
gui/dialogs/formdatabasecleanup.ui gui/dialogs/formdatabasecleanup.ui
gui/dialogs/formmain.ui
gui/dialogs/formlog.ui gui/dialogs/formlog.ui
gui/dialogs/formmain.ui
gui/dialogs/formmessagefiltersmanager.ui gui/dialogs/formmessagefiltersmanager.ui
gui/dialogs/formrestoredatabasesettings.ui gui/dialogs/formrestoredatabasesettings.ui
gui/dialogs/formsettings.ui gui/dialogs/formsettings.ui
gui/dialogs/formupdate.ui gui/dialogs/formupdate.ui
gui/itemdetails.ui
gui/newspaperpreviewer.ui
gui/notifications/articlelistnotification.ui
gui/notifications/notificationseditor.ui gui/notifications/notificationseditor.ui
gui/notifications/singlenotificationeditor.ui gui/notifications/singlenotificationeditor.ui
gui/notifications/articlelistnotification.ui
gui/notifications/toastnotification.ui gui/notifications/toastnotification.ui
gui/reusable/networkproxydetails.ui gui/reusable/networkproxydetails.ui
gui/itemdetails.ui
gui/richtexteditor/mrichtextedit.ui
gui/newspaperpreviewer.ui
gui/reusable/searchtextwidget.ui gui/reusable/searchtextwidget.ui
gui/richtexteditor/mrichtextedit.ui
gui/settings/settingsbrowsermail.ui gui/settings/settingsbrowsermail.ui
gui/settings/settingsdatabase.ui gui/settings/settingsdatabase.ui
gui/settings/settingsdownloads.ui gui/settings/settingsdownloads.ui
@ -462,44 +464,46 @@ set(UI_FILES
gui/settings/settingsgeneral.ui gui/settings/settingsgeneral.ui
gui/settings/settingsgui.ui gui/settings/settingsgui.ui
gui/settings/settingslocalization.ui gui/settings/settingslocalization.ui
gui/settings/settingsnotifications.ui
gui/settings/settingsnodejs.ui gui/settings/settingsnodejs.ui
gui/settings/settingsnotifications.ui
gui/settings/settingsshortcuts.ui gui/settings/settingsshortcuts.ui
gui/toolbars/toolbareditor.ui gui/toolbars/toolbareditor.ui
network-web/adblock/adblockdialog.ui
network-web/downloaditem.ui network-web/downloaditem.ui
network-web/downloadmanager.ui network-web/downloadmanager.ui
services/abstract/gui/authenticationdetails.ui services/abstract/gui/authenticationdetails.ui
services/abstract/gui/formaccountdetails.ui services/abstract/gui/formaccountdetails.ui
services/abstract/gui/formcategorydetails.ui
services/abstract/gui/formfeeddetails.ui
services/abstract/gui/formaddeditlabel.ui services/abstract/gui/formaddeditlabel.ui
services/abstract/gui/formaddeditprobe.ui services/abstract/gui/formaddeditprobe.ui
services/abstract/gui/formcategorydetails.ui
services/abstract/gui/formfeeddetails.ui
services/feedly/gui/feedlyaccountdetails.ui services/feedly/gui/feedlyaccountdetails.ui
services/gmail/gui/emailpreviewer.ui
services/gmail/gui/formaddeditemail.ui services/gmail/gui/formaddeditemail.ui
services/gmail/gui/gmailaccountdetails.ui services/gmail/gui/gmailaccountdetails.ui
services/gmail/gui/emailpreviewer.ui
services/greader/gui/greaderaccountdetails.ui services/greader/gui/greaderaccountdetails.ui
services/owncloud/gui/owncloudaccountdetails.ui services/owncloud/gui/owncloudaccountdetails.ui
services/reddit/gui/redditaccountdetails.ui services/reddit/gui/redditaccountdetails.ui
services/standard/gui/formdiscoverfeeds.ui
services/standard/gui/formstandardimportexport.ui services/standard/gui/formstandardimportexport.ui
services/standard/gui/standardfeeddetails.ui services/standard/gui/standardfeeddetails.ui
services/tt-rss/gui/formttrssnote.ui services/tt-rss/gui/formttrssnote.ui
services/tt-rss/gui/ttrssaccountdetails.ui services/tt-rss/gui/ttrssaccountdetails.ui
services/tt-rss/gui/ttrssfeeddetails.ui services/tt-rss/gui/ttrssfeeddetails.ui
network-web/adblock/adblockdialog.ui) )
if(USE_WEBENGINE) if(USE_WEBENGINE)
list(APPEND SOURCES list(APPEND SOURCES
# WebEngine-based web (and message) browser. # WebEngine-based web (and message) browser.
network-web/webengine/webenginepage.cpp
network-web/webengine/webenginepage.h
gui/webviewers/webengine/webengineviewer.cpp gui/webviewers/webengine/webengineviewer.cpp
gui/webviewers/webengine/webengineviewer.h gui/webviewers/webengine/webengineviewer.h
network-web/adblock/adblockurlinterceptor.cpp
network-web/adblock/adblockurlinterceptor.h
network-web/webengine/networkurlinterceptor.cpp network-web/webengine/networkurlinterceptor.cpp
network-web/webengine/networkurlinterceptor.h network-web/webengine/networkurlinterceptor.h
network-web/webengine/urlinterceptor.h network-web/webengine/urlinterceptor.h
network-web/adblock/adblockurlinterceptor.cpp network-web/webengine/webenginepage.cpp
network-web/adblock/adblockurlinterceptor.h network-web/webengine/webenginepage.h
) )
endif() endif()

View File

@ -32,6 +32,7 @@
#include "services/abstract/recyclebin.h" #include "services/abstract/recyclebin.h"
#include "services/abstract/serviceroot.h" #include "services/abstract/serviceroot.h"
#include <QClipboard>
#include <QCloseEvent> #include <QCloseEvent>
#include <QFileDialog> #include <QFileDialog>
#include <QRect> #include <QRect>
@ -323,7 +324,7 @@ void FormMain::updateAddItemMenu() {
root_menu->addAction(action_new_feed); root_menu->addAction(action_new_feed);
connect(action_new_feed, &QAction::triggered, activated_root, [activated_root]() { connect(action_new_feed, &QAction::triggered, activated_root, [activated_root]() {
activated_root->addNewFeed(activated_root); activated_root->addNewFeed(activated_root, QGuiApplication::clipboard()->text(QClipboard::Mode::Clipboard));
}); });
} }

View File

@ -206,8 +206,8 @@ void MessagesView::copyUrlOfSelectedArticles() const {
.toString(); .toString();
} }
if (qApp->clipboard() != nullptr && !urls.isEmpty()) { if (QGuiApplication::clipboard() != nullptr && !urls.isEmpty()) {
qApp->clipboard()->setText(urls.join(TextFactory::newline()), QClipboard::Mode::Clipboard); QGuiApplication::clipboard()->setText(urls.join(TextFactory::newline()), QClipboard::Mode::Clipboard);
} }
} }

View File

@ -0,0 +1,210 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "services/standard/gui/formdiscoverfeeds.h"
#include "gui/guiutilities.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "services/abstract/category.h"
#include "services/abstract/serviceroot.h"
#include "services/standard/standardfeed.h"
#include "services/standard/parsers/atomparser.h"
#include "services/standard/parsers/jsonparser.h"
#include "services/standard/parsers/rdfparser.h"
#include "services/standard/parsers/rssparser.h"
#include "services/standard/parsers/sitemapparser.h"
#include <QtConcurrentMap>
FormDiscoverFeeds::FormDiscoverFeeds(ServiceRoot* service_root,
RootItem* parent_to_select,
const QString& url,
QWidget* parent)
: QDialog(parent), m_serviceRoot(service_root), m_discoveredModel(new DiscoveredFeedsModel(this)) {
m_ui.setupUi(this);
GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("application-rss+xml")));
m_parsers = {new AtomParser({}), new RssParser({}), new RdfParser({}), new JsonParser({}), new SitemapParser({})};
m_btnImportSelectedFeeds =
m_ui.m_buttonBox->addButton(tr("Import selected feeds"), QDialogButtonBox::ButtonRole::ActionRole);
m_btnImportSelectedFeeds->setIcon(qApp->icons()->fromTheme(QSL("document-import")));
m_ui.m_btnDiscover->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
connect(m_ui.m_txtUrl->lineEdit(), &QLineEdit::textChanged, this, &FormDiscoverFeeds::onUrlChanged);
connect(m_btnImportSelectedFeeds, &QPushButton::clicked, this, &FormDiscoverFeeds::importSelectedFeeds);
connect(m_ui.m_btnDiscover, &QPushButton::clicked, this, &FormDiscoverFeeds::discoverFeeds);
connect(&m_watcherLookup, &QFutureWatcher<QList<StandardFeed*>>::progressValueChanged, this, [=](int prog) {
m_ui.m_pbDiscovery->setValue(prog);
qDebugNN << "progress";
});
connect(&m_watcherLookup, &QFutureWatcher<QList<StandardFeed*>>::finished, this, [=]() {
auto res = m_watcherLookup.future().result();
loadDiscoveredFeeds(res);
});
loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot);
m_ui.m_tvFeeds->setModel(m_discoveredModel);
m_ui.m_tvFeeds->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch);
m_ui.m_tvFeeds->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents);
m_ui.m_pbDiscovery->setVisible(false);
m_ui.m_txtUrl->lineEdit()->setText(url);
if (url.isEmpty()) {
emit m_ui.m_txtUrl->lineEdit()->textChanged(url);
}
m_ui.m_txtUrl->lineEdit()->selectAll();
m_ui.m_txtUrl->setFocus();
if (parent_to_select != nullptr) {
if (parent_to_select->kind() == RootItem::Kind::Category) {
m_ui.m_cmbParentCategory
->setCurrentIndex(m_ui.m_cmbParentCategory->findData(QVariant::fromValue((void*)parent_to_select)));
}
else if (parent_to_select->kind() == RootItem::Kind::Feed) {
int target_item = m_ui.m_cmbParentCategory->findData(QVariant::fromValue((void*)parent_to_select->parent()));
if (target_item >= 0) {
m_ui.m_cmbParentCategory->setCurrentIndex(target_item);
}
}
else {
m_ui.m_cmbParentCategory->setCurrentIndex(0);
}
}
}
FormDiscoverFeeds::~FormDiscoverFeeds() {
qDeleteAll(m_parsers);
}
void FormDiscoverFeeds::discoverFeeds() {
QString url = m_ui.m_txtUrl->lineEdit()->text();
std::function<QList<StandardFeed*>(const FeedParser*)> func = [=](const FeedParser* parser) -> QList<StandardFeed*> {
return parser->discoverFeeds(m_serviceRoot, url);
};
std::function<QList<StandardFeed*>(QList<StandardFeed*>&, const QList<StandardFeed*>&)> reducer =
[=](QList<StandardFeed*>& res, const QList<StandardFeed*>& interm) -> QList<StandardFeed*> {
res.append(interm);
return res;
};
#if QT_VERSION_MAJOR == 5
QFuture<QList<StandardFeed*>> fut = QtConcurrent::mappedReduced<QList<StandardFeed*>>(m_parsers, func, reducer);
#else
QFuture<QList<StandardFeed*>> fut =
QtConcurrent::mappedReduced<QList<StandardFeed*>>(qApp->workHorsePool(), m_parsers, func, reducer);
#endif
m_watcherLookup.setFuture(fut);
m_ui.m_pbDiscovery->setMaximum(m_parsers.size());
m_ui.m_pbDiscovery->setValue(0);
m_ui.m_pbDiscovery->setVisible(true);
}
void FormDiscoverFeeds::onUrlChanged(const QString& new_url) {
if (QUrl(new_url).isValid()) {
m_ui.m_txtUrl->setStatus(WidgetWithStatus::StatusType::Ok, tr("URL is valid."));
}
else {
m_ui.m_txtUrl->setStatus(WidgetWithStatus::StatusType::Error, tr("URL is NOT valid."));
}
}
void FormDiscoverFeeds::loadCategories(const QList<Category*>& categories, RootItem* root_item) {
m_ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue((void*)root_item));
for (Category* category : categories) {
m_ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue((void*)category));
}
}
void FormDiscoverFeeds::addSingleFeed(StandardFeed* feed) {
/*
QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(this,
selected_item,
feed->source(),
qApp->mainFormWidget()));
form_pointer->addEditFeed<StandardFeed>();
*/
}
void FormDiscoverFeeds::importSelectedFeeds() {}
void FormDiscoverFeeds::loadDiscoveredFeeds(const QList<StandardFeed*>& feeds) {
m_ui.m_pbDiscovery->setVisible(false);
m_discoveredModel->setDiscoveredFeeds(feeds);
qDebugNN << "finish";
}
DiscoveredFeedsModel::DiscoveredFeedsModel(QObject* parent) : QAbstractListModel(parent) {}
int DiscoveredFeedsModel::rowCount(const QModelIndex& parent) const {
return m_discoveredFeeds.size();
}
int DiscoveredFeedsModel::columnCount(const QModelIndex& parent) const {
return 2;
}
QVariant DiscoveredFeedsModel::data(const QModelIndex& index, int role) const {
switch (role) {
case Qt::ItemDataRole::DisplayRole: {
if (index.column() == 0) {
return m_discoveredFeeds.at(index.row())->title();
}
else {
return StandardFeed::typeToString(m_discoveredFeeds.at(index.row())->type());
}
}
case Qt::ItemDataRole::DecorationRole: {
if (index.column() == 0) {
return m_discoveredFeeds.at(index.row())->fullIcon();
}
}
default:
return {};
}
}
QList<StandardFeed*> DiscoveredFeedsModel::discoveredFeeds() const {
return m_discoveredFeeds;
}
void DiscoveredFeedsModel::setDiscoveredFeeds(const QList<StandardFeed*>& newDiscoveredFeeds) {
m_discoveredFeeds = newDiscoveredFeeds;
emit layoutAboutToBeChanged();
emit layoutChanged();
}
QVariant DiscoveredFeedsModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation == Qt::Orientation::Vertical) {
return {};
}
static QStringList headers = {tr("Title"), tr("Type")};
if (role == Qt::ItemDataRole::DisplayRole) {
return headers.at(section);
}
return {};
}

View File

@ -0,0 +1,65 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef FORMDISCOVERFEEDS_H
#define FORMDISCOVERFEEDS_H
#include <QDialog>
#include "ui_formdiscoverfeeds.h"
#include "services/standard/parsers/feedparser.h"
#include <QFutureWatcher>
class ServiceRoot;
class RootItem;
class Category;
class DiscoveredFeedsModel : public QAbstractListModel {
Q_OBJECT
public:
explicit DiscoveredFeedsModel(QObject* parent = {});
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
virtual int rowCount(const QModelIndex& parent) const;
virtual int columnCount(const QModelIndex& parent) const;
virtual QVariant data(const QModelIndex& index, int role) const;
QList<StandardFeed*> discoveredFeeds() const;
void setDiscoveredFeeds(const QList<StandardFeed*>& newDiscoveredFeeds);
private:
QList<StandardFeed*> m_discoveredFeeds;
};
class FormDiscoverFeeds : public QDialog {
Q_OBJECT
public:
explicit FormDiscoverFeeds(ServiceRoot* service_root,
RootItem* parent_to_select = {},
const QString& url = {},
QWidget* parent = {});
virtual ~FormDiscoverFeeds();
private slots:
void discoverFeeds();
void onUrlChanged(const QString& new_url);
void addSingleFeed(StandardFeed* feed);
void importSelectedFeeds();
private:
void loadDiscoveredFeeds(const QList<StandardFeed*>& feeds);
void loadCategories(const QList<Category*>& categories, RootItem* root_item);
private:
Ui::FormDiscoverFeeds m_ui;
QPushButton* m_btnImportSelectedFeeds;
ServiceRoot* m_serviceRoot;
QList<FeedParser*> m_parsers;
QFutureWatcher<QList<StandardFeed*>> m_watcherLookup;
DiscoveredFeedsModel* m_discoveredModel;
};
#endif // FORMDISCOVERFEEDS_H

View File

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FormDiscoverFeeds</class>
<widget class="QDialog" name="FormDiscoverFeeds">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>406</width>
<height>334</height>
</rect>
</property>
<property name="windowTitle">
<string>Discover feeds</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtUrl</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="LineEditWithStatus" name="m_txtUrl" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_btnDiscover">
<property name="text">
<string>Discover!</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="m_gbFeeds">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Discovered feeds</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="1" column="0" colspan="2">
<widget class="QTableView" name="m_tvFeeds">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="m_lblParentCategory">
<property name="text">
<string>Target parent folder</string>
</property>
<property name="buddy">
<cstring>m_cmbParentCategory</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QComboBox" name="m_cmbParentCategory">
<property name="toolTip">
<string>Select parent item for your feed.</string>
</property>
<property name="iconSize">
<size>
<width>12</width>
<height>12</height>
</size>
</property>
<property name="frame">
<bool>true</bool>
</property>
</widget>
</item>
<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>
</layout>
</item>
<item row="0" column="0" colspan="2">
<widget class="QProgressBar" name="m_pbDiscovery">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>5</height>
</size>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LineEditWithStatus</class>
<extends>QWidget</extends>
<header>lineeditwithstatus.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>m_buttonBox</sender>
<signal>accepted()</signal>
<receiver>FormDiscoverFeeds</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>m_buttonBox</sender>
<signal>rejected()</signal>
<receiver>FormDiscoverFeeds</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -75,7 +75,7 @@ void FormStandardFeedDetails::apply() {
StandardFeed::Type type = StandardFeed::Type type =
static_cast<StandardFeed::Type>(m_standardFeedDetails->m_ui.m_cmbType static_cast<StandardFeed::Type>(m_standardFeedDetails->m_ui.m_cmbType
->itemData(m_standardFeedDetails->m_ui.m_cmbType->currentIndex()) ->itemData(m_standardFeedDetails->m_ui.m_cmbType->currentIndex())
.value<int>()); .toInt());
// Setup data for new_feed. // Setup data for new_feed.
std_feed->setTitle(m_standardFeedDetails->m_ui.m_txtTitle->lineEdit()->text().simplified()); std_feed->setTitle(m_standardFeedDetails->m_ui.m_txtTitle->lineEdit()->text().simplified());

View File

@ -12,7 +12,6 @@
#include "services/abstract/category.h" #include "services/abstract/category.h"
#include "services/standard/definitions.h" #include "services/standard/definitions.h"
#include <QClipboard>
#include <QFileDialog> #include <QFileDialog>
#include <QImageReader> #include <QImageReader>
#include <QMenu> #include <QMenu>
@ -251,8 +250,9 @@ void StandardFeedDetails::onDescriptionChanged(const QString& new_description) {
} }
void StandardFeedDetails::onUrlChanged(const QString& new_url) { void StandardFeedDetails::onUrlChanged(const QString& new_url) {
if (sourceType() == StandardFeed::SourceType::Url) { switch (sourceType()) {
if (QRegularExpression(QSL(URL_REGEXP)).match(new_url).hasMatch()) { case StandardFeed::SourceType::Url: {
if (QUrl(new_url).isValid()) {
m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Ok, tr("The URL is ok.")); m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Ok, tr("The URL is ok."));
} }
else if (!new_url.simplified().isEmpty()) { else if (!new_url.simplified().isEmpty()) {
@ -263,8 +263,11 @@ void StandardFeedDetails::onUrlChanged(const QString& new_url) {
else { else {
m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Error, tr("The URL is empty.")); m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Error, tr("The URL is empty."));
} }
break;
} }
else if (sourceType() == StandardFeed::SourceType::Script) {
case StandardFeed::SourceType::Script: {
try { try {
TextFactory::tokenizeProcessArguments(new_url); TextFactory::tokenizeProcessArguments(new_url);
m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Ok, tr("Source is ok.")); m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Ok, tr("Source is ok."));
@ -272,8 +275,21 @@ void StandardFeedDetails::onUrlChanged(const QString& new_url) {
catch (const ApplicationException& ex) { catch (const ApplicationException& ex) {
m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Error, tr("Error: %1").arg(ex.message())); m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Error, tr("Error: %1").arg(ex.message()));
} }
break;
}
case StandardFeed::SourceType::LocalFile: {
if (QFile::exists(new_url)) {
m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Ok, tr("File exists."));
} }
else { else {
m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Error, tr("File does not exist."));
}
break;
}
default:
m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Ok, tr("The source is ok.")); m_ui.m_txtSource->setStatus(LineEditWithStatus::StatusType::Ok, tr("The source is ok."));
} }
} }
@ -358,9 +374,9 @@ void StandardFeedDetails::prepareForNewFeed(RootItem* parent_to_select, const QS
if (!url.isEmpty()) { if (!url.isEmpty()) {
m_ui.m_txtSource->textEdit()->setPlainText(url); m_ui.m_txtSource->textEdit()->setPlainText(url);
} }
else if (Application::clipboard()->mimeData()->hasText()) { /*else if (Application::clipboard()->mimeData()->hasText()) {
m_ui.m_txtSource->textEdit()->setPlainText(Application::clipboard()->text()); m_ui.m_txtSource->textEdit()->setPlainText(Application::clipboard()->text());
} }*/
m_ui.m_txtSource->setFocus(); m_ui.m_txtSource->setFocus();
m_ui.m_txtSource->textEdit()->selectAll(); m_ui.m_txtSource->textEdit()->selectAll();

View File

@ -23,6 +23,10 @@ AtomParser::AtomParser(const QString& data) : FeedParser(data) {
AtomParser::~AtomParser() {} AtomParser::~AtomParser() {}
QList<StandardFeed*> AtomParser::discoverFeeds(ServiceRoot* root, const QUrl& url) const {
return {};
}
QPair<StandardFeed*, QList<IconLocation>> AtomParser::guessFeed(const QByteArray& content, QPair<StandardFeed*, QList<IconLocation>> AtomParser::guessFeed(const QByteArray& content,
const QString& content_type) const { const QString& content_type) const {
QString xml_schema_encoding = QSL(DEFAULT_FEED_ENCODING); QString xml_schema_encoding = QSL(DEFAULT_FEED_ENCODING);

View File

@ -15,6 +15,8 @@ class AtomParser : public FeedParser {
explicit AtomParser(const QString& data); explicit AtomParser(const QString& data);
virtual ~AtomParser(); virtual ~AtomParser();
virtual QList<StandardFeed*> discoverFeeds(ServiceRoot* root, const QUrl& url) const;
virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content, virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content,
const QString& content_type) const; const QString& content_type) const;

View File

@ -41,7 +41,7 @@ FeedParser::FeedParser(QString data, bool is_xml)
FeedParser::~FeedParser() {} FeedParser::~FeedParser() {}
QStringList FeedParser::discoverFeeds(const QUrl& url) const { QList<StandardFeed*> FeedParser::discoverFeeds(ServiceRoot* root, const QUrl& url) const {
return {}; return {};
} }

View File

@ -11,8 +11,7 @@
#include "core/message.h" #include "core/message.h"
#include "definitions/typedefs.h" #include "definitions/typedefs.h"
#include "services/standard/standardfeed.h"
class StandardFeed;
// Base class for all XML-based feed parsers. // Base class for all XML-based feed parsers.
class FeedParser { class FeedParser {
@ -21,7 +20,7 @@ class FeedParser {
virtual ~FeedParser(); virtual ~FeedParser();
// Returns list of absolute URLs of discovered feeds from provided base URL. // Returns list of absolute URLs of discovered feeds from provided base URL.
virtual QStringList discoverFeeds(const QUrl& url) const; virtual QList<StandardFeed*> discoverFeeds(ServiceRoot* root, const QUrl& url) const;
// Guesses feed. // Guesses feed.
virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content, virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content,

View File

@ -18,6 +18,10 @@ JsonParser::JsonParser(const QString& data) : FeedParser(data, false) {}
JsonParser::~JsonParser() {} JsonParser::~JsonParser() {}
QList<StandardFeed*> JsonParser::discoverFeeds(ServiceRoot* root, const QUrl& url) const {
return {};
}
QPair<StandardFeed*, QList<IconLocation>> JsonParser::guessFeed(const QByteArray& content, QPair<StandardFeed*, QList<IconLocation>> JsonParser::guessFeed(const QByteArray& content,
const QString& content_type) const { const QString& content_type) const {
if (content_type.contains(QSL("json"), Qt::CaseSensitivity::CaseInsensitive) || if (content_type.contains(QSL("json"), Qt::CaseSensitivity::CaseInsensitive) ||

View File

@ -12,6 +12,8 @@ class JsonParser : public FeedParser {
explicit JsonParser(const QString& data); explicit JsonParser(const QString& data);
virtual ~JsonParser(); virtual ~JsonParser();
virtual QList<StandardFeed*> discoverFeeds(ServiceRoot* root, const QUrl& url) const;
virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content, virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content,
const QString& content_type) const; const QString& content_type) const;

View File

@ -17,6 +17,10 @@ RdfParser::RdfParser(const QString& data)
RdfParser::~RdfParser() {} RdfParser::~RdfParser() {}
QList<StandardFeed*> RdfParser::discoverFeeds(ServiceRoot* root, const QUrl& url) const {
return {};
}
QPair<StandardFeed*, QList<IconLocation>> RdfParser::guessFeed(const QByteArray& content, QPair<StandardFeed*, QList<IconLocation>> RdfParser::guessFeed(const QByteArray& content,
const QString& content_type) const { const QString& content_type) const {
QString xml_schema_encoding = QSL(DEFAULT_FEED_ENCODING); QString xml_schema_encoding = QSL(DEFAULT_FEED_ENCODING);

View File

@ -14,6 +14,8 @@ class RdfParser : public FeedParser {
explicit RdfParser(const QString& data); explicit RdfParser(const QString& data);
virtual ~RdfParser(); virtual ~RdfParser();
virtual QList<StandardFeed*> discoverFeeds(ServiceRoot* root, const QUrl& url) const;
virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content, virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content,
const QString& content_type) const; const QString& content_type) const;

View File

@ -3,7 +3,10 @@
#include "services/standard/parsers/rssparser.h" #include "services/standard/parsers/rssparser.h"
#include "exceptions/applicationexception.h" #include "exceptions/applicationexception.h"
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include "network-web/networkfactory.h"
#include "services/standard/definitions.h" #include "services/standard/definitions.h"
#include "services/standard/standardfeed.h" #include "services/standard/standardfeed.h"
@ -15,6 +18,89 @@ RssParser::RssParser(const QString& data) : FeedParser(data) {}
RssParser::~RssParser() {} RssParser::~RssParser() {}
QList<StandardFeed*> RssParser::discoverFeeds(ServiceRoot* root, const QUrl& url) const {
QList<StandardFeed*> feeds;
// Download URL.
int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray data;
auto res = NetworkFactory::performNetworkOperation(url.toString(),
timeout,
{},
data,
QNetworkAccessManager::Operation::GetOperation,
{},
{},
{},
{},
root->networkProxy());
if (res.m_networkError == QNetworkReply::NetworkError::NoError) {
// Parse result, might be HTML or directly the feed file.
try {
auto guessed_feed = guessFeed(data, res.m_contentType);
guessed_feed.first->setSource(url.toString());
return {guessed_feed.first};
}
catch (...) {
qDebugNN << LOGSEC_CORE << QUOTE_W_SPACE(url) << "is not a direct feed file.";
}
QRegularExpression rx(QSL(FEED_REGEX_MATCHER), QRegularExpression::PatternOption::CaseInsensitiveOption);
QRegularExpression rx_href(QSL(FEED_HREF_REGEX_MATCHER), QRegularExpression::PatternOption::CaseInsensitiveOption);
rx_href.optimize();
QRegularExpressionMatchIterator it_rx = rx.globalMatch(QString::fromUtf8(data));
while (it_rx.hasNext()) {
QRegularExpressionMatch mat_tx = it_rx.next();
QString link_tag = mat_tx.captured();
QString feed_link = rx_href.match(link_tag).captured(1);
if (feed_link.startsWith(QL1S("//"))) {
feed_link = QSL(URI_SCHEME_HTTP) + feed_link.mid(2);
}
else if (feed_link.startsWith(QL1C('/'))) {
feed_link = url.toString(QUrl::UrlFormattingOption::RemovePath | QUrl::UrlFormattingOption::RemoveQuery |
QUrl::UrlFormattingOption::StripTrailingSlash) +
feed_link;
}
QByteArray data;
auto res = NetworkFactory::performNetworkOperation(feed_link,
timeout,
{},
data,
QNetworkAccessManager::Operation::GetOperation,
{},
{},
{},
{},
root->networkProxy());
if (res.m_networkError == QNetworkReply::NetworkError::NoError) {
// Parse result, might be HTML or directly the feed file.
try {
auto guessed_feed = guessFeed(data, res.m_contentType);
guessed_feed.first->setSource(url.toString());
feeds.append(guessed_feed.first);
}
catch (const ApplicationException& ex) {
qDebugNN << LOGSEC_CORE << QUOTE_W_SPACE(url)
<< " should be direct link to feed file but was not recognized:" << QUOTE_W_SPACE_DOT(ex.message());
}
}
}
}
return feeds;
}
QPair<StandardFeed*, QList<IconLocation>> RssParser::guessFeed(const QByteArray& content, QPair<StandardFeed*, QList<IconLocation>> RssParser::guessFeed(const QByteArray& content,
const QString& content_type) const { const QString& content_type) const {
QString xml_schema_encoding = QSL(DEFAULT_FEED_ENCODING); QString xml_schema_encoding = QSL(DEFAULT_FEED_ENCODING);

View File

@ -14,6 +14,8 @@ class RssParser : public FeedParser {
explicit RssParser(const QString& data); explicit RssParser(const QString& data);
virtual ~RssParser(); virtual ~RssParser();
virtual QList<StandardFeed*> discoverFeeds(ServiceRoot* root, const QUrl& url) const;
virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content, virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content,
const QString& content_type) const; const QString& content_type) const;

View File

@ -20,6 +20,10 @@ SitemapParser::SitemapParser(const QString& data) : FeedParser(data) {}
SitemapParser::~SitemapParser() {} SitemapParser::~SitemapParser() {}
QList<StandardFeed*> SitemapParser::discoverFeeds(ServiceRoot* root, const QUrl& url) const {
return {};
}
QPair<StandardFeed*, QList<IconLocation>> SitemapParser::guessFeed(const QByteArray& content, QPair<StandardFeed*, QList<IconLocation>> SitemapParser::guessFeed(const QByteArray& content,
const QString& content_type) const { const QString& content_type) const {
QByteArray uncompressed_content; QByteArray uncompressed_content;

View File

@ -12,6 +12,8 @@ class SitemapParser : public FeedParser {
explicit SitemapParser(const QString& data); explicit SitemapParser(const QString& data);
virtual ~SitemapParser(); virtual ~SitemapParser();
virtual QList<StandardFeed*> discoverFeeds(ServiceRoot* root, const QUrl& url) const;
virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content, virtual QPair<StandardFeed*, QList<IconLocation>> guessFeed(const QByteArray& content,
const QString& content_type) const; const QString& content_type) const;

View File

@ -15,6 +15,7 @@
#include "network-web/networkfactory.h" #include "network-web/networkfactory.h"
#include "services/abstract/gui/formcategorydetails.h" #include "services/abstract/gui/formcategorydetails.h"
#include "services/standard/definitions.h" #include "services/standard/definitions.h"
#include "services/standard/gui/formdiscoverfeeds.h"
#include "services/standard/gui/formeditstandardaccount.h" #include "services/standard/gui/formeditstandardaccount.h"
#include "services/standard/gui/formstandardfeeddetails.h" #include "services/standard/gui/formstandardfeeddetails.h"
#include "services/standard/gui/formstandardimportexport.h" #include "services/standard/gui/formstandardimportexport.h"
@ -33,7 +34,6 @@
#endif #endif
#include <QAction> #include <QAction>
#include <QClipboard>
#include <QSqlTableModel> #include <QSqlTableModel>
#include <QStack> #include <QStack>
#include <QTextCodec> #include <QTextCodec>
@ -135,12 +135,22 @@ void StandardServiceRoot::addNewFeed(RootItem* selected_item, const QString& url
return; return;
} }
QScopedPointer<FormDiscoverFeeds> form_discover(new FormDiscoverFeeds(this,
selected_item,
url,
qApp->mainFormWidget()));
form_discover->exec();
/*
QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(this, QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(this,
selected_item, selected_item,
url, url,
qApp->mainFormWidget())); qApp->mainFormWidget()));
form_pointer->addEditFeed<StandardFeed>(); form_pointer->addEditFeed<StandardFeed>();
*/
qApp->feedUpdateLock()->unlock(); qApp->feedUpdateLock()->unlock();
} }

View File

@ -10,7 +10,6 @@
#include "services/tt-rss/ttrssnetworkfactory.h" #include "services/tt-rss/ttrssnetworkfactory.h"
#include "services/tt-rss/ttrssserviceroot.h" #include "services/tt-rss/ttrssserviceroot.h"
#include <QClipboard>
#include <QMimeData> #include <QMimeData>
#include <QTimer> #include <QTimer>
@ -69,9 +68,11 @@ void FormTtRssFeedDetails::loadFeedData() {
if (!m_urlToProcess.isEmpty()) { if (!m_urlToProcess.isEmpty()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(m_urlToProcess); m_feedDetails->ui.m_txtUrl->lineEdit()->setText(m_urlToProcess);
} }
/*
else if (Application::clipboard()->mimeData()->hasText()) { else if (Application::clipboard()->mimeData()->hasText()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(Application::clipboard()->text()); m_feedDetails->ui.m_txtUrl->lineEdit()->setText(Application::clipboard()->text());
} }
*/
m_feedDetails->ui.m_txtUrl->lineEdit()->selectAll(); m_feedDetails->ui.m_txtUrl->lineEdit()->selectAll();
m_feedDetails->ui.m_txtUrl->setFocus(); m_feedDetails->ui.m_txtUrl->setFocus();

View File

@ -19,7 +19,6 @@
#include "services/tt-rss/ttrssnetworkfactory.h" #include "services/tt-rss/ttrssnetworkfactory.h"
#include "services/tt-rss/ttrssserviceentrypoint.h" #include "services/tt-rss/ttrssserviceentrypoint.h"
#include <QClipboard>
#include <QPair> #include <QPair>
#include <QSqlTableModel> #include <QSqlTableModel>