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"
29 #include <QPushButton>
32 #include <QVBoxLayout>
33 #include <QHBoxLayout>
37 #include <KApplication>
40 #include <KIconLoader>
42 #include "scopeitem.h"
43 #include "docentrytraverser.h"
44 #include "kcmhelpcenter.h"
46 #include "searchengine.h"
48 #include <QtDBus/QDBusConnection>
52 SearchWidget::SearchWidget( SearchEngine
*engine
, QWidget
*parent
)
53 : QWidget( parent
), mEngine( engine
),
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..."),
114 connect( indexButton
, SIGNAL( clicked() ), SIGNAL( showIndexDialog() ) );
115 topLayout
->addWidget( indexButton
);
117 // FIXME: Use SearchHandler on double-clicked document
119 connect( mScopeListView
, SIGNAL( doubleClicked( Q3ListViewItem
* ) ),
120 SLOT( scopeDoubleClicked( Q3ListViewItem
* ) ) );
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(),
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() );
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() );
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();
204 state
= item
->entry()->searchEnabledDefault();
215 if ( state
!= item
->isOn() ) {
216 item
->setOn( state
);
225 QString
SearchWidget::method()
228 if ( mMethodCombo
->currentIndex() == 1)
234 int SearchWidget::pages()
236 int p
= mPagesCombo
->currentText().toInt();
241 QString
SearchWidget::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();
260 class ScopeTraverser
: public DocEntryTraverser
263 ScopeTraverser( SearchWidget
*widget
, int level
) :
264 mWidget( widget
), mLevel( level
), mParentItem( 0 ) {}
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() ) ) ) {
278 item
= new ScopeItem( mParentItem
, entry
);
280 item
= new ScopeItem( mWidget
->listView(), entry
);
282 item
->setOn( entry
->searchEnabled() );
286 DocEntryTraverser
*createChild( DocEntry
*entry
)
288 if ( mLevel
>= mNestingLevel
) {
292 ScopeTraverser
*t
= new ScopeTraverser( mWidget
, mLevel
+ 1 );
293 Q3ListViewItem
*item
= 0;
295 item
= new Q3ListViewItem( mParentItem
, entry
->name() );
297 item
= new Q3ListViewItem( mWidget
->listView(), entry
->name() );
299 item
->setOpen( true );
300 t
->mParentItem
= item
;
305 DocEntryTraverser
*parentTraverser()
307 if ( mLevel
> mNestingLevel
) return this;
311 void deleteTraverser()
313 if ( mLevel
> mNestingLevel
) --mLevel
;
318 SearchWidget
*mWidget
;
320 Q3ListViewItem
*mParentItem
;
322 static int mNestingLevel
;
325 int ScopeTraverser::mNestingLevel
= 2;
327 void SearchWidget::searchIndexUpdated()
329 KGlobal::config()->reparseConfiguration();
334 void SearchWidget::updateScopeList()
336 mScopeListView
->clear();
338 ScopeTraverser
t( this, 0 );
339 DocMetaInfo::self()->traverseEntries( &t
);
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
* )
360 mScopeCombo
->setCurrentIndex( ScopeCustom
);
363 QString
SearchWidget::scopeSelectionLabel( int id
) const
367 return i18nc("Label for searching documentation using custom (user defined) scope", "Custom");
369 return i18nc("Label for searching documentation using default search scope", "Default");
371 return i18nc("Label for searching documentation in all subsections", "All");
373 return i18nc("Label for scope that deselects all search subsections", "None");
375 return i18nc("Label for Unknown search scope, that should never appear", "unknown");
379 void SearchWidget::checkScope()
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() ) {
390 item
->entry()->enableSearch( item
->isOn() );
395 emit
scopeCountChanged( mScopeCount
);
398 int SearchWidget::scopeCount() const
405 #include "searchwidget.moc"