~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to parts/documentation/tools/htdig/htdigindex.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2006-05-23 18:39:42 UTC
  • Revision ID: james.westby@ubuntu.com-20060523183942-hucifbvh68k2bwz7
Tags: upstream-3.3.2
Import upstream version 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 1999-2001 by Matthias Hoelzer-Kluepfel                  *
 
3
 *   hoelzer@kde.org                                                       *
 
4
 *   Copyright (C) 2001 by Bernd Gehrmann                                  *
 
5
 *   bernd@kdevelop.org                                                    *
 
6
 *   Copyright (C) 2004 by Alexander Dymo                                  *
 
7
 *   cloudtemple@mksat.net                                                 *
 
8
 *                                                                         *
 
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.                                   *
 
13
 *                                                                         *
 
14
 ***************************************************************************/
 
15
#include "htdigindex.h"
 
16
 
 
17
#include <iostream>
 
18
 
 
19
#include <qapplication.h>
 
20
#include <qdir.h>
 
21
#include <qfile.h>
 
22
#include <qlayout.h>
 
23
#include <qtextstream.h>
 
24
#include <qtimer.h>
 
25
#include <qlabel.h>
 
26
 
 
27
#include <kaboutdata.h>
 
28
#include <kapplication.h>
 
29
#include <kcmdlineargs.h>
 
30
#include <kconfig.h>
 
31
#include <kdebug.h>
 
32
#include <kglobal.h>
 
33
#include <klocale.h>
 
34
#include <kmessagebox.h>
 
35
#include <kstandarddirs.h>
 
36
#include <kprocess.h>
 
37
#include <kdeversion.h>
 
38
#include <kprogress.h>
 
39
 
 
40
#define INDEXER
 
41
 
 
42
ProgressDialog::ProgressDialog(bool index, QWidget *parent, const char *name)
 
43
    :KDialogBase(KDialogBase::Plain, i18n("Generating Search Index"), Cancel | Ok, Close,
 
44
    parent, name, false)
 
45
{
 
46
    proc = 0;
 
47
 
 
48
    indexdir = kapp->dirs()->saveLocation("data", "kdevdocumentation/search");
 
49
    QDir d; d.mkdir(indexdir);
 
50
 
 
51
    KConfig config("kdevdocumentation", true);
 
52
    config.setGroup("htdig");
 
53
    databaseDir = config.readPathEntry("databaseDir", indexdir);
 
54
 
 
55
    if (!index)
 
56
        return;
 
57
 
 
58
    d.mkdir( databaseDir );
 
59
 
 
60
    showButtonOK( false );
 
61
    QGridLayout *grid = new QGridLayout(plainPage(), 5,3, spacingHint());
 
62
 
 
63
    QLabel *l = new QLabel(i18n("Scanning for files"), plainPage());
 
64
    grid->addMultiCellWidget(l, 0, 0, 1, 2);
 
65
 
 
66
    filesLabel = new QLabel(plainPage());
 
67
    grid->addWidget(filesLabel, 1, 2);
 
68
    setFilesScanned(0);
 
69
 
 
70
    check1 = new QLabel(plainPage());
 
71
    grid->addWidget(check1, 0, 0);
 
72
 
 
73
    l = new QLabel(i18n("Extracting search terms"), plainPage());
 
74
    grid->addMultiCellWidget(l, 2,2, 1,2);
 
75
 
 
76
    bar = new KProgress(plainPage());
 
77
    grid->addWidget(bar, 3,2);
 
78
 
 
79
    check2 = new QLabel(plainPage());
 
80
    grid->addWidget(check2, 2,0);
 
81
 
 
82
    l = new QLabel(i18n("Generating index..."), plainPage());
 
83
    grid->addMultiCellWidget(l, 4,4, 1,2);
 
84
 
 
85
    check3 = new QLabel(plainPage());
 
86
    grid->addWidget(check3, 4,0);
 
87
 
 
88
    setState(0);
 
89
 
 
90
    setMinimumWidth(300);
 
91
    connect(this, SIGNAL(cancelClicked()), this, SLOT(cancelClicked()));
 
92
    connect(this, SIGNAL(okClicked()), this, SLOT(okClicked()));
 
93
    QTimer::singleShot(0, this, SLOT(slotDelayedStart()));
 
94
}
 
95
 
 
96
ProgressDialog::~ProgressDialog()
 
97
{
 
98
}
 
99
 
 
100
void ProgressDialog::slotDelayedStart()
 
