delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / runtime / khelpcenter / searchwidget.cpp
blob0f49b23495579fd2da59fc6ec8f87d56e7af0ef5
1 /*
2 * searchwidget.cpp - part of the KDE Help Center
4 * Copyright (C) 1999 Matthias Elter (me@kde.org)
5 * (C) 2000 Matthias Hoelzer-Kluepfel (hoelzer@kde.org)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "searchwidget.h"
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <errno.h>
28 #include <QLabel>
29 #include <QPushButton>
30 #include <QComboBox>
31 #include <QLayout>
32 #include <QVBoxLayout>
33 #include <QHBoxLayout>
34 #include <QBoxLayout>
36 #include <KConfig>
37 #include <KApplication>
38 #include <KLocale>
39 #include <KDebug>
40 #include <KIconLoader>
42 #include "scopeitem.h"
43 #include "docentrytraverser.h"
44 #include "kcmhelpcenter.h"
45 #include "prefs.h"
46 #include "searchengine.h"
48 #include <QtDBus/QDBusConnection>
50 namespace KHC {
52 SearchWidget::SearchWidget( SearchEngine *engine, QWidget *parent )
53 : QWidget( parent ), mEngine( engine ),
54 mScopeCount( 0 )
56 QDBusConnection::sessionBus().registerObject("/SearchWidget", this, QDBusConnection::ExportScriptableSlots);
58 QBoxLayout *topLayout = new QVBoxLayout( this );
59 topLayout->setMargin( 2 );
60 topLayout->setSpacing( 2 );
62 QBoxLayout *hLayout = new QHBoxLayout();
63 topLayout->addLayout( hLayout );
65 mMethodCombo = new QComboBox( this );
66 mMethodCombo->addItem( i18n("and") );
67 mMethodCombo->addItem( i18n("or") );
69 QLabel *l = new QLabel( i18n("&Method:"), this );
70 l->setBuddy( mMethodCombo );
72 hLayout->addWidget( l );
73 hLayout->addWidget( mMethodCombo );
75 hLayout = new QHBoxLayout();
76 topLayout->addLayout( hLayout );
78 mPagesCombo = new QComboBox( this );
79 mPagesCombo->addItem( QLatin1String("5") );
80 mPagesCombo->addItem( QLatin1String("10") );
81 mPagesCombo->addItem( QLatin1String("25") );
82 mPagesCombo->addItem( QLatin1String("50") );
83 mPagesCombo->addItem( QLatin1String("1000") );
85 l = new QLabel( i18n("Max. &results:"), this );
86 l->setBuddy( mPagesCombo );
88 hLayout->addWidget( l );
89 hLayout->addWidget( mPagesCombo );
91 hLayout = new QHBoxLayout();
92 topLayout->addLayout( hLayout );
94 mScopeCombo = new QComboBox( this );
95 for (int i=0; i < ScopeNum; ++i ) {
96 mScopeCombo->addItem( scopeSelectionLabel( i ) );
98 connect( mScopeCombo, SIGNAL( activated( int ) ),
99 SLOT( scopeSelectionChanged( int ) ) );
101 l = new QLabel( i18n("&Scope selection:"), this );
102 l->setBuddy( mScopeCombo );
104 hLayout->addWidget( l );
105 hLayout->addWidget( mScopeCombo );
107 mScopeListView = new Q3ListView( this );
108 mScopeListView->setRootIsDecorated( true );
109 mScopeListView->addColumn( i18n("Scope") );
110 topLayout->addWidget( mScopeListView, 1 );
112 QPushButton *indexButton = new QPushButton( i18n("Build Search &Index..."),
113 this );
114 connect( indexButton, SIGNAL( clicked() ), SIGNAL( showIndexDialog() ) );
115 topLayout->addWidget( indexButton );
117 // FIXME: Use SearchHandler on double-clicked document
118 #if 0
119 connect( mScopeListView, SIGNAL( doubleClicked( Q3ListViewItem * ) ),
120 SLOT( scopeDoubleClicked( Q3ListViewItem * ) ) );
121 #endif
122 connect( mScopeListView, SIGNAL( clicked( Q3ListViewItem * ) ),
123 SLOT( scopeClicked( Q3ListViewItem * ) ) );
127 SearchWidget::~SearchWidget()
129 writeConfig( KGlobal::config().data() );
133 void SearchWidget::readConfig( KConfig *cfg )
135 KConfigGroup searchGroup(cfg, "Search");
136 int scopeSelection = searchGroup.readEntry( "ScopeSelection", (int)ScopeDefault );
137 mScopeCombo->setCurrentIndex( scopeSelection );
138 if ( scopeSelection != ScopeDefault ) scopeSelectionChanged( scopeSelection );
140 mMethodCombo->setCurrentIndex( Prefs::method() );
141 mPagesCombo->setCurrentIndex( Prefs::maxCount() );
143 if ( scopeSelection == ScopeCustom ) {
144 KConfigGroup searchScopeGroup(cfg, "Custom Search Scope" );
145 Q3ListViewItemIterator it( mScopeListView );
146 while( it.current() ) {
147 if ( it.current()->rtti() == ScopeItem::rttiId() ) {
148 ScopeItem *item = static_cast<ScopeItem *>( it.current() );
149 item->setOn( searchScopeGroup.readEntry(
150 item->entry()->identifier(),
151 item->isOn() ) );
153 ++it;
157 checkScope();
160 void SearchWidget::writeConfig( KConfig *cfg )
162 KConfigGroup cg (cfg, "Search");
164 cg.writeEntry( "ScopeSelection", mScopeCombo->currentIndex() );
165 Prefs::setMethod( mMethodCombo->currentIndex() );
166 Prefs::setMaxCount( mPagesCombo->currentIndex() );
168 if ( mScopeCombo->currentIndex() == ScopeCustom ) {
169 KConfigGroup cg2 (cfg, "Custom Search Scope");
170 Q3ListViewItemIterator it( mScopeListView );
171 while( it.current() ) {
172 if ( it.current()->rtti() == ScopeItem::rttiId() ) {
173 ScopeItem *item = static_cast<ScopeItem *>( it.current() );
174 cg2.writeEntry( item->entry()->identifier(), item->isOn() );
176 ++it;
181 void SearchWidget::slotSwitchBoxes()
183 Q3ListViewItemIterator it( mScopeListView );
184 while( it.current() ) {
185 if ( it.current()->rtti() == ScopeItem::rttiId() ) {
186 ScopeItem *item = static_cast<ScopeItem *>( it.current() );
187 item->setOn( !item->isOn() );
189 ++it;
192 checkScope();
195 void SearchWidget::scopeSelectionChanged( int id )
197 Q3ListViewItemIterator it( mScopeListView );
198 while( it.current() ) {
199 if ( it.current()->rtti() == ScopeItem::rttiId() ) {
200 ScopeItem *item = static_cast<ScopeItem *>( it.current() );
201 bool state = item->isOn();
202 switch( id ) {
203 case ScopeDefault:
204 state = item->entry()->searchEnabledDefault();
205 break;
206 case ScopeAll:
207 state = true;
208 break;
209 case ScopeNone:
210 state = false;
211 break;
212 default:
213 break;
215 if ( state != item->isOn() ) {
216 item->setOn( state );
219 ++it;
222 checkScope();
225 QString SearchWidget::method()
227 QString m = "and";
228 if ( mMethodCombo->currentIndex() == 1)
229 m = "or";
231 return m;
234 int SearchWidget::pages()
236 int p = mPagesCombo->currentText().toInt();
238 return p;
241 QString SearchWidget::scope()
243 QString scope;
245 Q3ListViewItemIterator it( mScopeListView );
246 while( it.current() ) {
247 if ( it.current()->rtti() == ScopeItem::rttiId() ) {
248 ScopeItem *item = static_cast<ScopeItem *>( it.current() );
249 if ( item->isOn() ) {
250 if ( !scope.isEmpty() ) scope += '&';
251 scope += QLatin1String("scope=") + item->entry()->identifier();
254 ++it;
257 return scope;
260 class ScopeTraverser : public DocEntryTraverser
262 public:
263 ScopeTraverser( SearchWidget *widget, int level ) :
264 mWidget( widget ), mLevel( level ), mParentItem( 0 ) {}
266 ~ScopeTraverser()
268 if( mParentItem && !mParentItem->childCount() ) delete mParentItem;
271 void process( DocEntry *entry )
273 if ( mWidget->engine()->canSearch( entry ) &&
274 ( !mWidget->engine()->needsIndex( entry ) ||
275 entry->indexExists( Prefs::indexDirectory() ) ) ) {
276 ScopeItem *item = 0;
277 if ( mParentItem ) {
278 item = new ScopeItem( mParentItem, entry );
279 } else {
280 item = new ScopeItem( mWidget->listView(), entry );
282 item->setOn( entry->searchEnabled() );
286 DocEntryTraverser *createChild( DocEntry *entry )
288 if ( mLevel >= mNestingLevel ) {
289 ++mLevel;
290 return this;
291 } else {
292 ScopeTraverser *t = new ScopeTraverser( mWidget, mLevel + 1 );
293 Q3ListViewItem *item = 0;
294 if ( mParentItem ) {
295 item = new Q3ListViewItem( mParentItem, entry->name() );
296 } else {
297 item = new Q3ListViewItem( mWidget->listView(), entry->name() );
299 item->setOpen( true );
300 t->mParentItem = item;
301 return t;
305 DocEntryTraverser *parentTraverser()
307 if ( mLevel > mNestingLevel ) return this;
308 else return mParent;
311 void deleteTraverser()
313 if ( mLevel > mNestingLevel ) --mLevel;
314 else delete this;
317 private:
318 SearchWidget *mWidget;
319 int mLevel;
320 Q3ListViewItem *mParentItem;
322 static int mNestingLevel;
325 int ScopeTraverser::mNestingLevel = 2;
327 void SearchWidget::searchIndexUpdated()
329 KGlobal::config()->reparseConfiguration();
330 updateScopeList();
331 update();
334 void SearchWidget::updateScopeList()
336 mScopeListView->clear();
338 ScopeTraverser t( this, 0 );
339 DocMetaInfo::self()->traverseEntries( &t );
341 checkScope();
344 void SearchWidget::scopeDoubleClicked( Q3ListViewItem *item )
346 if ( !item || item->rtti() != ScopeItem::rttiId() ) return;
347 ScopeItem *scopeItem = static_cast<ScopeItem *>( item );
349 QString searchUrl = scopeItem->entry()->search();
351 kDebug() << "DoubleClick: " << searchUrl;
353 emit searchResult( searchUrl );
356 void SearchWidget::scopeClicked( Q3ListViewItem * )
358 checkScope();
360 mScopeCombo->setCurrentIndex( ScopeCustom );
363 QString SearchWidget::scopeSelectionLabel( int id ) const
365 switch( id ) {
366 case ScopeCustom:
367 return i18nc("Label for searching documentation using custom (user defined) scope", "Custom");
368 case ScopeDefault:
369 return i18nc("Label for searching documentation using default search scope", "Default");
370 case ScopeAll:
371 return i18nc("Label for searching documentation in all subsections", "All");
372 case ScopeNone:
373 return i18nc("Label for scope that deselects all search subsections", "None");
374 default:
375 return i18nc("Label for Unknown search scope, that should never appear", "unknown");
379 void SearchWidget::checkScope()
381 mScopeCount = 0;
383 Q3ListViewItemIterator it( mScopeListView );
384 while( it.current() ) {
385 if ( it.current()->rtti() == ScopeItem::rttiId() ) {
386 ScopeItem *item = static_cast<ScopeItem *>( it.current() );
387 if ( item->isOn() ) {
388 ++mScopeCount;
390 item->entry()->enableSearch( item->isOn() );
392 ++it;
395 emit scopeCountChanged( mScopeCount );
398 int SearchWidget::scopeCount() const
400 return mScopeCount;
405 #include "searchwidget.moc"
407 // vim:ts=2:sw=2:et