Libksieve

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

KDE's Doxygen guidelines are available online.