101
{
 
102
    procdone = false;
 
103
    scanDirectories();
 
104
    if (!createConfig())
 
105
    {
 
106
      done(1);
 
107
      return;
 
108
    }
 
109
    generateIndex();
 
110
}
 
111
 
 
112
void ProgressDialog::done(int r)
 
113
{
 
114
    if (!r)
 
115
    {
 
116
        showButtonCancel( false );
 
117
        showButtonOK( true );
 
118
    }
 
119
    else
 
120
        KDialogBase::done(r);
 
121
}
 
122
 
 
123
void ProgressDialog::setFilesScanned(int n)
 
124
{
 
125
    filesLabel->setText(i18n("Files processed: %1").arg(n));
 
126
}
 
127
 
 
128
void ProgressDialog::setFilesToDig(int n)
 
129
{
 
130
    bar->setTotalSteps(n);
 
131
}
 
132
 
 
133
void ProgressDialog::setFilesDigged(int n)
 
134
{
 
135
    bar->setValue(n);
 
136
}
 
137
 
 
138
void ProgressDialog::setState(int n)
 
139
{
 
140
    QPixmap unchecked = QPixmap(locate("data", "kdevdocumentation/pics/unchecked.xpm"));
 
141
    QPixmap checked = QPixmap(locate("data", "kdevdocumentation/pics/checked.xpm"));
 
142
 
 
143
    check1->setPixmap( n > 0 ? checked : unchecked);
 
144
    check2->setPixmap( n > 1 ? checked : unchecked);
 
145
    check3->setPixmap( n > 2 ? checked : unchecked);
 
146
}
 
147
 
 
148
 
 
149
void ProgressDialog::addDir(const QString &dir)
 
150
{
 
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();
 
154
 
 
155
    QStringList::ConstIterator it;
 
156
    for ( it=list.begin(); it!=list.end(); ++it )
 
157
    {
 
158
        if( (*it).right( 12 ).lower( ) == "-source.html" )
 
159
            continue;
 
160
 
 
161
        files.append(dir + "/" + *it);
 
162
        setFilesScanned(++filesScanned);
 
163
    }
 
164
 
 
165
    QDir d2(dir, QString::null, QDir::Name|QDir::IgnoreCase, QDir::Dirs);
 
166
    QStringList dlist = d2.entryList();
 
167
 
 
168
    for ( it=dlist.begin(); it != dlist.end(); ++it )
 
169
    {
 
170
        if (*it != "." && *it != "..")
 
171
        {
 
172
            addDir(dir + "/" + *it);
 
173
            kapp->processEvents();
 
174
        }
 
175
        if (procdone)
 
176
        {
 
177
          return;
 
178
        }
 
179
    }
 
180
    kapp->processEvents();
 
181
}
 
182
 
 
183
void ProgressDialog::scanDirectories()
 
184
{
 
185
    QString ftsLocationsFile = locateLocal("data", "kdevdocumentation/search/locations.txt");
 
186
 
 
187
    QFile f(ftsLocationsFile);
 
188
    if (!f.open(IO_ReadOnly))
 
189
        return;
 
190
    QTextStream str(&f);
 
191
 
 
192
    filesScanned = 0;
 
193
 
 
194
    while (!str.eof())
 
195
    {
 
196
        QString loc = str.readLine();
 
197
        if (loc.isEmpty())
 
198
            continue;
 
199
        QFileInfo fi(loc);
 
200
        if (fi.isDir())
 
201
            addDir(loc);
 
202
        else if (fi.isFile())
 
203
        {
 
204
            files.append(loc);
 
205
            setFilesScanned(++filesScanned);
 
206
        }
 
207
    }
 
208
}
 
209
 
 
210
bool ProgressDialog::createConfig()
 
211
{
 
212
    // locate the common dir
 
213
    QString language = KGlobal::locale()->language();
 
214
    if (language == "C")
 
215
        language = "en";
 
216
 
 
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())
 
221
        return false;
 
222
    wrapper = wrapper.left(wrapper.length()-12);
 
223
 
 
224
    // locate the image dir
 
225
    QString images = locate("data", "kdevdocumentation/pics/star.png");
 
226
    if (images.isEmpty())
 
227
        return false;
 
228
    images = images.left(images.length()-8);
 
229
 
 
230
    QFile f(indexdir + "/htdig.conf");
 
231
    if (f.open(IO_WriteOnly))
 
