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 <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
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
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
00130
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
00204
00205 bool KListViewSearchLine::itemMatches(
const QListViewItem *item,
const QString &s)
const
00206
{
00207
if(s.isEmpty())
00208
return true;
00209
00210
00211
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
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
00273
if(allColumnsAreSearchColumns && !d->searchColumns.isEmpty())
00274 d->searchColumns.clear();
00275 }
00276
00277
return popup;
00278 }
00279
00281
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
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
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
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
00445
00446
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"