kde-playground/khelpcenter/searchwidget.cpp
2015-02-27 09:29:54 +00:00

407 lines
10 KiB
C++

/*
* 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 "searchwidget.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <QLabel>
#include <QPushButton>
#include <QComboBox>
#include <QLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QBoxLayout>
#include <QtDBus/QDBusConnection>
#include <KConfig>
#include <KApplication>
#include <KLocale>
#include <KDebug>
#include <KIconLoader>
#include "scopeitem.h"
#include "docentrytraverser.h"
#include "kcmhelpcenter.h"
#include "prefs.h"
#include "searchengine.h"
namespace KHC {
SearchWidget::SearchWidget( SearchEngine *engine, QWidget *parent )
: QWidget( parent ), mEngine( engine ),
mScopeCount( 0 )
{
QDBusConnection::sessionBus().registerObject("/SearchWidget", this, QDBusConnection::ExportScriptableSlots);
QBoxLayout *topLayout = new QVBoxLayout( this );
topLayout->setMargin( 2 );
topLayout->setSpacing( 2 );
QBoxLayout *hLayout = new QHBoxLayout();
topLayout->addLayout( hLayout );
mMethodCombo = new QComboBox( this );
mMethodCombo->addItem( i18n("and") );
mMethodCombo->addItem( i18n("or") );
QLabel *l = new QLabel( i18n("&Method:"), this );
l->setBuddy( mMethodCombo );
hLayout->addWidget( l );
hLayout->addWidget( mMethodCombo );
hLayout = new QHBoxLayout();
topLayout->addLayout( hLayout );
mPagesCombo = new QComboBox( this );
mPagesCombo->addItem( QLatin1String("5") );
mPagesCombo->addItem( QLatin1String("10") );
mPagesCombo->addItem( QLatin1String("25") );
mPagesCombo->addItem( QLatin1String("50") );
mPagesCombo->addItem( QLatin1String("1000") );
l = new QLabel( i18n("Max. &results:"), this );
l->setBuddy( mPagesCombo );
hLayout->addWidget( l );
hLayout->addWidget( mPagesCombo );
hLayout = new QHBoxLayout();
topLayout->addLayout( hLayout );
mScopeCombo = new QComboBox( this );
for (int i=0; i < ScopeNum; ++i ) {
mScopeCombo->addItem( scopeSelectionLabel( i ) );
}
connect( mScopeCombo, SIGNAL( activated( int ) ),
SLOT( scopeSelectionChanged( int ) ) );
l = new QLabel( i18n("&Scope selection:"), this );
l->setBuddy( mScopeCombo );
hLayout->addWidget( l );
hLayout->addWidget( mScopeCombo );
mScopeListView = new QTreeWidget( this );
mScopeListView->setColumnCount( 1 );
mScopeListView->setHeaderLabels( QStringList() << i18n("Scope") );
topLayout->addWidget( mScopeListView, 1 );
QPushButton *indexButton = new QPushButton( i18n("Build Search &Index..."),
this );
connect( indexButton, SIGNAL( clicked() ), SIGNAL( showIndexDialog() ) );
topLayout->addWidget( indexButton );
// FIXME: Use SearchHandler on double-clicked document
#if 0
connect( mScopeListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int) ),
SLOT(scopeDoubleClicked(QTreeWidgetItem*)) );
#endif
connect( mScopeListView, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
SLOT(scopeClicked(QTreeWidgetItem*)) );
}
SearchWidget::~SearchWidget()
{
writeConfig( KGlobal::config().data() );
}
void SearchWidget::readConfig( KConfig *cfg )
{
KConfigGroup searchGroup(cfg, "Search");
int scopeSelection = searchGroup.readEntry( "ScopeSelection", (int)ScopeDefault );
mScopeCombo->setCurrentIndex( scopeSelection );
if ( scopeSelection != ScopeDefault ) scopeSelectionChanged( scopeSelection );
mMethodCombo->setCurrentIndex( Prefs::method() );
mPagesCombo->setCurrentIndex( Prefs::maxCount() );
if ( scopeSelection == ScopeCustom ) {
KConfigGroup searchScopeGroup(cfg, "Custom Search Scope" );
QTreeWidgetItemIterator it( mScopeListView );
while( *it ) {
if ( (*it)->type() == ScopeItem::rttiId() ) {
ScopeItem *item = static_cast<ScopeItem *>(*it);
item->setOn( searchScopeGroup.readEntry(
item->entry()->identifier(),
item->isOn() ) );
}
++it;
}
}
checkScope();
}
void SearchWidget::writeConfig( KConfig *cfg )
{
KConfigGroup cg (cfg, "Search");
cg.writeEntry( "ScopeSelection", mScopeCombo->currentIndex() );
Prefs::setMethod( mMethodCombo->currentIndex() );
Prefs::setMaxCount( mPagesCombo->currentIndex() );
if ( mScopeCombo->currentIndex() == ScopeCustom ) {
KConfigGroup cg2 (cfg, "Custom Search Scope");
QTreeWidgetItemIterator it( mScopeListView );
while( (*it) ) {
if ( (*it)->type() == ScopeItem::rttiId() ) {
ScopeItem *item = static_cast<ScopeItem *>( (*it) );
cg2.writeEntry( item->entry()->identifier(), item->isOn() );
}
++it;
}
}
}
void SearchWidget::slotSwitchBoxes()
{
QTreeWidgetItemIterator it( mScopeListView );
while( (*it) ) {
if ( (*it)->type() == ScopeItem::rttiId() ) {
ScopeItem *item = static_cast<ScopeItem *>( (*it) );
item->setOn( !item->isOn() );
}
++it;
}
checkScope();
}
void SearchWidget::scopeSelectionChanged( int id )
{
QTreeWidgetItemIterator it( mScopeListView );
while( (*it) ) {
if ( (*it)->type() == ScopeItem::rttiId() ) {
ScopeItem *item = static_cast<ScopeItem *>( (*it) );
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();
}
QString SearchWidget::method()
{
QString m = "and";
if ( mMethodCombo->currentIndex() == 1)
m = "or";
return m;
}
int SearchWidget::pages()
{
int p = mPagesCombo->currentText().toInt();
return p;
}
QString SearchWidget::scope()
{
QString scope;
QTreeWidgetItemIterator it( mScopeListView );
while( (*it) ) {
if ( (*it)->type() == ScopeItem::rttiId() ) {
ScopeItem *item = static_cast<ScopeItem *>( (*it) );
if ( item->isOn() ) {
if ( !scope.isEmpty() ) scope += '&';
scope += QLatin1String("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 );
QTreeWidgetItem *item = 0;
if ( mParentItem ) {
item = new QTreeWidgetItem( mParentItem, QStringList() << entry->name() );
} else {
item = new QTreeWidgetItem( mWidget->listView(), QStringList() << entry->name() );
}
item->setExpanded( 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;
QTreeWidgetItem *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( QTreeWidgetItem* item )
{
if ( !item || item->type() != ScopeItem::rttiId() ) return;
ScopeItem *scopeItem = static_cast<ScopeItem *>( item );
QString searchUrl = scopeItem->entry()->search();
kDebug() << "DoubleClick: " << searchUrl;
emit searchResult( searchUrl );
}
void SearchWidget::scopeClicked( QTreeWidgetItem* )
{
checkScope();
mScopeCombo->setCurrentIndex( ScopeCustom );
}
QString SearchWidget::scopeSelectionLabel( int id ) const
{
switch( id ) {
case ScopeCustom:
return i18nc("Label for searching documentation using custom (user defined) scope", "Custom");
case ScopeDefault:
return i18nc("Label for searching documentation using default search scope", "Default");
case ScopeAll:
return i18nc("Label for searching documentation in all subsections", "All");
case ScopeNone:
return i18nc("Label for scope that deselects all search subsections", "None");
default:
return i18nc("Label for Unknown search scope, that should never appear", "unknown");
}
}
void SearchWidget::checkScope()
{
mScopeCount = 0;
QTreeWidgetItemIterator it( mScopeListView );
while( (*it) ) {
if ( (*it)->type() == ScopeItem::rttiId() ) {
ScopeItem *item = static_cast<ScopeItem *>( (*it) );
if ( item->isOn() ) {
++mScopeCount;
}
item->entry()->enableSearch( item->isOn() );
}
++it;
}
emit scopeCountChanged( mScopeCount );
}
int SearchWidget::scopeCount() const
{
return mScopeCount;
}
}
#include "moc_searchwidget.cpp"
// vim:ts=2:sw=2:et