Merge branch 'master' of github.com:martinrotter/rssguard

This commit is contained in:
Martin Rotter 2020-11-14 09:47:26 +01:00
commit 421de5e9d4
24 changed files with 79 additions and 16 deletions

View file

@ -15,6 +15,8 @@ RSS Guard is simple, light and easy-to-use RSS/ATOM feed aggregator developed us
* [Nextcloud News](https://apps.nextcloud.com/apps/news), * [Nextcloud News](https://apps.nextcloud.com/apps/news),
* [Gmail API](https://developers.google.com/gmail/api). * [Gmail API](https://developers.google.com/gmail/api).
Application icon was kindly contributed by Siddharth Yadav - @Siddharth_yd (Instagram), illustrationdesignsid@gmail.com (e-mail).
Development builds can be downloaded [here for Windows](https://bintray.com/martinrotter/rssguard/Development/Windows) and [here for Linux/Mac](https://bintray.com/martinrotter/rssguard/Development/LinuxMacOs). Development builds can be downloaded [here for Windows](https://bintray.com/martinrotter/rssguard/Development/Windows) and [here for Linux/Mac](https://bintray.com/martinrotter/rssguard/Development/LinuxMacOs).
Documentation is [here](https://github.com/martinrotter/rssguard/blob/master/resources/docs/Documentation.md). Documentation is [here](https://github.com/martinrotter/rssguard/blob/master/resources/docs/Documentation.md).

View file

@ -48,6 +48,19 @@ function filterMessage() {
return MSG_ACCEPT; return MSG_ACCEPT;
} }
``` ```
Make sure that your receive only one message with particular URL and all other messages with same URL are subsequently ignored.
```js
function filterMessage() {
if (msg.isDuplicateWithAttribute(2)) {
return MSG_IGNORE;
}
else {
return MSG_ACCEPT;
}
}
```
## `Message filters` dialog ## `Message filters` dialog
The dialog is accessible from menu `Messages -> Message filters` and is the central place for message filters management within RSS Guard. It allows you to: The dialog is accessible from menu `Messages -> Message filters` and is the central place for message filters management within RSS Guard. It allows you to:
* add or remove message filters, * add or remove message filters,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
resources/graphics/rssguard.ico Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 122 KiB

BIN
resources/graphics/rssguard.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 21 KiB

BIN
resources/graphics/rssguard_plain.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
resources/macosx/rssguard.icns Normal file → Executable file

Binary file not shown.

View file

@ -1,3 +1,17 @@
3.8.1
—————
Added:
▪ New applications icons. Contributed by Siddharth Yadav:
▪ @Siddharth_yd (Instagram)
▪ illustrationdesignsid@gmail.com (e-mail)
Fixed/changed:
3.8.0 3.8.0
————— —————

View file

@ -159,6 +159,7 @@ QList<QAction*> FormMain::allActions() const {
actions << m_ui->m_actionClearAllItems; actions << m_ui->m_actionClearAllItems;
actions << m_ui->m_actionShowOnlyUnreadItems; actions << m_ui->m_actionShowOnlyUnreadItems;
actions << m_ui->m_actionShowTreeBranches; actions << m_ui->m_actionShowTreeBranches;
actions << m_ui->m_actionAutoExpandItemsWhenSelected;
actions << m_ui->m_actionShowOnlyUnreadMessages; actions << m_ui->m_actionShowOnlyUnreadMessages;
actions << m_ui->m_actionMarkSelectedMessagesAsRead; actions << m_ui->m_actionMarkSelectedMessagesAsRead;
actions << m_ui->m_actionMarkSelectedMessagesAsUnread; actions << m_ui->m_actionMarkSelectedMessagesAsUnread;
@ -596,6 +597,8 @@ void FormMain::loadSize() {
SETTING(Feeds::ShowOnlyUnreadFeeds)).toBool()); SETTING(Feeds::ShowOnlyUnreadFeeds)).toBool());
m_ui->m_actionShowTreeBranches->setChecked(settings->value(GROUP(Feeds), m_ui->m_actionShowTreeBranches->setChecked(settings->value(GROUP(Feeds),
SETTING(Feeds::ShowTreeBranches)).toBool()); SETTING(Feeds::ShowTreeBranches)).toBool());
m_ui->m_actionAutoExpandItemsWhenSelected->setChecked(settings->value(GROUP(Feeds),
SETTING(Feeds::AutoExpandOnSelection)).toBool());
m_ui->m_actionShowOnlyUnreadMessages->setChecked(settings->value(GROUP(Messages), m_ui->m_actionShowOnlyUnreadMessages->setChecked(settings->value(GROUP(Messages),
SETTING(Messages::ShowOnlyUnreadMessages)).toBool()); SETTING(Messages::ShowOnlyUnreadMessages)).toBool());
m_ui->m_actionAlternateColorsInLists->setChecked(settings->value(GROUP(GUI), m_ui->m_actionAlternateColorsInLists->setChecked(settings->value(GROUP(GUI),
@ -763,6 +766,8 @@ void FormMain::createConnections() {
tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowOnlyUnreadFeeds); tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowOnlyUnreadFeeds);
connect(m_ui->m_actionShowTreeBranches, &QAction::toggled, connect(m_ui->m_actionShowTreeBranches, &QAction::toggled,
tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowFeedTreeBranches); tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowFeedTreeBranches);
connect(m_ui->m_actionAutoExpandItemsWhenSelected, &QAction::toggled,
tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleItemsAutoExpandingOnSelection);
connect(m_ui->m_actionAlternateColorsInLists, &QAction::toggled, connect(m_ui->m_actionAlternateColorsInLists, &QAction::toggled,
tabWidget()->feedMessageViewer(), &FeedMessageViewer::alternateRowColorsInLists); tabWidget()->feedMessageViewer(), &FeedMessageViewer::alternateRowColorsInLists);
connect(m_ui->m_actionShowOnlyUnreadMessages, &QAction::toggled, connect(m_ui->m_actionShowOnlyUnreadMessages, &QAction::toggled,

View file

@ -116,6 +116,7 @@
<addaction name="m_actionDeleteSelectedItem"/> <addaction name="m_actionDeleteSelectedItem"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="m_actionShowOnlyUnreadItems"/> <addaction name="m_actionShowOnlyUnreadItems"/>
<addaction name="m_actionAutoExpandItemsWhenSelected"/>
<addaction name="m_actionShowTreeBranches"/> <addaction name="m_actionShowTreeBranches"/>
<addaction name="m_actionExpandCollapseItem"/> <addaction name="m_actionExpandCollapseItem"/>
<addaction name="separator"/> <addaction name="separator"/>
@ -784,6 +785,14 @@
<string>Alternate row colors in lists</string> <string>Alternate row colors in lists</string>
</property> </property>
</action> </action>
<action name="m_actionAutoExpandItemsWhenSelected">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Automatically &amp;expand items when selected</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View file

@ -188,6 +188,12 @@ void FeedMessageViewer::toggleShowFeedTreeBranches() {
qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowTreeBranches, origin->isChecked()); qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowTreeBranches, origin->isChecked());
} }
void FeedMessageViewer::toggleItemsAutoExpandingOnSelection() {
const QAction* origin = qobject_cast<QAction*>(sender());
qApp->settings()->setValue(GROUP(Feeds), Feeds::AutoExpandOnSelection, origin->isChecked());
}
void FeedMessageViewer::alternateRowColorsInLists() { void FeedMessageViewer::alternateRowColorsInLists() {
const QAction* origin = qobject_cast<QAction*>(sender()); const QAction* origin = qobject_cast<QAction*>(sender());

View file

@ -66,6 +66,7 @@ class RSSGUARD_DLLSPEC FeedMessageViewer : public TabContent {
void toggleShowOnlyUnreadMessages(); void toggleShowOnlyUnreadMessages();
void toggleShowOnlyUnreadFeeds(); void toggleShowOnlyUnreadFeeds();
void toggleShowFeedTreeBranches(); void toggleShowFeedTreeBranches();
void toggleItemsAutoExpandingOnSelection();
void alternateRowColorsInLists(); void alternateRowColorsInLists();
private slots: private slots:

View file

@ -713,6 +713,11 @@ void FeedsView::selectionChanged(const QItemSelection& selected, const QItemSele
emit itemSelected(selected_item); emit itemSelected(selected_item);
m_proxyModel->invalidateReadFeedsFilter(); m_proxyModel->invalidateReadFeedsFilter();
if (!selectedIndexes().isEmpty() &&
qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::AutoExpandOnSelection)).toBool()) {
expand(selectedIndexes().first());
}
} }
void FeedsView::keyPressEvent(QKeyEvent* event) { void FeedsView::keyPressEvent(QKeyEvent* event) {

View file

@ -124,26 +124,26 @@ void SystemTrayIcon::setNumber(int number, bool any_new_message) {
// Numbers with more than 2 digits won't be readable, display // Numbers with more than 2 digits won't be readable, display
// infinity symbol in that case. // infinity symbol in that case.
if (number > 999) { if (number > 999) {
m_font.setPixelSize(100); m_font.setPixelSize(background.width() * 0.78);
tray_painter.setFont(m_font); tray_painter.setFont(m_font);
tray_painter.drawText(QRect(0, 0, 128, 128), Qt::AlignVCenter | Qt::AlignCenter, QChar(8734)); tray_painter.drawText(background.rect(), Qt::AlignVCenter | Qt::AlignCenter, QChar(8734));
} }
else { else {
// Smaller number if it has 3 digits. // Smaller number if it has 3 digits.
if (number > 99) { if (number > 99) {
m_font.setPixelSize(55); m_font.setPixelSize(background.width() * 0.43);
} }
else if (number > 9) { else if (number > 9) {
m_font.setPixelSize(80); m_font.setPixelSize(background.width() * 0.56);
} }
// Bigger number if it has just one digit. // Bigger number if it has just one digit.
else { else {
m_font.setPixelSize(100); m_font.setPixelSize(background.width() * 0.78);
} }
tray_painter.setFont(m_font); tray_painter.setFont(m_font);
tray_painter.drawText(QRect(0, 0, 128, 128), tray_painter.drawText(background.rect(),
Qt::AlignmentFlag::AlignVCenter | Qt::AlignmentFlag::AlignCenter, Qt::AlignmentFlag::AlignVCenter | Qt::AlignmentFlag::AlignCenter,
QString::number(number)); QString::number(number));
} }

View file

@ -888,9 +888,9 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
} }
int id_existing_message = -1; int id_existing_message = -1;
qint64 date_existing_message; qint64 date_existing_message = 0;
bool is_read_existing_message; bool is_read_existing_message = false;
bool is_important_existing_message; bool is_important_existing_message = false;
QString contents_existing_message; QString contents_existing_message;
QString feed_id_existing_message; QString feed_id_existing_message;
@ -973,19 +973,22 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
// Message is already in the DB. // Message is already in the DB.
// //
// Now, we update it if at least one of next conditions is true: // Now, we update it if at least one of next conditions is true:
// 1) Message has custom ID AND (its date OR read status OR starred status are changed). // 1) Message has custom ID AND (its date OR read status OR starred status are changed or message
// was moved from one feed to another - this can particularly happen in Gmail feeds).
//
// 2) Message has its date fetched from feed AND its date is different from date in DB and contents is changed. // 2) Message has its date fetched from feed AND its date is different from date in DB and contents is changed.
if (/* 1 */ (!message.m_customId.isEmpty() && (message.m_created.toMSecsSinceEpoch() != date_existing_message || if (/* 1 */ (!message.m_customId.isEmpty() && (message.m_created.toMSecsSinceEpoch() != date_existing_message ||
message.m_isRead != is_read_existing_message || message.m_isRead != is_read_existing_message ||
message.m_isImportant != is_important_existing_message || message.m_isImportant != is_important_existing_message ||
message.m_feedId != feed_id_existing_message)) || message.m_feedId != feed_id_existing_message ||
message.m_contents != contents_existing_message)) ||
/* 2 */ (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message /* 2 */ (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message
&& message.m_contents != contents_existing_message)) { && message.m_contents != contents_existing_message)) {
// Message exists, it is changed, update it. // Message exists, it is changed, update it.
query_update.bindValue(QSL(":title"), unnulifyString(message.m_title)); query_update.bindValue(QSL(":title"), unnulifyString(message.m_title));
query_update.bindValue(QSL(":is_read"), (int) message.m_isRead); query_update.bindValue(QSL(":is_read"), int(message.m_isRead));
query_update.bindValue(QSL(":is_important"), (int) message.m_isImportant); query_update.bindValue(QSL(":is_important"), int(message.m_isImportant));
query_update.bindValue(QSL(":url"), unnulifyString(message.m_url)); query_update.bindValue(QSL(":url"), unnulifyString(message.m_url));
query_update.bindValue(QSL(":author"), unnulifyString(message.m_author)); query_update.bindValue(QSL(":author"), unnulifyString(message.m_author));
query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch()); query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
@ -1019,8 +1022,8 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
// Message with this URL is not fetched in this feed yet. // Message with this URL is not fetched in this feed yet.
query_insert.bindValue(QSL(":feed"), unnulifyString(feed_custom_id)); query_insert.bindValue(QSL(":feed"), unnulifyString(feed_custom_id));
query_insert.bindValue(QSL(":title"), unnulifyString(message.m_title)); query_insert.bindValue(QSL(":title"), unnulifyString(message.m_title));
query_insert.bindValue(QSL(":is_read"), (int) message.m_isRead); query_insert.bindValue(QSL(":is_read"), int(message.m_isRead));
query_insert.bindValue(QSL(":is_important"), (int) message.m_isImportant); query_insert.bindValue(QSL(":is_important"), int(message.m_isImportant));
query_insert.bindValue(QSL(":url"), unnulifyString( message.m_url)); query_insert.bindValue(QSL(":url"), unnulifyString( message.m_url));
query_insert.bindValue(QSL(":author"), unnulifyString(message.m_author)); query_insert.bindValue(QSL(":author"), unnulifyString(message.m_author));
query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch()); query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());

View file

@ -60,6 +60,9 @@ DVALUE(bool) Feeds::ShowOnlyUnreadFeedsDef = false;
DKEY Feeds::ShowTreeBranches = "show_tree_branches"; DKEY Feeds::ShowTreeBranches = "show_tree_branches";
DVALUE(bool) Feeds::ShowTreeBranchesDef = true; DVALUE(bool) Feeds::ShowTreeBranchesDef = true;
DKEY Feeds::AutoExpandOnSelection = "auto_expand_on_selection";
DVALUE(bool) Feeds::AutoExpandOnSelectionDef = false;
DKEY Feeds::ListFont = "list_font"; DKEY Feeds::ListFont = "list_font";
// Messages. // Messages.

View file

@ -79,6 +79,9 @@ namespace Feeds {
KEY ShowTreeBranches; KEY ShowTreeBranches;
VALUE(bool) ShowTreeBranchesDef; VALUE(bool) ShowTreeBranchesDef;
KEY AutoExpandOnSelection;
VALUE(bool) AutoExpandOnSelectionDef;
KEY ListFont; KEY ListFont;
} }

View file

@ -435,7 +435,6 @@ QList<Message> StandardFeed::obtainNewMessages(bool* error_during_obtaining) {
QList<QPair<QByteArray, QByteArray>> headers; QList<QPair<QByteArray, QByteArray>> headers;
headers << NetworkFactory::generateBasicAuthHeader(username(), password()); headers << NetworkFactory::generateBasicAuthHeader(username(), password());
m_networkError = NetworkFactory::performNetworkOperation(url(), m_networkError = NetworkFactory::performNetworkOperation(url(),
download_timeout, download_timeout,
QByteArray(), QByteArray(),