Messagelib

searchlinestatus.cpp
1/*
2 SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "searchlinestatus.h"
8
9#include "configurefiltersdialog.h"
10#include "core/filtersavedmanager.h"
11#include "filtersavedmenu.h"
12#include "messagelist_debug.h"
13#include <KStatefulBrush>
14
15#include <KColorScheme>
16#include <KLocalizedString>
17#include <QAbstractItemView>
18#include <QAction>
19#include <QActionGroup>
20#include <QCompleter>
21#include <QContextMenuEvent>
22#include <QMenu>
23#include <QPushButton>
24#include <QStandardPaths>
25#include <QStringListModel>
26#include <QWidgetAction>
27
28static const char qLineEditclearButtonActionNameC[] = "_q_qlineeditclearaction";
29#define MAX_COMPLETION_ITEMS 20
30using namespace MessageList::Core;
31SearchLineStatus::SearchLineStatus(QWidget *parent)
32 : QLineEdit(parent)
33 , mCompleter(new QCompleter(this))
34 , mCompleterListModel(new QStringListModel(this))
35{
36 setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags{Qt::BottomEdge}));
37 mCompleter->setCaseSensitivity(Qt::CaseInsensitive);
38 mCompleter->setModel(mCompleterListModel);
39 setCompleter(mCompleter);
40
41 setClearButtonEnabled(true);
42 initializeActions();
43 auto act = findChild<QAction *>(QLatin1StringView(qLineEditclearButtonActionNameC));
44 if (act) {
45 connect(act, &QAction::triggered, this, &SearchLineStatus::slotClear);
46 } else {
47 qCWarning(MESSAGELIST_LOG) << "Clear button name was changed ! Please verify qt code";
48 }
49 connect(FilterSavedManager::self(), &FilterSavedManager::activateFilter, this, &SearchLineStatus::slotActivateFilter);
50}
51
52SearchLineStatus::~SearchLineStatus() = default;
53
54void SearchLineStatus::keyPressEvent(QKeyEvent *e)
55{
56 if (e->key() == Qt::Key_Escape) {
57 if (mCompleter->popup()->isVisible()) {
59 } else {
60 Q_EMIT forceLostFocus();
61 }
62 } else if (e->key() == Qt::Key_Q && (e->modifiers().testFlag(Qt::ShiftModifier) && e->modifiers().testFlag(Qt::AltModifier))) {
63 mLockAction->trigger();
64 } else {
66 }
67}
68
69void SearchLineStatus::slotClear()
70{
71 Q_EMIT clearButtonClicked();
72}
73
74void SearchLineStatus::updateLockAction()
75{
76 if (mLocked) {
77 mLockAction->setIcon(QIcon::fromTheme(QStringLiteral("object-locked")));
78 mLockAction->setToolTip(i18nc("@info:tooltip", "Prevent the quick search field from being cleared when changing folders"));
79 } else {
80 mLockAction->setIcon(QIcon::fromTheme(QStringLiteral("object-unlocked")));
81 mLockAction->setToolTip(i18nc("@info:tooltip", "Clear the quick search field when changing folders"));
82 }
83}
84
85void SearchLineStatus::setLocked(bool b)
86{
87 if (mLocked != b) {
88 slotToggledLockAction();
89 }
90}
91
92bool SearchLineStatus::locked() const
93{
94 return mLocked;
95}
96
97void SearchLineStatus::initializeActions()
98{
99#if USE_SEARCH_COMMAND_LINE
100 mSearchCommandAction = addAction(QIcon::fromTheme(QStringLiteral("settings-configure")), QLineEdit::TrailingPosition);
101 mSearchCommandAction->setWhatsThis(i18nc("@info:whatsthis", "Toggle this button if you want show or hide search command line widget."));
102 connect(mSearchCommandAction, &QAction::triggered, this, &SearchLineStatus::searchCommandActionRequested);
103#endif
104 mLockAction = addAction(QIcon::fromTheme(QStringLiteral("object-locked")), QLineEdit::TrailingPosition);
105 mLockAction->setWhatsThis(i18nc("@info:whatsthis",
106 "Toggle this button if you want to keep your quick search "
107 "locked when moving to other folders or when narrowing the search "
108 "by message status."));
109
110 connect(mLockAction, &QAction::triggered, this, &SearchLineStatus::slotToggledLockAction);
111 updateLockAction();
112
113 mSaveFilterAction = addAction(QIcon::fromTheme(QStringLiteral("edit-find")), QLineEdit::LeadingPosition);
114 mSaveFilterAction->setToolTip(i18nc("@info:tooltip", "Saved Filter"));
115 mFilterSavedMenu = new FilterSavedMenu(this);
116 mSaveFilterAction->setMenu(mFilterSavedMenu);
117 connect(mSaveFilterAction, &QAction::triggered, this, &SearchLineStatus::showSavedFiltersMenu);
118 connect(mFilterSavedMenu, &FilterSavedMenu::saveFilter, this, &SearchLineStatus::saveFilter);
119 connect(mFilterSavedMenu, &FilterSavedMenu::configureFilters, this, &SearchLineStatus::slotConfigureFilters);
120}
121
122void SearchLineStatus::slotActivateFilter(const QString &identifier)
123{
124 Filter *f = FilterSavedManager::self()->loadFilter(identifier);
125 if (f) {
126 Q_EMIT activateFilter(f);
127 } else {
128 qCWarning(MESSAGELIST_LOG) << "Impossible to load Filter from identifier :" << identifier;
129 }
130}
131
132void SearchLineStatus::slotConfigureFilters()
133{
134 ConfigureFiltersDialog dlg(this);
135 dlg.exec();
136}
137
138void SearchLineStatus::slotToggledLockAction()
139{
140 mLocked = !mLocked;
141 updateLockAction();
142}
143
144void SearchLineStatus::showSavedFiltersMenu()
145{
146 mFilterSavedMenu->exec(mapToGlobal(QPoint(0, height())));
147}
148
149void SearchLineStatus::clearFilterAction()
150{
151 mHasFilter = false;
152 updateFilterLineEditBackgroundColor();
153}
154
155void SearchLineStatus::updateFilterLineEditBackgroundColor()
156{
157 if (mColorName.isEmpty()) {
159 KStatefulBrush bgBrush(KColorScheme::View, bgColorScheme);
160 mColorName = bgBrush.brush(palette()).color().name();
161 }
162 setStyleSheet(mHasFilter ? QStringLiteral("QLineEdit{ background-color:%1 }").arg(mColorName) : QString());
163}
164
165void SearchLineStatus::clearFilterButtonClicked()
166{
167 mHasFilter = false;
168 updateFilterLineEditBackgroundColor();
169}
170
171void SearchLineStatus::filterAdded()
172{
173 mHasFilter = true;
174 updateFilterLineEditBackgroundColor();
175}
176
177void SearchLineStatus::addCompletionItem(const QString &str)
178{
179 mListCompetion.removeAll(str);
180 mListCompetion.prepend(str);
181 while (mListCompetion.size() > MAX_COMPLETION_ITEMS) {
182 mListCompetion.removeLast();
183 }
184 mCompleterListModel->setStringList(mListCompetion);
185}
186
187void SearchLineStatus::contextMenuEvent(QContextMenuEvent *e)
188{
190 if (popup) {
191 popup->addSeparator();
192 popup->addAction(QIcon::fromTheme(QStringLiteral("edit-clear-locationbar-rtl")), i18n("Clear History"), this, &SearchLineStatus::slotClearHistory);
193 popup->exec(e->globalPos());
194 delete popup;
195 }
196}
197
198void SearchLineStatus::slotClearHistory()
199{
200 mListCompetion.clear();
201 mCompleterListModel->setStringList(mListCompetion);
202}
203
204void SearchLineStatus::slotInsertCommand(const QString &command)
205{
206 if (!text().isEmpty() && text().back() != QLatin1Char(' ')) {
207 insert(QStringLiteral(" "));
208 }
209 insert(command);
210}
211
212#include "moc_searchlinestatus.cpp"
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KGuiItem back(BidiMode useBidi=IgnoreRTL)
The implementation independent part of the MessageList library.
Definition aggregation.h:22
QCA_EXPORT void setProperty(const QString &name, const QVariant &value)
void setIcon(const QIcon &icon)
void setMenu(QMenu *menu)
void setToolTip(const QString &tip)
void trigger()
void triggered(bool checked)
void setWhatsThis(const QString &what)
QAbstractItemView * popup() const const
const QPoint & globalPos() const const
QIcon fromTheme(const QString &name)
int key() const const
Qt::KeyboardModifiers modifiers() const const
QAction * addAction(const QIcon &icon, ActionPosition position)
QMenu * createStandardContextMenu()
void insert(const QString &newText)
virtual void keyPressEvent(QKeyEvent *event) override
void clear()
void prepend(parameter_type value)
qsizetype removeAll(const AT &t)
void removeLast()
qsizetype size() const const
QAction * addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut)
QAction * addSeparator()
QAction * exec()
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool isEmpty() const const
void setStringList(const QStringList &strings)
CaseInsensitive
BottomEdge
Key_Escape
ShiftModifier
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)
QPoint mapToGlobal(const QPoint &pos) const const
void setStyleSheet(const QString &styleSheet)
bool isVisible() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 29 2024 11:50:54 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.