• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDE3Support

k3listviewsearchline.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
00003    Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "k3listviewsearchline.h"
00021 
00022 #include <k3listview.h>
00023 #include <kiconloader.h>
00024 #include <ktoolbar.h>
00025 #include <kdebug.h>
00026 #include <klocale.h>
00027 
00028 #include <QApplication>
00029 #include <QTimer>
00030 #include <QMenu>
00031 #include <QLabel>
00032 #include <QContextMenuEvent>
00033 #include <QList>
00034 #include <Q3Header>
00035 #include <QToolButton>
00036 
00037 class K3ListViewSearchLine::K3ListViewSearchLinePrivate
00038 {
00039 public:
00040     K3ListViewSearchLinePrivate() :
00041         caseSensitive(Qt::CaseInsensitive),
00042         activeSearch(false),
00043         keepParentsVisible(true),
00044         canChooseColumns(true),
00045         queuedSearches(0),
00046         allVisibleColumnsAction(0)
00047     {}
00048 
00049     QList<K3ListView *> listViews;
00050     Qt::CaseSensitivity caseSensitive;
00051     bool activeSearch;
00052     bool keepParentsVisible;
00053     bool canChooseColumns;
00054     QString search;
00055     int queuedSearches;
00056     QList<int> searchColumns;
00057     QAction *allVisibleColumnsAction;
00058 };
00059 
00061 // public methods
00063 
00064 K3ListViewSearchLine::K3ListViewSearchLine(QWidget *parent, K3ListView *listView) :
00065     KLineEdit(parent)
00066 {
00067     d = new K3ListViewSearchLinePrivate;
00068     setClearButtonShown( true );
00069 
00070     connect(this, SIGNAL(textChanged(const QString &)),
00071             this, SLOT(queueSearch(const QString &)));
00072 
00073     setListView( listView );
00074     if( !listView)
00075         setEnabled(false);
00076 }
00077 
00078 K3ListViewSearchLine::K3ListViewSearchLine(QWidget *parent,
00079                                        const QList<K3ListView *> &listViews) :
00080      KLineEdit(parent)
00081 {
00082     d = new K3ListViewSearchLinePrivate;
00083     setClearButtonShown( true );
00084 
00085     connect(this, SIGNAL(textChanged(const QString &)),
00086             this, SLOT(queueSearch(const QString &)));
00087 
00088     setListViews( listViews );
00089 }
00090 
00091 
00092 K3ListViewSearchLine::~K3ListViewSearchLine()
00093 {
00094     delete d;
00095 }
00096 
00097 bool K3ListViewSearchLine::caseSensitive() const
00098 {
00099     return (d->caseSensitive ==Qt::CaseSensitive);
00100 }
00101 
00102 QList<int> K3ListViewSearchLine::searchColumns() const
00103 {
00104     if (d->canChooseColumns)
00105         return d->searchColumns;
00106     else
00107         return QList<int>();
00108 }
00109 
00110 bool K3ListViewSearchLine::keepParentsVisible() const
00111 {
00112     return d->keepParentsVisible;
00113 }
00114 
00115 K3ListView *K3ListViewSearchLine::listView() const
00116 {
00117     if ( d->listViews.count() == 1 )
00118         return d->listViews.first();
00119     else
00120         return 0;
00121 }
00122 
00123 const QList<K3ListView *> &K3ListViewSearchLine::listViews() const
00124 {
00125     return d->listViews;
00126 }
00127 
00128 
00130 // public slots
00132 
00133 void K3ListViewSearchLine::addListView(K3ListView *lv)
00134 {
00135     if (lv) {
00136         connectListView(lv);
00137 
00138         d->listViews.append(lv);
00139         setEnabled(!d->listViews.isEmpty());
00140 
00141         checkColumns();
00142     }
00143 }
00144 
00145 void K3ListViewSearchLine::removeListView(K3ListView *lv)
00146 {
00147     if (lv) {
00148         int idx = d->listViews.indexOf(lv);
00149 
00150         if ( idx != -1 ) {
00151             d->listViews.removeAt( idx );
00152             checkColumns();
00153 
00154             disconnectListView(lv);
00155 
00156             setEnabled(!d->listViews.isEmpty());
00157         }
00158     }
00159 }
00160 
00161 void K3ListViewSearchLine::updateSearch(const QString &s)
00162 {
00163     d->search = s.isNull() ? text() : s;
00164 
00165     for (QList<K3ListView *>::Iterator it = d->listViews.begin();
00166          it != d->listViews.end(); ++it)
00167         updateSearch( *it );
00168 }
00169 
00170 void K3ListViewSearchLine::updateSearch(K3ListView *listView)
00171 {
00172     if(!listView)
00173         return;
00174 
00175 
00176     // If there's a selected item that is visible, make sure that it's visible
00177     // when the search changes too (assuming that it still matches).
00178 
00179     Q3ListViewItem *currentItem = 0;
00180 
00181     switch(listView->selectionMode())
00182     {
00183     case K3ListView::NoSelection:
00184         break;
00185     case K3ListView::Single:
00186         currentItem = listView->selectedItem();
00187         break;
00188     default:
00189     {
00190         int flags = Q3ListViewItemIterator::Selected | Q3ListViewItemIterator::Visible;
00191         for(Q3ListViewItemIterator it(listView, flags);
00192             it.current() && !currentItem;
00193             ++it)
00194         {
00195             if(listView->itemRect(it.current()).isValid())
00196                 currentItem = it.current();
00197         }
00198     }
00199     }
00200 
00201     if(d->keepParentsVisible)
00202         checkItemParentsVisible(listView->firstChild());
00203     else
00204         checkItemParentsNotVisible(listView);
00205 
00206     if(currentItem)
00207         listView->ensureItemVisible(currentItem);
00208 }
00209 
00210 void K3ListViewSearchLine::setCaseSensitive(bool cs)
00211 {
00212     d->caseSensitive = cs?Qt::CaseSensitive:Qt::CaseInsensitive;
00213 }
00214 
00215 void K3ListViewSearchLine::setKeepParentsVisible(bool v)
00216 {
00217     d->keepParentsVisible = v;
00218 }
00219 
00220 void K3ListViewSearchLine::setSearchColumns(const QList<int> &columns)
00221 {
00222     if (d->canChooseColumns)
00223         d->searchColumns = columns;
00224 }
00225 
00226 void K3ListViewSearchLine::setListView(K3ListView *lv)
00227 {
00228     setListViews(QList<K3ListView *>());
00229     addListView(lv);
00230 }
00231 
00232 void K3ListViewSearchLine::setListViews(const QList<K3ListView *> &lv)
00233 {
00234     for (QList<K3ListView *>::Iterator it = d->listViews.begin();
00235          it != d->listViews.end(); ++it)
00236              disconnectListView(*it);
00237 
00238     d->listViews = lv;
00239 
00240     for (QList<K3ListView *>::Iterator it = d->listViews.begin();
00241          it != d->listViews.end(); ++it)
00242         connectListView(*it);
00243 
00244     checkColumns();
00245     setEnabled(!d->listViews.isEmpty());
00246 }
00247 
00249 // protected members
00251 
00252 bool K3ListViewSearchLine::itemMatches(const Q3ListViewItem *item, const QString &s) const
00253 {
00254     if(s.isEmpty())
00255         return true;
00256 
00257     // If the search column list is populated, search just the columns
00258     // specifified.  If it is empty default to searching all of the columns.
00259 
00260     if(!d->searchColumns.isEmpty()) {
00261         QList<int>::ConstIterator it = d->searchColumns.constBegin();
00262         for(; it != d->searchColumns.constEnd(); ++it) {
00263             if(*it < item->listView()->columns() &&
00264                item->text(*it).indexOf(s, 0, d->caseSensitive) >= 0)
00265                 return true;
00266         }
00267     }
00268     else {
00269         for(int i = 0; i < item->listView()->columns(); i++) {
00270             if(item->listView()->columnWidth(i) > 0 &&
00271                item->text(i).indexOf(s, 0, d->caseSensitive) >= 0)
00272             {
00273                 return true;
00274             }
00275         }
00276     }
00277 
00278     return false;
00279 }
00280 
00281 void K3ListViewSearchLine::contextMenuEvent( QContextMenuEvent*e )
00282 {
00283     QMenu *popup = KLineEdit::createStandardContextMenu();
00284 
00285     if (d->canChooseColumns) {
00286         popup->addSeparator();
00287         QMenu *subMenu = popup->addMenu(i18n("Search Columns"));
00288         connect(subMenu, SIGNAL(triggered(QAction*)), this, SLOT(searchColumnsMenuActivated(QAction*)));
00289 
00290         d->allVisibleColumnsAction = subMenu->addAction(i18n("All Visible Columns"));
00291         d->allVisibleColumnsAction->setCheckable( true );
00292         subMenu->addSeparator();
00293 
00294         bool allColumnsAreSearchColumns = true;
00295         // TODO Make the entry order match the actual column order
00296         Q3Header* const header = d->listViews.first()->header();
00297         int visibleColumns = 0;
00298         for(int i = 0; i < d->listViews.first()->columns(); i++) {
00299           if(d->listViews.first()->columnWidth(i)>0) {
00300             QString columnText = d->listViews.first()->columnText(i);
00301             if(columnText.isEmpty()) {
00302               int visiblePosition=1;
00303               for(int j = 0; j < header->mapToIndex(i); j++)
00304                 if(d->listViews.first()->columnWidth(header->mapToSection(j))>0)
00305                   visiblePosition++;
00306 
00307               columnText = i18nc("Column number %1","Column No. %1", visiblePosition);
00308             }
00309             QAction *action = subMenu->addAction(columnText);
00310             action->setData( visibleColumns );
00311             action->setCheckable( true );
00312 
00313             if(d->searchColumns.isEmpty() || d->searchColumns.indexOf(i) != -1)
00314               action->setChecked(true);
00315             else
00316               allColumnsAreSearchColumns = false;
00317 
00318             visibleColumns++;
00319           }
00320         }
00321         d->allVisibleColumnsAction->setChecked( allColumnsAreSearchColumns );
00322 
00323         // searchColumnsMenuActivated() relies on one possible "all" representation
00324         if(allColumnsAreSearchColumns && !d->searchColumns.isEmpty())
00325             d->searchColumns.clear();
00326     }
00327 
00328     popup->exec( e->globalPos() );
00329 
00330     delete popup;
00331 }
00332 
00333 void K3ListViewSearchLine::connectListView(K3ListView *lv)
00334 {
00335     connect(lv, SIGNAL(destroyed( QObject * )),
00336             this, SLOT(listViewDeleted( QObject *)));
00337     connect(lv, SIGNAL(itemAdded(Q3ListViewItem *)),
00338             this, SLOT(itemAdded(Q3ListViewItem *)));
00339 }
00340 
00341 void K3ListViewSearchLine::disconnectListView(K3ListView *lv)
00342 {
00343     disconnect(lv, SIGNAL(destroyed( QObject * )),
00344               this, SLOT(listViewDeleted( QObject *)));
00345     disconnect(lv, SIGNAL(itemAdded(Q3ListViewItem *)),
00346               this, SLOT(itemAdded(Q3ListViewItem *)));
00347 }
00348 
00349 bool K3ListViewSearchLine::canChooseColumnsCheck()
00350 {
00351     // This is true if either of the following is true:
00352 
00353     // there are no listviews connected
00354     if (d->listViews.isEmpty())
00355         return false;
00356 
00357     const K3ListView *first = d->listViews.first();
00358 
00359     const unsigned int numcols = first->columns();
00360     // the listviews have only one column,
00361     if (numcols < 2)
00362         return false;
00363 
00364     QStringList headers;
00365     for (unsigned int i = 0; i < numcols; ++i)
00366         headers.append(first->columnText(i));
00367 
00368     QList<K3ListView *>::ConstIterator it = d->listViews.constBegin();
00369     for (++it /* skip the first one */; it !=d->listViews.constEnd(); ++it) {
00370         // the listviews have different numbers of columns,
00371         if ((unsigned int) (*it)->columns() != numcols)
00372             return false;
00373 
00374         // the listviews differ in column labels.
00375         QStringList::ConstIterator jt;
00376         unsigned int i;
00377         for (i = 0, jt = headers.constBegin(); i < numcols; ++i, ++jt) {
00378                 Q_ASSERT(jt != headers.constEnd());
00379                 if ((*it)->columnText(i) != *jt)
00380                     return false;
00381             }
00382     }
00383 
00384     return true;
00385 }
00386 
00388 // protected slots
00390 
00391 void K3ListViewSearchLine::queueSearch(const QString &search)
00392 {
00393     d->queuedSearches++;
00394     d->search = search;
00395     QTimer::singleShot(200, this, SLOT(activateSearch()));
00396 }
00397 
00398 void K3ListViewSearchLine::activateSearch()
00399 {
00400     --(d->queuedSearches);
00401 
00402     if(d->queuedSearches == 0)
00403         updateSearch(d->search);
00404 }
00405 
00407 // private slots
00409 
00410 void K3ListViewSearchLine::itemAdded(Q3ListViewItem *item) const
00411 {
00412     item->setVisible(itemMatches(item, text()));
00413 }
00414 
00415 void K3ListViewSearchLine::listViewDeleted(QObject *o)
00416 {
00417     d->listViews.removeAll(static_cast<K3ListView *>(o));
00418     setEnabled(d->listViews.isEmpty());
00419 }
00420 
00421 void K3ListViewSearchLine::searchColumnsMenuActivated(QAction *action)
00422 {
00423     int id = action->data().toInt();
00424 
00425     if(action == d->allVisibleColumnsAction) {
00426         if(d->searchColumns.isEmpty())
00427             d->searchColumns.append(0);
00428         else
00429             d->searchColumns.clear();
00430     }
00431     else {
00432         if(d->searchColumns.indexOf(id) != -1)
00433             d->searchColumns.removeAll(id);
00434         else {
00435             if(d->searchColumns.isEmpty()) {
00436                 for(int i = 0; i < d->listViews.first()->columns(); i++) {
00437                     if(i != id)
00438                         d->searchColumns.append(i);
00439                 }
00440             }
00441             else
00442                 d->searchColumns.append(id);
00443         }
00444     }
00445     updateSearch();
00446 }
00447 
00449 // private methods
00451 
00452 void K3ListViewSearchLine::checkColumns()
00453 {
00454     d->canChooseColumns = canChooseColumnsCheck();
00455 }
00456 
00457 void K3ListViewSearchLine::checkItemParentsNotVisible(K3ListView *listView)
00458 {
00459     Q3ListViewItemIterator it(listView);
00460     for(; it.current(); ++it)
00461     {
00462         Q3ListViewItem *item = it.current();
00463         if(itemMatches(item, d->search))
00464             item->setVisible(true);
00465         else
00466             item->setVisible(false);
00467     }
00468 }
00469 
00470 #include <kvbox.h>
00471 
00481 bool K3ListViewSearchLine::checkItemParentsVisible(Q3ListViewItem *item, Q3ListViewItem *highestHiddenParent)
00482 {
00483     bool visible = false;
00484     Q3ListViewItem * first = item;
00485     for(; item; item = item->nextSibling())
00486     {
00487         //What we pass to our children as highestHiddenParent:
00488         Q3ListViewItem * hhp = highestHiddenParent ? highestHiddenParent : item->isVisible() ? 0L : item;
00489         bool childMatch = false;
00490         if(item->firstChild() && checkItemParentsVisible(item->firstChild(), hhp))
00491             childMatch = true;
00492         // Should this item be shown? It should if any children should be, or if it matches.
00493         if(childMatch || itemMatches(item, d->search))
00494         {
00495             visible = true;
00496             if (highestHiddenParent)
00497             {
00498                 highestHiddenParent->setVisible(true);
00499                 // Calling setVisible on our ancestor will unhide all its descendents. Hide the ones
00500                 // before us that should not be shown.
00501                 for(Q3ListViewItem *hide = first; hide != item; hide = hide->nextSibling())
00502                     hide->setVisible(false);
00503                 highestHiddenParent = 0;
00504                 // If we matched, than none of our children matched, yet the setVisible() call on our
00505                 // ancestor unhid them, undo the damage:
00506                 if(!childMatch)
00507                     for(Q3ListViewItem *hide = item->firstChild(); hide; hide = hide->nextSibling())
00508                         hide->setVisible(false);
00509             }
00510             else
00511                 item->setVisible(true);
00512         }
00513         else
00514             item->setVisible(false);
00515     }
00516     return visible;
00517 }
00518 
00520 // K3ListViewSearchLineWidget
00522 
00523 class K3ListViewSearchLineWidget::K3ListViewSearchLineWidgetPrivate
00524 {
00525 public:
00526     K3ListViewSearchLineWidgetPrivate() : listView(0), searchLine(0) {}
00527     K3ListView *listView;
00528     K3ListViewSearchLine *searchLine;
00529 };
00530 
00531 K3ListViewSearchLineWidget::K3ListViewSearchLineWidget(K3ListView *listView,
00532                                                      QWidget *parent) :
00533     KHBox(parent)
00534 {
00535     d = new K3ListViewSearchLineWidgetPrivate;
00536     d->listView = listView;
00537 
00538     setSpacing(5);
00539 
00540     QTimer::singleShot(0, this, SLOT(createWidgets()));
00541 }
00542 
00543 K3ListViewSearchLineWidget::~K3ListViewSearchLineWidget()
00544 {
00545     delete d;
00546 }
00547 
00548 K3ListViewSearchLine *K3ListViewSearchLineWidget::createSearchLine(K3ListView *listView)
00549 {
00550     if(!d->searchLine)
00551         d->searchLine = new K3ListViewSearchLine(this, listView);
00552     return d->searchLine;
00553 }
00554 
00555 void K3ListViewSearchLineWidget::createWidgets()
00556 {
00557     QLabel *label = new QLabel(i18n("S&earch:"), this);
00558     label->setObjectName(QLatin1String("kde toolbar widget"));
00559 
00560     d->searchLine = createSearchLine(d->listView);
00561     d->searchLine->show();
00562 
00563     label->setBuddy(d->searchLine);
00564     label->show();
00565 }
00566 
00567 K3ListViewSearchLine *K3ListViewSearchLineWidget::searchLine() const
00568 {
00569     return d->searchLine;
00570 }
00571 
00572 #include "k3listviewsearchline.moc"

KDE3Support

Skip menu "KDE3Support"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal