/***************************************************************************
* Copyright ( C ) 1999 - 2001 by Matthias Hoelzer - Kluepfel *
* hoelzer @ kde . org *
* Copyright ( C ) 2001 by Bernd Gehrmann *
* bernd @ kdevelop . org *
* Copyright ( C ) 2004 by Alexander Dymo *
* cloudtemple @ mksat . net *
* *
* 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 "searchview.h"
# include <tqlayout.h>
# include <tqlabel.h>
# include <tqfile.h>
# include <tqtextstream.h>
# include <tqdir.h>
# include <tqregexp.h>
# include <kpushbutton.h>
# include <klistview.h>
# include <klineedit.h>
# include <kcombobox.h>
# include <klocale.h>
# include <kdialog.h>
# include <kprocess.h>
# include <kapplication.h>
# include <kstandarddirs.h>
# include <kconfig.h>
# include <kmessagebox.h>
# include <kdebug.h>
# include <kdevpartcontroller.h>
# include <kdevdocumentationplugin.h>
# include "documentation_part.h"
# include "docutils.h"
SearchView : : SearchView ( DocumentationPart * part , TQWidget * parent , const char * name )
: TQWidget ( parent , name ) , m_part ( part )
{
TQVBoxLayout * l = new TQVBoxLayout ( this , 0 , KDialog : : spacingHint ( ) ) ;
TQVBoxLayout * l2 = new TQVBoxLayout ( l , 0 ) ;
TQLabel * editLabel = new TQLabel ( i18n ( " Wor&ds to search: " ) , this ) ;
l2 - > addWidget ( editLabel ) ;
TQHBoxLayout * l21 = new TQHBoxLayout ( l2 , 0 ) ;
m_edit = new KLineEdit ( this ) ;
editLabel - > setBuddy ( m_edit ) ;
m_goSearchButton = new KPushButton ( i18n ( " Se&arch " ) , this ) ;
l21 - > addWidget ( m_edit ) ;
l21 - > addWidget ( m_goSearchButton ) ;
TQGridLayout * l3 = new TQGridLayout ( l , 2 , 2 , 0 ) ;
m_searchMethodBox = new KComboBox ( this ) ;
m_searchMethodBox - > insertItem ( i18n ( " and " ) ) ;
m_searchMethodBox - > insertItem ( i18n ( " or " ) ) ;
TQLabel * smLabel = new TQLabel ( m_searchMethodBox , i18n ( " &Method: " ) , this ) ;
m_sortMethodBox = new KComboBox ( this ) ;
m_sortMethodBox - > insertItem ( i18n ( " Score " ) ) ;
m_sortMethodBox - > insertItem ( i18n ( " Title " ) ) ;
m_sortMethodBox - > insertItem ( i18n ( " Date " ) ) ;
TQLabel * rmLabel = new TQLabel ( m_sortMethodBox , i18n ( " S&ort by: " ) , this ) ;
l3 - > addWidget ( smLabel , 0 , 0 ) ;
l3 - > addWidget ( m_searchMethodBox , 0 , 1 ) ;
l3 - > addWidget ( rmLabel , 1 , 0 ) ;
l3 - > addWidget ( m_sortMethodBox , 1 , 1 ) ;
TQVBoxLayout * l4 = new TQVBoxLayout ( l , 0 ) ;
m_view = new KListView ( this ) ;
TQLabel * vLabel = new TQLabel ( m_view , i18n ( " Search &results: " ) , this ) ;
l4 - > addWidget ( vLabel ) ;
l4 - > addWidget ( m_view ) ;
TQHBoxLayout * l5 = new TQHBoxLayout ( l , KDialog : : spacingHint ( ) ) ;
m_configButton = new KPushButton ( i18n ( " Update Config " ) , this ) ;
m_indexButton = new KPushButton ( i18n ( " Update Index " ) , this ) ;
l5 - > addWidget ( m_configButton ) ;
l5 - > addWidget ( m_indexButton ) ;
l5 - > addItem ( new TQSpacerItem ( 1 , 1 , TQSizePolicy : : Expanding , TQSizePolicy : : Fixed ) ) ;
l - > addSpacing ( 2 ) ;
m_view - > setSorting ( - 1 ) ;
m_view - > addColumn ( i18n ( " Relevance " ) ) ;
m_view - > addColumn ( i18n ( " Title " ) ) ;
m_view - > setColumnWidthMode ( 0 , TQListView : : Maximum ) ;
m_view - > setColumnWidthMode ( 1 , TQListView : : Maximum ) ;
m_view - > setAllColumnsShowFocus ( true ) ;
m_view - > setResizeMode ( TQListView : : LastColumn ) ;
connect ( m_configButton , TQT_SIGNAL ( clicked ( ) ) , this , TQT_SLOT ( updateConfig ( ) ) ) ;
connect ( m_indexButton , TQT_SIGNAL ( clicked ( ) ) , this , TQT_SLOT ( updateIndex ( ) ) ) ;
connect ( m_edit , TQT_SIGNAL ( returnPressed ( ) ) , this , TQT_SLOT ( search ( ) ) ) ;
connect ( m_goSearchButton , TQT_SIGNAL ( clicked ( ) ) , this , TQT_SLOT ( search ( ) ) ) ;
connect ( m_view , TQT_SIGNAL ( executed ( TQListViewItem * ) ) , this , TQT_SLOT ( executed ( TQListViewItem * ) ) ) ;
connect ( m_view , TQT_SIGNAL ( mouseButtonPressed ( int , TQListViewItem * , const TQPoint & , int ) ) ,
this , TQT_SLOT ( itemMouseButtonPressed ( int , TQListViewItem * , const TQPoint & , int ) ) ) ;
}
SearchView : : ~ SearchView ( )
{
}
void SearchView : : updateConfig ( )
{
runHtdig ( " -c " ) ;
}
void SearchView : : updateIndex ( )
{
runHtdig ( " -i " ) ;
KConfig * config = m_part - > config ( ) ;
config - > setGroup ( " htdig " ) ;
config - > writeEntry ( " IsSetup " , true ) ;
config - > sync ( ) ;
}
void SearchView : : runHtdig ( const TQString & arg )
{
KProcess proc ;
proc < < " kdevelop-htdig " < < arg ;
proc . start ( KProcess : : DontCare ) ;
}
void qt_enter_modal ( TQWidget * widget ) ;
void qt_leave_modal ( TQWidget * widget ) ;
void SearchView : : search ( )
{
KConfig * config = m_part - > config ( ) ;
config - > setGroup ( " htdig " ) ;
if ( config - > readBoolEntry ( " IsSetup " , false ) = = false )
{
KMessageBox : : information ( this , i18n ( " Full text search has to be set up before usage. " ) ) ;
if ( ! m_part - > configure ( 1 ) )
return ;
KMessageBox : : information ( this , i18n ( " Now the full text search database will be created. \n Wait for database creation to finish and then repeat search. " ) ) ;
updateIndex ( ) ;
return ;
}
TQString exe = config - > readPathEntry ( " htsearchbin " , kapp - > dirs ( ) - > findExe ( " htsearch " ) ) ;
if ( exe . isEmpty ( ) )
{
KMessageBox : : error ( this , i18n ( " Cannot find the htsearch executable. \n It is part of the ht://Dig package that is used by KDevelop to perform full text search. Please install ht://Dig and use Documentation page in Configure KDevelop dialog to set the htsearch location. " ) ) ;
kdDebug ( ) < < " Can not find htsearch " < < endl ;
return ;
}
TQString indexdir = kapp - > dirs ( ) - > saveLocation ( " data " , " kdevdocumentation/search " ) ;
TQDir d ;
if ( indexdir . isEmpty ( ) | | ! TQFile : : exists ( indexdir + " /htdig.conf " ) )
{
if ( TQFile : : exists ( " /var/lib/kdevelop3/helpindex/htdig.conf " ) )
indexdir = " /var/lib/kdevelop3/helpindex " ;
else if ( TQFile : : exists ( " /var/lib/kdevelop/helpindex/htdig.conf " ) )
indexdir = " /var/lib/kdevelop/helpindex " ;
if ( ! TQFile : : exists ( indexdir + " /htdig.conf " ) )
{
KMessageBox : : error ( this , i18n ( " Cannot find the htdig configuration file. " ) ) ;
kdDebug ( ) < < " Cannot find the htdig configuration file " < < endl ;
return ;
}
}
TQString savedir = kapp - > dirs ( ) - > saveLocation ( " data " , " kdevdocumentation/search " ) ;
if ( ! d . exists ( savedir ) )
d . mkdir ( savedir ) ;
TQString query = TQString ( " words=%1;method=%2;matchesperpage=%3;format=%4;sort=%5 " )
. tqarg ( m_edit - > text ( ) )
. tqarg ( m_searchMethodBox - > currentItem ( ) = = 1 ? " or " : " and " )
. tqarg ( 50 )
. tqarg ( " builtin-short " )
. tqarg ( m_sortMethodBox - > currentItem ( ) = = 2 ? " date " : m_sortMethodBox - > currentItem ( ) = = 1 ? " title " : " score " ) ;
kdDebug ( 9002 ) < < " starting kprocess " < < endl ;
kdDebug ( 9002 ) < < " htdig line: " < < exe < < " -c " < < ( indexdir + " /htdig.conf " ) < < query < < endl ;
KProcess * proc = new KProcess ;
TQString picdir = kapp - > dirs ( ) - > findResourceDir ( " data " , " kdevdocumentation/pics/htdig.png " ) ;
proc - > setEnvironment ( " PICDIR " , picdir ) ;
* proc < < exe < < " -c " < < ( indexdir + " /htdig.conf " ) < < query ;
connect ( proc , TQT_SIGNAL ( receivedStdout ( KProcess * , char * , int ) ) ,
this , TQT_SLOT ( htsearchStdout ( KProcess * , char * , int ) ) ) ;
connect ( proc , TQT_SIGNAL ( processExited ( KProcess * ) ) ,
this , TQT_SLOT ( htsearchExited ( KProcess * ) ) ) ;
searchResult = " " ;
if ( ! proc - > start ( KProcess : : NotifyOnExit , KProcess : : Stdout ) )
{
KMessageBox : : error ( this , i18n ( " Cannot start the htsearch executable. " ) ) ;
kdDebug ( ) < < " process start failed " < < endl ;
delete proc ;
return ;
}
// While receiving data from the subprocess, we want
// to block the user interface, but still get tqrepaint
// events. Hack taken from NetAccess...
kapp - > setOverrideCursor ( waitCursor ) ;
TQWidget blocker ( 0 , 0 , WType_Dialog | WShowModal ) ;
qt_enter_modal ( & blocker ) ;
kapp - > enter_loop ( ) ;
qt_leave_modal ( & blocker ) ;
kapp - > restoreOverrideCursor ( ) ;
if ( ! proc - > normalExit ( ) | | proc - > exitStatus ( ) ! = 0 )
{
kdDebug ( ) < < " Error running htsearch... returning now " < < endl ;
delete proc ;
return ;
}
delete proc ;
// modify the search result
searchResult = searchResult . replace ( TQRegExp ( " http://localhost/ " ) , " file:/ " ) ;
searchResult = searchResult . replace ( TQRegExp ( " Content-type: text/html " ) , " " ) ;
// dump the search result
TQFile f ( savedir + " /results.html " ) ;
if ( f . open ( IO_WriteOnly ) )
{
TQTextStream ts ( & f ) ;
ts < < searchResult < < endl ;
f . close ( ) ;
}
//show results
analyseSearchResults ( ) ;
// m_part->partController()->showDocument(KURL("file://" + indexdir + "/results.html"));
}
void SearchView : : htsearchStdout ( KProcess * , char * buffer , int len )
{
searchResult + = TQString : : fromLocal8Bit ( buffer , len ) ;
}
void SearchView : : htsearchExited ( KProcess * )
{
kapp - > exit_loop ( ) ;
}
void SearchView : : analyseSearchResults ( )
{
m_view - > clear ( ) ;
TQTextStream str ( searchResult , IO_ReadOnly ) ;
DocumentationItem * former = 0 ;
while ( ! str . eof ( ) )
{
TQString line = str . readLine ( ) ;
TQRegExp starsExp ( " alt= \" \\ * \" " ) ;
starsExp . setMinimal ( true ) ;
int stars = line . contains ( starsExp ) ;
TQRegExp urlExp ( " <strong><a href= \" (.*) \ " >(.*)</a></strong> " ) ;
if ( urlExp . search ( line ) = = - 1 )
continue ;
TQString url = urlExp . cap ( 1 ) ;
TQString title = urlExp . cap ( 2 ) ;
TQString starsStr ;
for ( int i = 0 ; i < stars ; + + i )
starsStr + = " * " ;
if ( former )
former = new DocumentationItem ( DocumentationItem : : Document , m_view , former , starsStr ) ;
else
former = new DocumentationItem ( DocumentationItem : : Document , m_view , starsStr ) ;
former - > setText ( 1 , title ) ;
former - > setURL ( KURL ( url ) ) ;
}
executed ( m_view - > firstChild ( ) ) ;
}
void SearchView : : executed ( TQListViewItem * item )
{
DocumentationItem * d = dynamic_cast < DocumentationItem * > ( item ) ;
if ( ! d )
return ;
m_part - > partController ( ) - > showDocument ( d - > url ( ) ) ;
}
void SearchView : : itemMouseButtonPressed ( int button , TQListViewItem * item , const TQPoint & pos , int // c
)
{
if ( ( button ! = Qt : : RightButton ) | | ( ! item ) )
return ;
DocumentationItem * docItem = dynamic_cast < DocumentationItem * > ( item ) ;
if ( ! docItem )
return ;
DocUtils : : docItemPopup ( m_part , docItem , pos , true , false , 1 ) ;
}
void SearchView : : setSearchTerm ( const TQString & term )
{
m_edit - > setText ( term ) ;
}
void SearchView : : askSearchTerm ( )
{
m_edit - > setFocus ( ) ;
}
void SearchView : : focusInEvent ( TQFocusEvent */ * e */ )
{
m_edit - > setFocus ( ) ;
}
# include "searchview.moc"