1
/***************************************************************************
2
* Copyright (C) 1999-2001 by Matthias Hoelzer-Kluepfel *
4
* Copyright (C) 2001 by Bernd Gehrmann *
6
* Copyright (C) 2004 by Alexander Dymo *
7
* cloudtemple@mksat.net *
9
* This program is free software; you can redistribute it and/or modify *
10
* it under the terms of the GNU General Public License as published by *
11
* the Free Software Foundation; either version 2 of the License, or *
12
* (at your option) any later version. *
14
***************************************************************************/
15
#include "htdigindex.h"
19
#include <qapplication.h>
23
#include <qtextstream.h>
27
#include <kaboutdata.h>
28
#include <kapplication.h>
29
#include <kcmdlineargs.h>
34
#include <kmessagebox.h>
35
#include <kstandarddirs.h>
37
#include <kdeversion.h>
38
#include <kprogress.h>
42
ProgressDialog::ProgressDialog(bool index, QWidget *parent, const char *name)
43
:KDialogBase(KDialogBase::Plain, i18n("Generating Search Index"), Cancel | Ok, Close,
48
indexdir = kapp->dirs()->saveLocation("data", "kdevdocumentation/search");
49
QDir d; d.mkdir(indexdir);
51
KConfig config("kdevdocumentation", true);
52
config.setGroup("htdig");
53
databaseDir = config.readPathEntry("databaseDir", indexdir);
58
d.mkdir( databaseDir );
60
showButtonOK( false );
61
QGridLayout *grid = new QGridLayout(plainPage(), 5,3, spacingHint());
63
QLabel *l = new QLabel(i18n("Scanning for files"), plainPage());
64
grid->addMultiCellWidget(l, 0, 0, 1, 2);
66
filesLabel = new QLabel(plainPage());
67
grid->addWidget(filesLabel, 1, 2);
70
check1 = new QLabel(plainPage());
71
grid->addWidget(check1, 0, 0);
73
l = new QLabel(i18n("Extracting search terms"), plainPage());
74
grid->addMultiCellWidget(l, 2,2, 1,2);
76
bar = new KProgress(plainPage());
77
grid->addWidget(bar, 3,2);
79
check2 = new QLabel(plainPage());
80
grid->addWidget(check2, 2,0);
82
l = new QLabel(i18n("Generating index..."), plainPage());
83
grid->addMultiCellWidget(l, 4,4, 1,2);
85
check3 = new QLabel(plainPage());
86
grid->addWidget(check3, 4,0);
91
connect(this, SIGNAL(cancelClicked()), this, SLOT(cancelClicked()));
92
connect(this, SIGNAL(okClicked()), this, SLOT(okClicked()));
93
QTimer::singleShot(0, this, SLOT(slotDelayedStart()));
96
ProgressDialog::~ProgressDialog()
100
void ProgressDialog::slotDelayedStart()
112
void ProgressDialog::done(int r)
116
showButtonCancel( false );
117
showButtonOK( true );
120
KDialogBase::done(r);
123
void ProgressDialog::setFilesScanned(int n)
125
filesLabel->setText(i18n("Files processed: %1").arg(n));
128
void ProgressDialog::setFilesToDig(int n)
130
bar->setTotalSteps(n);
133
void ProgressDialog::setFilesDigged(int n)
138
void ProgressDialog::setState(int n)
140
QPixmap unchecked = QPixmap(locate("data", "kdevdocumentation/pics/unchecked.xpm"));
141
QPixmap checked = QPixmap(locate("data", "kdevdocumentation/pics/checked.xpm"));
143
check1->setPixmap( n > 0 ? checked : unchecked);
144
check2->setPixmap( n > 1 ? checked : unchecked);
145
check3->setPixmap( n > 2 ? checked : unchecked);
149
void ProgressDialog::addDir(const QString &dir)
151
kdDebug(9002) << "Add dir : " << dir << endl;
152
QDir d(dir, "*.html", QDir::Name|QDir::IgnoreCase, QDir::Files | QDir::Readable);
153
QStringList list = d.entryList();
155
QStringList::ConstIterator it;
156
for ( it=list.begin(); it!=list.end(); ++it )
158
if( (*it).right( 12 ).lower( ) == "-source.html" )
161
files.append(dir + "/" + *it);
162
setFilesScanned(++filesScanned);
165
QDir d2(dir, QString::null, QDir::Name|QDir::IgnoreCase, QDir::Dirs);
166
QStringList dlist = d2.entryList();
168
for ( it=dlist.begin(); it != dlist.end(); ++it )
170
if (*it != "." && *it != "..")
172
addDir(dir + "/" + *it);
173
kapp->processEvents();
180
kapp->processEvents();
183
void ProgressDialog::scanDirectories()
185
QString ftsLocationsFile = locateLocal("data", "kdevdocumentation/search/locations.txt");
187
QFile f(ftsLocationsFile);
188
if (!f.open(IO_ReadOnly))
196
QString loc = str.readLine();
202
else if (fi.isFile())
205
setFilesScanned(++filesScanned);
210
bool ProgressDialog::createConfig()
212
// locate the common dir
213
QString language = KGlobal::locale()->language();
217
QString wrapper = locate("data", QString("kdevdocumentation/%1/wrapper.html").arg(language));
218
if (wrapper.isEmpty())
219
wrapper = locate("data", QString("kdevdocumentation/en/wrapper.html"));
220
if (wrapper.isEmpty())
222
wrapper = wrapper.left(wrapper.length()-12);
224
// locate the image dir
225
QString images = locate("data", "kdevdocumentation/pics/star.png");
226
if (images.isEmpty())
228
images = images.left(images.length()-8);
230
QFile f(indexdir + "/htdig.conf");
231
if (f.open(IO_WriteOnly))
235
ts << "database_dir:\t\t" << databaseDir << endl;
236
ts << "start_url:\t\t`" << indexdir << "/files`" << endl;
237
ts << "local_urls:\t\thttp://localhost/=/" << endl;
238
// ts << "local_urls:\t\tfile://=" << endl;
239
ts << "local_urls_only:\ttrue" << endl;
240
ts << "limit_urls_to:\t\tfile:// http://localhost/" << endl;
241
ts << "maximum_pages:\t\t1" << endl;
242
ts << "image_url_prefix:\t" << images << endl;
243
ts << "star_image:\t\t" << images << "star.png" << endl;
244
ts << "star_blank:\t\t" << images << "star_blank.png" << endl;
245
ts << "compression_level:\t6" << endl;
246
ts << "max_hop_count:\t\t0" << endl;
248
ts << "search_results_wrapper:\t" << wrapper << "wrapper.html" << endl;
249
ts << "nothing_found_file:\t" << wrapper << "nomatch.html" << endl;
250
ts << "syntax_error_file:\t" << wrapper << "syntax.html" << endl;
251
ts << "bad_word_list:\t\t" << wrapper << "bad_words" << endl;
260
#define CHUNK_SIZE 100
262
void ProgressDialog::startHtdigProcess(bool initial)
264
kdDebug(9002) << "htdig started" << endl;
266
proc = new KProcess();
267
*proc << exe << "-c" << (indexdir + "/htdig.conf");
271
connect(proc, SIGNAL(processExited(KProcess *)),
272
this, SLOT(htdigExited(KProcess *)));
277
QFile f(indexdir+"/files");
278
if (!f.open(IO_WriteOnly)) {
279
kdDebug(9002) << "Could not open `files` for writing" << endl;
284
for (int i=0; i<CHUNK_SIZE; ++i, ++count) {
285
if (count >= filesToDig) {
289
// ts << "file://localhost/" + files[count] << endl;
290
ts << "http://localhost/" + files[count] << endl;
295
proc->start(KProcess::NotifyOnExit, KProcess::Stdout);
298
bool ProgressDialog::generateIndex()
303
KConfig config("kdevdocumentation", true);
304
config.setGroup("htdig");
305
exe = config.readPathEntry("htdigbin", kapp->dirs()->findExe("htdig"));
311
filesToDig = files.count();
313
setFilesToDig(filesToDig);
316
// QDir d; d.mkdir(indexdir);
317
startHtdigProcess(true);
321
void ProgressDialog::htdigStdout(KProcess *, char *buffer, int len)
323
QString line = QString(buffer).left(len);
326
while ( (index = line.find("http://", index+1)) > 0)
331
while ( (index = line.find("not changed", index+1)) > 0)
335
setFilesDigged(filesDigged);
338
void ProgressDialog::htdigExited(KProcess *proc)
340
kdDebug(9002) << "htdig terminated" << endl;
341
if (!proc->normalExit())
348
if (proc && proc->exitStatus() != 0)
350
KMessageBox::sorry(0, i18n("Running htdig failed"));
356
htdigRunning = false;
357
filesDigged += CHUNK_SIZE;
358
setFilesDigged(filesDigged);
361
startHtdigProcess(false);
365
setFilesDigged(filesToDig);
368
KConfig config("kdevdocumentation", true);
369
config.setGroup("htdig");
370
// run htmerge -----------------------------------------------------
371
exe = config.readPathEntry("htmergebin", kapp->dirs()->findExe("htmerge"));
377
startHtmergeProcess();
381
void ProgressDialog::startHtmergeProcess()
383
kdDebug(9002) << "htmerge started" << endl;
385
proc = new KProcess();
386
*proc << exe << "-c" << (indexdir + "/htdig.conf");
388
kdDebug(9002) << "Running htmerge" << endl;
390
connect(proc, SIGNAL(processExited(KProcess *)),
391
this, SLOT(htmergeExited(KProcess *)));
393
htmergeRunning = true;
395
proc->start(KProcess::NotifyOnExit, KProcess::Stdout);
398
void ProgressDialog::htmergeExited(KProcess *proc)
400
kdDebug(9002) << "htmerge terminated" << endl;
401
htmergeRunning = false;
402
if (!proc->normalExit())
409
if (proc && proc->exitStatus() != 0)
411
KMessageBox::sorry(0, i18n("Running htmerge failed"));
421
void ProgressDialog::cancelClicked()
423
if ((htdigRunning || htmergeRunning) && proc && proc->isRunning())
425
kdDebug(9002) << "Killing " << (htdigRunning ? "htdig" : "htmerge") << "daemon with Sig. 9" << endl;
427
htdigRunning = htmergeRunning = false;
436
void ProgressDialog::okClicked()
441
KDialogBase::done(0);
444
int main(int argc, char *argv[])
446
static const KCmdLineOptions options[] =
448
{ "c", I18N_NOOP( "Update user's htdig configuration file only" ), 0 },
449
{ "i", I18N_NOOP( "-c and generate index" ), 0 },
453
KAboutData aboutData("kdevelop-htdig", I18N_NOOP("KDevelop ht://Dig Indexer"),
454
"0.2", I18N_NOOP("KDE Index generator for documentation files."));
456
KCmdLineArgs::init(argc, argv, &aboutData);
457
KCmdLineArgs::addCmdLineOptions(options);
461
KGlobal::locale()->setMainCatalogue("kdevelop");
463
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
465
if (args->isSet("c"))
467
ProgressDialog *search = new ProgressDialog( false, 0, "progress dialog");
469
if (search->createConfig())
470
KMessageBox::information(0, i18n("Configuration file updated."));
472
KMessageBox::error(0, i18n("Configuration file update failed."));
475
if (args->isSet("i"))
477
ProgressDialog *search = new ProgressDialog(true, 0, "progress dialog");
478
app.setMainWidget(search);
484
std::cerr << "Internal error generating index - unknown argument\n" << std::endl;
491
#include "htdigindex.moc"