Messagelib

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

KDE's Doxygen guidelines are available online.