| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# klistviewsearchline.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
    00003
    00004    This library is free software; you can redistribute it and/or
    00005    modify it under the terms of the GNU Library General Public
    00006    License version 2 as published by the Free Software Foundation.
    00007
    00008    This library is distributed in the hope that it will be useful,
    00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00011    Library General Public License for more details.
    00012
    00013    You should have received a copy of the GNU Library General Public License
    00014    along with this library; see the file COPYING.LIB.  If not, write to
    00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00016    Boston, MA 02111-1307, USA.
    00017 */
    00018
    00019 #include "klistviewsearchline.h"
    00020
    00021 #include <klistview.h>
    00022 #include <kiconloader.h>
    00023 #include <ktoolbar.h>
    00024 #include <ktoolbarbutton.h>
    00025 #include <kdebug.h>
    00026 #include <klocale.h>
    00027
    00028 #include <qapplication.h>
    00029 #include <qtimer.h>
    00030 #include <qpopupmenu.h>
    00031 #include <qlabel.h>
    00032 #include <qheader.h>
    00033
    00034 #define KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID 2004
    00035
    00036 class KListViewSearchLine::KListViewSearchLinePrivate
    00037 {
    00038 public:
    00039     KListViewSearchLinePrivate() :
    00040         listView(0),
    00041         caseSensitive(false),
    00042         activeSearch(false),
    00043         keepParentsVisible(true),
    00044         queuedSearches(0) {}
    00045
    00046     KListView *listView;
    00047     bool caseSensitive;
    00048     bool activeSearch;
    00049     bool keepParentsVisible;
    00050     QString search;
    00051     int queuedSearches;
    00052     QValueList<int> searchColumns;
    00053 };
    00054
    00056 // public methods
    00058
    00059 KListViewSearchLine::KListViewSearchLine(QWidget *parent, KListView *listView, const char *name) :
    00060     KLineEdit(parent, name)
    00061 {
    00062     d = new KListViewSearchLinePrivate;
    00063
    00064     d->listView = listView;
    00065
    00066     connect(this, SIGNAL(textChanged(const QString &)),
    00067             this, SLOT(queueSearch(const QString &)));
    00068
    00069     if(listView) {
    00070         connect(listView, SIGNAL(destroyed()),
    00071                 this, SLOT(listViewDeleted()));
    00072
    00073         connect(listView, SIGNAL(itemAdded(QListViewItem *)),
    00074                 this, SLOT(itemAdded(QListViewItem *)));
    00075     }
    00076     else
    00077         setEnabled(false);
    00078 }
    00079
    00080 KListViewSearchLine::KListViewSearchLine(QWidget *parent, const char *name) :
    00081     KLineEdit(parent, name)
    00082 {
    00083     d = new KListViewSearchLinePrivate;
    00084
    00085     d->listView = 0;
    00086
    00087     connect(this, SIGNAL(textChanged(const QString &)),
    00088             this, SLOT(queueSearch(const QString &)));
    00089
    00090     setEnabled(false);
    00091 }
    00092
    00093 KListViewSearchLine::~KListViewSearchLine()
    00094 {
    00095     delete d;
    00096 }
    00097
    00098 bool KListViewSearchLine::caseSensitive() const
    00099 {
    00100     return d->caseSensitive;
    00101 }
    00102
    00103 QValueList<int> KListViewSearchLine::searchColumns() const
    00104 {
    00105     return d->searchColumns;
    00106 }
    00107
    00108 bool KListViewSearchLine::keepParentsVisible() const
    00109 {
    00110     return d->keepParentsVisible;
    00111 }
    00112
    00113 KListView *KListViewSearchLine::listView() const
    00114 {
    00115     return d->listView;
    00116 }
    00117
    00119 // public slots
    00121
    00122 void KListViewSearchLine::updateSearch(const QString &s)
    00123 {
    00124     if(!d->listView)
    00125         return;
    00126
    00127     d->search = s.isNull() ? text() : s;
    00128
    00129     // If there's a selected item that is visible, make sure that it's visible
    00130     // when the search changes too (assuming that it still matches).
    00131
    00132     QListViewItem *currentItem = 0;
    00133
    00134     switch(d->listView->selectionMode())
    00135     {
    00136     case KListView::NoSelection:
    00137         break;
    00138     case KListView::Single:
    00139         currentItem = d->listView->selectedItem();
    00140         break;
    00141     default:
    00142     {
    00143         int flags = QListViewItemIterator::Selected | QListViewItemIterator::Visible;
    00144         for(QListViewItemIterator it(d->listView, flags);
    00145             it.current() && !currentItem;
    00146             ++it)
    00147         {
    00148             if(d->listView->itemRect(it.current()).isValid())
    00149                 currentItem = it.current();
    00150         }
    00151     }
    00152     }
    00153
    00154     if(d->keepParentsVisible)
    00155         checkItemParentsVisible(d->listView->firstChild());
    00156     else
    00157         checkItemParentsNotVisible();
    00158
    00159     if(currentItem)
    00160         d->listView->ensureItemVisible(currentItem);
    00161 }
    00162
    00163 void KListViewSearchLine::setCaseSensitive(bool cs)
    00164 {
    00165     d->caseSensitive = cs;
    00166 }
    00167
    00168 void KListViewSearchLine::setKeepParentsVisible(bool v)
    00169 {
    00170     d->keepParentsVisible = v;
    00171 }
    00172
    00173 void KListViewSearchLine::setSearchColumns(const QValueList<int> &columns)
    00174 {
    00175     d->searchColumns = columns;
    00176 }
    00177
    00178 void KListViewSearchLine::setListView(KListView *lv)
    00179 {
    00180     if(d->listView) {
    00181         disconnect(d->listView, SIGNAL(destroyed()),
    00182                    this, SLOT(listViewDeleted()));
    00183
    00184         disconnect(d->listView, SIGNAL(itemAdded(QListViewItem *)),
    00185                    this, SLOT(itemAdded(QListViewItem *)));
    00186     }
    00187
    00188     d->listView = lv;
    00189
    00190     if(lv) {
    00191         connect(d->listView, SIGNAL(destroyed()),
    00192                 this, SLOT(listViewDeleted()));
    00193
    00194         connect(d->listView, SIGNAL(itemAdded(QListViewItem *)),
    00195                 this, SLOT(itemAdded(QListViewItem *)));
    00196     }
    00197
    00198     setEnabled(bool(lv));
    00199 }
    00200
    00202 // protected members
    00204
    00205 bool KListViewSearchLine::itemMatches(const QListViewItem *item, const QString &s) const
    00206 {
    00207     if(s.isEmpty())
    00208         return true;
    00209
    00210     // If the search column list is populated, search just the columns
    00211     // specifified.  If it is empty default to searching all of the columns.
    00212
    00213     if(!d->searchColumns.isEmpty()) {
    00214         QValueList<int>::ConstIterator it = d->searchColumns.begin();
    00215         for(; it != d->searchColumns.end(); ++it) {
    00216             if(*it < item->listView()->columns() &&
    00217                item->text(*it).find(s, 0, d->caseSensitive) >= 0)
    00218                 return true;
    00219         }
    00220     }
    00221     else {
    00222         for(int i = 0; i < item->listView()->columns(); i++) {
    00223             if(item->listView()->columnWidth(i) > 0 &&
    00224                item->text(i).find(s, 0, d->caseSensitive) >= 0)
    00225             {
    00226                 return true;
    00227             }
    00228         }
    00229     }
    00230
    00231     return false;
    00232 }
    00233
    00234 QPopupMenu *KListViewSearchLine::createPopupMenu()
    00235 {
    00236     QPopupMenu *popup = KLineEdit::createPopupMenu();
    00237
    00238     if (d->listView->columns()>1) {
    00239         QPopupMenu *subMenu = new QPopupMenu(popup);
    00240         connect(subMenu, SIGNAL(activated(int)), this, SLOT(searchColumnsMenuActivated(int)));
    00241
    00242         popup->insertSeparator();
    00243         popup->insertItem(i18n("Search Columns"), subMenu);
    00244
    00245         subMenu->insertItem(i18n("All Visible Columns"), KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID);
    00246         subMenu->insertSeparator();
    00247
    00248         bool allColumnsAreSearchColumns = true;
    00249     // TODO Make the entry order match the actual column order
    00250     QHeader* const header = d->listView->header();
    00251     int visibleColumns = 0;
    00252     for(int i = 0; i < d->listView->columns(); i++) {
    00253         if(d->listView->columnWidth(i)>0) {
    00254             QString columnText = d->listView->columnText(i);
    00255             if(columnText.isEmpty()) {
    00256             int visiblePosition=1;
    00257             for(int j = 0; j < header->mapToIndex(i); j++)
    00258                 if(d->listView->columnWidth(header->mapToSection(j))>0)
    00259                     visiblePosition++;
    00260             columnText = i18n("Column number %1","Column No. %1").arg(visiblePosition);
    00261             }
    00262                 subMenu->insertItem(columnText, visibleColumns);
    00263             if(d->searchColumns.isEmpty() || d->searchColumns.find(i) != d->searchColumns.end())
    00264             subMenu->setItemChecked(visibleColumns, true);
    00265                 else
    00266                     allColumnsAreSearchColumns = false;
    00267             visibleColumns++;
    00268         }
    00269         }
    00270         subMenu->setItemChecked(KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID, allColumnsAreSearchColumns);
    00271
    00272         // searchColumnsMenuActivated() relies on one possible "all" representation
    00273         if(allColumnsAreSearchColumns && !d->searchColumns.isEmpty())
    00274             d->searchColumns.clear();
    00275     }
    00276
    00277     return popup;
    00278 }
    00279
    00281 // protected slots
    00283
    00284 void KListViewSearchLine::queueSearch(const QString &search)
    00285 {
    00286     d->queuedSearches++;
    00287     d->search = search;
    00288     QTimer::singleShot(200, this, SLOT(activateSearch()));
    00289 }
    00290
    00291 void KListViewSearchLine::activateSearch()
    00292 {
    00293     --(d->queuedSearches);
    00294
    00295     if(d->queuedSearches == 0)
    00296         updateSearch(d->search);
    00297 }
    00298
    00300 // private slots
    00302
    00303 void KListViewSearchLine::itemAdded(QListViewItem *item) const
    00304 {
    00305     item->setVisible(itemMatches(item, text()));
    00306 }
    00307
    00308 void KListViewSearchLine::listViewDeleted()
    00309 {
    00310     d->listView = 0;
    00311     setEnabled(false);
    00312 }
    00313
    00314 void KListViewSearchLine::searchColumnsMenuActivated(int id)
    00315 {
    00316     if(id == KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID) {
    00317         if(d->searchColumns.isEmpty())
    00318             d->searchColumns.append(0);
    00319         else
    00320             d->searchColumns.clear();
    00321     }
    00322     else {
    00323         if(d->searchColumns.find(id) != d->searchColumns.end())
    00324             d->searchColumns.remove(id);
    00325         else {
    00326             if(d->searchColumns.isEmpty()) {
    00327                 for(int i = 0; i < d->listView->columns(); i++) {
    00328                     if(i != id)
    00329                         d->searchColumns.append(i);
    00330                 }
    00331             }
    00332             else
    00333                 d->searchColumns.append(id);
    00334         }
    00335     }
    00336     updateSearch();
    00337 }
    00338
    00340 // private methods
    00342
    00343 void KListViewSearchLine::checkItemParentsNotVisible()
    00344 {
    00345     QListViewItemIterator it(d->listView);
    00346     for(; it.current(); ++it)
    00347     {
    00348         QListViewItem *item = it.current();
    00349         if(itemMatches(item, d->search))
    00350             item->setVisible(true);
    00351         else
    00352             item->setVisible(false);
    00353     }
    00354 }
    00355
    00356 bool KListViewSearchLine::checkItemParentsVisible(QListViewItem *item)
    00357 {
    00358     bool visible = false;
    00359     for(; item; item = item->nextSibling()) {
    00360         if((item->firstChild() && checkItemParentsVisible(item->firstChild())) ||
    00361            itemMatches(item, d->search))
    00362         {
    00363             item->setVisible( true );
    00364             visible = true;
    00365         }
    00366         else
    00367             item->setVisible(false);
    00368     }
    00369     return visible;
    00370 }
    00371
    00373 // KListViewSearchLineWidget
    00375
    00376 class KListViewSearchLineWidget::KListViewSearchLineWidgetPrivate
    00377 {
    00378 public:
    00379     KListViewSearchLineWidgetPrivate() : listView(0), searchLine(0), clearButton(0) {}
    00380     KListView *listView;
    00381     KListViewSearchLine *searchLine;
    00382     QToolButton *clearButton;
    00383 };
    00384
    00385 KListViewSearchLineWidget::KListViewSearchLineWidget(KListView *listView,
    00386                                                      QWidget *parent,
    00387                                                      const char *name) :
    00388     QHBox(parent, name)
    00389 {
    00390     d = new KListViewSearchLineWidgetPrivate;
    00391     d->listView = listView;
    00392
    00393     setSpacing(5);
    00394
    00395     QTimer::singleShot(0, this, SLOT(createWidgets()));
    00396 }
    00397
    00398 KListViewSearchLineWidget::~KListViewSearchLineWidget()
    00399 {
    00400     delete d;
    00401 }
    00402
    00403 KListViewSearchLine *KListViewSearchLineWidget::createSearchLine(KListView *listView)
    00404 {
    00405     if(!d->searchLine)
    00406         d->searchLine = new KListViewSearchLine(this, listView);
    00407     return d->searchLine;
    00408 }
    00409
    00410 void KListViewSearchLineWidget::createWidgets()
    00411 {
    00412     positionInToolBar();
    00413
    00414     if(!d->clearButton) {
    00415         d->clearButton = new QToolButton(this);
    00416         QIconSet icon = SmallIconSet(QApplication::reverseLayout() ? "clear_left" : "locationbar_erase");
    00417         d->clearButton->setIconSet(icon);
    00418     }
    00419
    00420     d->clearButton->show();
    00421
    00422     QLabel *label = new QLabel(i18n("S&earch:"), this, "kde toolbar widget");
    00423
    00424     d->searchLine = createSearchLine(d->listView);
    00425     d->searchLine->show();
    00426
    00427     label->setBuddy(d->searchLine);
    00428     label->show();
    00429
    00430     connect(d->clearButton, SIGNAL(clicked()), d->searchLine, SLOT(clear()));
    00431 }
    00432
    00433 KListViewSearchLine *KListViewSearchLineWidget::searchLine() const
    00434 {
    00435     return d->searchLine;
    00436 }
    00437
    00438 void KListViewSearchLineWidget::positionInToolBar()
    00439 {
    00440     KToolBar *toolBar = dynamic_cast<KToolBar *>(parent());
    00441
    00442     if(toolBar) {
    00443
    00444         // Here we have The Big Ugly.  Figure out how many widgets are in the
    00445         // and do a hack-ish iteration over them to find this widget so that we
    00446         // can insert the clear button before it.
    00447
    00448         int widgetCount = toolBar->count();
    00449
    00450         for(int index = 0; index < widgetCount; index++) {
    00451             int id = toolBar->idAt(index);
    00452             if(toolBar->getWidget(id) == this) {
    00453                 toolBar->setItemAutoSized(id);
    00454                 if(!d->clearButton) {
    00455                     QString icon = QApplication::reverseLayout() ? "clear_left" : "locationbar_erase";
    00456                     d->clearButton = new KToolBarButton(icon, 2005, toolBar);
    00457                 }
    00458                 toolBar->insertWidget(2005, d->clearButton->width(), d->clearButton, index);
    00459                 break;
    00460             }
    00461         }
    00462     }
    00463
    00464     if(d->searchLine)
    00465         d->searchLine->show();
    00466 }
    00467
    00468 #include "klistviewsearchline.moc"

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:18 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003