File indexing completed on 2024-05-05 05:13:11
0001 /* 0002 This file is part of Akregator. 0003 0004 SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0007 */ 0008 0009 #include "searchbar.h" 0010 #include "akregatorconfig.h" 0011 0012 #include "article.h" 0013 #include <TextUtils/ConvertText> 0014 0015 #include <KLineEdit> 0016 #include <KLocalizedString> 0017 0018 #include <QHBoxLayout> 0019 #include <QStandardPaths> 0020 #include <QString> 0021 #include <chrono> 0022 0023 using namespace std::chrono_literals; 0024 0025 using namespace Akregator; 0026 using namespace Akregator::Filters; 0027 0028 SearchBar::SearchBar(QWidget *parent) 0029 : QWidget(parent) 0030 , m_searchLine(new StatusSearchLine(this)) 0031 { 0032 m_delay = 400; 0033 auto layout = new QHBoxLayout(this); 0034 0035 layout->setContentsMargins({}); 0036 layout->setSpacing(5); 0037 setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed)); 0038 0039 m_searchLine->setClearButtonEnabled(true); 0040 m_searchLine->setPlaceholderText(i18n("Search articles...")); 0041 layout->addWidget(m_searchLine); 0042 0043 connect(m_searchLine, &KLineEdit::textChanged, this, &SearchBar::slotSearchStringChanged); 0044 connect(m_searchLine, &StatusSearchLine::forceLostFocus, this, &SearchBar::forceLostFocus); 0045 connect(m_searchLine, &StatusSearchLine::statusChanged, this, &SearchBar::slotStatusChanged); 0046 0047 connect(&m_timer, &QTimer::timeout, this, &SearchBar::slotActivateSearch); 0048 m_timer.setSingleShot(true); 0049 } 0050 0051 SearchBar::~SearchBar() = default; 0052 0053 QString SearchBar::text() const 0054 { 0055 return m_searchText; 0056 } 0057 0058 StatusSearchLine::Status SearchBar::status() const 0059 { 0060 return m_searchLine->status(); 0061 } 0062 0063 void SearchBar::setDelay(int ms) 0064 { 0065 m_delay = ms; 0066 } 0067 0068 int SearchBar::delay() const 0069 { 0070 return m_delay; 0071 } 0072 0073 void SearchBar::setFocusSearchLine() 0074 { 0075 m_searchLine->setFocus(); 0076 } 0077 0078 void SearchBar::slotClearSearch() 0079 { 0080 if (status() != Akregator::StatusSearchLine::AllArticles || !m_searchLine->text().trimmed().isEmpty()) { 0081 m_searchLine->clear(); 0082 m_searchLine->setStatus(Akregator::StatusSearchLine::AllArticles); 0083 m_timer.stop(); 0084 slotStopActiveSearch(); 0085 } 0086 } 0087 0088 void SearchBar::slotSetStatus(int status) 0089 { 0090 m_searchLine->setStatus(static_cast<Akregator::StatusSearchLine::Status>(status)); 0091 triggerTimer(); 0092 } 0093 0094 void SearchBar::slotSetText(const QString &text) 0095 { 0096 m_searchLine->setText(text); 0097 triggerTimer(); 0098 } 0099 0100 void SearchBar::slotStatusChanged(Akregator::StatusSearchLine::Status /*status*/) 0101 { 0102 triggerTimer(); 0103 } 0104 0105 std::vector<QSharedPointer<const AbstractMatcher>> SearchBar::matchers() const 0106 { 0107 return m_matchers; 0108 } 0109 0110 void SearchBar::updateQuickSearchLineText(const QString &searchLineShortcut) 0111 { 0112 m_searchLine->setPlaceholderText(i18n("Search articles...<%1>", searchLineShortcut)); 0113 } 0114 0115 void SearchBar::slotSearchStringChanged(const QString &search) 0116 { 0117 m_searchText = search; 0118 triggerTimer(); 0119 } 0120 0121 void SearchBar::slotStopActiveSearch() 0122 { 0123 std::vector<QSharedPointer<const AbstractMatcher>> matchers; 0124 Settings::setStatusFilter(m_searchLine->status()); 0125 Settings::setTextFilter(m_searchText); 0126 m_matchers = matchers; 0127 Q_EMIT signalSearch(matchers); 0128 } 0129 0130 void SearchBar::slotActivateSearch() 0131 { 0132 QList<Criterion> textCriteria; 0133 QList<Criterion> statusCriteria; 0134 0135 if (!m_searchText.isEmpty()) { 0136 const QString searchTextDiacritic(TextUtils::ConvertText::normalize(m_searchText)); 0137 textCriteria.reserve(3); 0138 Criterion subjCrit(Criterion::Title, Criterion::Contains, searchTextDiacritic); 0139 textCriteria << subjCrit; 0140 Criterion crit1(Criterion::Description, Criterion::Contains, searchTextDiacritic); 0141 textCriteria << crit1; 0142 Criterion authCrit(Criterion::Author, Criterion::Contains, searchTextDiacritic); 0143 textCriteria << authCrit; 0144 } 0145 0146 switch (m_searchLine->status()) { 0147 case StatusSearchLine::AllArticles: 0148 break; 0149 case StatusSearchLine::NewArticles: { 0150 Criterion crit(Criterion::Status, Criterion::Equals, New); 0151 statusCriteria << crit; 0152 break; 0153 } 0154 case StatusSearchLine::UnreadArticles: { 0155 Criterion crit1(Criterion::Status, Criterion::Equals, New); 0156 Criterion crit2(Criterion::Status, Criterion::Equals, Unread); 0157 statusCriteria << crit1; 0158 statusCriteria << crit2; 0159 break; 0160 } 0161 case StatusSearchLine::ReadArticles: { 0162 Criterion crit(Criterion::Status, Criterion::Equals, Read); 0163 statusCriteria << crit; 0164 break; 0165 } 0166 case StatusSearchLine::ImportantArticles: { 0167 Criterion crit(Criterion::KeepFlag, Criterion::Equals, true); 0168 statusCriteria << crit; 0169 break; 0170 } 0171 } 0172 0173 std::vector<QSharedPointer<const AbstractMatcher>> matchers; 0174 if (!textCriteria.isEmpty()) { 0175 matchers.push_back(QSharedPointer<const AbstractMatcher>(new ArticleMatcher(textCriteria, ArticleMatcher::LogicalOr))); 0176 } 0177 if (!statusCriteria.isEmpty()) { 0178 matchers.push_back(QSharedPointer<const AbstractMatcher>(new ArticleMatcher(statusCriteria, ArticleMatcher::LogicalOr))); 0179 } 0180 Settings::setStatusFilter(m_searchLine->status()); 0181 Settings::setTextFilter(m_searchText); 0182 m_matchers = matchers; 0183 Q_EMIT signalSearch(matchers); 0184 } 0185 0186 void Akregator::SearchBar::triggerTimer() 0187 { 0188 if (m_timer.isActive()) { 0189 m_timer.stop(); 0190 } 0191 0192 m_timer.start(200ms); 0193 } 0194 0195 #include "moc_searchbar.cpp"