diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a4a0d2b1..eea59a14d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,9 @@ # IS_FLATPAK_BUILD - Set to "ON" when building RSS Guard with Flatpak. # FORCE_BUNDLE_ICONS - Forcibly bundles icons into executables. # ENABLE_COMPRESSED_SITEMAP - Set to "ON" if you want to enable support for "sitemap.xml.gz" format. -# This requires "zlib" library. +# This requires "zlib" library and if you want to use specific +# zlib location, then use "ZLIB_ROOT" variable, for example +# -DZLIB_ROOT="C:\\zlib" # USE_WEBENGINE - if specified, then QtWebEngine module for internal web browser is used. # Otherwise simple text component is used and some features will be disabled. # Default value is "false". If QtWebEngine is installed during compilation, then diff --git a/src/librssguard/services/abstract/gui/formcategorydetails.cpp b/src/librssguard/services/abstract/gui/formcategorydetails.cpp index f94946299..b21507ac4 100644 --- a/src/librssguard/services/abstract/gui/formcategorydetails.cpp +++ b/src/librssguard/services/abstract/gui/formcategorydetails.cpp @@ -64,10 +64,10 @@ void FormCategoryDetails::loadCategoryData() { if (m_parentToSelect != nullptr) { if (m_parentToSelect->kind() == RootItem::Kind::Category) { m_ui->m_cmbParentCategory - ->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*)m_parentToSelect))); + ->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue(m_parentToSelect))); } else if (m_parentToSelect->kind() == RootItem::Kind::Feed) { - int target_item = m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*)m_parentToSelect->parent())); + int target_item = m_ui->m_cmbParentCategory->findData(QVariant::fromValue(m_parentToSelect->parent())); if (target_item >= 0) { m_ui->m_cmbParentCategory->setCurrentIndex(target_item); @@ -79,7 +79,7 @@ void FormCategoryDetails::loadCategoryData() { GuiUtilities::applyDialogProperties(*this, m_category->fullIcon(), tr("Edit \"%1\"").arg(m_category->title())); m_ui->m_cmbParentCategory - ->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*)m_category->parent()))); + ->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue(m_category->parent()))); } m_ui->m_txtTitle->lineEdit()->setText(m_category->title()); @@ -90,9 +90,7 @@ void FormCategoryDetails::loadCategoryData() { } void FormCategoryDetails::apply() { - RootItem* parent = - static_cast(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()) - .value()); + RootItem* parent = m_ui->m_cmbParentCategory->currentData().value(); m_category->setTitle(m_ui->m_txtTitle->lineEdit()->text()); m_category->setDescription(m_ui->m_txtDescription->lineEdit()->text()); @@ -207,7 +205,7 @@ void FormCategoryDetails::initialize() { void FormCategoryDetails::loadCategories(const QList& categories, RootItem* root_item, Category* input_category) { - m_ui->m_cmbParentCategory->addItem(root_item->icon(), root_item->title(), QVariant::fromValue((void*)root_item)); + m_ui->m_cmbParentCategory->addItem(root_item->icon(), root_item->title(), QVariant::fromValue(root_item)); for (Category* category : categories) { if (input_category != nullptr && (category == input_category || category->isChildOf(input_category))) { @@ -219,6 +217,6 @@ void FormCategoryDetails::loadCategories(const QList& categories, m_ui->m_cmbParentCategory->addItem(category->data(FDS_MODEL_TITLE_INDEX, Qt::DecorationRole).value(), category->title(), - QVariant::fromValue((void*)category)); + QVariant::fromValue(category)); } } diff --git a/src/librssguard/services/standard/gui/formdiscoverfeeds.cpp b/src/librssguard/services/standard/gui/formdiscoverfeeds.cpp index e9125acfa..0d25d6ff3 100644 --- a/src/librssguard/services/standard/gui/formdiscoverfeeds.cpp +++ b/src/librssguard/services/standard/gui/formdiscoverfeeds.cpp @@ -10,6 +10,7 @@ #include "services/abstract/category.h" #include "services/abstract/serviceroot.h" #include "services/standard/definitions.h" +#include "services/standard/gui/formstandardfeeddetails.h" #include "services/standard/standardfeed.h" #include "services/standard/parsers/atomparser.h" @@ -32,26 +33,29 @@ FormDiscoverFeeds::FormDiscoverFeeds(ServiceRoot* service_root, m_parsers = {new AtomParser({}), new RssParser({}), new RdfParser({}), new JsonParser({}), new SitemapParser({})}; m_btnGoAdvanced = m_ui.m_buttonBox->addButton(tr("Close && &advanced mode"), QDialogButtonBox::ButtonRole::NoRole); - m_btnImportSelectedFeeds = - m_ui.m_buttonBox->addButton(tr("Import selected feeds"), QDialogButtonBox::ButtonRole::ActionRole); - m_btnGoAdvanced ->setToolTip(tr("Close this dialog and display dialog for adding individual feeds with advanced options.")); + m_ui.m_btnSelecAll->setIcon(qApp->icons()->fromTheme(QSL("dialog-yes"), QSL("edit-select-all"))); + m_ui.m_btnSelectNone->setIcon(qApp->icons()->fromTheme(QSL("dialog-no"), QSL("edit-select-none"))); + m_ui.m_btnAddIndividually->setIcon(qApp->icons()->fromTheme(QSL("list-add"))); m_btnGoAdvanced->setIcon(qApp->icons()->fromTheme(QSL("system-upgrade"))); - m_btnImportSelectedFeeds->setIcon(qApp->icons()->fromTheme(QSL("document-import"))); + m_ui.m_btnImportSelected->setIcon(qApp->icons()->fromTheme(QSL("document-import"))); + m_ui.m_buttonBox->button(QDialogButtonBox::StandardButton::Close) + ->setIcon(qApp->icons()->fromTheme(QSL("window-close"))); 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_btnImportSelected, &QPushButton::clicked, this, &FormDiscoverFeeds::importSelectedFeeds); + connect(m_ui.m_btnSelecAll, &QPushButton::clicked, m_discoveredModel, &DiscoveredFeedsModel::checkAllItems); + connect(m_ui.m_btnSelectNone, &QPushButton::clicked, m_discoveredModel, &DiscoveredFeedsModel::uncheckAllItems); + connect(m_ui.m_btnAddIndividually, &QPushButton::clicked, this, &FormDiscoverFeeds::addSingleFeed); connect(m_btnGoAdvanced, &QPushButton::clicked, this, &FormDiscoverFeeds::userWantsAdvanced); connect(m_ui.m_btnDiscover, &QPushButton::clicked, this, &FormDiscoverFeeds::discoverFeeds); - connect(&m_watcherLookup, &QFutureWatcher>::progressValueChanged, this, &FormDiscoverFeeds::onDiscoveryProgress); - connect(&m_watcherLookup, &QFutureWatcher>::finished, this, @@ -64,6 +68,11 @@ FormDiscoverFeeds::FormDiscoverFeeds(ServiceRoot* service_root, m_ui.m_tvFeeds->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); m_ui.m_tvFeeds->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents); + connect(m_ui.m_tvFeeds->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + &FormDiscoverFeeds::onFeedSelectionChanged); + m_ui.m_pbDiscovery->setVisible(false); m_ui.m_txtUrl->lineEdit()->setText(url); @@ -77,10 +86,10 @@ FormDiscoverFeeds::FormDiscoverFeeds(ServiceRoot* service_root, 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))); + ->setCurrentIndex(m_ui.m_cmbParentCategory->findData(QVariant::fromValue(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())); + int target_item = m_ui.m_cmbParentCategory->findData(QVariant::fromValue(parent_to_select->parent())); if (target_item >= 0) { m_ui.m_cmbParentCategory->setCurrentIndex(target_item); @@ -109,6 +118,16 @@ void FormDiscoverFeeds::onDiscoveryFinished() { setEnabled(true); } +StandardFeed* FormDiscoverFeeds::selectedFeed() const { + RootItem* it = m_discoveredModel->itemForIndex(m_ui.m_tvFeeds->currentIndex()); + + return qobject_cast(it); +} + +RootItem* FormDiscoverFeeds::targetParent() const { + return m_ui.m_cmbParentCategory->currentData().value(); +} + FormDiscoverFeeds::~FormDiscoverFeeds() { qDeleteAll(m_parsers); @@ -168,26 +187,34 @@ void FormDiscoverFeeds::onUrlChanged(const QString& new_url) { } void FormDiscoverFeeds::loadCategories(const QList& categories, RootItem* root_item) { - m_ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue((void*)root_item)); + m_ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue(root_item)); for (Category* category : categories) { - m_ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue((void*)category)); + m_ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue(category)); } } -void FormDiscoverFeeds::addSingleFeed(StandardFeed* feed) { - /* - QScopedPointer form_pointer(new FormStandardFeedDetails(this, - selected_item, - feed->source(), +void FormDiscoverFeeds::addSingleFeed() { + auto* fd = selectedFeed(); + + if (fd == nullptr) { + return; + } + + QScopedPointer form_pointer(new FormStandardFeedDetails(m_serviceRoot, + targetParent(), + fd->source(), qApp->mainFormWidget())); form_pointer->addEditFeed(); - */ } void FormDiscoverFeeds::importSelectedFeeds() {} +void FormDiscoverFeeds::onFeedSelectionChanged() { + m_ui.m_btnAddIndividually->setEnabled(selectedFeed() != nullptr); +} + void FormDiscoverFeeds::userWantsAdvanced() { setResult(ADVANCED_FEED_ADD_DIALOG_CODE); close(); @@ -237,3 +264,19 @@ QVariant DiscoveredFeedsModel::headerData(int section, Qt::Orientation orientati return {}; } + +void FormDiscoverFeeds::closeEvent(QCloseEvent* event) { + try { + // Wait for discovery to finish. + if (m_watcherLookup.isRunning()) { + m_watcherLookup.result(); + } + } + catch (...) { + } + + // Clear all remaining items. + m_discoveredModel->setRootItem(nullptr); + + QDialog::closeEvent(event); +} diff --git a/src/librssguard/services/standard/gui/formdiscoverfeeds.h b/src/librssguard/services/standard/gui/formdiscoverfeeds.h index dcd35989f..69dc8a2af 100644 --- a/src/librssguard/services/standard/gui/formdiscoverfeeds.h +++ b/src/librssguard/services/standard/gui/formdiscoverfeeds.h @@ -37,16 +37,23 @@ class FormDiscoverFeeds : public QDialog { QWidget* parent = {}); virtual ~FormDiscoverFeeds(); + protected: + virtual void closeEvent(QCloseEvent* event); + private slots: void discoverFeeds(); void onUrlChanged(const QString& new_url); - void addSingleFeed(StandardFeed* feed); + void addSingleFeed(); void importSelectedFeeds(); + void onFeedSelectionChanged(); void onDiscoveryProgress(int progress); void onDiscoveryFinished(); private: + StandardFeed* selectedFeed() const; + RootItem* targetParent() const; + QList discoverFeedsWithParser(const FeedParser* parser, const QString& url); void userWantsAdvanced(); @@ -55,7 +62,6 @@ class FormDiscoverFeeds : public QDialog { private: Ui::FormDiscoverFeeds m_ui; - QPushButton* m_btnImportSelectedFeeds; QPushButton* m_btnGoAdvanced; ServiceRoot* m_serviceRoot; QList m_parsers; diff --git a/src/librssguard/services/standard/gui/formdiscoverfeeds.ui b/src/librssguard/services/standard/gui/formdiscoverfeeds.ui index 1fc2e3d47..9c016f319 100644 --- a/src/librssguard/services/standard/gui/formdiscoverfeeds.ui +++ b/src/librssguard/services/standard/gui/formdiscoverfeeds.ui @@ -45,6 +45,19 @@ + + + + + 16777215 + 8 + + + + false + + + @@ -57,6 +70,82 @@ Discovered feeds + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + 0 + + + true + + + false + + + true + + + false + + + + + + + + + Select &all + + + + + + + &Unselect all + + + + + + + false + + + Add single feed with advanced details + + + + + + + &Import checked feeds + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -100,34 +189,6 @@ - - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - 0 - - - true - - - false - - - true - - - false - - - @@ -141,19 +202,6 @@ - - - - - 16777215 - 8 - - - - false - - - @@ -164,6 +212,14 @@ 1 + + m_btnDiscover + m_tvFeeds + m_btnSelecAll + m_btnSelectNone + m_btnAddIndividually + m_cmbParentCategory + diff --git a/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp b/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp index e946027e7..c609ec3d6 100644 --- a/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp +++ b/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp @@ -67,10 +67,7 @@ void FormStandardFeedDetails::apply() { FormFeedDetails::apply(); auto* std_feed = feed(); - RootItem* parent = - static_cast(m_standardFeedDetails->m_ui.m_cmbParentCategory - ->itemData(m_standardFeedDetails->m_ui.m_cmbParentCategory->currentIndex()) - .value()); + RootItem* parent = m_standardFeedDetails->m_ui.m_cmbParentCategory->currentData().value(); StandardFeed::Type type = static_cast(m_standardFeedDetails->m_ui.m_cmbType diff --git a/src/librssguard/services/standard/gui/formstandardimportexport.cpp b/src/librssguard/services/standard/gui/formstandardimportexport.cpp index e946861e0..b40ac1986 100644 --- a/src/librssguard/services/standard/gui/formstandardimportexport.cpp +++ b/src/librssguard/services/standard/gui/formstandardimportexport.cpp @@ -347,8 +347,7 @@ void FormStandardImportExport::exportFeeds() { void FormStandardImportExport::importFeeds() { QString output_message; - RootItem* parent = - static_cast(m_ui->m_cmbRootNode->itemData(m_ui->m_cmbRootNode->currentIndex()).value()); + RootItem* parent = m_ui->m_cmbRootNode->currentData().value(); if (m_serviceRoot->mergeImportExportModel(m_model, parent, output_message)) { m_serviceRoot->requestItemExpand(parent->getSubTree(), true); @@ -360,9 +359,9 @@ void FormStandardImportExport::importFeeds() { } void FormStandardImportExport::loadCategories(const QList& categories, RootItem* root_item) { - m_ui->m_cmbRootNode->addItem(root_item->icon(), root_item->title(), QVariant::fromValue((void*)root_item)); + m_ui->m_cmbRootNode->addItem(root_item->icon(), root_item->title(), QVariant::fromValue(root_item)); for (Category* category : categories) { - m_ui->m_cmbRootNode->addItem(category->icon(), category->title(), QVariant::fromValue((void*)category)); + m_ui->m_cmbRootNode->addItem(category->icon(), category->title(), QVariant::fromValue(category)); } } diff --git a/src/librssguard/services/standard/gui/standardfeeddetails.cpp b/src/librssguard/services/standard/gui/standardfeeddetails.cpp index 00d787ae4..2c471e03d 100644 --- a/src/librssguard/services/standard/gui/standardfeeddetails.cpp +++ b/src/librssguard/services/standard/gui/standardfeeddetails.cpp @@ -357,10 +357,10 @@ void StandardFeedDetails::prepareForNewFeed(RootItem* parent_to_select, const QS 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))); + ->setCurrentIndex(m_ui.m_cmbParentCategory->findData(QVariant::fromValue(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())); + int target_item = m_ui.m_cmbParentCategory->findData(QVariant::fromValue(parent_to_select->parent())); if (target_item >= 0) { m_ui.m_cmbParentCategory->setCurrentIndex(target_item); @@ -384,8 +384,7 @@ void StandardFeedDetails::prepareForNewFeed(RootItem* parent_to_select, const QS void StandardFeedDetails::setExistingFeed(StandardFeed* feed) { m_ui.m_cmbSourceType->setCurrentIndex(m_ui.m_cmbSourceType->findData(QVariant::fromValue(feed->sourceType()))); - m_ui.m_cmbParentCategory - ->setCurrentIndex(m_ui.m_cmbParentCategory->findData(QVariant::fromValue((void*)feed->parent()))); + m_ui.m_cmbParentCategory->setCurrentIndex(m_ui.m_cmbParentCategory->findData(QVariant::fromValue(feed->parent()))); m_ui.m_txtTitle->lineEdit()->setText(feed->title()); m_ui.m_txtDescription->lineEdit()->setText(feed->description()); m_ui.m_btnIcon->setIcon(feed->icon()); @@ -398,9 +397,9 @@ void StandardFeedDetails::setExistingFeed(StandardFeed* feed) { } void StandardFeedDetails::loadCategories(const QList& categories, RootItem* root_item) { - m_ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue((void*)root_item)); + m_ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue(root_item)); for (Category* category : categories) { - m_ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue((void*)category)); + m_ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue(category)); } } diff --git a/src/librssguard/services/standard/parsers/atomparser.cpp b/src/librssguard/services/standard/parsers/atomparser.cpp index 474709524..413726607 100644 --- a/src/librssguard/services/standard/parsers/atomparser.cpp +++ b/src/librssguard/services/standard/parsers/atomparser.cpp @@ -167,11 +167,15 @@ QList AtomParser::discoverFeeds(ServiceRoot* root, const QUrl& ur // 5. my_url = url.toString(QUrl::UrlFormattingOption::StripTrailingSlash); - if (QRegularExpression(QSL(GITHUB_URL_REGEX)).match(my_url).isValid()) { + auto mtch = QRegularExpression(QSL(GITHUB_URL_REGEX)).match(my_url); + + if (mtch.isValid()) { QStringList github_feeds = {QSL("releases.atom"), QSL("commits.atom"), QSL("tags.atom")}; + QString gh_username = mtch.captured(1); + QString gh_repo = mtch.captured(2); for (const QString& github_feed : github_feeds) { - my_url = url.toString(QUrl::UrlFormattingOption::StripTrailingSlash) + QL1C('/') + github_feed; + my_url = QSL("https://github.com/%1/%2/%3").arg(gh_username, gh_repo, github_feed); res = NetworkFactory::performNetworkOperation(my_url, timeout, {}, diff --git a/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp b/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp index b40b60d6e..11760f7a3 100644 --- a/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp +++ b/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp @@ -27,9 +27,7 @@ void FormTtRssFeedDetails::apply() { FormFeedDetails::apply(); } else { - RootItem* parent = static_cast(m_feedDetails->ui.m_cmbParentCategory - ->itemData(m_feedDetails->ui.m_cmbParentCategory->currentIndex()) - .value()); + RootItem* parent = m_feedDetails->ui.m_cmbParentCategory->currentData().value(); auto* root = qobject_cast(parent->getParentServiceRoot()); const int category_id = parent->kind() == RootItem::Kind::ServiceRoot ? 0 : parent->customId().toInt(); const TtRssSubscribeToFeedResponse response = diff --git a/src/librssguard/services/tt-rss/gui/ttrssfeeddetails.cpp b/src/librssguard/services/tt-rss/gui/ttrssfeeddetails.cpp index 3279c7179..3e5963679 100644 --- a/src/librssguard/services/tt-rss/gui/ttrssfeeddetails.cpp +++ b/src/librssguard/services/tt-rss/gui/ttrssfeeddetails.cpp @@ -35,19 +35,18 @@ void TtRssFeedDetails::onUrlChanged(const QString& new_url) { void TtRssFeedDetails::loadCategories(const QList& categories, RootItem* root_item, RootItem* parent_to_select) { - ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue((void*)root_item)); + ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue(root_item)); for (Category* category : categories) { - ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue((void*)category)); + ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue(category)); } if (parent_to_select != nullptr) { if (parent_to_select->kind() == RootItem::Kind::Category) { - ui.m_cmbParentCategory - ->setCurrentIndex(ui.m_cmbParentCategory->findData(QVariant::fromValue((void*)parent_to_select))); + ui.m_cmbParentCategory->setCurrentIndex(ui.m_cmbParentCategory->findData(QVariant::fromValue(parent_to_select))); } else if (parent_to_select->kind() == RootItem::Kind::Feed) { - int target_item = ui.m_cmbParentCategory->findData(QVariant::fromValue((void*)parent_to_select->parent())); + int target_item = ui.m_cmbParentCategory->findData(QVariant::fromValue(parent_to_select->parent())); if (target_item >= 0) { ui.m_cmbParentCategory->setCurrentIndex(target_item);