KDevelop API Documentation

docdoxygenplugin.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2004 by Alexander Dymo                                  *
00003  *   cloudtemple@mksat.net                                                 *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include "docdoxygenplugin.h"
00021 
00022 #include <unistd.h>
00023 
00024 #include <qdom.h>
00025 #include <qfile.h>
00026 #include <qfileinfo.h>
00027 #include <qdialog.h>
00028 #include <qregexp.h>
00029 
00030 #include <kurl.h>
00031 #include <kaboutdata.h>
00032 #include <kconfig.h>
00033 #include <klocale.h>
00034 #include <kstandarddirs.h>
00035 
00036 #include <urlutil.h>
00037 #include <kdevgenericfactory.h>
00038 
00039 #include "../../../../config.h"
00040 
00041 class DoxyDocumentationCatalogItem: public DocumentationCatalogItem
00042 {
00043 public:
00044     DoxyDocumentationCatalogItem(const QString &origUrl, DocumentationPlugin* plugin,
00045         KListView *parent, const QString &name)
00046         :DocumentationCatalogItem(plugin, parent, name), m_origUrl(origUrl)
00047     {
00048     }
00049     DoxyDocumentationCatalogItem(const QString &origUrl, DocumentationPlugin* plugin,
00050         DocumentationItem *parent, const QString &name)
00051         :DocumentationCatalogItem(plugin, parent, name), m_origUrl(origUrl)
00052     {
00053     }
00054     QString origUrl() const { return m_origUrl; }
00055     
00056 private:
00057     QString m_origUrl;
00058 };
00059 
00060 
00061 static const KAboutData data("docdoxygenplugin", I18N_NOOP("Doxygen documentation plugin"), "1.0");
00062 typedef KDevGenericFactory<DocDoxygenPlugin> DocDoxygenPluginFactory;
00063 K_EXPORT_COMPONENT_FACTORY( libdocdoxygenplugin, DocDoxygenPluginFactory(&data) )
00064 
00065 DocDoxygenPlugin::DocDoxygenPlugin(QObject* parent, const char* name, const QStringList)
00066     :DocumentationPlugin(DocDoxygenPluginFactory::instance()->config(), parent, name)
00067 {
00068     setCapabilities(Index | FullTextSearch | ProjectDocumentation);
00069     autoSetup();
00070 }
00071 
00072 DocDoxygenPlugin::~DocDoxygenPlugin()
00073 {
00074 }
00075 
00076 QPair<KFile::Mode, QString> DocDoxygenPlugin::catalogLocatorProps()
00077 {
00078     return QPair<KFile::Mode, QString>(KFile::File, "index.html *.tag");
00079 }
00080 
00081 QString DocDoxygenPlugin::catalogTitle(const QString& url)
00082 {
00083     QFileInfo fi(url);
00084     if (!fi.exists())
00085         return QString::null;
00086     
00087     if (fi.extension(false) == "html")
00088     {
00089         QFile f(url);
00090         if (!f.open(IO_ReadOnly))
00091             return QString::null;
00092         
00093         QTextStream ts(&f);
00094         QString contents = ts.read();
00095         QRegExp re(".*<title>(.*)</title>.*");
00096         re.setCaseSensitive(false);
00097         re.search(contents);
00098         return re.cap(1);   
00099     }
00100     else if (fi.extension(false) == "tag")
00101     {
00102         QFile *f = 0;
00103         QFile f1(fi.dirPath(true) + "/html/index.html");
00104         if (f1.open(IO_ReadOnly))
00105             f = &f1;
00106         QFile f2(fi.dirPath(true) + "/index.html");
00107         if (f2.open(IO_ReadOnly))
00108             f = &f2;
00109         if (f != 0)
00110         {
00111             QTextStream ts(f);
00112             QString contents = ts.read();
00113             QRegExp re(".*<title>(.*)</title>.*");
00114             re.setCaseSensitive(false);
00115             re.search(contents);
00116             return re.cap(1);   
00117         }
00118     }
00119     return QString::null;
00120 }
00121 
00122 QString DocDoxygenPlugin::pluginName() const
00123 {
00124     return i18n("Doxygen Documentation Collection");
00125 }
00126 
00127 QStringList DocDoxygenPlugin::fullTextSearchLocations()
00128 {
00129     QStringList locs;
00130         
00131     QMap<QString, QString> entryMap = config->entryMap("Locations");
00132 
00133     for (QMap<QString, QString>::const_iterator it = entryMap.begin();
00134         it != entryMap.end(); ++it)
00135     {
00136         config->setGroup("Search Settings");
00137         if (config->readBoolEntry(it.key(), false))
00138         {
00139             config->setGroup("Locations");
00140             QFileInfo fi(config->readPathEntry(it.key()));
00141             locs << fi.dirPath(true);
00142         }
00143     }
00144     
00145     return locs;
00146 }
00147 
00148 void DocDoxygenPlugin::setCatalogURL(DocumentationCatalogItem* item)
00149 {
00150     if (item->url().url().endsWith("tag"))
00151     {
00152         QFileInfo fi(item->url().directory(false) + "html/index.html");
00153         if (fi.exists())
00154         {
00155             item->setURL(KURL::fromPathOrURL(fi.absFilePath()));
00156             return;
00157         }
00158         QFileInfo fi2(item->url().directory(false) + "index.html");
00159         if (fi2.exists())
00160         {
00161             item->setURL(KURL::fromPathOrURL(fi2.absFilePath()));
00162             return;
00163         }
00164         item->setURL(KURL());
00165     }
00166 }
00167 
00168 bool DocDoxygenPlugin::needRefreshIndex(DocumentationCatalogItem* item)
00169 {
00170     DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
00171     if (!doxyItem)
00172         return false;
00173     
00174     QFileInfo fi(doxyItem->origUrl());
00175     config->setGroup("Index");
00176     if (fi.lastModified() > config->readDateTimeEntry(item->text(0), new QDateTime()))
00177     {
00178         kdDebug() << "need rebuild index for " << item->text(0) << endl;
00179         config->writeEntry(item->text(0), fi.lastModified());
00180         return true;
00181     }
00182     else
00183         return false;
00184 }
00185 
00186 void DocDoxygenPlugin::autoSetupPlugin()
00187 {
00188     QString doxyDocDir(KDELIBS_DOXYDIR);
00189     doxyDocDir = URLUtil::envExpand(doxyDocDir);
00190     if (doxyDocDir.isEmpty())
00191     {
00192         QStringList apiDirs = DocDoxygenPluginFactory::instance()->dirs()->findDirs("html", "kdelibs-apidocs");
00193         if (apiDirs.count() > 0)
00194             doxyDocDir = apiDirs.first();
00195     }
00196     if (!doxyDocDir.isEmpty())
00197     {
00198         config->setGroup("Search Settings");
00199         config->writeEntry("The KDE API Reference (The KDE API Reference)", true);
00200         config->setGroup("Index Settings");
00201         config->writeEntry("The KDE API Reference (The KDE API Reference)", true);
00202         config->setGroup("Locations");
00203         config->writePathEntry("The KDE API Reference (The KDE API Reference)", doxyDocDir + QString("/index.html"));
00204     }
00205 }
00206 
00207 void DocDoxygenPlugin::createIndex(IndexBox* index, DocumentationCatalogItem* item)
00208 {
00209     QFileInfo fi(item->url().path());
00210     if (!fi.exists())
00211         return;
00212 
00213     DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
00214     if (!doxyItem)
00215         return;
00216     
00217     //doxygen documentation mode (if catalog points to a .tag)
00218     if (doxyItem->origUrl().endsWith("tag"))
00219     {
00220         QString htmlUrl;
00221         QFileInfo fi2(item->url().directory(false) + "index.html");
00222         if (fi2.exists())
00223             htmlUrl = fi2.dirPath(true) + "/";
00224         QFileInfo fi(item->url().directory(false) + "html/index.html");
00225         if (fi.exists())
00226             htmlUrl = fi.dirPath(true) + "/";
00227         
00228         createBookIndex(doxyItem->origUrl(), index, item, htmlUrl);
00229     }
00230     
00231     //KDE doxygen documentation mode (if catalog points to a index.html)
00232     QDir d(fi.dirPath(true));
00233     QStringList fileList = d.entryList("*", QDir::Dirs);
00234     
00235     QStringList::ConstIterator it;
00236     for (it = fileList.begin(); it != fileList.end(); ++it)
00237     {
00238         QString dirName = (*it);
00239         if (dirName == "." || dirName == ".." || dirName == "common")
00240             continue;
00241         if (QFile::exists(d.absFilePath(*it) + "/html/index.html"))
00242         {
00243             createBookIndex(d.absFilePath(*it) + "/" + *it + ".tag", index, item);
00244         }
00245     }
00246 }
00247 
00248 void DocDoxygenPlugin::createTOC(DocumentationCatalogItem* item)
00249 {
00250     QFileInfo fi(item->url().path());
00251     if (!fi.exists())
00252         return;
00253     
00254     DoxyDocumentationCatalogItem *doxyItem = dynamic_cast<DoxyDocumentationCatalogItem*>(item);
00255     if (!doxyItem)
00256         return;
00257     
00258     //doxygen documentation mode (if catalog points to a .tag)
00259     if (doxyItem->origUrl().endsWith("tag"))
00260     {
00261         QString htmlUrl;
00262         QFileInfo fi2(item->url().directory(false) + "index.html");
00263         if (fi2.exists())
00264             htmlUrl = fi2.dirPath(true) + "/";
00265         QFileInfo fi(item->url().directory(false) + "html/index.html");
00266         if (fi.exists())
00267             htmlUrl = fi.dirPath(true) + "/";
00268         if (!htmlUrl.isEmpty())
00269             createBookTOC(item, doxyItem->origUrl(), htmlUrl);
00270     }
00271     
00272     //KDE doxygen documentation mode (if catalog points to a index.html)
00273     QDir d(fi.dirPath(true));
00274     QStringList fileList = d.entryList("*", QDir::Dirs, QDir::Name | QDir::Reversed);
00275     QStringList::ConstIterator it;
00276     for (it = fileList.begin(); it != fileList.end(); ++it)
00277     {
00278         QString dirName = (*it);
00279         if (dirName == "." || dirName == ".." || dirName == "common")
00280             continue;
00281         if (QFile::exists(d.absFilePath(*it) + "/html/index.html"))
00282         {
00283             DocumentationItem *docItem = new DocumentationItem(DocumentationItem::Book, item, *it);
00284             docItem->setURL(KURL(d.absFilePath(*it) + "/html/index.html"));
00285             docItem->setExpandable(true);
00286             createBookTOC(docItem);
00287         }
00288     }
00289 }
00290 
00291 DocumentationCatalogItem *DocDoxygenPlugin::createCatalog(KListView *contents, const QString &title, const QString &url)
00292 {
00293     kdDebug() << "DocDoxygenPlugin::createCatalog: url=" << url << endl;
00294     DocumentationCatalogItem *item = new DoxyDocumentationCatalogItem(url, this, contents, title);
00295     item->setURL(url);
00296     return item;
00297 }
00298 
00299 void DocDoxygenPlugin::createBookTOC(DocumentationItem *item, const QString &tagUrl, const QString &baseHtmlUrl)
00300 {
00301     QString tagName;
00302     if (tagUrl.isEmpty())
00303         tagName = item->url().upURL().directory(false) + item->text(0) + ".tag";
00304     else
00305         tagName = tagUrl;
00306     
00307     QString baseUrl;
00308     if (baseHtmlUrl.isEmpty())
00309         baseUrl = item->url().directory(false);
00310     else
00311         baseUrl = baseHtmlUrl;
00312             
00313     //@todo list html files in the directory if tag was not found
00314     if (!QFile::exists(tagName))
00315         return;
00316     
00317     QFile f(tagName);
00318     if (!f.open(IO_ReadOnly))
00319     {
00320         kdDebug(9002) << "Could not open tag file: " << f.name() << endl;
00321         return;
00322     }
00323 
00324     QDomDocument dom;
00325     if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile")
00326     {
00327         kdDebug(9002) << "No valid tag file" << endl;
00328         return;
00329     }
00330     f.close();
00331 
00332     QDomElement docEl = dom.documentElement();
00333 
00334     QDomElement childEl = docEl.lastChild().toElement();
00335     while (!childEl.isNull())
00336     {
00337         if (childEl.tagName() == "compound" && childEl.attribute("kind") == "class")
00338         {
00339             QString classname = childEl.namedItem("name").firstChild().toText().data();
00340             QString filename = childEl.namedItem("filename").firstChild().toText().data();
00341 
00342             if (QFile::exists(baseUrl + filename))
00343             {
00344                 DocumentationItem *docItem = new DocumentationItem(DocumentationItem::Document,
00345                     item, classname);
00346                 docItem->setURL(KURL(baseUrl + filename));
00347             }
00348         }
00349         childEl = childEl.previousSibling().toElement();
00350     }
00351 }
00352 
00353 void DocDoxygenPlugin::createBookIndex(const QString &tagfile, IndexBox* index, DocumentationCatalogItem* item, const QString &baseHtmlUrl)
00354 {
00355     QString tagName = tagfile;
00356     kdDebug() << tagfile << endl;
00357     if (!QFile::exists(tagName))
00358         return;
00359     
00360     QFile f(tagName);
00361     if (!f.open(IO_ReadOnly))
00362     {
00363         kdDebug(9002) << "Could not open tag file: " << f.name() << endl;
00364         return;
00365     }
00366 
00367     QDomDocument dom;
00368     if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile")
00369     {
00370         kdDebug(9002) << "No valid tag file" << endl;
00371         return;
00372     }
00373     f.close();
00374 
00375     QDomElement docEl = dom.documentElement();
00376     QString prefix = baseHtmlUrl.isEmpty() ? KURL(tagfile).directory(false) + "html/" : baseHtmlUrl;
00377     createIndexFromTag(dom, index, item, docEl, prefix);
00378 }
00379 
00380 void DocDoxygenPlugin::createIndexFromTag(QDomDocument &dom, IndexBox *index,
00381     DocumentationCatalogItem *item, QDomElement &parentEl, const QString &prefix)
00382 {
00383     QDomElement docEl = parentEl;
00384 
00385     QDomElement childEl = docEl.firstChild().toElement();
00386     while (!childEl.isNull())
00387     {
00388         if (childEl.tagName() == "compound" && 
00389             ((childEl.attribute("kind") == "class")
00390             || (childEl.attribute("kind") == "struct")
00391             || (childEl.attribute("kind") == "namespace") ))
00392         {
00393             QString classname = childEl.namedItem("name").firstChild().toText().data();
00394             QString filename = childEl.namedItem("filename").firstChild().toText().data();
00395 
00396             IndexItemProto *indexItem = new IndexItemProto(this, item, index, classname, 
00397             i18n("%1 Class Reference").arg(classname));
00398             indexItem->addURL(KURL(prefix + filename));
00399             
00400             createIndexFromTag(dom, index, item, childEl, prefix + filename);
00401         }
00402         else if ((childEl.tagName() == "member") && 
00403             ((childEl.attribute("kind") == "function")
00404             || (childEl.attribute("kind") == "slot")
00405             || (childEl.attribute("kind") == "signal") ))
00406         {
00407             QString classname = parentEl.namedItem("name").firstChild().toText().data();
00408             QString membername = childEl.namedItem("name").firstChild().toText().data();
00409             QString anchor = childEl.namedItem("anchor").firstChild().toText().data();
00410             QString arglist = childEl.namedItem("arglist").firstChild().toText().data();
00411             
00412             if (classname != membername)
00413             {
00414                 IndexItemProto *indexItem = new IndexItemProto(this, item, index, membername,i18n("%1::%2%3 Member Reference").arg(classname).arg(membername).arg(arglist));
00415                 indexItem->addURL(KURL(prefix + "#" + anchor));
00416             }
00417         }
00418         childEl = childEl.nextSibling().toElement();
00419     }
00420 }
00421 
00422 ProjectDocumentationPlugin *DocDoxygenPlugin::projectDocumentationPlugin(ProjectDocType type)
00423 {
00424     if (type == APIDocs)
00425         return new ProjectDocumentationPlugin(this, type);
00426     return DocumentationPlugin::projectDocumentationPlugin(type);
00427 }
00428 
00429 #include "docdoxygenplugin.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 00:03:56 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003