bunch of GUI QOL enhancements for queries, ability to "clean"

This commit is contained in:
Martin Rotter 2023-08-15 14:03:40 +02:00
parent 0e9a2e2595
commit 6566349838
8 changed files with 78 additions and 14 deletions

View file

@ -1857,6 +1857,38 @@ bool DatabaseQueries::cleanLabelledMessages(const QSqlDatabase& db, bool clean_r
} }
} }
void DatabaseQueries::cleanProbedMessages(const QSqlDatabase& db, bool clean_read_only, Search* probe) {
QSqlQuery q(db);
q.setForwardOnly(true);
if (clean_read_only) {
q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted "
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" is_read = 1 AND "
" account_id = :account_id AND "
" (title REGEXP :fltr OR contents REGEXP :fltr);"));
}
else {
q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted "
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" account_id = :account_id AND "
" (title REGEXP :fltr OR contents REGEXP :fltr);"));
}
q.bindValue(QSL(":deleted"), 1);
q.bindValue(QSL(":account_id"), probe->getParentServiceRoot()->accountId());
q.bindValue(QSL(":fltr"), probe->filter());
if (!q.exec()) {
throw ApplicationException(q.lastError().text());
}
}
bool DatabaseQueries::cleanImportantMessages(const QSqlDatabase& db, bool clean_read_only, int account_id) { bool DatabaseQueries::cleanImportantMessages(const QSqlDatabase& db, bool clean_read_only, int account_id) {
QSqlQuery q(db); QSqlQuery q(db);

View file

@ -173,6 +173,7 @@ class DatabaseQueries {
bool delete_messages_too, bool delete_messages_too,
bool delete_labels_too); bool delete_labels_too);
static bool cleanLabelledMessages(const QSqlDatabase& db, bool clean_read_only, Label* label); static bool cleanLabelledMessages(const QSqlDatabase& db, bool clean_read_only, Label* label);
static void cleanProbedMessages(const QSqlDatabase& db, bool clean_read_only, Search* probe);
static bool cleanImportantMessages(const QSqlDatabase& db, bool clean_read_only, int account_id); static bool cleanImportantMessages(const QSqlDatabase& db, bool clean_read_only, int account_id);
static bool cleanUnreadMessages(const QSqlDatabase& db, int account_id); static bool cleanUnreadMessages(const QSqlDatabase& db, int account_id);
static bool cleanFeeds(const QSqlDatabase& db, const QStringList& ids, bool clean_read_only, int account_id); static bool cleanFeeds(const QSqlDatabase& db, const QStringList& ids, bool clean_read_only, int account_id);

View file

@ -7,19 +7,19 @@
#include "gui/reusable/plaintoolbutton.h" #include "gui/reusable/plaintoolbutton.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "network-web/webfactory.h"
#include <QGridLayout> #include <QGridLayout>
#include <QParallelAnimationGroup> #include <QParallelAnimationGroup>
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include <QScrollArea> #include <QScrollArea>
#include <QTextEdit> #include <QTextBrowser>
#include <QToolButton> #include <QToolButton>
HelpSpoiler::HelpSpoiler(QWidget* parent) HelpSpoiler::HelpSpoiler(QWidget* parent)
: QWidget(parent), m_btnToggle(new QToolButton(this)), m_content(new QScrollArea(this)), : QWidget(parent), m_btnToggle(new QToolButton(this)), m_content(new QScrollArea(this)),
m_animation(new QParallelAnimationGroup(this)), m_layout(new QGridLayout(this)), m_text(new QTextEdit(this)), m_animation(new QParallelAnimationGroup(this)), m_layout(new QGridLayout(this)), m_text(new QTextBrowser(this)),
m_btnHelp(new PlainToolButton(this)) { m_btnHelp(new PlainToolButton(this)) {
m_btnToggle->setStyleSheet(QSL("QToolButton { border: none; }")); m_btnToggle->setStyleSheet(QSL("QToolButton { border: none; }"));
m_btnToggle->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextBesideIcon); m_btnToggle->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextBesideIcon);
m_btnToggle->setArrowType(Qt::ArrowType::RightArrow); m_btnToggle->setArrowType(Qt::ArrowType::RightArrow);
@ -47,7 +47,9 @@ HelpSpoiler::HelpSpoiler(QWidget* parent)
m_layout->addWidget(m_btnToggle, 0, 1, 1, 1, Qt::AlignmentFlag::AlignLeft); m_layout->addWidget(m_btnToggle, 0, 1, 1, 1, Qt::AlignmentFlag::AlignLeft);
m_layout->addWidget(m_content, 1, 0, 1, 2); m_layout->addWidget(m_content, 1, 0, 1, 2);
QObject::connect(m_btnToggle, &QToolButton::clicked, [this](const bool checked) { connect(m_text, &QTextBrowser::anchorClicked, this, &HelpSpoiler::onAnchorClicked);
connect(m_btnToggle, &QToolButton::clicked, [this](const bool checked) {
const auto collapsed_height = m_btnHelp->height(); const auto collapsed_height = m_btnHelp->height();
auto content_height = m_text->document()->size().height() + 22; auto content_height = m_text->document()->size().height() + 22;
@ -74,7 +76,8 @@ HelpSpoiler::HelpSpoiler(QWidget* parent)
m_text->viewport()->setAutoFillBackground(false); m_text->viewport()->setAutoFillBackground(false);
m_text->setFrameShape(QFrame::Shape::NoFrame); m_text->setFrameShape(QFrame::Shape::NoFrame);
m_text->setTextInteractionFlags(Qt::TextInteractionFlag::TextBrowserInteraction); m_text->setOpenLinks(false);
m_text->setOpenExternalLinks(false);
m_text->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); m_text->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
m_text->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); m_text->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
m_text->setWordWrapMode(QTextOption::WrapMode::WordWrap); m_text->setWordWrapMode(QTextOption::WrapMode::WordWrap);
@ -102,3 +105,7 @@ void HelpSpoiler::setHelpText(const QString& text, bool is_warning, bool force_h
m_text->document()->setDocumentMargin(0); m_text->document()->setDocumentMargin(0);
} }
void HelpSpoiler::onAnchorClicked(const QUrl& url) {
qApp->web()->openUrlInExternalBrowser(url.toString());
}

View file

@ -5,7 +5,7 @@
#include <QWidget> #include <QWidget>
class QTextEdit; class QTextBrowser;
class QGridLayout; class QGridLayout;
class QToolButton; class QToolButton;
class QParallelAnimationGroup; class QParallelAnimationGroup;
@ -21,12 +21,15 @@ class HelpSpoiler : public QWidget {
void setHelpText(const QString& title, const QString& text, bool is_warning, bool force_html = false); void setHelpText(const QString& title, const QString& text, bool is_warning, bool force_html = false);
void setHelpText(const QString& text, bool is_warning, bool force_html = false); void setHelpText(const QString& text, bool is_warning, bool force_html = false);
private slots:
void onAnchorClicked(const QUrl& url);
private: private:
QToolButton* m_btnToggle; QToolButton* m_btnToggle;
QScrollArea* m_content; QScrollArea* m_content;
QParallelAnimationGroup* m_animation; QParallelAnimationGroup* m_animation;
QGridLayout* m_layout; QGridLayout* m_layout;
QTextEdit* m_text; QTextBrowser* m_text;
PlainToolButton* m_btnHelp; PlainToolButton* m_btnHelp;
}; };

View file

@ -12,6 +12,14 @@ FormAddEditProbe::FormAddEditProbe(QWidget* parent) : QDialog(parent), m_editabl
m_ui.m_txtName->lineEdit()->setPlaceholderText(tr("Name for your query")); m_ui.m_txtName->lineEdit()->setPlaceholderText(tr("Name for your query"));
m_ui.m_txtFilter->lineEdit()->setPlaceholderText(tr("Regular expression")); m_ui.m_txtFilter->lineEdit()->setPlaceholderText(tr("Regular expression"));
m_ui.m_help->setHelpText(
tr("What is regular expression?"),
tr(
"A regular expression (shortened as regex or regexp) is a sequence of characters that "
R"(specifies a match pattern in text. See more <a href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference">info</a>.)"),
false,
true);
connect(m_ui.m_txtName->lineEdit(), &QLineEdit::textChanged, this, [this](const QString& text) { connect(m_ui.m_txtName->lineEdit(), &QLineEdit::textChanged, this, [this](const QString& text) {
if (text.isEmpty()) { if (text.isEmpty()) {
m_ui.m_txtName->setStatus(LineEditWithStatus::StatusType::Error, tr("Regex query name cannot be empty.")); m_ui.m_txtName->setStatus(LineEditWithStatus::StatusType::Error, tr("Regex query name cannot be empty."));

View file

@ -24,7 +24,7 @@
<item row="1" column="1"> <item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtFilter" native="true"/> <widget class="LineEditWithStatus" name="m_txtFilter" native="true"/>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="3" column="0" colspan="2">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -37,7 +37,7 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="m_buttonBox"> <widget class="QDialogButtonBox" name="m_buttonBox">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -47,6 +47,9 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2">
<widget class="HelpSpoiler" name="m_help" native="true"/>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
@ -61,6 +64,12 @@
<header>lineeditwithstatus.h</header> <header>lineeditwithstatus.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>HelpSpoiler</class>
<extends>QWidget</extends>
<header>helpspoiler.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>m_btnColor</tabstop> <tabstop>m_btnColor</tabstop>

View file

@ -151,18 +151,21 @@ bool Search::cleanMessages(bool clear_only_read) {
ServiceRoot* service = getParentServiceRoot(); ServiceRoot* service = getParentServiceRoot();
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
return false; try {
/* DatabaseQueries::cleanProbedMessages(database, clear_only_read, this);
if (DatabaseQueries::cleanLabelledMessages(database, clear_only_read, this)) {
service->updateCounts(true); service->updateCounts(true);
service->itemChanged(service->getSubTree()); service->itemChanged(service->getSubTree());
service->requestReloadMessageList(true); service->requestReloadMessageList(true);
return true; return true;
} }
else { catch (const ApplicationException& ex) {
qCriticalNN << LOGSEC_CORE << "Failed to clean messages of probe:" << QUOTE_W_SPACE_DOT(ex.message());
return false; return false;
} }
*/ }
QString Search::additionalTooltip() const {
return tr("Regular expression: %1").arg(QSL("<code>%1</code>").arg(filter()));
} }
bool Search::markAsReadUnread(RootItem::ReadStatus status) { bool Search::markAsReadUnread(RootItem::ReadStatus status) {

View file

@ -27,6 +27,7 @@ class RSSGUARD_DLLSPEC Search : public RootItem {
void setCountOfUnreadMessages(int unreadCount); void setCountOfUnreadMessages(int unreadCount);
virtual bool cleanMessages(bool clear_only_read); virtual bool cleanMessages(bool clear_only_read);
virtual QString additionalTooltip() const;
virtual bool markAsReadUnread(ReadStatus status); virtual bool markAsReadUnread(ReadStatus status);
virtual int countOfAllMessages() const; virtual int countOfAllMessages() const;
virtual int countOfUnreadMessages() const; virtual int countOfUnreadMessages() const;