232
    {
 
233
        QTextStream ts(&f);
 
234
 
 
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;
 
247
 
 
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;
 
252
 
 
253
        f.close();
 
254
        return true;
 
255
    }
 
256
 
 
257
    return false;
 
258
}
 
259
 
 
260
#define CHUNK_SIZE 100
 
261
 
 
262
void ProgressDialog::startHtdigProcess(bool initial)
 
263
{
 
264
    kdDebug(9002) << "htdig started" << endl;
 
265
    delete proc;
 
266
    proc = new KProcess();
 
267
    *proc << exe << "-c" << (indexdir + "/htdig.conf");
 
268
    if (initial) {
 
269
        *proc << "-i";
 
270
    }
 
271
    connect(proc, SIGNAL(processExited(KProcess *)),
 
272
            this, SLOT(htdigExited(KProcess *)));
 
273
 
 
274
    htdigRunning = true;
 
275
 
 
276
    // write out file
 
277
    QFile f(indexdir+"/files");
 
278
    if (!f.open(IO_WriteOnly)) {
 
279
        kdDebug(9002) << "Could not open `files` for writing" << endl;
 
280
        done(1);
 
281
        return;
 
282
    }
 
283
    QTextStream ts(&f);
 
284
    for (int i=0; i<CHUNK_SIZE; ++i, ++count) {
 
285
        if (count >= filesToDig) {
 
286
            procdone = true;
 
287
            break;
 
288
        }
 
289
    //    ts << "file://localhost/" + files[count] << endl;
 
290
        ts << "http://localhost/" + files[count] << endl;
 
291
    }
 
292
    f.close();
 
293
 
 
294
    // execute htdig
 
295
    proc->start(KProcess::NotifyOnExit, KProcess::Stdout);
 
296
}
 
297
 
 
298
bool ProgressDialog::generateIndex()
 
299
{
 
300
    setState(1);
 
301
    procdone = false;
 
302
    // run htdig
 
303
    KConfig config("kdevdocumentation", true);
 
304
    config.setGroup("htdig");
 
305
    exe = config.readPathEntry("htdigbin", kapp->dirs()->findExe("htdig"));
 
306
    if (exe.isEmpty())
 
307
    {
 
308
        done(1);
 
309
        return true;
 
310
    }
 
311
    filesToDig = files.count();
 
312
    count = 0;
 
313
    setFilesToDig(filesToDig);
 
314
    filesDigged = 0;
 
315
 
 
316
    //    QDir d; d.mkdir(indexdir);
 
317
    startHtdigProcess(true);
 
318
    return true;
 
319
}
 
320
 
 
321
void ProgressDialog::htdigStdout(KProcess *, char *buffer, int len)
 
322
{
 
323
    QString line = QString(buffer).left(len);
 
324
 
 
325
    int cnt=0, index=-1;
 
326
    while ( (index = line.find("http://", index+1)) > 0)
 
327
        cnt++;
 
328
    filesDigged += cnt;
 
329
 
 
330
    cnt=0, index=-1;
 
331
    while ( (index = line.find("not changed", index+1)) > 0)
 
332
        cnt++;
 
333
    filesDigged -= cnt;
 
334
 
 
335
    setFilesDigged(filesDigged);
 
336
}
 
337
 
 
338
void ProgressDialog::htdigExited(KProcess *proc)
 
339
{
 
340
    kdDebug(9002) << "htdig terminated" << endl;
 
341
    if (!proc->normalExit())
 
342
    {
 
343
        delete proc;
 
344
        proc = 0L;
 
345
        done(1);
 
346
        return;
 
347
    }
 
348
    if (proc && proc->exitStatus() != 0)
 
349
    {
 
350
        KMessageBox::sorry(0, i18n("Running htdig failed"));
 
351
        delete proc;
 
352
        proc = 0L;
 
353
        done(1);
 
354
        return;
 
355
    }
 
356
    htdigRunning = false;
 
357
    filesDigged += CHUNK_SIZE;
 
358
    setFilesDigged(filesDigged);
 
359
    if (!procdone)
 
360
    {
 
361
        startHtdigProcess(false);
 
362
    }
 
363
    else
 
364
    {
 
365
        setFilesDigged(filesToDig);
 
366
        setState(2);
 
367
 
 
368
        KConfig config("kdevdocumentation", true);
 
369
        config.setGroup("htdig");
 
370
        // run htmerge -----------------------------------------------------
 
371
        exe = config.readPathEntry("htmergebin", kapp->dirs()->findExe("htmerge"));
 
372
        if (exe.isEmpty())
 
373
        {
 
374
            done(1);
 
375
            return;
 
376
        }
 
377
        startHtmergeProcess();
 
378
    }
 
379
}
 
