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

« back to all changes in this revision

Viewing changes to parts/documentation/plugins/doxygen/docdoxygenplugin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2010-05-05 07:21:55 UTC
  • mfrom: (1.2.3 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505072155-h78lx19pu04sbhtn
Tags: 4:4.0.0-2
* Upload to unstable (Closes: #579947, #481832).
* Acknowledge obsolete NMU fixes (Closes: #562410, #546961).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright (C) 2004 by Alexander Dymo                                  *
3
 
 *   cloudtemple@mksat.net                                                 *
4
 
 *                                                                         *
5
 
 *   This program is free software; you can redistribute it and/or modify  *
6
 
 *   it under the terms of the GNU General Public License as published by  *
7
 
 *   the Free Software Foundation; either version 2 of the License, or     *
8
 
 *   (at your option) any later version.                                   *
9
 
 *                                                                         *
10
 
 *   This program is distributed in the hope that it will be useful,       *
11
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13
 
 *   GNU General Public License for more details.                          *
14
 
 *                                                                         *
15
 
 *   You should have received a copy of the GNU General Public License     *
16
 
 *   along with this program; if not, write to the                         *
17
 
 *   Free Software Foundation, Inc.,                                       *
18
 
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19
 
 ***************************************************************************/
20
 
#include "docdoxygenplugin.h"
21
 
 
22
 
#include <unistd.h>
23
 
 
24
 
#include <qdom.h>
25
 
#include <qfile.h>
26
 
#include <qfileinfo.h>
27
 
#include <qdialog.h>
28
 
#include <qregexp.h>
29
 
#include <qvaluestack.h>
30
 
 
31
 
#include <kurl.h>
32
 
#include <kaboutdata.h>
33
 
#include <kconfig.h>
34
 
#include <klocale.h>
35
 
#include <kstandarddirs.h>
36
 
 
37
 
#include <urlutil.h>
38
 
#include <kdevgenericfactory.h>
39
 
#include <kdevplugininfo.h>
40
 
 
41
 
#include "../../../../config.h"
42
 
 
43
 
class DoxyDocumentationCatalogItem: public DocumentationCatalogItem
44
 
{
45
 
public:
46
 
    DoxyDocumentationCatalogItem(const QString &origUrl, DocumentationPlugin* plugin,
47
 
        KListView *parent, const QString &name)
48
 
        :DocumentationCatalogItem(plugin, parent, name), m_origUrl(origUrl)
49
 
    {
50
 
    }
51
 
    DoxyDocumentationCatalogItem(const QString &origUrl, DocumentationPlugin* plugin,
52
 
        DocumentationItem *parent, const QString &name)
53
 
        :DocumentationCatalogItem(plugin, parent, name), m_origUrl(origUrl)
54
 
    {
55
 
    }
56
 
    QString origUrl() const { return m_origUrl; }
57
 
    
58
 
private:
59
 
    QString m_origUrl;
60
 
};
61
 
 
62
 
 
63
 
static const KDevPluginInfo data("docdoxygenplugin");
64
 
typedef KDevGenericFactory<DocDoxygenPlugin> DocDoxygenPluginFactory;
65
 
K_EXPORT_COMPONENT_FACTORY( libdocdoxygenplugin, DocDoxygenPluginFactory(data) )
66
 
 
67
 
DocDoxygenPlugin::DocDoxygenPlugin(QObject* parent, const char* name, const QStringList)
68
 
    :DocumentationPlugin(DocDoxygenPluginFactory::instance()->config(), parent, name)
69
 
{
70
 
    setCapabilities(Index | FullTextSearch | ProjectDocumentation | CustomDocumentationTitles );
71
 
    autoSetup();
72
 
}
73
 
 
74
 
DocDoxygenPlugin::~DocDoxygenPlugin()
75
 
{
76
 
}
77
 
 
78
 
QPair<KFile::Mode, QString> DocDoxygenPlugin::catalogLocatorProps()
79
 
{
80
 
    return QPair<KFile::Mode, QString>(KFile::File, "index.html *.tag");
81
 
}
82
 
 
83
 
QString DocDoxygenPlugin::catalogTitle(const QString& url)
84
 
{
85
 
    QFileInfo fi(url);
86
 
    if (!fi.exists())
87
 
        return QString::null;
88
 
    
89
 
    if (fi.extension(false) == "html")
90
 
    {
91
 
        QFile f(url);
92
 
        if (!f.open(IO_ReadOnly))
93
 
            return QString::null;
94
 
        
95
 
        QTextStream ts(&f);
96
 
        QString contents = ts.read();
97
 
        QRegExp re(".*<title>(.*)</title>.*");
98
 
        re.setCaseSensitive(false);
99
 
        re.search(contents);
100
 
        return re.cap(1);   
101
 
    }
102
 
    else if (fi.extension(false) == "tag")
103
 
    {
104
 
        QFile *f = 0;
105
 
        QFile f1(fi.dirPath(true) + "/html/index.html");
106
 
        if (f1.open(IO_ReadOnly))
107
 
            f = &f1;
108
 
        QFile f2(fi.dirPath(true) + "/index.html");
109
 
        if (f2.open(IO_ReadOnly))
110
 
            f = &f2;
111
 
        if (f != 0)
112
 
        {
113
 
            QTextStream ts(f);
114
 
            QString contents = ts.read();
115
 
            QRegExp re(".*<title>(.*)</title>.*");
116
 
            re.setCaseSensitive(false);
117
 
            re.search(contents);
118
 
            return re.cap(1);   
119
 
        }
120
 
    }
121
 
    return QString::null;
122
 
}
123
 
 
124
 
QString DocDoxygenPlugin::pluginName() const
125
 
{
126
 
    return i18n("Doxygen Documentation Collection");
127
 
}
128
 
 
129
 
QStringList DocDoxygenPlugin::fullTextSearchLocations()
130
 
{
131
 
    QStringList locs;
132
 
        
133
 
    QMap<QString, QString> entryMap = config->entryMap("Locations");
134
 
 
135
 
    for (QMap<QString, QString>::const_iterator it = entryMap.begin();
136
 
        it != entryMap.end(); ++it)
137
 
    {
138
 
        config->setGroup("Search Settings");
139
 
        if (config->readBoolEntry(it.key(), false))
140
 
        {
141
 
            config->setGroup("Locations");
142
 
            QFileInfo fi(config->readPathEntry(it.key()));
143
 
            locs << fi.dirPath(true);
144
 
        }
145
 
    }
146
 
    
147
 
    return locs;
148
 
}
149
 
 
150
 
void DocDoxygenPlugin::setCatalogURL(DocumentationCatalogItem* item)
151
 
{
152
 
    if (item->url().url().endsWith("tag"))
153
 
    {
154
 
        QFileInfo fi(item->url().directory(false) + "html/index.html");
155
 
        if (fi.exists())
156
 
        {
157
 
            item->setURL(KURL::fromPathOrURL(fi.absFilePath()));
158
 
            return;
159
 
        }
160
 
        QFileInfo fi2(item->url().directory(false) + "index.html");
161
 
        if (fi2.exists())
162
 
        {
163
 
            item->setURL(KURL::fromPathOrURL(fi2.absFilePath()));
164
 
            return;
165
 
        }
166
 
        item->setURL(KURL());
167
 
    }
168
 
}
169
 
 
170
 
bool DocDoxygenPlugin::needRefreshIndex(DocumentationCatalogItem* item)
171
 
{
172
 
    DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
173
 
    if (!doxyItem)
174
 
        return false;
175
 
    
176
 
    QFileInfo fi(doxyItem->origUrl());
177
 
    config->setGroup("Index");
178
 
    if (fi.lastModified() > config->readDateTimeEntry(item->text(0), new QDateTime()))
179
 
    {
180
 
        kdDebug() << "need rebuild index for " << item->text(0) << endl;
181
 
        config->writeEntry(item->text(0), fi.lastModified());
182
 
        return true;
183
 
    }
184
 
    else
185
 
        return false;
186
 
}
187
 
 
188
 
void DocDoxygenPlugin::autoSetupPlugin()
189
 
{
190
 
    autoSetupDocs(KDELIBS_DOXYDIR, "en/kdelibs-apidocs", "The KDE API Reference (The KDE API Reference)");
191
 
    autoSetupDocs("", "en/kdevelop-apidocs", "The KDevelop Platform API Documentation (KDevelop)");
192
 
    
193
 
}
194
 
 
195
 
void DocDoxygenPlugin::autoSetupDocs(const QString &defaultDir, const QString &searchDir,
196
 
    const QString &name)
197
 
{
198
 
    QString doxyDocDir(defaultDir);
199
 
    doxyDocDir = URLUtil::envExpand(doxyDocDir);
200
 
    if (doxyDocDir.isEmpty())
201
 
    {
202
 
        QStringList apiDirs = DocDoxygenPluginFactory::instance()->dirs()->findDirs("html", searchDir);
203
 
        for (QStringList::const_iterator it = apiDirs.begin(); it != apiDirs.end(); ++it )
204
 
        {
205
 
            doxyDocDir = *it;
206
 
            QString indexFile = doxyDocDir + "index.html";
207
 
            if (QFile::exists(indexFile))
208
 
            {
209
 
                doxyDocDir = doxyDocDir + "/" + searchDir;
210
 
                break;
211
 
            }
212
 
            doxyDocDir = "";
213
 
        }
214
 
    }
215
 
    if (!doxyDocDir.isEmpty())
216
 
    {
217
 
        config->setGroup("Search Settings");
218
 
        config->writeEntry(name, true);
219
 
        config->setGroup("Index Settings");
220
 
        config->writeEntry(name, true);
221
 
        config->setGroup("Locations");
222
 
        config->writePathEntry(name, doxyDocDir + QString("/index.html"));
223
 
    }
224
 
}
225
 
 
226
 
void DocDoxygenPlugin::createIndex(IndexBox* index, DocumentationCatalogItem* item)
227
 
{
228
 
    QFileInfo fi(item->url().path());
229
 
    if (!fi.exists())
230
 
        return;
231
 
 
232
 
    DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
233
 
    if (!doxyItem)
234
 
        return;
235
 
    
236
 
    //doxygen documentation mode (if catalog points to a .tag)
237
 
    if (doxyItem->origUrl().endsWith("tag"))
238
 
    {
239
 
        QString htmlUrl;
240
 
        QFileInfo fi2(item->url().directory(false) + "index.html");
241
 
        if (fi2.exists())
242
 
            htmlUrl = fi2.dirPath(true) + "/";
243
 
        QFileInfo fi(item->url().directory(false) + "html/index.html");
244
 
        if (fi.exists())
245
 
            htmlUrl = fi.dirPath(true) + "/";
246
 
        
247
 
        createBookIndex(doxyItem->origUrl(), index, item, htmlUrl);
248
 
    }
249
 
    
250
 
    //KDE doxygen documentation mode (if catalog points to a index.html)
251
 
    QDir d;
252
 
    QValueStack<QString> dirStack;
253
 
    dirStack.push(fi.dirPath(true));
254
 
    do {
255
 
        d.setPath(dirStack.pop());
256
 
        if (!d.exists())
257
 
            continue;
258
 
 
259
 
        const QFileInfoList *dirEntries = d.entryInfoList();
260
 
        if (!dirEntries) continue;
261
 
        QPtrListIterator<QFileInfo> it(*dirEntries);
262
 
        for (; it.current(); ++it)
263
 
        {
264
 
            QString fileName = it.current()->fileName();
265
 
            if (fileName == "." || fileName == ".." || fileName == "common" || fileName == "html")
266
 
                continue;
267
 
            if (it.current()->isDir())
268
 
                dirStack.push(it.current()->absFilePath());
269
 
        }
270
 
 
271
 
        if (QFile::exists(d.absPath() + "/html/index.html"))
272
 
            createBookIndex(d.absPath() + "/" + d.dirName() + ".tag", index, item);
273
 
    } while (!dirStack.isEmpty());
274
 
}
275
 
 
276
 
void DocDoxygenPlugin::createTOC(DocumentationCatalogItem* item)
277
 
{
278
 
    QFileInfo fi(item->url().path());
279
 
    if (!fi.exists())
280
 
        return;
281
 
    
282
 
    DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
283
 
    if (!doxyItem)
284
 
        return;
285
 
    
286
 
    //doxygen documentation mode (if catalog points to a .tag)
287
 
    if (doxyItem->origUrl().endsWith("tag"))
288
 
    {
289
 
        QString htmlUrl;
290
 
        QFileInfo fi2(item->url().directory(false) + "index.html");
291
 
        if (fi2.exists())
292
 
            htmlUrl = fi2.dirPath(true) + "/";
293
 
        QFileInfo fi(item->url().directory(false) + "html/index.html");
294
 
        if (fi.exists())
295
 
            htmlUrl = fi.dirPath(true) + "/";
296
 
        if (!htmlUrl.isEmpty())
297
 
            createBookTOC(item, doxyItem->origUrl(), htmlUrl);
298
 
    }
299
 
    
300
 
    //KDE doxygen documentation mode (if catalog points to a index.html)
301
 
    QDir d;
302
 
    QValueStack<QString> dirStack;
303
 
    dirStack.push(fi.dirPath(true));
304
 
    do {
305
 
        d.setPath(dirStack.pop());
306
 
        if (!d.exists())
307
 
            continue;
308
 
 
309
 
        const QFileInfoList *dirEntries = d.entryInfoList();
310
 
        if (!dirEntries) continue;
311
 
        QPtrListIterator<QFileInfo> it(*dirEntries);
312
 
        for (; it.current(); ++it)
313
 
        {
314
 
            QString fileName = it.current()->fileName();
315
 
            if (fileName == "." || fileName == ".." || fileName == "common" || fileName == "html")
316
 
                continue;
317
 
            if (it.current()->isDir())
318
 
                dirStack.push(it.current()->absFilePath());
319
 
        }
320
 
 
321
 
        if (QFile::exists(d.absPath() + "/html/index.html"))
322
 
        {
323
 
            DocumentationItem *docItem = new DocumentationItem(DocumentationItem::Book, item, d.dirName());
324
 
            docItem->setURL(KURL(d.absPath() + "/html/index.html"));
325
 
            docItem->setExpandable(true);
326
 
            createBookTOC(docItem);
327
 
        }
328
 
    } while (!dirStack.isEmpty());
329
 
}
330
 
 
331
 
DocumentationCatalogItem *DocDoxygenPlugin::createCatalog(KListView *contents, const QString &title, const QString &url)
332
 
{
333
 
    kdDebug() << "DocDoxygenPlugin::createCatalog: url=" << url << endl;
334
 
    DocumentationCatalogItem *item = new DoxyDocumentationCatalogItem(url, this, contents, title);
335
 
    item->setURL(url);
336
 
    return item;
337
 
}
338
 
 
339
 
void DocDoxygenPlugin::createBookTOC(DocumentationItem *item, const QString &tagUrl, const QString &baseHtmlUrl)
340
 
{
341
 
    QString tagName;
342
 
    if (tagUrl.isEmpty())
343
 
        tagName = item->url().upURL().directory(false) + item->text(0) + ".tag";
344
 
    else
345
 
        tagName = tagUrl;
346
 
    
347
 
    QString baseUrl;
348
 
    if (baseHtmlUrl.isEmpty())
349
 
        baseUrl = item->url().directory(false);
350
 
    else
351
 
        baseUrl = baseHtmlUrl;
352
 
            
353
 
    //@todo list html files in the directory if tag was not found
354
 
    if (!QFile::exists(tagName))
355
 
        return;
356
 
 
357
 
    QStringList tagFileList;
358
 
    if (tagName.endsWith(".tag"))
359
 
        tagFileList = tagFiles(QFileInfo(tagName).dirPath() + "/");
360
 
    else
361
 
        tagFileList += tagName;
362
 
 
363
 
    QStringList::ConstIterator end = tagFileList.constEnd();
364
 
    for (QStringList::ConstIterator it = tagFileList.constBegin(); it != end; ++it)
365
 
    {
366
 
        QFile f(*it);
367
 
        if (!f.open(IO_ReadOnly))
368
 
        {
369
 
            kdDebug(9002) << "Could not open tag file: " << f.name() << endl;
370
 
            return;
371
 
        }
372
 
    
373
 
        QDomDocument dom;
374
 
        if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile")
375
 
        {
376
 
            kdDebug(9002) << "No valid tag file" << endl;
377
 
            return;
378
 
        }
379
 
        f.close();
380
 
    
381
 
        QDomElement docEl = dom.documentElement();
382
 
    
383
 
        QDomElement childEl = docEl.lastChild().toElement();
384
 
        while (!childEl.isNull())
385
 
        {
386
 
            if (childEl.tagName() == "compound" && childEl.attribute("kind") == "class")
387
 
            {
388
 
                QString classname = childEl.namedItem("name").firstChild().toText().data();
389
 
                QString filename = childEl.namedItem("filename").firstChild().toText().data();
390
 
    
391
 
                if (QFile::exists(baseUrl + filename))
392
 
                {
393
 
                    DocumentationItem *docItem = new DocumentationItem(DocumentationItem::Document,
394
 
                        item, classname);
395
 
                    docItem->setURL(KURL(baseUrl + filename));
396
 
                }
397
 
            }
398
 
            childEl = childEl.previousSibling().toElement();
399
 
        }
400
 
    }
401
 
}
402
 
 
403
 
void DocDoxygenPlugin::createBookIndex(const QString &tagfile, IndexBox* index, DocumentationCatalogItem* item, const QString &baseHtmlUrl)
404
 
{
405
 
    QString tagName = tagfile;
406
 
    kdDebug() << tagfile << endl;
407
 
    if (!QFile::exists(tagName))
408
 
        return;
409
 
    QString prefix = baseHtmlUrl.isEmpty() ? KURL(tagfile).directory(false) + "html/" : baseHtmlUrl;
410
 
    
411
 
    QStringList tagFileList = tagFiles(QFileInfo(tagName).dirPath() + "/");
412
 
 
413
 
    QStringList::ConstIterator end = tagFileList.constEnd();
414
 
    for (QStringList::ConstIterator it = tagFileList.constBegin(); it != end; ++it)
415
 
    {
416
 
        QFile f(*it);
417
 
        if (!f.open(IO_ReadOnly))
418
 
        {
419
 
            kdDebug(9002) << "Could not open tag file: " << f.name() << endl;
420
 
            return;
421
 
        }
422
 
 
423
 
        QDomDocument dom;
424
 
        if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile")
425
 
        {
426
 
            kdDebug(9002) << "No valid tag file" << endl;
427
 
            return;
428
 
        }
429
 
        f.close();
430
 
 
431
 
        QDomElement docEl = dom.documentElement();
432
 
        createIndexFromTag(dom, index, item, docEl, prefix);
433
 
  }
434
 
}
435
 
 
436
 
void DocDoxygenPlugin::createIndexFromTag(QDomDocument &dom, IndexBox *index,
437
 
    DocumentationCatalogItem *item, QDomElement &parentEl, const QString &prefix)
438
 
{
439
 
    QDomElement docEl = parentEl;
440
 
 
441
 
    QDomElement childEl = docEl.firstChild().toElement();
442
 
    while (!childEl.isNull())
443
 
    {
444
 
        if (childEl.tagName() == "compound" && 
445
 
            ((childEl.attribute("kind") == "class")
446
 
            || (childEl.attribute("kind") == "struct")
447
 
            || (childEl.attribute("kind") == "namespace") ))
448
 
        {
449
 
            QString classname = childEl.namedItem("name").firstChild().toText().data();
450
 
            QString filename = childEl.namedItem("filename").firstChild().toText().data();
451
 
 
452
 
            IndexItemProto *indexItem = new IndexItemProto(this, item, index, classname, 
453
 
            i18n("%1 Class Reference").arg(classname));
454
 
            indexItem->addURL(KURL(prefix + filename));
455
 
            
456
 
            createIndexFromTag(dom, index, item, childEl, prefix + filename);
457
 
        }
458
 
        else if ((childEl.tagName() == "member") && 
459
 
            ((childEl.attribute("kind") == "function")
460
 
            || (childEl.attribute("kind") == "slot")
461
 
            || (childEl.attribute("kind") == "signal") ))
462
 
        {
463
 
            QString classname = parentEl.namedItem("name").firstChild().toText().data();
464
 
            QString membername = childEl.namedItem("name").firstChild().toText().data();
465
 
            QString anchor = childEl.namedItem("anchor").firstChild().toText().data();
466
 
            QString arglist = childEl.namedItem("arglist").firstChild().toText().data();
467
 
            
468
 
            if (classname != membername)
469
 
            {
470
 
                IndexItemProto *indexItem = new IndexItemProto(this, item, index, membername,i18n("%1::%2%3 Member Reference").arg(classname).arg(membername).arg(arglist));
471
 
                indexItem->addURL(KURL(prefix + "#" + anchor));
472
 
            }
473
 
        }
474
 
        childEl = childEl.nextSibling().toElement();
475
 
    }
476
 
}
477
 
 
478
 
ProjectDocumentationPlugin *DocDoxygenPlugin::projectDocumentationPlugin(ProjectDocType type)
479
 
{
480
 
    if (type == APIDocs)
481
 
        return new ProjectDocumentationPlugin(this, type);
482
 
    return DocumentationPlugin::projectDocumentationPlugin(type);
483
 
}
484
 
 
485
 
QStringList DocDoxygenPlugin::tagFiles(const QString& path, int level)
486
 
{
487
 
  QStringList r;
488
 
  QDir dir(path);
489
 
  if (level > 10) return r;
490
 
  if (!dir.isReadable()) return r;
491
 
  if (!dir.exists()) return r;
492
 
 
493
 
  QStringList  dirList;
494
 
  QStringList  fileList;
495
 
  QStringList::Iterator it;
496
 
 
497
 
  dir.setFilter ( QDir::Dirs);
498
 
  dirList = dir.entryList();
499
 
 
500
 
  dirList.remove(".");
501
 
  dirList.remove("..");
502
 
 
503
 
  dir.setFilter(QDir::Files | QDir::Hidden | QDir::System);
504
 
  fileList = dir.entryList();
505
 
  QStringList::Iterator end = dirList.end();
506
 
  for ( it = dirList.begin(); it != end; ++it )
507
 
  {
508
 
    QString name = *it;
509
 
    if (QFileInfo( dir, *it ).isSymLink())
510
 
      continue;
511
 
    r += tagFiles(path + name + "/", level + 1 );
512
 
  }
513
 
 
514
 
  QStringList::Iterator fend = fileList.end();
515
 
  for ( it = fileList.begin(); it != fend; ++it )
516
 
  {
517
 
    QString name = *it;
518
 
    QFileInfo fi( dir, *it );
519
 
    if (fi.isSymLink() || !fi.isFile())
520
 
      continue;
521
 
 
522
 
    if (QDir::match(QString("*.tag"), name))
523
 
      r += (path+name);
524
 
  }
525
 
 
526
 
  return r;
527
 
}
528
 
 
529
 
#include "docdoxygenplugin.moc"