Messagelib

findbarbase.cpp
1/* SPDX-FileCopyrightText: 2010 Torgny Nyblom <nyblom@kde.org>
2 * SPDX-FileCopyrightText: 2010-2024 Laurent Montel <montel@kde.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "findbarbase.h"
8#include <KStatefulBrush>
9
10#include <PimCommon/LineEditWithCompleterNg>
11
12#include <KColorScheme>
13#include <KLocalizedString>
14#include <QIcon>
15#include <QLineEdit>
16
17#include <QApplication>
18#include <QEvent>
19#include <QHBoxLayout>
20#include <QKeyEvent>
21#include <QLabel>
22#include <QMenu>
23#include <QPushButton>
24#include <QTimer>
25#include <QToolButton>
26
27using namespace WebEngineViewer;
28
29FindBarBase::FindBarBase(QWidget *parent)
30 : QWidget(parent)
31{
32 auto lay = new QHBoxLayout(this);
33 lay->setContentsMargins({});
34
35 auto closeBtn = new QToolButton(this);
36 closeBtn->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close")));
37 closeBtn->setObjectName(QLatin1StringView("close"));
38 closeBtn->setIconSize(QSize(16, 16));
39 closeBtn->setToolTip(i18n("Close"));
40
41#ifndef QT_NO_ACCESSIBILITY
42 closeBtn->setAccessibleName(i18n("Close"));
43#endif
44
45 closeBtn->setAutoRaise(true);
46 lay->addWidget(closeBtn);
47
48 auto label = new QLabel(i18nc("Find text", "F&ind:"), this);
49 lay->addWidget(label);
50
51 mSearch = new PimCommon::LineEditWithCompleterNg(this);
52 mSearch->setObjectName(QLatin1StringView("searchline"));
53 mSearch->setToolTip(i18n("Text to search for"));
54 mSearch->setClearButtonEnabled(true);
55 label->setBuddy(mSearch);
56 lay->addWidget(mSearch);
57
58 mFindNextBtn = new QPushButton(QIcon::fromTheme(QStringLiteral("go-down-search")), i18nc("Find and go to the next search match", "Next"), this);
59 mFindNextBtn->setToolTip(i18n("Jump to next match"));
60 mFindNextBtn->setObjectName(QLatin1StringView("findnext"));
61 lay->addWidget(mFindNextBtn);
62 mFindNextBtn->setEnabled(false);
63
64 mFindPrevBtn = new QPushButton(QIcon::fromTheme(QStringLiteral("go-up-search")), i18nc("Find and go to the previous search match", "Previous"), this);
65 mFindPrevBtn->setToolTip(i18n("Jump to previous match"));
66 mFindPrevBtn->setObjectName(QLatin1StringView("findprevious"));
67 lay->addWidget(mFindPrevBtn);
68 mFindPrevBtn->setEnabled(false);
69
70 auto optionsBtn = new QPushButton(this);
71 optionsBtn->setText(i18n("Options"));
72 optionsBtn->setToolTip(i18n("Modify search behavior"));
73 mOptionsMenu = new QMenu(optionsBtn);
74 mCaseSensitiveAct = mOptionsMenu->addAction(i18n("Case sensitive"));
75 mCaseSensitiveAct->setCheckable(true);
76
77 optionsBtn->setMenu(mOptionsMenu);
78 lay->addWidget(optionsBtn);
79
80 connect(closeBtn, &QToolButton::clicked, this, &FindBarBase::closeBar);
81 connect(mFindNextBtn, &QPushButton::clicked, this, &FindBarBase::findNext);
82 connect(mFindPrevBtn, &QPushButton::clicked, this, &FindBarBase::findPrev);
83 connect(mCaseSensitiveAct, &QAction::toggled, this, &FindBarBase::caseSensitivityChanged);
84 connect(mSearch, &QLineEdit::textChanged, this, &FindBarBase::autoSearch);
85 connect(mSearch, &QLineEdit::returnPressed, this, &FindBarBase::findNext);
86
87 mStatus = new QLabel(this);
88 mStatus->setObjectName(QLatin1StringView("status"));
89 mStatus->setTextFormat(Qt::PlainText);
90 QFontMetrics fm(mStatus->font());
91 mNotFoundString = i18n("Phrase not found");
92 mStatus->setFixedWidth(fm.boundingRect(mNotFoundString).width());
93 lay->addWidget(mStatus);
94
96 hide();
97 qGuiApp->installEventFilter(this);
98}
99
100FindBarBase::~FindBarBase() = default;
101
102QMenu *FindBarBase::optionsMenu() const
103{
104 return mOptionsMenu;
105}
106
107QString FindBarBase::text() const
108{
109 return mSearch->text();
110}
111
112void FindBarBase::setText(const QString &text)
113{
114 mSearch->setText(text);
115 addToCompletion(text);
116}
117
118void FindBarBase::focusAndSetCursor()
119{
120 setFocus();
121 mStatus->clear();
122 mSearch->selectAll();
123 mSearch->setFocus();
124}
125
126void FindBarBase::slotClearSearch()
127{
128 clearSelections();
129}
130
131void FindBarBase::autoSearch(const QString &str)
132{
133 const bool isNotEmpty = (!str.isEmpty());
134 mFindPrevBtn->setEnabled(isNotEmpty);
135 mFindNextBtn->setEnabled(isNotEmpty);
136 if (isNotEmpty) {
137 QTimer::singleShot(0, this, [this]() {
138 slotSearchText();
139 });
140 } else {
141 mStatus->clear();
142 clearSelections();
143 }
144}
145
146void FindBarBase::slotSearchText(bool backward, bool isAutoSearch)
147{
148 searchText(backward, isAutoSearch);
149}
150
151void FindBarBase::updatePalette()
152{
154 mPositiveBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch->palette()).color().name());
156 mNegativeBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch->palette()).color().name());
157}
158
159void FindBarBase::setFoundMatch(bool match)
160{
161#ifndef QT_NO_STYLE_STYLESHEET
163
164 if (!mSearch->text().isEmpty()) {
165 if (mNegativeBackground.isEmpty()) {
166 updatePalette();
167 }
168 if (match) {
169 styleSheet = mPositiveBackground;
170 mStatus->clear();
171 } else {
172 styleSheet = mNegativeBackground;
173 mStatus->setText(mNotFoundString);
174 }
175 }
176 mSearch->setStyleSheet(styleSheet);
177#endif
178}
179
180void FindBarBase::searchText(bool backward, bool isAutoSearch)
181{
182 Q_UNUSED(backward)
184}
185
186void FindBarBase::addToCompletion(const QString &text)
187{
188 mSearch->addCompletionItem(text);
189}
190
191void FindBarBase::findNext()
192{
193 searchText(false, false);
194 addToCompletion(mLastSearchStr);
195}
196
197void FindBarBase::findPrev()
198{
199 searchText(true, false);
200 addToCompletion(mLastSearchStr);
201}
202
203void FindBarBase::caseSensitivityChanged(bool b)
204{
205 updateSensitivity(b);
206}
207
208void FindBarBase::updateSensitivity(bool)
209{
210}
211
212void FindBarBase::slotHighlightAllChanged(bool b)
213{
214 updateHighLight(b);
215}
216
217void FindBarBase::updateHighLight(bool)
218{
219}
220
221void FindBarBase::clearSelections()
222{
223 setFoundMatch(false);
224}
225
226void FindBarBase::closeBar()
227{
228 // Make sure that all old searches are cleared
229 mSearch->clear();
230 clearSelections();
231 mSearch->clearFocus();
232 Q_EMIT hideFindBar();
233}
234
235bool FindBarBase::event(QEvent *e)
236{
237 // Close the bar when pressing Escape.
238 // Not using a QShortcut for this because it could conflict with
239 // window-global actions (e.g. Emil Sedgh binds Esc to "close tab").
240 // With a shortcut override we can catch this before it gets to kactions.
241 const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride);
242 if (shortCutOverride || e->type() == QEvent::KeyPress) {
243 auto kev = static_cast<QKeyEvent *>(e);
244 if (kev->key() == Qt::Key_Escape) {
245 if (shortCutOverride) {
246 e->accept();
247 return true;
248 }
249 e->accept();
250 closeBar();
251 return true;
252 } else if (kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return) {
253 e->accept();
254 if (shortCutOverride) {
255 return true;
256 }
257 if (mSearch->text().isEmpty()) {
258 return true;
259 }
260 if (kev->modifiers() & Qt::ShiftModifier) {
261 findPrev();
262 } else if (kev->modifiers() == Qt::NoModifier) {
263 findNext();
264 }
265 return true;
266 }
267 }
268 return QWidget::event(e);
269}
270
271bool FindBarBase::eventFilter(QObject *obj, QEvent *event)
272{
273 Q_UNUSED(obj);
275 updatePalette();
276 }
277 return false;
278}
279
280#include "moc_findbarbase.cpp"
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
QString label(StandardShortcut id)
void clicked(bool checked)
void toggled(bool checked)
ShortcutOverride
void accept()
Type type() const const
QIcon fromTheme(const QString &name)
void clear()
void setText(const QString &)
void clear()
void returnPressed()
void selectAll()
void textChanged(const QString &text)
Q_EMITQ_EMIT
T qobject_cast(QObject *object)
QString arg(Args &&... args) const const
bool isEmpty() const const
Key_Escape
ShiftModifier
PlainText
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void clearFocus()
void setEnabled(bool)
virtual bool event(QEvent *event) override
void setFocus()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:12:44 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.