380
 
 
381
void ProgressDialog::startHtmergeProcess()
 
382
{
 
383
    kdDebug(9002) << "htmerge started" << endl;
 
384
    delete proc;
 
385
    proc = new KProcess();
 
386
    *proc << exe << "-c" << (indexdir + "/htdig.conf");
 
387
 
 
388
    kdDebug(9002) << "Running htmerge" << endl;
 
389
 
 
390
    connect(proc, SIGNAL(processExited(KProcess *)),
 
391
            this, SLOT(htmergeExited(KProcess *)));
 
392
 
 
393
    htmergeRunning = true;
 
394
 
 
395
    proc->start(KProcess::NotifyOnExit, KProcess::Stdout);
 
396
}
 
397
 
 
398
void ProgressDialog::htmergeExited(KProcess *proc)
 
399
{
 
400
    kdDebug(9002) << "htmerge terminated" << endl;
 
401
    htmergeRunning = false;
 
402
    if (!proc->normalExit())
 
403
    {
 
404
        delete proc;
 
405
        proc = 0L;
 
406
        done(1);
 
407
        return;
 
408
    }
 
409
    if (proc && proc->exitStatus() != 0)
 
410
    {
 
411
        KMessageBox::sorry(0, i18n("Running htmerge failed"));
 
412
        delete proc;
 
413
        proc = 0L;
 
414
        done(1);
 
415
        return;
 
416
    }
 
417
    setState(3);
 
418
    done(0);
 
419
}
 
420
 
 
421
void ProgressDialog::cancelClicked()
 
422
{
 
423
    if ((htdigRunning || htmergeRunning) && proc && proc->isRunning())
 
424
    {
 
425
        kdDebug(9002) << "Killing " << (htdigRunning ? "htdig" : "htmerge") << "daemon with Sig. 9" << endl;
 
426
        proc->kill(9);
 
427
        htdigRunning = htmergeRunning = false;
 
428
    }
 
429
    else
 
430
    {
 
431
        procdone = true;
 
432
        done(2);
 
433
    }
 
434
}
 
435
 
 
436
void ProgressDialog::okClicked()
 
437
{
 
438
    if (proc)
 
439
        proc->kill();
 
440
 
 
441
    KDialogBase::done(0);
 
442
}
 
443
 
 
444
int main(int argc, char *argv[])
 
445
{
 
446
    static const KCmdLineOptions options[] =
 
447
    {
 
448
        { "c", I18N_NOOP( "Update user's htdig configuration file only" ), 0 },
 
449
        { "i",  I18N_NOOP( "-c and generate index" ), 0 },
 
450
        KCmdLineLastOption
 
451
    };
 
452
 
 
453
    KAboutData aboutData("kdevelop-htdig", I18N_NOOP("KDevelop ht://Dig Indexer"),
 
454
                         "0.2", I18N_NOOP("KDE Index generator for documentation files."));
 
455
 
 
456
    KCmdLineArgs::init(argc, argv, &aboutData);
 
457
    KCmdLineArgs::addCmdLineOptions(options);
 
458
 
 
459
    KApplication app;
 
460
 
 
461
    KGlobal::locale()->setMainCatalogue("kdevelop");
 
462
 
 
463
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
 
464
 
 
465
    if (args->isSet("c"))
 
466
    {
 
467
        ProgressDialog *search = new ProgressDialog( false, 0, "progress dialog");
 
468
 
 
469
        if (search->createConfig())
 
470
            KMessageBox::information(0, i18n("Configuration file updated."));
 
471
        else
 
472
            KMessageBox::error(0, i18n("Configuration file update failed."));
 
473
    }
 
474
    else
 
475
        if (args->isSet("i"))
 
476
        {
 
477
            ProgressDialog *search = new ProgressDialog(true, 0, "progress dialog");
 
478
            app.setMainWidget(search);
 
479
            search->show();
 
480
            app.exec();
 
481
        }
 
482
        else
 
483
        {
 
484
            std::cerr << "Internal error generating index - unknown argument\n" << std::endl;
 
485
            return 1;
 
486
        }
 
487
 
 
488
    return 0;
 
489
}
 
490
 
 
491
#include "htdigindex.moc"