You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/khelpcenter/searchwidget.cpp

393 lines
9.8 KiB

/*
* 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