Messagelib

findbarbase.cpp
1 /* SPDX-FileCopyrightText: 2010 Torgny Nyblom <[email protected]>
2  * SPDX-FileCopyrightText: 2010-2023 Laurent Montel <[email protected]>
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 
27 using namespace WebEngineViewer;
28 
29 FindBarBase::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(QStringLiteral("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(QStringLiteral("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(QStringLiteral("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(QStringLiteral("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;
88  mStatus->setObjectName(QStringLiteral("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 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
98  connect(qApp, &QApplication::paletteChanged, this, &FindBarBase::updatePalette);
99 #endif
100 }
101 
102 FindBarBase::~FindBarBase() = default;
103 
104 QMenu *FindBarBase::optionsMenu() const
105 {
106  return mOptionsMenu;
107 }
108 
109 QString FindBarBase::text() const
110 {
111  return mSearch->text();
112 }
113 
114 void FindBarBase::setText(const QString &text)
115 {
116  mSearch->setText(text);
117  addToCompletion(text);
118 }
119 
120 void FindBarBase::focusAndSetCursor()
121 {
122  setFocus();
123  mStatus->clear();
124  mSearch->selectAll();
125  mSearch->setFocus();
126 }
127 
128 void FindBarBase::slotClearSearch()
129 {
130  clearSelections();
131 }
132 
133 void FindBarBase::autoSearch(const QString &str)
134 {
135  const bool isNotEmpty = (!str.isEmpty());
136  mFindPrevBtn->setEnabled(isNotEmpty);
137  mFindNextBtn->setEnabled(isNotEmpty);
138  if (isNotEmpty) {
139  QTimer::singleShot(0, this, [this]() {
140  slotSearchText();
141  });
142  } else {
143  mStatus->clear();
144  clearSelections();
145  }
146 }
147 
148 void FindBarBase::slotSearchText(bool backward, bool isAutoSearch)
149 {
150  searchText(backward, isAutoSearch);
151 }
152 
153 void FindBarBase::updatePalette()
154 {
156  mPositiveBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch->palette()).color().name());
158  mNegativeBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch->palette()).color().name());
159 }
160 
161 void FindBarBase::setFoundMatch(bool match)
162 {
163 #ifndef QT_NO_STYLE_STYLESHEET
164  QString styleSheet;
165 
166  if (!mSearch->text().isEmpty()) {
167  if (mNegativeBackground.isEmpty()) {
168  updatePalette();
169  }
170  if (match) {
171  styleSheet = mPositiveBackground;
172  mStatus->clear();
173  } else {
174  styleSheet = mNegativeBackground;
175  mStatus->setText(mNotFoundString);
176  }
177  }
178  mSearch->setStyleSheet(styleSheet);
179 #endif
180 }
181 
182 void FindBarBase::searchText(bool backward, bool isAutoSearch)
183 {
184  Q_UNUSED(backward)
185  Q_UNUSED(isAutoSearch)
186 }
187 
188 void FindBarBase::addToCompletion(const QString &text)
189 {
190  mSearch->addCompletionItem(text);
191 }
192 
193 void FindBarBase::findNext()
194 {
195  searchText(false, false);
196  addToCompletion(mLastSearchStr);
197 }
198 
199 void FindBarBase::findPrev()
200 {
201  searchText(true, false);
202  addToCompletion(mLastSearchStr);
203 }
204 
205 void FindBarBase::caseSensitivityChanged(bool b)
206 {
207  updateSensitivity(b);
208 }
209 
210 void FindBarBase::updateSensitivity(bool)
211 {
212 }
213 
214 void FindBarBase::slotHighlightAllChanged(bool b)
215 {
216  updateHighLight(b);
217 }
218 
219 void FindBarBase::updateHighLight(bool)
220 {
221 }
222 
223 void FindBarBase::clearSelections()
224 {
225  setFoundMatch(false);
226 }
227 
228 void FindBarBase::closeBar()
229 {
230  // Make sure that all old searches are cleared
231  mSearch->clear();
232  clearSelections();
233  mSearch->clearFocus();
234  Q_EMIT hideFindBar();
235 }
236 
237 bool FindBarBase::event(QEvent *e)
238 {
239  // Close the bar when pressing Escape.
240  // Not using a QShortcut for this because it could conflict with
241  // window-global actions (e.g. Emil Sedgh binds Esc to "close tab").
242  // With a shortcut override we can catch this before it gets to kactions.
243  const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride);
244  if (shortCutOverride || e->type() == QEvent::KeyPress) {
245  auto kev = static_cast<QKeyEvent *>(e);
246  if (kev->key() == Qt::Key_Escape) {
247  if (shortCutOverride) {
248  e->accept();
249  return true;
250  }
251  e->accept();
252  closeBar();
253  return true;
254  } else if (kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return) {
255  e->accept();
256  if (shortCutOverride) {
257  return true;
258  }
259  if (mSearch->text().isEmpty()) {
260  return true;
261  }
262  if (kev->modifiers() & Qt::ShiftModifier) {
263  findPrev();
264  } else if (kev->modifiers() == Qt::NoModifier) {
265  findNext();
266  }
267  return true;
268  }
269  }
270 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
272  updatePalette();
273  }
274 #endif
275  return QWidget::event(e);
276 }
void paletteChanged(const QPalette &palette)
PlainText
ShortcutOverride
void clear()
void clicked(bool checked)
virtual bool event(QEvent *event) override
QIcon fromTheme(const QString &name)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
const QList< QKeySequence > & findNext()
QString i18n(const char *text, const TYPE &arg...)
void toggled(bool checked)
void textChanged(const QString &text)
bool isEmpty() const const
void returnPressed()
Key_Escape
QString label(StandardShortcut id)
QEvent::Type type() const const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
ShiftModifier
const QList< QKeySequence > & findPrev()
void accept()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Fri Mar 24 2023 04:08:31 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.