diff --git a/resources/desktop/com.github.rssguard.appdata.xml b/resources/desktop/com.github.rssguard.appdata.xml
index 4d3f9db79..3c575bea3 100644
--- a/resources/desktop/com.github.rssguard.appdata.xml
+++ b/resources/desktop/com.github.rssguard.appdata.xml
@@ -30,7 +30,7 @@
https://martinrotter.github.io/donate/
-
+
none
diff --git a/resources/docs/Documentation.md b/resources/docs/Documentation.md
index e8f06f480..da2650049 100644
--- a/resources/docs/Documentation.md
+++ b/resources/docs/Documentation.md
@@ -11,6 +11,7 @@
* [RSS Guard 3 vs. RSS Guard 4](#rss-guard-3-vs-rss-guard-4)
* [Features](#features)
* [List of main features](#list-of-main-features)
+ * [Core concepts](#core-concepts)
* [Supported feed formats and online feed services](Feed-formats.md)
* [Message filtering](Message-filters.md)
* [Database backends](#database-backends)
@@ -120,8 +121,7 @@ RSS Guard is simple (yet powerful) feed reader. It is able to fetch the most kno
* support for all feed formats (RSS/RDF/ATOM/JSON),
* full support of podcasts (RSS/ATOM/JSON),
* import/export of feeds to/from OPML 2.0,
- * universal plugin for online services with [Google Reader API](#google-reader-api),
- * possibility of using custom 3rd-party feed synchronization services,
+ * possibility of using custom 3rd-party feed [synchronization services](Feed-formats.md),
* feed metadata fetching including icons,
* support for [scraping websites](#websites-scraping) which do not offer RSS/ATOM feeds and other related advanced features,
* simple internal Chromium-based web viewer (or alternative version with simpler and much more lightweight internal viewer),
@@ -144,7 +144,6 @@ RSS Guard is simple (yet powerful) feed reader. It is able to fetch the most kno
* support for `feed://` URI scheme.
* user interface:
* message list filter with regular expressions,
- * drag-n-drop for feed list,
* able to show unread feeds/messages only,
* can be controlled via keyboard,
* fully adjustable toolbars (changeable buttons and style),
@@ -155,9 +154,18 @@ RSS Guard is simple (yet powerful) feed reader. It is able to fetch the most kno
* tabbed interface,
* ability to hide list of feeds/categories,
* desktop integration via tray icon,
- * localizations to some languages,
+ * localizations to many languages,
* ability to tweak columns in displayed list of messages.
+## Core concepts
+RSS Guard is multi-protocol and multi-account application. If you start it for the first time, `Add account` dialog will pop-up.
+
+
+
+You can also display this dialog from main menu `Accounts -> Add new account`.
+
+You must have added some account to start using RSS Guard. Each account provides access to some specific online service while `Standard online feeds` account is there to provide access to classic `RSS` and `ATOM` feeds. You can have activated many accounts in the same time and even multiple accounts of the same type, for example two distinct `Gmail` accounts.
+
## Database backends
RSS Guard offers switchable database backends which hold your data. At this point, two backends are available:
* MariaDB,
@@ -187,7 +195,6 @@ Note that even when all Google Reader API enabled services should follow the API
For example The Old Reader does not seem to offer tags/labels functionality, therefore tags/labels in RSS Guard are not synchronized, but you can still use offline labels.
## Websites scraping
-
> **Only proceed if you consider yourself to be a power user and you know what you are doing!**
RSS Guard 3.9.0+ offers extra advanced features which are inspired by [Liferea](https://lzone.de/liferea/).
diff --git a/resources/docs/Downloads.md b/resources/docs/Downloads.md
index 2f63370ef..6047ba025 100755
--- a/resources/docs/Downloads.md
+++ b/resources/docs/Downloads.md
@@ -12,7 +12,7 @@ Official downloads are available [here](https://github.com/martinrotter/rssguard
Development builds can be downloaded [here](https://github.com/martinrotter/rssguard/releases/tag/devbuild).
## Installation packages naming
-**Windows builds** of RSS Guard are generated automatically by the tool called AppVeyor. These builds have auto-generated names. In RSS Guard [downloads page](https://github.com/martinrotter/rssguard/releases) you can see filenames like:
+**All builds** of RSS Guard are generated automatically by GitHub. These builds have auto-generated names. In RSS Guard [downloads page](https://github.com/martinrotter/rssguard/releases) you can see filenames like:
* `rssguard-3.4.2-7bad9d1-nowebengine-win32.7z`,
* `rssguard-3.4.2-7bad9d1-win32.7z`,
* `rssguard-3.4.2-95ee6be-nowebengine-win32.exe`,
@@ -25,4 +25,6 @@ The structure of these filenames is quite trivial and easily understandable for
* `` = `win32` (This is the target platform which the application can run on.),
* `` = `exe` (This is self-explanatory.).
-Note that same file naming scheme for development builds might be little different. Specifically, `` field is omitted.
\ No newline at end of file
+Note that same file naming scheme for development builds might be little different. Specifically, `` field is omitted.
+
+If you use `7z` packages on Windows, then you need to manually install all needed MSVC++ runtime libraries. Their installers are included inside the archive.
\ No newline at end of file
diff --git a/resources/docs/images/add-acc.png b/resources/docs/images/add-acc.png
new file mode 100755
index 000000000..0f46df137
Binary files /dev/null and b/resources/docs/images/add-acc.png differ
diff --git a/src/librssguard/gui/dialogs/formmain.cpp b/src/librssguard/gui/dialogs/formmain.cpp
index 34129fc4b..29814a4fc 100755
--- a/src/librssguard/gui/dialogs/formmain.cpp
+++ b/src/librssguard/gui/dialogs/formmain.cpp
@@ -190,6 +190,7 @@ QList FormMain::allActions() const {
actions << m_ui->m_actionSelectPreviousMessage;
actions << m_ui->m_actionSelectNextUnreadMessage;
actions << m_ui->m_actionExpandCollapseItem;
+ actions << m_ui->m_actionExpandCollapseItemRecursively;
actions << m_ui->m_actionMessageFilters;
#if defined(USE_WEBENGINE)
@@ -448,7 +449,8 @@ void FormMain::updateFeedButtonsAvailability() {
m_ui->m_actionUpdateSelectedItemsWithCustomTimers->setEnabled(!critical_action_running);
m_ui->m_actionUpdateSelectedItems->setEnabled(!critical_action_running && (feed_selected || category_selected || service_selected));
m_ui->m_actionViewSelectedItemsNewspaperMode->setEnabled(anything_selected);
- m_ui->m_actionExpandCollapseItem->setEnabled(anything_selected);
+ m_ui->m_actionExpandCollapseItem->setEnabled(category_selected || service_selected);
+ m_ui->m_actionExpandCollapseItemRecursively->setEnabled(category_selected || service_selected);
m_ui->m_actionServiceDelete->setEnabled(service_selected);
m_ui->m_actionServiceEdit->setEnabled(service_selected);
m_ui->m_actionAddFeedIntoSelectedItem->setEnabled(anything_selected);
@@ -545,6 +547,7 @@ void FormMain::setupIcons() {
m_ui->m_actionShowOnlyUnreadItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
m_ui->m_actionShowOnlyUnreadMessages->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
m_ui->m_actionExpandCollapseItem->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more")));
+ m_ui->m_actionExpandCollapseItemRecursively->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more")));
m_ui->m_actionRestoreSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh")));
m_ui->m_actionRestoreAllRecycleBins->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh")));
m_ui->m_actionEmptyAllRecycleBins->setIcon(icon_theme_factory->fromTheme(QSL("edit-clear")));
@@ -741,7 +744,17 @@ void FormMain::createConnections() {
connect(m_ui->m_actionMarkSelectedItemsAsRead,
&QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markSelectedItemRead);
connect(m_ui->m_actionExpandCollapseItem,
- &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::expandCollapseCurrentItem);
+ &QAction::triggered,
+ tabWidget()->feedMessageViewer()->feedsView(),
+ [this]() {
+ tabWidget()->feedMessageViewer()->feedsView()->expandCollapseCurrentItem(false);
+ });
+ connect(m_ui->m_actionExpandCollapseItemRecursively,
+ &QAction::triggered,
+ tabWidget()->feedMessageViewer()->feedsView(),
+ [this]() {
+ tabWidget()->feedMessageViewer()->feedsView()->expandCollapseCurrentItem(true);
+ });
connect(m_ui->m_actionMarkSelectedItemsAsUnread,
&QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markSelectedItemUnread);
connect(m_ui->m_actionClearSelectedItems,
diff --git a/src/librssguard/gui/dialogs/formmain.ui b/src/librssguard/gui/dialogs/formmain.ui
index 43edc1194..a256b44c1 100755
--- a/src/librssguard/gui/dialogs/formmain.ui
+++ b/src/librssguard/gui/dialogs/formmain.ui
@@ -120,6 +120,7 @@
+
@@ -805,6 +806,11 @@
Message viewer toolbars
+
+
+ Expand/collapse selected item &recursively
+
+
diff --git a/src/librssguard/gui/feedsview.cpp b/src/librssguard/gui/feedsview.cpp
index 6e245f8a7..3a76164d1 100755
--- a/src/librssguard/gui/feedsview.cpp
+++ b/src/librssguard/gui/feedsview.cpp
@@ -191,7 +191,7 @@ void FeedsView::addCategoryIntoSelectedAccount() {
}
}
-void FeedsView::expandCollapseCurrentItem() {
+void FeedsView::expandCollapseCurrentItem(bool recursive) {
if (selectionModel()->selectedRows().size() == 1) {
QModelIndex index = selectionModel()->selectedRows().at(0);
@@ -200,7 +200,32 @@ void FeedsView::expandCollapseCurrentItem() {
index = index.parent();
}
- isExpanded(index) ? collapse(index) : expand(index);
+ if (recursive) {
+ QList to_process = { index };
+ bool expa = !isExpanded(index);
+
+ while (!to_process.isEmpty()) {
+ auto idx = to_process.takeFirst();
+
+ if (idx.isValid()) {
+ setExpanded(idx, expa);
+
+ for (int i = 0; i < m_proxyModel->rowCount(idx); i++) {
+ auto new_idx = m_proxyModel->index(i, 0, idx);
+
+ if (new_idx.isValid()) {
+ to_process << new_idx;
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+ else {
+ isExpanded(index) ? collapse(index) : expand(index);
+ }
}
}
@@ -460,14 +485,15 @@ QMenu* FeedsView::initializeContextMenuService(RootItem* clicked_item) {
QList specific_actions = clicked_item->contextMenuFeedsList();
- m_contextMenuService->addActions(QList() <<
- qApp->mainForm()->m_ui->m_actionUpdateSelectedItems <<
- qApp->mainForm()->m_ui->m_actionEditSelectedItem <<
- qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed <<
- qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
- qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
- qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread <<
- qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
+ m_contextMenuService->addActions({ qApp->mainForm()->m_ui->m_actionUpdateSelectedItems,
+ qApp->mainForm()->m_ui->m_actionEditSelectedItem,
+ qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed,
+ qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode,
+ qApp->mainForm()->m_ui->m_actionExpandCollapseItem,
+ qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively,
+ qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead,
+ qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread,
+ qApp->mainForm()->m_ui->m_actionDeleteSelectedItem });
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
@@ -545,14 +571,15 @@ QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) {
QList specific_actions = clicked_item->contextMenuFeedsList();
- m_contextMenuCategories->addActions(QList() <<
- qApp->mainForm()->m_ui->m_actionUpdateSelectedItems <<
- qApp->mainForm()->m_ui->m_actionEditSelectedItem <<
- qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed <<
- qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
- qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
- qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread <<
- qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
+ m_contextMenuCategories->addActions({ qApp->mainForm()->m_ui->m_actionUpdateSelectedItems,
+ qApp->mainForm()->m_ui->m_actionEditSelectedItem,
+ qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed,
+ qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode,
+ qApp->mainForm()->m_ui->m_actionExpandCollapseItem,
+ qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively,
+ qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead,
+ qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread,
+ qApp->mainForm()->m_ui->m_actionDeleteSelectedItem });
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
diff --git a/src/librssguard/gui/feedsview.h b/src/librssguard/gui/feedsview.h
index 2bd7c0ab3..debb5a6d0 100755
--- a/src/librssguard/gui/feedsview.h
+++ b/src/librssguard/gui/feedsview.h
@@ -45,7 +45,7 @@ class RSSGUARD_DLLSPEC FeedsView : public QTreeView {
void addFeedIntoSelectedAccount();
void addCategoryIntoSelectedAccount();
- void expandCollapseCurrentItem();
+ void expandCollapseCurrentItem(bool recursive);
// Feed updating.
void updateSelectedItems();