/* * searchwidget.cpp - part of the KDE Help Center * * Copyright (C) 1999 Matthias Elter (me@kde.org) * (C) 2000 Matthias Hoelzer-Kluepfel (hoelzer@kde.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <tqlabel.h> #include <tqpushbutton.h> #include <tqcombobox.h> #include <tqlayout.h> #include <ksimpleconfig.h> #include <kapplication.h> #include <klocale.h> #include <kdebug.h> #include <kiconloader.h> #include "scopeitem.h" #include "docentrytraverser.h" #include "kcmhelpcenter.h" #include "prefs.h" #include "searchengine.h" #include "searchwidget.h" namespace KHC { SearchWidget::SearchWidget( SearchEngine *engine, TQWidget *parent ) : TQWidget( parent ), DCOPObject( "SearchWidget" ), mEngine( engine ), mScopeCount( 0 ) { TQBoxLayout *topLayout = new TQVBoxLayout( this, 2, 2 ); TQBoxLayout *hLayout = new TQHBoxLayout( topLayout ); mMethodCombo = new TQComboBox( this ); mMethodCombo->insertItem( i18n("and") ); mMethodCombo->insertItem( i18n("or") ); TQLabel *l = new TQLabel( mMethodCombo, i18n("&Method:"), this ); hLayout->addWidget( l ); hLayout->addWidget( mMethodCombo ); hLayout = new TQHBoxLayout( topLayout ); mPagesCombo = new TQComboBox( this ); mPagesCombo->insertItem( "5" ); mPagesCombo->insertItem( "10" ); mPagesCombo->insertItem( "25" ); mPagesCombo->insertItem( "50" ); mPagesCombo->insertItem( "1000" ); l = new TQLabel( mPagesCombo, i18n("Max. &results:"), this ); hLayout->addWidget( l ); hLayout->addWidget( mPagesCombo ); hLayout = new TQHBoxLayout( topLayout ); mScopeCombo = new TQComboBox( this ); for (int i=0; i < ScopeNum; ++i ) { mScopeCombo->insertItem( scopeSelectionLabel( i ) ); } connect( mScopeCombo, TQT_SIGNAL( activated( int ) ), TQT_SLOT( scopeSelectionChanged( int ) ) ); l = new TQLabel( mScopeCombo, i18n("&Scope selection:"), this ); hLayout->addWidget( l ); hLayout->addWidget( mScopeCombo ); mScopeListView = new TQListView( this ); mScopeListView->setRootIsDecorated( true ); mScopeListView->addColumn( i18n("Scope") ); topLayout->addWidget( mScopeListView, 1 ); TQPushButton *indexButton = new TQPushButton( i18n("Build Search &Index..."), this ); connect( indexButton, TQT_SIGNAL( clicked() ), TQT_SIGNAL( showIndexDialog() ) ); topLayout->addWidget( indexButton ); // FIXME: Use SearchHandler on double-clicked document #if 0 connect( mScopeListView, TQT_SIGNAL( doubleClicked( TQListViewItem * ) ), TQT_SLOT( scopeDoubleClicked( TQListViewItem * ) ) ); #endif connect( mScopeListView, TQT_SIGNAL( clicked( TQListViewItem * ) ), TQT_SLOT( scopeClicked( TQListViewItem * ) ) ); } SearchWidget::~SearchWidget() { writeConfig( KGlobal::config() ); } void SearchWidget::readConfig( KConfig *cfg ) { cfg->setGroup( "Search" ); int scopeSelection = cfg->readNumEntry( "ScopeSelection", ScopeDefault ); mScopeCombo->setCurrentItem( scopeSelection ); if ( scopeSelection != ScopeDefault ) scopeSelectionChanged( scopeSelection ); mMethodCombo->setCurrentItem( Prefs::method() ); mPagesCombo->setCurrentItem( Prefs::maxCount() ); if ( scopeSelection == ScopeCustom ) { cfg->setGroup( "Custom Search Scope" ); TQListViewItemIterator it( mScopeListView ); while( it.current() ) { if ( it.current()->rtti() == ScopeItem::rttiId() ) { ScopeItem *item = static_cast<ScopeItem *>( it.current() ); item->setOn( cfg->readBoolEntry( item->entry()->identifier(), item->isOn() ) ); } ++it; } } checkScope(); } void SearchWidget::writeConfig( KConfig *cfg ) { cfg->setGroup( "Search" ); cfg->writeEntry( "ScopeSelection", mScopeCombo->currentItem() ); Prefs::setMethod( mMethodCombo->currentItem() ); Prefs::setMaxCount( mPagesCombo->currentItem() ); if ( mScopeCombo->currentItem() == ScopeCustom ) { cfg->setGroup( "Custom Search Scope" ); TQListViewItemIterator it( mScopeListView ); while( it.current() ) { if ( it.current()->rtti() == ScopeItem::rttiId() ) { ScopeItem *item = static_cast<ScopeItem *>( it.current() ); cfg->writeEntry( item->entry()->identifier(), item->isOn() ); } ++it; } } } void SearchWidget::slotSwitchBoxes() { TQListViewItemIterator it( mScopeListView ); while( it.current() ) { if ( it.current()->rtti() == ScopeItem::rttiId() ) { ScopeItem *item = static_cast<ScopeItem *>( it.current() ); item->setOn( !item->isOn() ); } ++it; } checkScope(); } void SearchWidget::scopeSelectionChanged( int id ) { TQListViewItemIterator it( mScopeListView ); while( it.current() ) { if ( it.current()->rtti() == ScopeItem::rttiId() ) { ScopeItem *item = static_cast<ScopeItem *>( it.current() ); bool state = item->isOn(); switch( id ) { case ScopeDefault: state = item->entry()->searchEnabledDefault(); break; case ScopeAll: state = true; break; case ScopeNone: state = false; break; default: break; } if ( state != item->isOn() ) { item->setOn( state ); } } ++it; } checkScope(); } TQString SearchWidget::method() { TQString m = "and"; if ( mMethodCombo->currentItem() == 1) m = "or"; return m; } int SearchWidget::pages() { int p = mPagesCombo->currentText().toInt(); return p; } TQString SearchWidget::scope() { TQString scope; TQListViewItemIterator it( mScopeListView ); while( it.current() ) { if ( it.current()->rtti() == ScopeItem::rttiId() ) { ScopeItem *item = static_cast<ScopeItem *>( it.current() ); if ( item->isOn() ) { if ( !scope.isEmpty() ) scope += "&"; scope += "scope=" + item->entry()->identifier(); } } ++it; } return scope; } class ScopeTraverser : public DocEntryTraverser { public: ScopeTraverser( SearchWidget *widget, int level ) : mWidget( widget ), mLevel( level ), mParentItem( 0 ) {} ~ScopeTraverser() { if( mParentItem && !mParentItem->childCount() ) delete mParentItem; } void process( DocEntry *entry ) { if ( mWidget->engine()->canSearch( entry ) && ( !mWidget->engine()->needsIndex( entry ) || entry->indexExists( Prefs::indexDirectory() ) ) ) { ScopeItem *item = 0; if ( mParentItem ) { item = new ScopeItem( mParentItem, entry ); } else { item = new ScopeItem( mWidget->listView(), entry ); } item->setOn( entry->searchEnabled() ); } } DocEntryTraverser *createChild( DocEntry *entry ) { if ( mLevel >= mNestingLevel ) { ++mLevel; return this; } else { ScopeTraverser *t = new ScopeTraverser( mWidget, mLevel + 1 ); TQListViewItem *item = 0; if ( mParentItem ) { item = new TQListViewItem( mParentItem, entry->name() ); } else { item = new TQListViewItem( mWidget->listView(), entry->name() ); } item->setOpen( true ); t->mParentItem = item; return t; } } DocEntryTraverser *parentTraverser() { if ( mLevel > mNestingLevel ) return this; else return mParent; } void deleteTraverser() { if ( mLevel > mNestingLevel ) --mLevel; else delete this; } private: SearchWidget *mWidget; int mLevel; TQListViewItem *mParentItem; static int mNestingLevel; }; int ScopeTraverser::mNestingLevel = 2; void SearchWidget::searchIndexUpdated() { KGlobal::config()->reparseConfiguration(); updateScopeList(); update(); } void SearchWidget::updateScopeList() { mScopeListView->clear(); ScopeTraverser t( this, 0 ); DocMetaInfo::self()->traverseEntries( &t ); checkScope(); } void SearchWidget::scopeDoubleClicked( TQListViewItem *item ) { if ( !item || item->rtti() != ScopeItem::rttiId() ) return; ScopeItem *scopeItem = static_cast<ScopeItem *>( item ); TQString searchUrl = scopeItem->entry()->search(); kdDebug() << "DoubleClick: " << searchUrl << endl; emit searchResult( searchUrl ); } void SearchWidget::scopeClicked( TQListViewItem * ) { checkScope(); mScopeCombo->setCurrentItem( ScopeCustom ); } TQString SearchWidget::scopeSelectionLabel( int id ) const { switch( id ) { case ScopeCustom: return i18n("Custom"); case ScopeDefault: return i18n("Default"); case ScopeAll: return i18n("All"); case ScopeNone: return i18n("None"); default: return i18n("unknown"); } } void SearchWidget::checkScope() { mScopeCount = 0; TQListViewItemIterator it( mScopeListView ); while( it.current() ) { if ( it.current()->rtti() == ScopeItem::rttiId() ) { ScopeItem *item = static_cast<ScopeItem *>( it.current() ); if ( item->isOn() ) { ++mScopeCount; } item->entry()->enableSearch( item->isOn() ); } ++it; } emit scopeCountChanged( mScopeCount ); } int SearchWidget::scopeCount() const { return mScopeCount; } } #include "searchwidget.moc" // vim:ts=2:sw=2:et