1
/***************************************************************************
2
* Copyright (C) 2004 by Alexander Dymo *
3
* cloudtemple@mksat.net *
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. *
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. *
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"
26
#include <qfileinfo.h>
29
#include <qvaluestack.h>
32
#include <kaboutdata.h>
35
#include <kstandarddirs.h>
38
#include <kdevgenericfactory.h>
39
#include <kdevplugininfo.h>
41
#include "../../../../config.h"
43
class DoxyDocumentationCatalogItem: public DocumentationCatalogItem
46
DoxyDocumentationCatalogItem(const QString &origUrl, DocumentationPlugin* plugin,
47
KListView *parent, const QString &name)
48
:DocumentationCatalogItem(plugin, parent, name), m_origUrl(origUrl)
51
DoxyDocumentationCatalogItem(const QString &origUrl, DocumentationPlugin* plugin,
52
DocumentationItem *parent, const QString &name)
53
:DocumentationCatalogItem(plugin, parent, name), m_origUrl(origUrl)
56
QString origUrl() const { return m_origUrl; }
63
static const KDevPluginInfo data("docdoxygenplugin");
64
typedef KDevGenericFactory<DocDoxygenPlugin> DocDoxygenPluginFactory;
65
K_EXPORT_COMPONENT_FACTORY( libdocdoxygenplugin, DocDoxygenPluginFactory(data) )
67
DocDoxygenPlugin::DocDoxygenPlugin(QObject* parent, const char* name, const QStringList)
68
:DocumentationPlugin(DocDoxygenPluginFactory::instance()->config(), parent, name)
70
setCapabilities(Index | FullTextSearch | ProjectDocumentation | CustomDocumentationTitles );
74
DocDoxygenPlugin::~DocDoxygenPlugin()
78
QPair<KFile::Mode, QString> DocDoxygenPlugin::catalogLocatorProps()
80
return QPair<KFile::Mode, QString>(KFile::File, "index.html *.tag");
83
QString DocDoxygenPlugin::catalogTitle(const QString& url)
89
if (fi.extension(false) == "html")
92
if (!f.open(IO_ReadOnly))
96
QString contents = ts.read();
97
QRegExp re(".*<title>(.*)</title>.*");
98
re.setCaseSensitive(false);
102
else if (fi.extension(false) == "tag")
105
QFile f1(fi.dirPath(true) + "/html/index.html");
106
if (f1.open(IO_ReadOnly))
108
QFile f2(fi.dirPath(true) + "/index.html");
109
if (f2.open(IO_ReadOnly))
114
QString contents = ts.read();
115
QRegExp re(".*<title>(.*)</title>.*");
116
re.setCaseSensitive(false);
121
return QString::null;
124
QString DocDoxygenPlugin::pluginName() const
126
return i18n("Doxygen Documentation Collection");
129
QStringList DocDoxygenPlugin::fullTextSearchLocations()
133
QMap<QString, QString> entryMap = config->entryMap("Locations");
135
for (QMap<QString, QString>::const_iterator it = entryMap.begin();
136
it != entryMap.end(); ++it)
138
config->setGroup("Search Settings");
139
if (config->readBoolEntry(it.key(), false))
141
config->setGroup("Locations");
142
QFileInfo fi(config->readPathEntry(it.key()));
143
locs << fi.dirPath(true);
150
void DocDoxygenPlugin::setCatalogURL(DocumentationCatalogItem* item)
152
if (item->url().url().endsWith("tag"))
154
QFileInfo fi(item->url().directory(false) + "html/index.html");
157
item->setURL(KURL::fromPathOrURL(fi.absFilePath()));
160
QFileInfo fi2(item->url().directory(false) + "index.html");
163
item->setURL(KURL::fromPathOrURL(fi2.absFilePath()));
166
item->setURL(KURL());
170
bool DocDoxygenPlugin::needRefreshIndex(DocumentationCatalogItem* item)
172
DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
176
QFileInfo fi(doxyItem->origUrl());
177
config->setGroup("Index");
178
if (fi.lastModified() > config->readDateTimeEntry(item->text(0), new QDateTime()))
180
kdDebug() << "need rebuild index for " << item->text(0) << endl;
181
config->writeEntry(item->text(0), fi.lastModified());
188
void DocDoxygenPlugin::autoSetupPlugin()
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)");
195
void DocDoxygenPlugin::autoSetupDocs(const QString &defaultDir, const QString &searchDir,
198
QString doxyDocDir(defaultDir);
199
doxyDocDir = URLUtil::envExpand(doxyDocDir);
200
if (doxyDocDir.isEmpty())
202
QStringList apiDirs = DocDoxygenPluginFactory::instance()->dirs()->findDirs("html", searchDir);
203
for (QStringList::const_iterator it = apiDirs.begin(); it != apiDirs.end(); ++it )
206
QString indexFile = doxyDocDir + "index.html";
207
if (QFile::exists(indexFile))
209
doxyDocDir = doxyDocDir + "/" + searchDir;
215
if (!doxyDocDir.isEmpty())
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"));
226
void DocDoxygenPlugin::createIndex(IndexBox* index, DocumentationCatalogItem* item)
228
QFileInfo fi(item->url().path());
232
DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
236
//doxygen documentation mode (if catalog points to a .tag)
237
if (doxyItem->origUrl().endsWith("tag"))
240
QFileInfo fi2(item->url().directory(false) + "index.html");
242
htmlUrl = fi2.dirPath(true) + "/";
243
QFileInfo fi(item->url().directory(false) + "html/index.html");
245
htmlUrl = fi.dirPath(true) + "/";
247
createBookIndex(doxyItem->origUrl(), index, item, htmlUrl);
250
//KDE doxygen documentation mode (if catalog points to a index.html)
252
QValueStack<QString> dirStack;
253
dirStack.push(fi.dirPath(true));
255
d.setPath(dirStack.pop());
259
const QFileInfoList *dirEntries = d.entryInfoList();
260
if (!dirEntries) continue;
261
QPtrListIterator<QFileInfo> it(*dirEntries);
262
for (; it.current(); ++it)
264
QString fileName = it.current()->fileName();
265
if (fileName == "." || fileName == ".." || fileName == "common" || fileName == "html")
267
if (it.current()->isDir())
268
dirStack.push(it.current()->absFilePath());
271
if (QFile::exists(d.absPath() + "/html/index.html"))
272
createBookIndex(d.absPath() + "/" + d.dirName() + ".tag", index, item);
273
} while (!dirStack.isEmpty());
276
void DocDoxygenPlugin::createTOC(DocumentationCatalogItem* item)
278
QFileInfo fi(item->url().path());
282
DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
286
//doxygen documentation mode (if catalog points to a .tag)
287
if (doxyItem->origUrl().endsWith("tag"))
290
QFileInfo fi2(item->url().directory(false) + "index.html");
292
htmlUrl = fi2.dirPath(true) + "/";
293
QFileInfo fi(item->url().directory(false) + "html/index.html");
295
htmlUrl = fi.dirPath(true) + "/";
296
if (!htmlUrl.isEmpty())
297
createBookTOC(item, doxyItem->origUrl(), htmlUrl);
300
//KDE doxygen documentation mode (if catalog points to a index.html)
302
QValueStack<QString> dirStack;
303
dirStack.push(fi.dirPath(true));
305
d.setPath(dirStack.pop());
309
const QFileInfoList *dirEntries = d.entryInfoList();
310
if (!dirEntries) continue;
311
QPtrListIterator<QFileInfo> it(*dirEntries);
312
for (; it.current(); ++it)
314
QString fileName = it.current()->fileName();
315
if (fileName == "." || fileName == ".." || fileName == "common" || fileName == "html")
317
if (it.current()->isDir())
318
dirStack.push(it.current()->absFilePath());
321
if (QFile::exists(d.absPath() + "/html/index.html"))
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);
328
} while (!dirStack.isEmpty());
331
DocumentationCatalogItem *DocDoxygenPlugin::createCatalog(KListView *contents, const QString &title, const QString &url)
333
kdDebug() << "DocDoxygenPlugin::createCatalog: url=" << url << endl;
334
DocumentationCatalogItem *item = new DoxyDocumentationCatalogItem(url, this, contents, title);
339
void DocDoxygenPlugin::createBookTOC(DocumentationItem *item, const QString &tagUrl, const QString &baseHtmlUrl)
342
if (tagUrl.isEmpty())
343
tagName = item->url().upURL().directory(false) + item->text(0) + ".tag";
348
if (baseHtmlUrl.isEmpty())
349
baseUrl = item->url().directory(false);
351
baseUrl = baseHtmlUrl;
353
//@todo list html files in the directory if tag was not found
354
if (!QFile::exists(tagName))
357
QStringList tagFileList;
358
if (tagName.endsWith(".tag"))
359
tagFileList = tagFiles(QFileInfo(tagName).dirPath() + "/");
361
tagFileList += tagName;
363
QStringList::ConstIterator end = tagFileList.constEnd();
364
for (QStringList::ConstIterator it = tagFileList.constBegin(); it != end; ++it)
367
if (!f.open(IO_ReadOnly))
369
kdDebug(9002) << "Could not open tag file: " << f.name() << endl;
374
if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile")
376
kdDebug(9002) << "No valid tag file" << endl;
381
QDomElement docEl = dom.documentElement();
383
QDomElement childEl = docEl.lastChild().toElement();
384
while (!childEl.isNull())
386
if (childEl.tagName() == "compound" && childEl.attribute("kind") == "class")
388
QString classname = childEl.namedItem("name").firstChild().toText().data();
389
QString filename = childEl.namedItem("filename").firstChild().toText().data();
391
if (QFile::exists(baseUrl + filename))
393
DocumentationItem *docItem = new DocumentationItem(DocumentationItem::Document,
395
docItem->setURL(KURL(baseUrl + filename));
398
childEl = childEl.previousSibling().toElement();
403
void DocDoxygenPlugin::createBookIndex(const QString &tagfile, IndexBox* index, DocumentationCatalogItem* item, const QString &baseHtmlUrl)
405
QString tagName = tagfile;
406
kdDebug() << tagfile << endl;
407
if (!QFile::exists(tagName))
409
QString prefix = baseHtmlUrl.isEmpty() ? KURL(tagfile).directory(false) + "html/" : baseHtmlUrl;
411
QStringList tagFileList = tagFiles(QFileInfo(tagName).dirPath() + "/");
413
QStringList::ConstIterator end = tagFileList.constEnd();
414
for (QStringList::ConstIterator it = tagFileList.constBegin(); it != end; ++it)
417
if (!f.open(IO_ReadOnly))
419
kdDebug(9002) << "Could not open tag file: " << f.name() << endl;
424
if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile")
426
kdDebug(9002) << "No valid tag file" << endl;
431
QDomElement docEl = dom.documentElement();
432
createIndexFromTag(dom, index, item, docEl, prefix);
436
void DocDoxygenPlugin::createIndexFromTag(QDomDocument &dom, IndexBox *index,
437
DocumentationCatalogItem *item, QDomElement &parentEl, const QString &prefix)
439
QDomElement docEl = parentEl;
441
QDomElement childEl = docEl.firstChild().toElement();
442
while (!childEl.isNull())
444
if (childEl.tagName() == "compound" &&
445
((childEl.attribute("kind") == "class")
446
|| (childEl.attribute("kind") == "struct")
447
|| (childEl.attribute("kind") == "namespace") ))
449
QString classname = childEl.namedItem("name").firstChild().toText().data();
450
QString filename = childEl.namedItem("filename").firstChild().toText().data();
452
IndexItemProto *indexItem = new IndexItemProto(this, item, index, classname,
453
i18n("%1 Class Reference").arg(classname));
454
indexItem->addURL(KURL(prefix + filename));
456
createIndexFromTag(dom, index, item, childEl, prefix + filename);
458
else if ((childEl.tagName() == "member") &&
459
((childEl.attribute("kind") == "function")
460
|| (childEl.attribute("kind") == "slot")
461
|| (childEl.attribute("kind") == "signal") ))
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();
468
if (classname != membername)
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));
474
childEl = childEl.nextSibling().toElement();
478
ProjectDocumentationPlugin *DocDoxygenPlugin::projectDocumentationPlugin(ProjectDocType type)
481
return new ProjectDocumentationPlugin(this, type);
482
return DocumentationPlugin::projectDocumentationPlugin(type);
485
QStringList DocDoxygenPlugin::tagFiles(const QString& path, int level)
489
if (level > 10) return r;
490
if (!dir.isReadable()) return r;
491
if (!dir.exists()) return r;
494
QStringList fileList;
495
QStringList::Iterator it;
497
dir.setFilter ( QDir::Dirs);
498
dirList = dir.entryList();
501
dirList.remove("..");
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 )
509
if (QFileInfo( dir, *it ).isSymLink())
511
r += tagFiles(path + name + "/", level + 1 );
514
QStringList::Iterator fend = fileList.end();
515
for ( it = fileList.begin(); it != fend; ++it )
518
QFileInfo fi( dir, *it );
519
if (fi.isSymLink() || !fi.isFile())
522
if (QDir::match(QString("*.tag"), name))
529
#include "docdoxygenplugin.moc"