diff options
Diffstat (limited to 'parts/documentation/tools/htdig/htdigindex.cpp')
-rw-r--r-- | parts/documentation/tools/htdig/htdigindex.cpp | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/parts/documentation/tools/htdig/htdigindex.cpp b/parts/documentation/tools/htdig/htdigindex.cpp new file mode 100644 index 00000000..80161301 --- /dev/null +++ b/parts/documentation/tools/htdig/htdigindex.cpp @@ -0,0 +1,491 @@ +/*************************************************************************** + * Copyright (C) 1999-2001 by Matthias Hoelzer-Kluepfel * + * [email protected] * + * Copyright (C) 2001 by Bernd Gehrmann * + * [email protected] * + * Copyright (C) 2004 by Alexander Dymo * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ +#include "htdigindex.h" + +#include <iostream> + +#include <qapplication.h> +#include <qdir.h> +#include <qfile.h> +#include <qlayout.h> +#include <qtextstream.h> +#include <qtimer.h> +#include <qlabel.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <kprocess.h> +#include <kdeversion.h> +#include <kprogress.h> + +#define INDEXER + +ProgressDialog::ProgressDialog(bool index, QWidget *parent, const char *name) + :KDialogBase(KDialogBase::Plain, i18n("Generating Search Index"), Cancel | Ok, Close, + parent, name, false) +{ + proc = 0; + + indexdir = kapp->dirs()->saveLocation("data", "kdevdocumentation/search"); + QDir d; d.mkdir(indexdir); + + KConfig config("kdevdocumentation", true); + config.setGroup("htdig"); + databaseDir = config.readPathEntry("databaseDir", indexdir); + + if (!index) + return; + + d.mkdir( databaseDir ); + + showButtonOK( false ); + QGridLayout *grid = new QGridLayout(plainPage(), 5,3, spacingHint()); + + QLabel *l = new QLabel(i18n("Scanning for files"), plainPage()); + grid->addMultiCellWidget(l, 0, 0, 1, 2); + + filesLabel = new QLabel(plainPage()); + grid->addWidget(filesLabel, 1, 2); + setFilesScanned(0); + + check1 = new QLabel(plainPage()); + grid->addWidget(check1, 0, 0); + + l = new QLabel(i18n("Extracting search terms"), plainPage()); + grid->addMultiCellWidget(l, 2,2, 1,2); + + bar = new KProgress(plainPage()); + grid->addWidget(bar, 3,2); + + check2 = new QLabel(plainPage()); + grid->addWidget(check2, 2,0); + + l = new QLabel(i18n("Generating index..."), plainPage()); + grid->addMultiCellWidget(l, 4,4, 1,2); + + check3 = new QLabel(plainPage()); + grid->addWidget(check3, 4,0); + + setState(0); + + setMinimumWidth(300); + connect(this, SIGNAL(cancelClicked()), this, SLOT(cancelClicked())); + connect(this, SIGNAL(okClicked()), this, SLOT(okClicked())); + QTimer::singleShot(0, this, SLOT(slotDelayedStart())); +} + +ProgressDialog::~ProgressDialog() +{ +} + +void ProgressDialog::slotDelayedStart() +{ + procdone = false; + scanDirectories(); + if (!createConfig()) + { + done(1); + return; + } + generateIndex(); +} + +void ProgressDialog::done(int r) +{ + if (!r) + { + showButtonCancel( false ); + showButtonOK( true ); + } + else + KDialogBase::done(r); +} + +void ProgressDialog::setFilesScanned(int n) +{ + filesLabel->setText(i18n("Files processed: %1").arg(n)); +} + +void ProgressDialog::setFilesToDig(int n) +{ + bar->setTotalSteps(n); +} + +void ProgressDialog::setFilesDigged(int n) +{ + bar->setValue(n); +} + +void ProgressDialog::setState(int n) +{ + QPixmap unchecked = QPixmap(locate("data", "kdevdocumentation/pics/unchecked.xpm")); + QPixmap checked = QPixmap(locate("data", "kdevdocumentation/pics/checked.xpm")); + + check1->setPixmap( n > 0 ? checked : unchecked); + check2->setPixmap( n > 1 ? checked : unchecked); + check3->setPixmap( n > 2 ? checked : unchecked); +} + + +void ProgressDialog::addDir(const QString &dir) +{ + kdDebug(9002) << "Add dir : " << dir << endl; + QDir d(dir, "*.html", QDir::Name|QDir::IgnoreCase, QDir::Files | QDir::Readable); + QStringList list = d.entryList(); + + QStringList::ConstIterator it; + for ( it=list.begin(); it!=list.end(); ++it ) + { + if( (*it).right( 12 ).lower( ) == "-source.html" ) + continue; + + files.append(dir + "/" + *it); + setFilesScanned(++filesScanned); + } + + QDir d2(dir, QString::null, QDir::Name|QDir::IgnoreCase, QDir::Dirs); + QStringList dlist = d2.entryList(); + + for ( it=dlist.begin(); it != dlist.end(); ++it ) + { + if (*it != "." && *it != "..") + { + addDir(dir + "/" + *it); + kapp->processEvents(); + } + if (procdone) + { + return; + } + } + kapp->processEvents(); +} + +void ProgressDialog::scanDirectories() +{ + QString ftsLocationsFile = locateLocal("data", "kdevdocumentation/search/locations.txt"); + + QFile f(ftsLocationsFile); + if (!f.open(IO_ReadOnly)) + return; + QTextStream str(&f); + + filesScanned = 0; + + while (!str.eof()) + { + QString loc = str.readLine(); + if (loc.isEmpty()) + continue; + QFileInfo fi(loc); + if (fi.isDir()) + addDir(loc); + else if (fi.isFile()) + { + files.append(loc); + setFilesScanned(++filesScanned); + } + } +} + +bool ProgressDialog::createConfig() +{ + // locate the common dir + QString language = KGlobal::locale()->language(); + if (language == "C") + language = "en"; + + QString wrapper = locate("data", QString("kdevdocumentation/%1/wrapper.html").arg(language)); + if (wrapper.isEmpty()) + wrapper = locate("data", QString("kdevdocumentation/en/wrapper.html")); + if (wrapper.isEmpty()) + return false; + wrapper = wrapper.left(wrapper.length()-12); + + // locate the image dir + QString images = locate("data", "kdevdocumentation/pics/star.png"); + if (images.isEmpty()) + return false; + images = images.left(images.length()-8); + + QFile f(indexdir + "/htdig.conf"); + if (f.open(IO_WriteOnly)) + { + QTextStream ts(&f); + + ts << "database_dir:\t\t" << databaseDir << endl; + ts << "start_url:\t\t`" << indexdir << "/files`" << endl; + ts << "local_urls:\t\thttp://localhost/=/" << endl; +// ts << "local_urls:\t\tfile://=" << endl; + ts << "local_urls_only:\ttrue" << endl; + ts << "limit_urls_to:\t\tfile:// http://localhost/" << endl; + ts << "maximum_pages:\t\t1" << endl; + ts << "image_url_prefix:\t" << images << endl; + ts << "star_image:\t\t" << images << "star.png" << endl; + ts << "star_blank:\t\t" << images << "star_blank.png" << endl; + ts << "compression_level:\t6" << endl; + ts << "max_hop_count:\t\t0" << endl; + + ts << "search_results_wrapper:\t" << wrapper << "wrapper.html" << endl; + ts << "nothing_found_file:\t" << wrapper << "nomatch.html" << endl; + ts << "syntax_error_file:\t" << wrapper << "syntax.html" << endl; + ts << "bad_word_list:\t\t" << wrapper << "bad_words" << endl; + + f.close(); + return true; + } + + return false; +} + +#define CHUNK_SIZE 100 + +void ProgressDialog::startHtdigProcess(bool initial) +{ + kdDebug(9002) << "htdig started" << endl; + delete proc; + proc = new KProcess(); + *proc << exe << "-c" << (indexdir + "/htdig.conf"); + if (initial) { + *proc << "-i"; + } + connect(proc, SIGNAL(processExited(KProcess *)), + this, SLOT(htdigExited(KProcess *))); + + htdigRunning = true; + + // write out file + QFile f(indexdir+"/files"); + if (!f.open(IO_WriteOnly)) { + kdDebug(9002) << "Could not open `files` for writing" << endl; + done(1); + return; + } + QTextStream ts(&f); + for (int i=0; i<CHUNK_SIZE; ++i, ++count) { + if (count >= filesToDig) { + procdone = true; + break; + } + // ts << "file://localhost/" + files[count] << endl; + ts << "http://localhost/" + files[count] << endl; + } + f.close(); + + // execute htdig + proc->start(KProcess::NotifyOnExit, KProcess::Stdout); +} + +bool ProgressDialog::generateIndex() +{ + setState(1); + procdone = false; + // run htdig + KConfig config("kdevdocumentation", true); + config.setGroup("htdig"); + exe = config.readPathEntry("htdigbin", kapp->dirs()->findExe("htdig")); + if (exe.isEmpty()) + { + done(1); + return true; + } + filesToDig = files.count(); + count = 0; + setFilesToDig(filesToDig); + filesDigged = 0; + + // QDir d; d.mkdir(indexdir); + startHtdigProcess(true); + return true; +} + +void ProgressDialog::htdigStdout(KProcess *, char *buffer, int len) +{ + QString line = QString(buffer).left(len); + + int cnt=0, index=-1; + while ( (index = line.find("http://", index+1)) > 0) + cnt++; + filesDigged += cnt; + + cnt=0, index=-1; + while ( (index = line.find("not changed", index+1)) > 0) + cnt++; + filesDigged -= cnt; + + setFilesDigged(filesDigged); +} + +void ProgressDialog::htdigExited(KProcess *proc) +{ + kdDebug(9002) << "htdig terminated" << endl; + if (!proc->normalExit()) + { + delete proc; + proc = 0L; + done(1); + return; + } + if (proc && proc->exitStatus() != 0) + { + KMessageBox::sorry(0, i18n("Running htdig failed")); + delete proc; + proc = 0L; + done(1); + return; + } + htdigRunning = false; + filesDigged += CHUNK_SIZE; + setFilesDigged(filesDigged); + if (!procdone) + { + startHtdigProcess(false); + } + else + { + setFilesDigged(filesToDig); + setState(2); + + KConfig config("kdevdocumentation", true); + config.setGroup("htdig"); + // run htmerge ----------------------------------------------------- + exe = config.readPathEntry("htmergebin", kapp->dirs()->findExe("htmerge")); + if (exe.isEmpty()) + { + done(1); + return; + } + startHtmergeProcess(); + } +} + +void ProgressDialog::startHtmergeProcess() +{ + kdDebug(9002) << "htmerge started" << endl; + delete proc; + proc = new KProcess(); + *proc << exe << "-c" << (indexdir + "/htdig.conf"); + + kdDebug(9002) << "Running htmerge" << endl; + + connect(proc, SIGNAL(processExited(KProcess *)), + this, SLOT(htmergeExited(KProcess *))); + + htmergeRunning = true; + + proc->start(KProcess::NotifyOnExit, KProcess::Stdout); +} + +void ProgressDialog::htmergeExited(KProcess *proc) +{ + kdDebug(9002) << "htmerge terminated" << endl; + htmergeRunning = false; + if (!proc->normalExit()) + { + delete proc; + proc = 0L; + done(1); + return; + } + if (proc && proc->exitStatus() != 0) + { + KMessageBox::sorry(0, i18n("Running htmerge failed")); + delete proc; + proc = 0L; + done(1); + return; + } + setState(3); + done(0); +} + +void ProgressDialog::cancelClicked() +{ + if ((htdigRunning || htmergeRunning) && proc && proc->isRunning()) + { + kdDebug(9002) << "Killing " << (htdigRunning ? "htdig" : "htmerge") << "daemon with Sig. 9" << endl; + proc->kill(9); + htdigRunning = htmergeRunning = false; + } + else + { + procdone = true; + done(2); + } +} + +void ProgressDialog::okClicked() +{ + if (proc) + proc->kill(); + + KDialogBase::done(0); +} + +int main(int argc, char *argv[]) +{ + static const KCmdLineOptions options[] = + { + { "c", I18N_NOOP( "Update user's htdig configuration file only" ), 0 }, + { "i", I18N_NOOP( "-c and generate index" ), 0 }, + KCmdLineLastOption + }; + + KAboutData aboutData("kdevelop-htdig", I18N_NOOP("KDevelop ht://Dig Indexer"), + "0.2", I18N_NOOP("KDE Index generator for documentation files.")); + + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions(options); + + KApplication app; + + KGlobal::locale()->setMainCatalogue("kdevelop"); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if (args->isSet("c")) + { + ProgressDialog *search = new ProgressDialog( false, 0, "progress dialog"); + + if (search->createConfig()) + KMessageBox::information(0, i18n("Configuration file updated.")); + else + KMessageBox::error(0, i18n("Configuration file update failed.")); + } + else + if (args->isSet("i")) + { + ProgressDialog *search = new ProgressDialog(true, 0, "progress dialog"); + app.setMainWidget(search); + search->show(); + app.exec(); + } + else + { + std::cerr << "Internal error generating index - unknown argument\n" << std::endl; + return 1; + } + + return 0; +} + +#include "htdigindex.moc" |