File indexing completed on 2024-04-28 09:45:43
0001 /* This file is part of the KDE project 0002 Copyright (C) 2005 Daniel Teske <teske@squorn.de> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public License as 0006 published by the Free Software Foundation; either version 2 of 0007 the License, or (at your option) version 3. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <http://www.gnu.org/licenses/> 0016 */ 0017 0018 #ifndef __kebsearchline_h 0019 #define __kebsearchline_h 0020 0021 #include <KLineEdit> 0022 #include <QAbstractItemView> 0023 #include <QList> 0024 0025 class QAction; 0026 class KViewSearchLinePrivate; 0027 /** 0028 * This class makes it easy to add a search line for filtering the items in a 0029 * QListView/QTreeView based on a simple text search. 0030 * 0031 * No changes to the application other than instantiating this class with an 0032 * appropriate QListView/QTreeView should be needed. 0033 * 0034 * This class automatically responds to the dataChanged(), rowsInserted(), 0035 * rowsRemoved() and similar signals. 0036 * This means that the view needs to be bound to a model(). 0037 * 0038 * Note: Don't call setModel() on the view while a KViewSearchLine filters 0039 * the view. (Instead call setView(0) before and setView(view) after calling 0040 * setModel() 0041 * 0042 * 0043 * Note: You need to call updateSearch() if you called QListView::setModelColumn() 0044 */ 0045 0046 // FIXME delete KViewSearchLine if there is a replacement in kdelibs 0047 class KViewSearchLine : public KLineEdit 0048 { 0049 Q_OBJECT 0050 0051 public: 0052 /** 0053 * Constructs a KViewSearchLine with \a view being the QTreeView/QListView 0054 * to be filtered. 0055 * 0056 * If \a view is null then the widget will be disabled until a listview 0057 * is set with setListView(). 0058 */ 0059 explicit KViewSearchLine(QWidget *parent = nullptr, QAbstractItemView *view = nullptr); 0060 0061 /** 0062 * Constructs a KViewSearchLine without any QListView/QTreeView to filter. The 0063 * QListView/QTreeView object has to be set later with setListView(). 0064 */ 0065 explicit KViewSearchLine(QWidget *parent); 0066 0067 /** 0068 * Destroys the KViewSearchLine. 0069 */ 0070 ~KViewSearchLine() override; 0071 0072 /** 0073 * Returns true if the search is case sensitive. This defaults to false. 0074 * 0075 * @see setCaseSensitive() 0076 */ 0077 bool caseSensitive() const; 0078 0079 /** 0080 * Returns the current list of columns that will be searched. If the 0081 * returned list is empty all visible columns will be searched. 0082 * 0083 * @see setSearchColumns 0084 */ 0085 QList<int> searchColumns() const; 0086 0087 /** 0088 * If this is true (the default) then the parents of matched items will also 0089 * be shown. 0090 * 0091 * @see setKeepParentsVisible() 0092 */ 0093 bool keepParentsVisible() const; 0094 0095 /** 0096 * Returns the view that is currently filtered by the search. 0097 * 0098 * @see setView() 0099 */ 0100 QAbstractItemView *view() const; 0101 0102 using KLineEdit::setVisible; 0103 0104 public Q_SLOTS: 0105 /** 0106 * Updates search to only make visible the items that match \a s. If 0107 * \a s is null then the line edit's text will be used. 0108 */ 0109 virtual void updateSearch(const QString &s = QString()); 0110 0111 /** 0112 * Make the search case sensitive or case insensitive. 0113 * 0114 * @see caseSenstive() 0115 */ 0116 void setCaseSensitive(bool cs); 0117 0118 /** 0119 * When a search is active on a list that's organized into a tree view if 0120 * a parent or ancestor of an item is does not match the search then it 0121 * will be hidden and as such so too will any children that match. 0122 * 0123 * If this is set to true (the default) then the parents of matching items 0124 * will be shown. 0125 * 0126 * This applies only to QTreeViews. 0127 * 0128 * @see keepParentsVisible 0129 */ 0130 void setKeepParentsVisible(bool v); 0131 0132 /** 0133 * Sets the list of columns to be searched. The default is to search all, 0134 * visible columns which can be restored by passing \a columns as an empty 0135 * list. 0136 * This has no effect if the view is a QListView. 0137 * 0138 * @see searchColumns 0139 */ 0140 void setSearchColumns(const QList<int> &columns); 0141 0142 /** 0143 * Sets the view that is filtered by this search line. 0144 * If \a v is null then the widget will be disabled. 0145 * v must be either a QListView or a QTreeView 0146 * (That includes QListWidget and QTreeWidget) 0147 * @see view() 0148 */ 0149 void setView(QAbstractItemView *v); 0150 0151 protected: 0152 /** 0153 * Returns true if the row including \a item matches the search \a s. 0154 * This will be evaluated based on the value of caseSensitive() and 0155 * searchColumns(). This can be overridden in subclasses to implement 0156 * more complicated matching schemes. 0157 */ 0158 virtual bool itemMatches(const QModelIndex &item, const QString &s) const; 0159 0160 /** 0161 * Re-implemented for internal reasons. API not affected. 0162 */ 0163 void contextMenuEvent(QContextMenuEvent *e) override; 0164 0165 protected Q_SLOTS: 0166 /** 0167 * When keys are pressed a new search string is created and a timer is 0168 * activated. The most recent search is activated when this timer runs out 0169 * if another key has not yet been pressed. 0170 * 0171 * This method makes @param search the most recent search and starts the 0172 * timer. 0173 * 0174 * Together with activateSearch() this makes it such that searches are not 0175 * started until there is a short break in the users typing. 0176 * 0177 * @see activateSearch() 0178 */ 0179 void queueSearch(const QString &search); 0180 0181 /** 0182 * When the timer started with queueSearch() expires this slot is called. 0183 * If there has been another timer started then this slot does nothing. 0184 * However if there are no other pending searches this starts the list view 0185 * search. 0186 * 0187 * @see queueSearch() 0188 */ 0189 void activateSearch(); 0190 0191 private: 0192 /** 0193 * QListView's and QTreeView's setRowHidden are slightly different. 0194 */ 0195 void setVisible(const QModelIndex &index, bool v); 0196 0197 /** 0198 * This is used in case parent items of matching items shouldn't be 0199 * visible. It hides all items that don't match the search string. 0200 */ 0201 void checkItemParentsNotVisible(); 0202 0203 /** 0204 * This is used in case parent items of matching items should be visible. 0205 * It makes a recursive call to all children. It returns true if at least 0206 * one item in the subtree with the given root item is visible. 0207 */ 0208 bool checkItemParentsVisible(QModelIndex index); 0209 0210 /** 0211 * returns whether any row between first and last is visible 0212 */ 0213 bool anyVisible(const QModelIndex &first, const QModelIndex &last); 0214 0215 /** 0216 * rechecks indices first-last after a dataChanged() signal 0217 * sets their visibility and returns true if any item should be 0218 * visible 0219 */ 0220 bool recheck(const QModelIndex &first, const QModelIndex &last); 0221 0222 /** 0223 * Hide QListView/QTreeView's different isRowHidden 0224 */ 0225 bool isVisible(const QModelIndex &index); 0226 0227 /** 0228 * returns the model() of the view() 0229 */ 0230 QAbstractItemModel *model() const; 0231 0232 /** 0233 * returns the index exactly one row below \p index 0234 */ 0235 QModelIndex nextRow(const QModelIndex &index); 0236 0237 private Q_SLOTS: 0238 void listViewDeleted(); 0239 void slotDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); 0240 void slotRowsInserted(const QModelIndex &parent, int first, int last); 0241 void slotRowsRemoved(const QModelIndex &parent, int first, int last); 0242 void slotColumnsInserted(const QModelIndex &parent, int first, int last); 0243 void slotColumnsRemoved(const QModelIndex &parent, int first, int last); 0244 void slotModelReset(); 0245 void searchColumnsMenuActivated(QAction *act); 0246 0247 private: 0248 class KViewSearchLinePrivate; 0249 KViewSearchLinePrivate *d; 0250 QList<QAction *> actions; 0251 }; 0252 0253 /** 0254 * Creates a widget featuring a KViewSearchLine, a label with the text 0255 * "Search" and a button to clear the search. 0256 */ 0257 class KViewSearchLineWidget : public QWidget 0258 { 0259 Q_OBJECT 0260 0261 public: 0262 /** 0263 * Creates a KListViewSearchLineWidget for \a view with \a parent as the 0264 * parent 0265 */ 0266 explicit KViewSearchLineWidget(QAbstractItemView *view = nullptr, QWidget *parent = nullptr); 0267 0268 /** 0269 * Destroys the KListViewSearchLineWidget 0270 */ 0271 ~KViewSearchLineWidget() override; 0272 0273 /** 0274 * Creates the search line. This can be useful to reimplement in cases where 0275 * a KViewSearchLine subclass is used. 0276 */ 0277 virtual KViewSearchLine *createSearchLine(QAbstractItemView *view); 0278 0279 /** 0280 * Returns a pointer to the search line. 0281 */ 0282 KViewSearchLine *searchLine() const; 0283 0284 protected Q_SLOTS: 0285 /** 0286 * Creates the widgets inside of the widget. This is called from the 0287 * constructor via a single shot timer so that it it guaranteed to run 0288 * after construction is complete. This makes it suitable for overriding in 0289 * subclasses. 0290 */ 0291 virtual void createWidgets(); 0292 0293 private: 0294 class KViewSearchLineWidgetPrivate; 0295 KViewSearchLineWidgetPrivate *d; 0296 }; 0297 0298 #endif