KDevelop API Documentation

searchview.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 1999-2001 by Matthias Hoelzer-Kluepfel                  *
00003  *   hoelzer@kde.org                                                       *
00004  *   Copyright (C) 2001 by Bernd Gehrmann                                  *
00005  *   bernd@kdevelop.org                                                    *
00006  *   Copyright (C) 2004 by Alexander Dymo                                  *
00007  *   cloudtemple@mksat.net                                                 *
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  *   This program is distributed in the hope that it will be useful,       *
00015  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017  *   GNU General Public License for more details.                          *
00018  *                                                                         *
00019  *   You should have received a copy of the GNU General Public License     *
00020  *   along with this program; if not, write to the                         *
00021  *   Free Software Foundation, Inc.,                                       *
00022  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00023  ***************************************************************************/
00024 #include "searchview.h"
00025 
00026 #include <qlayout.h>
00027 #include <qlabel.h>
00028 #include <qfile.h>
00029 #include <qtextstream.h>
00030 #include <qdir.h>
00031 #include <qregexp.h>
00032 
00033 #include <kpushbutton.h>
00034 #include <klistview.h>
00035 #include <klineedit.h>
00036 #include <kcombobox.h>
00037 #include <klocale.h>
00038 #include <kdialog.h>
00039 #include <kprocess.h>
00040 #include <kapplication.h>
00041 #include <kstddirs.h>
00042 #include <kconfig.h>
00043 #include <kmessagebox.h>
00044 #include <kdebug.h>
00045 
00046 #include <kdevpartcontroller.h>
00047 #include <kdevdocumentationplugin.h>
00048 
00049 #include "documentation_part.h"
00050 #include "docutils.h"
00051 
00052 SearchView::SearchView(DocumentationPart *part, QWidget *parent, const char *name)
00053     :QWidget(parent, name), m_part(part)
00054 {
00055     QVBoxLayout *l = new QVBoxLayout(this, 0, KDialog::spacingHint());
00056     
00057     QVBoxLayout *l2 = new QVBoxLayout(l, 0);
00058     QLabel *editLabel = new QLabel(i18n("Wor&ds to search:"), this);
00059     l2->addWidget(editLabel);
00060     QHBoxLayout *l21 = new QHBoxLayout(l2, 0);
00061     m_edit = new KLineEdit(this);
00062     editLabel->setBuddy(m_edit);
00063     m_goSearchButton = new KPushButton(i18n("Se&arch"), this);
00064     l21->addWidget(m_edit);
00065     l21->addWidget(m_goSearchButton);
00066         
00067     QGridLayout *l3 = new QGridLayout(l, 2, 2, 0);
00068     m_searchMethodBox = new KComboBox(this);
00069     m_searchMethodBox->insertItem(i18n("and"));
00070     m_searchMethodBox->insertItem(i18n("or"));
00071     QLabel *smLabel = new QLabel(m_searchMethodBox, i18n("&Method:"), this);
00072     m_sortMethodBox = new KComboBox(this);
00073     m_sortMethodBox->insertItem(i18n("Score"));
00074     m_sortMethodBox->insertItem(i18n("Title"));
00075     m_sortMethodBox->insertItem(i18n("Date"));
00076     QLabel *rmLabel = new QLabel(m_sortMethodBox, i18n("S&ort by:"), this);
00077     l3->addWidget(smLabel, 0, 0);
00078     l3->addWidget(m_searchMethodBox, 0, 1);
00079     l3->addWidget(rmLabel, 1, 0);
00080     l3->addWidget(m_sortMethodBox, 1, 1);
00081     
00082     QVBoxLayout *l4 = new QVBoxLayout(l, 0);
00083     m_view = new KListView(this);
00084     QLabel *vLabel = new QLabel(m_view, i18n("Search &results:"), this);
00085     l4->addWidget(vLabel);
00086     l4->addWidget(m_view);
00087     
00088     QHBoxLayout *l5 = new QHBoxLayout(l, KDialog::spacingHint());
00089     m_configButton = new KPushButton(i18n("Update Config"), this);
00090     m_indexButton = new KPushButton(i18n("Update Index"), this);
00091     l5->addWidget(m_configButton);
00092     l5->addWidget(m_indexButton);
00093     l5->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed));
00094 
00095     l->addSpacing(2);
00096     
00097     m_view->setSorting(-1);
00098     m_view->addColumn(i18n("Relevance"));
00099     m_view->addColumn(i18n("Title"));
00100     m_view->setColumnWidthMode(0, QListView::Maximum);
00101     m_view->setColumnWidthMode(1, QListView::Maximum);
00102     m_view->setAllColumnsShowFocus(true);
00103 
00104     connect(m_configButton, SIGNAL(clicked()), this, SLOT(updateConfig()));
00105     connect(m_indexButton, SIGNAL(clicked()), this, SLOT(updateIndex()));
00106     connect(m_edit, SIGNAL(returnPressed()), this, SLOT(search()));
00107     connect(m_goSearchButton, SIGNAL(clicked()), this, SLOT(search()));
00108     connect(m_view, SIGNAL(executed(QListViewItem*)), this, SLOT(executed(QListViewItem*)));
00109     connect(m_view, SIGNAL(mouseButtonPressed(int, QListViewItem*, const QPoint&, int )),
00110         this, SLOT(itemMouseButtonPressed(int, QListViewItem*, const QPoint&, int )));
00111 }
00112 
00113 SearchView::~SearchView()
00114 {
00115 }
00116 
00117 void SearchView::updateConfig()
00118 {
00119     runHtdig("-c");
00120 }
00121 
00122 void SearchView::updateIndex()
00123 {
00124     runHtdig("-i");
00125 }
00126 
00127 void SearchView::runHtdig(const QString &arg)
00128 {
00129     KProcess proc;
00130     proc << "kdevelop-htdig" << arg;
00131     proc.start(KProcess::DontCare);
00132 }
00133 
00134 void qt_enter_modal(QWidget *widget);
00135 void qt_leave_modal(QWidget *widget);
00136 
00137 void SearchView::search()
00138 {
00139     KConfig *config = m_part->config();
00140     config->setGroup("htdig");
00141     if (config->readBoolEntry("IsSetup", false) == false)
00142     {
00143         KMessageBox::information(this, i18n("Full text search has to be set up before usage."));
00144         if (!m_part->configure(1))
00145             return;
00146         config->writeEntry("IsSetup", true);
00147         KMessageBox::information(this, i18n("Now the full text search database will be created.\nWait for database creation to finish and then repeat search."));
00148         updateIndex();
00149         return;
00150     }
00151     QString exe = config->readPathEntry("htsearchbin", kapp->dirs()->findExe("htsearch"));
00152     if (exe.isEmpty())
00153     {
00154         KMessageBox::error(this, i18n("Cannot find the htsearch executable."));
00155         kdDebug() << "Can not find htsearch" << endl;
00156         return;
00157     }
00158 
00159     QString indexdir = kapp->dirs()->saveLocation("data", "kdevdocumentation/search");
00160     QDir d;
00161     if (indexdir.isEmpty() || !QFile::exists(indexdir + "/htdig.conf"))
00162     {
00163         if (QFile::exists("/var/lib/kdevelop3/helpindex/htdig.conf")) 
00164             indexdir = "/var/lib/kdevelop3/helpindex";
00165         else if (QFile::exists("/var/lib/kdevelop/helpindex/htdig.conf"))
00166             indexdir = "/var/lib/kdevelop/helpindex";
00167         
00168         if (!QFile::exists(indexdir + "/htdig.conf"))
00169         {
00170             KMessageBox::error(this, i18n("Can not find the htdig configuration file."));
00171             kdDebug() << "Cannot find the htdig configuration file" << endl;
00172             return;
00173         }
00174     }
00175 
00176     QString savedir = kapp->dirs()->saveLocation("data", "kdevdocumentation/search");
00177     if (!d.exists(savedir))
00178         d.mkdir(savedir);
00179 
00180     QString query = QString("words=%1;method=%2;matchesperpage=%3;format=%4;sort=%5")
00181         .arg(m_edit->text())
00182         .arg(m_searchMethodBox->currentItem()==1? "or" : "and")
00183         .arg(50)
00184         .arg("builtin-short")
00185         .arg(m_sortMethodBox->currentItem()==2? "date" : m_sortMethodBox->currentItem()==1? "title" : "score");
00186 
00187     kdDebug(9002) << "starting kprocess" << endl;
00188     kdDebug(9002) << "htdig line:" << exe << " -c " << (indexdir + "/htdig.conf ") << query <<  endl;
00189     KProcess *proc = new KProcess;
00190     QString picdir = kapp->dirs()->findResourceDir("data", "kdevdocumentation/pics/htdig.png");
00191     proc->setEnvironment("PICDIR", picdir);
00192     *proc << exe << "-c" << (indexdir + "/htdig.conf") << query;
00193 
00194     connect( proc, SIGNAL(receivedStdout(KProcess *,char*,int)),
00195              this, SLOT(htsearchStdout(KProcess *,char*,int)) );
00196     connect( proc, SIGNAL(processExited(KProcess *)),
00197              this, SLOT(htsearchExited(KProcess *)) );
00198 
00199     searchResult = "";
00200 
00201     if (!proc->start(KProcess::NotifyOnExit, KProcess::Stdout)) 
00202     {
00203         KMessageBox::error(this, i18n("Cannot start the htsearch executable."));
00204         kdDebug() << "process start failed" << endl;
00205         delete proc;
00206         return;
00207     }
00208 
00209     // While receiving data from the subprocess, we want
00210     // to block the user interface, but still get repaint
00211     // events. Hack taken from NetAccess...
00212     kapp->setOverrideCursor(waitCursor);
00213     QWidget blocker(0, 0, WType_Dialog | WShowModal);
00214     qt_enter_modal(&blocker);
00215     kapp->enter_loop();
00216     qt_leave_modal(&blocker);
00217     kapp->restoreOverrideCursor();
00218 
00219     if (!proc->normalExit() || proc->exitStatus() != 0)
00220     {
00221         kdDebug() << "Error running htsearch... returning now" << endl;
00222         delete proc;
00223         return;
00224     }
00225 
00226     delete proc;
00227 
00228     // modify the search result
00229     searchResult = searchResult.replace(QRegExp("http://localhost/"), "file:/");
00230     searchResult = searchResult.replace(QRegExp("Content-type: text/html"), "");
00231 
00232     // dump the search result
00233     QFile f(savedir + "/results.html");
00234     if (f.open(IO_WriteOnly))
00235     {
00236         QTextStream ts(&f);
00237         ts << searchResult << endl;
00238         f.close();
00239     }
00240 
00241     //show results
00242     analyseSearchResults();
00243 //    m_part->partController()->showDocument(KURL("file://" + indexdir + "/results.html"));
00244 }
00245 
00246 void SearchView::htsearchStdout(KProcess *, char *buffer, int len)
00247 {
00248     searchResult += QString::fromLocal8Bit(buffer, len);
00249 }
00250 
00251 void SearchView::htsearchExited(KProcess *)
00252 {
00253     kapp->exit_loop();
00254 }
00255 
00256 void SearchView::analyseSearchResults()
00257 {
00258     m_view->clear();
00259     QTextStream str(searchResult, IO_ReadOnly);
00260     DocumentationItem *former = 0;
00261     while (!str.eof())
00262     {
00263         QString line = str.readLine();
00264         
00265         QRegExp starsExp("alt=\"\\*\"");
00266         starsExp.setMinimal(true);
00267         int stars = line.contains(starsExp);
00268         
00269         QRegExp urlExp("<strong><a href=\"(.*)\">(.*)</a></strong>");
00270         if (urlExp.search(line)==-1)
00271             continue;
00272         QString url = urlExp.cap(1);
00273         QString title = urlExp.cap(2);
00274         
00275         QString starsStr;
00276         for (int i = 0; i < stars; ++i)
00277             starsStr += "*";
00278         
00279         if (former)
00280             former = new DocumentationItem(DocumentationItem::Document, m_view, former, starsStr);
00281         else
00282             former = new DocumentationItem(DocumentationItem::Document, m_view, starsStr);
00283         former->setText(1, title);
00284         former->setURL(KURL(url));
00285     }
00286 }
00287 
00288 void SearchView::executed(QListViewItem *item)
00289 {
00290     DocumentationItem *d = dynamic_cast<DocumentationItem*>(item);
00291     if (!d)
00292         return;
00293     
00294     m_part->partController()->showDocument(d->url());
00295 }
00296 
00297 void SearchView::itemMouseButtonPressed(int button, QListViewItem *item, const QPoint &pos, int c)
00298 {
00299     if ((button != Qt::RightButton) || (!item))
00300         return;
00301     DocumentationItem *docItem = dynamic_cast<DocumentationItem*>(item);
00302     if (!docItem)
00303         return;
00304     
00305     DocUtils::docItemPopup(m_part, docItem, pos, true, false, 1);
00306 }
00307 
00308 void SearchView::setSearchTerm(const QString &term)
00309 {
00310     m_edit->setText(term);
00311 }
00312 
00313 void SearchView::askSearchTerm()
00314 {
00315     m_edit->setFocus();
00316 }
00317 
00318 void SearchView::focusInEvent(QFocusEvent */*e*/)
00319 {
00320     m_edit->setFocus();
00321 }
00322 
00323 #include "searchview.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:40 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003