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