00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "klistviewsearchline.h"
00020
00021 #include <klistview.h>
00022 #include <kdebug.h>
00023 #include <klocale.h>
00024
00025 #include <qtimer.h>
00026 #include <qpopupmenu.h>
00027
00028 #define KLISTVIEWSEARCHLINE_ALLCOLUMNS_ID 2004
00029
00030 class KListViewSearchLine::KListViewSearchLinePrivate
00031 {
00032 public:
00033 KListViewSearchLinePrivate() :
00034 listView(0),
00035 caseSensitive(false),
00036 activeSearch(false),
00037 keepParentsVisible(true),
00038 queuedSearches(0) {}
00039
00040 KListView *listView;
00041 bool caseSensitive;
00042 bool activeSearch;
00043 bool keepParentsVisible;
00044 QString search;
00045 int queuedSearches;
00046 QValueList<int> searchColumns;
00047 };
00048
00050
00052
00053 KListViewSearchLine::KListViewSearchLine(QWidget *parent, KListView *listView, const char *name) :
00054 KLineEdit(parent, name)
00055 {
00056 d = new KListViewSearchLinePrivate;
00057
00058 d->listView = listView;
00059
00060 connect(this, SIGNAL(textChanged(const QString &)),
00061 this, SLOT(queueSearch(const QString &)));
00062
00063 if(listView) {
00064 connect(listView, SIGNAL(destroyed()),
00065 this, SLOT(listViewDeleted()));
00066
00067 connect(listView, SIGNAL(itemAdded(QListViewItem *)),
00068 this, SLOT(itemAdded(QListViewItem *)));
00069 }
00070 else
00071 setEnabled(false);
00072 }
00073
00074 KListViewSearchLine::KListViewSearchLine(QWidget *parent, const char *name) :
00075 KLineEdit(parent, name)
00076 {
00077 d = new KListViewSearchLinePrivate;
00078
00079 d->listView = 0L;
00080
00081 connect(this, SIGNAL(textChanged(const QString &)),
00082 this, SLOT(queueSearch(const QString &)));
00083
00084 setEnabled(false);
00085 }
00086
00087 KListViewSearchLine::~KListViewSearchLine()
00088 {
00089 delete d;
00090 }
00091
00092 bool KListViewSearchLine::caseSensitive() const
00093 {
00094 return d->caseSensitive;
00095 }
00096
00097 QValueList<int> KListViewSearchLine::searchColumns() const
00098 {
00099 return d->searchColumns;
00100 }
00101
00102 bool KListViewSearchLine::keepParentsVisible() const
00103 {
00104 return d->keepParentsVisible;
00105 }
00106
00107 KListView *KListViewSearchLine::listView() const
00108 {
00109 return d->listView;
00110 }
00111
00113
00115
00116 void KListViewSearchLine::updateSearch(const QString &s)
00117 {
00118 if(!d->listView)
00119 return;
00120
00121 d->search = s.isNull() ? text() : s;
00122
00123
00124
00125
00126 QListViewItem *currentItem = 0;
00127
00128 switch(d->listView->selectionMode())
00129 {
00130 case KListView::NoSelection:
00131 break;
00132 case KListView::Single:
00133 currentItem = d->listView->selectedItem();
00134 break;
00135 default:
00136 {
00137 int flags = QListViewItemIterator::Selected | QListViewItemIterator::Visible;
00138 for(QListViewItemIterator it(d->listView, flags);
00139 it.current() && !currentItem;
00140 ++it)
00141 {
00142 if(d->listView->itemRect(it.current()).isValid())
00143 currentItem = it.current();
00144 }
00145 }
00146 }
00147
00148 if(d->keepParentsVisible)
00149 checkItemParentsVisible(d->listView->firstChild());
00150 else
00151 checkItemParentsNotVisible();
00152
00153 if(currentItem)
00154 d->listView->ensureItemVisible(currentItem);
00155 }
00156
00157 void KListViewSearchLine::setCaseSensitive(bool cs)
00158 {
00159 d->caseSensitive = cs;
00160 }
00161
00162 void KListViewSearchLine::setKeepParentsVisible(bool v)
00163 {
00164 d->keepParentsVisible = v;
00165 }
00166
00167 void KListViewSearchLine::setSearchColumns(const QValueList<int> &columns)
00168 {
00169 d->searchColumns = columns;
00170 }
00171
00172 void KListViewSearchLine::setListView(KListView *lv)
00173 {
00174 if(d->listView) {
00175 disconnect(d->listView, SIGNAL(destroyed()),
00176 this, SLOT(listViewDeleted()));
00177
00178 disconnect(d->listView, SIGNAL(itemAdded(QListViewItem *)),
00179 this, SLOT(itemAdded(QListViewItem *)));
00180 }
00181
00182 d->listView = lv;
00183
00184 if(lv) {
00185 connect(d->listView, SIGNAL(destroyed()),
00186 this, SLOT(listViewDeleted()));
00187
00188 connect(d->listView, SIGNAL(itemAdded(QListViewItem *)),
00189 this, SLOT(itemAdded(QListViewItem *)));
00190 }
00191
00192 setEnabled(bool(lv));
00193 }
00194
00196
00198
00199 bool KListViewSearchLine::itemMatches(const QListViewItem *item, const QString &s) const
00200 {
00201 if(s.isEmpty())
00202 return true;
00203
00204
00205
00206
00207 if(!d->searchColumns.isEmpty()) {
00208 QValueList<int>::ConstIterator it = d->searchColumns.begin();
00209 for(; it != d->searchColumns.end(); ++it) {
00210 if(*it < item->listView()->columns() &&
00211 item->text(*it).find(s, 0, d->caseSensitive) >= 0)
00212 return true;
00213 }
00214 }
00215 else {
00216 for(int i = 0; i < item->listView()->columns(); i++) {
00217 if(item->text(i).find(s, 0, d->caseSensitive) >= 0)
00218 return true;
00219 }
00220 }
00221
00222 return false;
00223 }
00224
00225 QPopupMenu *KListViewSearchLine::createPopupMenu()
00226 {
00227 QPopupMenu *popup = KLineEdit::createPopupMenu();
00228
00229 if (d->listView->columns()>1) {
00230 QPopupMenu *subMenu = new QPopupMenu( popup );
00231 connect( subMenu, SIGNAL( activated(int) ), this, SLOT( searchColumnsMenuActivated(int) ) );
00232
00233 popup->insertSeparator();
00234 popup->insertItem( i18n("Search Columns"), subMenu );
00235
00236 subMenu->insertItem(i18n("All Columns"), KLISTVIEWSEARCHLINE_ALLCOLUMNS_ID);
00237 subMenu->insertSeparator();
00238
00239 bool allColumnsAreSearchColumns = true;
00240 for(int i = 0; i < d->listView->columns(); i++) {
00241 subMenu->insertItem(d->listView->columnText(i), i);
00242 if (d->searchColumns.isEmpty() || d->searchColumns.find(i) != d->searchColumns.end())
00243 subMenu->setItemChecked(i, true);
00244 else
00245 allColumnsAreSearchColumns = false;
00246 }
00247 subMenu->setItemChecked(KLISTVIEWSEARCHLINE_ALLCOLUMNS_ID, allColumnsAreSearchColumns);
00248
00249
00250 if (allColumnsAreSearchColumns && !d->searchColumns.isEmpty())
00251 d->searchColumns.clear();
00252 }
00253
00254 return popup;
00255 }
00256
00258
00260
00261 void KListViewSearchLine::queueSearch(const QString &search)
00262 {
00263 d->queuedSearches++;
00264 d->search = search;
00265 QTimer::singleShot(200, this, SLOT(activateSearch()));
00266 }
00267
00268 void KListViewSearchLine::activateSearch()
00269 {
00270 d->queuedSearches--;
00271
00272 if(d->queuedSearches == 0)
00273 updateSearch(d->search);
00274 }
00275
00277
00279
00280 void KListViewSearchLine::itemAdded(QListViewItem *item) const
00281 {
00282 item->setVisible(itemMatches(item, text()));
00283 }
00284
00285 void KListViewSearchLine::listViewDeleted()
00286 {
00287 d->listView = 0;
00288 setEnabled(false);
00289 }
00290
00291 void KListViewSearchLine::searchColumnsMenuActivated(int id)
00292 {
00293 if (id==KLISTVIEWSEARCHLINE_ALLCOLUMNS_ID) {
00294 if (d->searchColumns.isEmpty())
00295 d->searchColumns.append(0);
00296 else
00297 d->searchColumns.clear();
00298 }
00299 else {
00300 if (d->searchColumns.find(id) != d->searchColumns.end())
00301 d->searchColumns.remove(id);
00302 else {
00303 if (d->searchColumns.isEmpty())
00304 for(int i = 0; i < d->listView->columns(); i++) {
00305 if (i!=id)
00306 d->searchColumns.append(i);
00307 }
00308 else
00309 d->searchColumns.append(id);
00310 }
00311 }
00312 updateSearch();
00313 }
00314
00316
00318
00319 void KListViewSearchLine::checkItemParentsNotVisible()
00320 {
00321 QListViewItemIterator it(d->listView);
00322 for(; it.current(); ++it)
00323 {
00324 QListViewItem *item = it.current();
00325 if(itemMatches(item, d->search))
00326 item->setVisible(true);
00327 else
00328 item->setVisible(false);
00329 }
00330 }
00331
00332 bool KListViewSearchLine::checkItemParentsVisible(QListViewItem *item)
00333 {
00334 bool visible = false;
00335 for(; item; item = item->nextSibling()) {
00336 if((item->firstChild() && checkItemParentsVisible(item->firstChild())) ||
00337 itemMatches(item, d->search))
00338 {
00339 item->setVisible( true );
00340 visible = true;
00341 }
00342 else
00343 item->setVisible(false);
00344 }
00345 return visible;
00346 }
00347
00348 #include "klistviewsearchline.moc"