KItemViews

klistwidgetsearchline.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2003 Scott Wheeler <[email protected]>
4  SPDX-FileCopyrightText: 2004 Gustavo Sverzut Barbieri <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #include "klistwidgetsearchline.h"
10 
11 #include <QListWidget>
12 #include <QApplication>
13 #include <QKeyEvent>
14 #include <QEvent>
15 #include <QTimer>
16 
17 class Q_DECL_HIDDEN KListWidgetSearchLine::KListWidgetSearchLinePrivate
18 {
19 public:
20  KListWidgetSearchLinePrivate(KListWidgetSearchLine *parent) :
21  q(parent)
22  {}
23 
24  void _k_listWidgetDeleted();
25  void _k_queueSearch(const QString &);
26  void _k_activateSearch();
27  void _k_rowsInserted(const QModelIndex &, int, int);
28  void _k_dataChanged(const QModelIndex &, const QModelIndex &);
29 
30  void init(QListWidget *listWidget = nullptr);
31  void updateHiddenState(int start, int end);
32 
33  KListWidgetSearchLine *const q;
34  QListWidget *listWidget = nullptr;
35  Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive;
36  bool activeSearch = false;
37  QString search;
38  int queuedSearches = 0;
39 };
40 
41 /******************************************************************************
42  * Public Methods *
43  *****************************************************************************/
45  QLineEdit(parent),
46  d(new KListWidgetSearchLinePrivate(this))
47 
48 {
49  d->init(listWidget);
50 }
51 
53 {
54  clear(); // returning items back to listWidget
55  delete d;
56 }
57 
59 {
60  return d->caseSensitivity;
61 }
62 
64 {
65  return d->listWidget;
66 }
67 
68 /******************************************************************************
69  * Public Slots *
70  *****************************************************************************/
72 {
73  d->search = s.isNull() ? text() : s;
74  if (d->listWidget) {
75  d->updateHiddenState(0, d->listWidget->count() - 1);
76  }
77 }
78 
80 {
81  // Show items back to QListWidget
82  if (d->listWidget != nullptr) {
83  for (int i = 0; i < d->listWidget->count(); ++i) {
84  d->listWidget->item(i)->setHidden(false);
85  }
86  }
87 
88  d->search = QString();
89  d->queuedSearches = 0;
91 }
92 
94 {
95  d->caseSensitivity = cs;
96 }
97 
99 {
100  if (d->listWidget != nullptr) {
101  disconnect(d->listWidget, SIGNAL(destroyed()),
102  this, SLOT(_k_listWidgetDeleted()));
103  d->listWidget->model()->disconnect(this);
104  }
105 
106  d->listWidget = lw;
107 
108  if (lw != nullptr) {
109  connect(d->listWidget, SIGNAL(destroyed()),
110  this, SLOT(_k_listWidgetDeleted()));
111  connect(d->listWidget->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
112  this, SLOT(_k_rowsInserted(QModelIndex,int,int)));
113  connect(d->listWidget->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
114  this, SLOT(_k_dataChanged(QModelIndex,QModelIndex)));
115  setEnabled(true);
116  } else {
117  setEnabled(false);
118  }
119 }
120 
121 /******************************************************************************
122  * Protected Methods *
123  *****************************************************************************/
125  const QString &s) const
126 {
127  if (s.isEmpty()) {
128  return true;
129  }
130 
131  if (item == nullptr) {
132  return false;
133  }
134 
135  return (item->text().indexOf(s, 0,
137 }
138 
139 void KListWidgetSearchLine::KListWidgetSearchLinePrivate::init(QListWidget *_listWidget)
140 {
141  listWidget = _listWidget;
142 
143  connect(q, SIGNAL(textChanged(QString)),
144  q, SLOT(_k_queueSearch(QString)));
145 
146  if (listWidget != nullptr) {
147  connect(listWidget, SIGNAL(destroyed()),
148  q, SLOT(_k_listWidgetDeleted()));
149  connect(listWidget->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
150  q, SLOT(_k_rowsInserted(QModelIndex,int,int)));
151  connect(listWidget->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
152  q, SLOT(_k_dataChanged(QModelIndex,QModelIndex)));
153  q->setEnabled(true);
154  } else {
155  q->setEnabled(false);
156  }
157  q->setClearButtonEnabled(true);
158 }
159 
160 void KListWidgetSearchLine::KListWidgetSearchLinePrivate::updateHiddenState(int start, int end)
161 {
162  if (!listWidget) {
163  return;
164  }
165 
166  QListWidgetItem *currentItem = listWidget->currentItem();
167 
168  // Remove Non-Matching items
169  for (int index = start; index <= end; ++index) {
170  QListWidgetItem *item = listWidget->item(index);
171  if (! q->itemMatches(item, search)) {
172  item->setHidden(true);
173 
174  if (item == currentItem) {
175  currentItem = nullptr; // It's not in listWidget anymore.
176  }
177  } else if (item->isHidden()) {
178  item->setHidden(false);
179  }
180  }
181 
182  if (listWidget->isSortingEnabled()) {
184  }
185 
186  if (currentItem != nullptr) {
187  listWidget->scrollToItem(currentItem);
188  }
189 }
190 
192 {
193 
194  if (event->type() == QEvent::KeyPress) {
195  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
200  ) {
201  if (d->listWidget) {
202  QApplication::sendEvent(d->listWidget, event);
203  return true;
204  }
205  } else if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
206 
207  if (d->listWidget) {
208  QApplication::sendEvent(d->listWidget, event);
209  return true;
210  }
211  }
212  }
213  return QLineEdit::event(event);
214 }
215 /******************************************************************************
216  * Protected Slots *
217  *****************************************************************************/
218 void KListWidgetSearchLine::KListWidgetSearchLinePrivate::_k_queueSearch(const QString &s)
219 {
220  queuedSearches++;
221  search = s;
222  QTimer::singleShot(200, q, SLOT(_k_activateSearch()));
223 }
224 
225 void KListWidgetSearchLine::KListWidgetSearchLinePrivate::_k_activateSearch()
226 {
227  queuedSearches--;
228 
229  if (queuedSearches <= 0) {
230  q->updateSearch(search);
231  queuedSearches = 0;
232  }
233 }
234 
235 /******************************************************************************
236  * KListWidgetSearchLinePrivate Slots *
237  *****************************************************************************/
238 void KListWidgetSearchLine::KListWidgetSearchLinePrivate::_k_listWidgetDeleted()
239 {
240  listWidget = nullptr;
241  q->setEnabled(false);
242 }
243 
244 void KListWidgetSearchLine::KListWidgetSearchLinePrivate::_k_rowsInserted(const QModelIndex &parent, int start, int end)
245 {
246  if (parent.isValid()) {
247  return;
248  }
249 
250  updateHiddenState(start, end);
251 }
252 
253 void KListWidgetSearchLine::KListWidgetSearchLinePrivate::_k_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
254 {
255  if (topLeft.parent().isValid()) {
256  return;
257  }
258 
259  updateHiddenState(topLeft.row(), bottomRight.row());
260 }
261 
262 #include "moc_klistwidgetsearchline.cpp"
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QEvent::Type type() const const
QListWidgetItem * currentItem() const const
bool isSortingEnabled() const const
bool event(QEvent *event) override
Re-implemented for internal reasons.
void clear()
QString text() const const
virtual bool event(QEvent *e) override
void textChanged(const QString &text)
void clear()
Clear line edit and empty hiddenItems, returning elements to listWidget.
void sortItems(Qt::SortOrder order)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual void updateSearch(const QString &s=QString())
Updates search to only make visible the items that match s.
void setCaseSensitivity(Qt::CaseSensitivity cs)
Make the search case sensitive or case insensitive.
bool isNull() const const
KListWidgetSearchLine(QWidget *parent=nullptr, QListWidget *listWidget=nullptr)
Constructs a KListWidgetSearchLine with listWidget being the QListWidget to be filtered.
bool isValid() const const
void setEnabled(bool)
void setListWidget(QListWidget *lv)
Sets the QListWidget that is filtered by this search line.
CaseSensitivity
bool isEmpty() const const
bool isHidden() const const
int row() const const
bool sendEvent(QObject *receiver, QEvent *event)
virtual ~KListWidgetSearchLine()
Destroys the KListWidgetSearchLine.
QListWidgetItem * item(int row) const const
QModelIndex parent() const const
bool matches(QKeySequence::StandardKey key) const const
QListWidget * listWidget() const
Returns the listWidget that is currently filtered by the search.
void setHidden(bool hide)
int key() const const
virtual bool itemMatches(const QListWidgetItem *item, const QString &s) const
Returns true if item matches the search s.
QCA_EXPORT void init()
void end(bool mark)
void scrollToItem(const QListWidgetItem *item, QAbstractItemView::ScrollHint hint)
QAbstractItemModel * model() const const
This class makes it easy to add a search line for filtering the items in a listwidget based on a simp...
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
Qt::CaseSensitivity caseSensitive() const
Returns if the search is case sensitive.
void destroyed(QObject *obj)
Key_Enter
QString text() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Nov 26 2020 22:38:10 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.