/*************************************************************************** * Copyright (C) 2004 by Alexander Dymo * * cloudtemple@mksat.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "docdoxygenplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../../../config.h" class DoxyDocumentationCatalogItem: public DocumentationCatalogItem { public: DoxyDocumentationCatalogItem(const TQString &origUrl, DocumentationPlugin* plugin, TDEListView *parent, TDEListViewItem *after, const TQString &name) :DocumentationCatalogItem(plugin, parent, after, name), m_origUrl(origUrl) { } DoxyDocumentationCatalogItem(const TQString &origUrl, DocumentationPlugin* plugin, DocumentationItem *parent, const TQString &name) :DocumentationCatalogItem(plugin, parent, name), m_origUrl(origUrl) { } TQString origUrl() const { return m_origUrl; } private: TQString m_origUrl; }; static const KDevPluginInfo data("docdoxygenplugin"); typedef KDevGenericFactory DocDoxygenPluginFactory; K_EXPORT_COMPONENT_FACTORY( libdocdoxygenplugin, DocDoxygenPluginFactory(data) ) DocDoxygenPlugin::DocDoxygenPlugin(TQObject* parent, const char* name, const TQStringList) :DocumentationPlugin(DocDoxygenPluginFactory::instance()->config(), parent, name) { setCapabilities(Index | FullTextSearch | ProjectDocumentation); autoSetup(); } DocDoxygenPlugin::~DocDoxygenPlugin() { } TQPair DocDoxygenPlugin::catalogLocatorProps() { return TQPair(KFile::File, "index.html *.tag"); } TQString DocDoxygenPlugin::catalogTitle(const TQString& url) { TQFileInfo fi(url); if (!fi.exists()) return TQString(); if (fi.extension(false) == "html") { TQFile f(url); if (!f.open(IO_ReadOnly)) return TQString(); TQTextStream ts(&f); TQString contents = ts.read(); TQRegExp re(".*(.*).*"); re.setCaseSensitive(false); re.search(contents); return re.cap(1); } else if (fi.extension(false) == "tag") { TQFile *f = 0; TQFile f1(fi.dirPath(true) + "/html/index.html"); if (f1.open(IO_ReadOnly)) f = &f1; TQFile f2(fi.dirPath(true) + "/index.html"); if (f2.open(IO_ReadOnly)) f = &f2; if (f != 0) { TQTextStream ts(f); TQString contents = ts.read(); TQRegExp re(".*(.*).*"); re.setCaseSensitive(false); re.search(contents); return re.cap(1); } } return TQString(); } TQString DocDoxygenPlugin::pluginName() const { return i18n("Doxygen Documentation Collection"); } TQStringList DocDoxygenPlugin::fullTextSearchLocations() { TQStringList locs; TQMap entryMap = config->entryMap("Locations"); for (TQMap::const_iterator it = entryMap.begin(); it != entryMap.end(); ++it) { config->setGroup("Search Settings"); if (config->readBoolEntry(it.key(), false)) { config->setGroup("Locations"); TQFileInfo fi(config->readPathEntry(it.key())); locs << fi.dirPath(true); } } return locs; } void DocDoxygenPlugin::setCatalogURL(DocumentationCatalogItem* item) { if (item->url().url().endsWith("tag")) { TQFileInfo fi(item->url().directory(false) + "html/index.html"); if (fi.exists()) { item->setURL(KURL::fromPathOrURL(fi.absFilePath())); return; } TQFileInfo fi2(item->url().directory(false) + "index.html"); if (fi2.exists()) { item->setURL(KURL::fromPathOrURL(fi2.absFilePath())); return; } item->setURL(KURL()); } } bool DocDoxygenPlugin::needRefreshIndex(DocumentationCatalogItem* item) { DoxyDocumentationCatalogItem *doxyItem = dynamic_cast(item); if (!doxyItem) return false; TQFileInfo fi(doxyItem->origUrl()); config->setGroup("Index"); if (fi.lastModified() > config->readDateTimeEntry(item->text(0), new TQDateTime())) { kdDebug() << "need rebuild index for " << item->text(0) << endl; config->writeEntry(item->text(0), fi.lastModified()); return true; } else return false; } void DocDoxygenPlugin::autoSetupPlugin() { // Clear groups, to allow for re-autosetup calls config->deleteGroup("Index"); config->deleteGroup("Index Settings"); config->deleteGroup("Locations"); config->deleteGroup("Search Settings"); config->deleteGroup("TOC Settings"); config->sync(); autoSetupDocs(TDELIBS_DOXYDIR, "en/tdelibs-apidocs", "The TDE API Reference"); autoSetupDocs("", "en/tdevelop-apidocs", "The TDevelop Platform API Documentation"); config->sync(); } void DocDoxygenPlugin::autoSetupDocs(const TQString &defaultDir, const TQString &searchDir, const TQString &name) { TQString doxyDocDir(defaultDir); doxyDocDir = URLUtil::envExpand(doxyDocDir); if (doxyDocDir.isEmpty()) { TQStringList apiDirs = DocDoxygenPluginFactory::instance()->dirs()->findDirs("html", searchDir); for (TQStringList::const_iterator it = apiDirs.begin(); it != apiDirs.end(); ++it ) { doxyDocDir = *it; TQString indexFile = doxyDocDir + "index.html"; if (TQFile::exists(indexFile)) { doxyDocDir = doxyDocDir + "/" + searchDir; break; } doxyDocDir = ""; } } if (!doxyDocDir.isEmpty()) { config->setGroup("Search Settings"); config->writeEntry(name, true); config->setGroup("Index Settings"); config->writeEntry(name, true); config->setGroup("Locations"); config->writePathEntry(name, doxyDocDir + TQString("/index.html")); } } void DocDoxygenPlugin::createIndex(IndexBox* index, DocumentationCatalogItem* item) { TQFileInfo fi(item->url().path()); if (!fi.exists()) return; DoxyDocumentationCatalogItem *doxyItem = dynamic_cast(item); if (!doxyItem) return; //doxygen documentation mode (if catalog points to a .tag) if (doxyItem->origUrl().endsWith("tag")) { TQString htmlUrl; TQFileInfo fi2(item->url().directory(false) + "index.html"); if (fi2.exists()) htmlUrl = fi2.dirPath(true) + "/"; TQFileInfo fi(item->url().directory(false) + "html/index.html"); if (fi.exists()) htmlUrl = fi.dirPath(true) + "/"; createBookIndex(doxyItem->origUrl(), index, item, htmlUrl); } //KDE doxygen documentation mode (if catalog points to a index.html) TQDir d; TQValueStack dirStack; dirStack.push(fi.dirPath(true)); do { d.setPath(dirStack.pop()); if (!d.exists()) continue; const TQFileInfoList *dirEntries = d.entryInfoList(); if (!dirEntries) continue; TQPtrListIterator it(*dirEntries); for (; it.current(); ++it) { TQString fileName = it.current()->fileName(); if (fileName == "." || fileName == ".." || fileName == "common" || fileName == "html") continue; if (it.current()->isDir()) dirStack.push(it.current()->absFilePath()); } if (TQFile::exists(d.absPath() + "/html/index.html")) createBookIndex(d.absPath() + "/" + d.dirName() + ".tag", index, item); } while (!dirStack.isEmpty()); } void DocDoxygenPlugin::createTOC(DocumentationCatalogItem* item) { TQFileInfo fi(item->url().path()); if (!fi.exists()) return; DoxyDocumentationCatalogItem *doxyItem = dynamic_cast(item); if (!doxyItem) return; //doxygen documentation mode (if catalog points to a .tag) if (doxyItem->origUrl().endsWith("tag")) { TQString htmlUrl; TQFileInfo fi2(item->url().directory(false) + "index.html"); if (fi2.exists()) htmlUrl = fi2.dirPath(true) + "/"; TQFileInfo fi(item->url().directory(false) + "html/index.html"); if (fi.exists()) htmlUrl = fi.dirPath(true) + "/"; if (!htmlUrl.isEmpty()) createBookTOC(item, doxyItem->origUrl(), htmlUrl); } //KDE doxygen documentation mode (if catalog points to a index.html) TQDir d; TQValueStack dirStack; dirStack.push(fi.dirPath(true)); do { d.setPath(dirStack.pop()); if (!d.exists()) continue; const TQFileInfoList *dirEntries = d.entryInfoList(); if (!dirEntries) continue; TQPtrListIterator it(*dirEntries); for (; it.current(); ++it) { TQString fileName = it.current()->fileName(); if (fileName == "." || fileName == ".." || fileName == "common" || fileName == "html") continue; if (it.current()->isDir()) dirStack.push(it.current()->absFilePath()); } if (TQFile::exists(d.absPath() + "/html/index.html")) { DocumentationItem *docItem = new DocumentationItem(DocumentationItem::Book, item, d.dirName()); docItem->setURL(KURL(d.absPath() + "/html/index.html")); docItem->setExpandable(true); createBookTOC(docItem); } } while (!dirStack.isEmpty()); } DocumentationCatalogItem *DocDoxygenPlugin::createCatalog(TDEListView *contents, TDEListViewItem *after, const TQString &title, const TQString &url) { kdDebug() << "DocDoxygenPlugin::createCatalog: url=" << url << endl; DocumentationCatalogItem *item = new DoxyDocumentationCatalogItem(url, this, contents, after, title); item->setURL(url); return item; } void DocDoxygenPlugin::createBookTOC(DocumentationItem *item, const TQString &tagUrl, const TQString &baseHtmlUrl) { TQString tagName; if (tagUrl.isEmpty()) tagName = item->url().upURL().directory(false) + item->text(0) + ".tag"; else tagName = tagUrl; TQString baseUrl; if (baseHtmlUrl.isEmpty()) baseUrl = item->url().directory(false); else baseUrl = baseHtmlUrl; //@todo list html files in the directory if tag was not found if (!TQFile::exists(tagName)) return; TQStringList tagFileList; if (tagName.endsWith(".tag")) tagFileList = tagFiles(TQFileInfo(tagName).dirPath() + "/"); else tagFileList += tagName; TQStringList::ConstIterator end = tagFileList.constEnd(); for (TQStringList::ConstIterator it = tagFileList.constBegin(); it != end; ++it) { TQFile f(*it); if (!f.open(IO_ReadOnly)) { kdDebug(9002) << "Could not open tag file: " << f.name() << endl; return; } TQDomDocument dom; if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile") { kdDebug(9002) << "No valid tag file" << endl; return; } f.close(); TQDomElement docEl = dom.documentElement(); TQDomElement childEl = docEl.lastChild().toElement(); while (!childEl.isNull()) { if (childEl.tagName() == "compound" && childEl.attribute("kind") == "class") { TQString classname = childEl.namedItem("name").firstChild().toText().data(); TQString filename = childEl.namedItem("filename").firstChild().toText().data(); if (TQFile::exists(baseUrl + filename)) { DocumentationItem *docItem = new DocumentationItem(DocumentationItem::Document, item, classname); docItem->setURL(KURL(baseUrl + filename)); } } childEl = childEl.previousSibling().toElement(); } } } void DocDoxygenPlugin::createBookIndex(const TQString &tagfile, IndexBox* index, DocumentationCatalogItem* item, const TQString &baseHtmlUrl) { TQString tagName = tagfile; kdDebug() << tagfile << endl; if (!TQFile::exists(tagName)) return; TQString prefix = baseHtmlUrl.isEmpty() ? KURL(tagfile).directory(false) + "html/" : baseHtmlUrl; TQStringList tagFileList = tagFiles(TQFileInfo(tagName).dirPath() + "/"); TQStringList::ConstIterator end = tagFileList.constEnd(); for (TQStringList::ConstIterator it = tagFileList.constBegin(); it != end; ++it) { TQFile f(*it); if (!f.open(IO_ReadOnly)) { kdDebug(9002) << "Could not open tag file: " << f.name() << endl; return; } TQDomDocument dom; if (!dom.setContent(&f) || dom.documentElement().nodeName() != "tagfile") { kdDebug(9002) << "No valid tag file" << endl; return; } f.close(); TQDomElement docEl = dom.documentElement(); createIndexFromTag(dom, index, item, docEl, prefix); } } void DocDoxygenPlugin::createIndexFromTag(TQDomDocument &dom, IndexBox *index, DocumentationCatalogItem *item, TQDomElement &parentEl, const TQString &prefix) { TQDomElement docEl = parentEl; TQDomElement childEl = docEl.firstChild().toElement(); while (!childEl.isNull()) { if (childEl.tagName() == "compound" && ((childEl.attribute("kind") == "class") || (childEl.attribute("kind") == "struct") || (childEl.attribute("kind") == "namespace") )) { TQString classname = childEl.namedItem("name").firstChild().toText().data(); TQString filename = childEl.namedItem("filename").firstChild().toText().data(); IndexItemProto *indexItem = new IndexItemProto(this, item, index, classname, i18n("%1 Class Reference").arg(classname)); indexItem->addURL(KURL(prefix + filename)); createIndexFromTag(dom, index, item, childEl, prefix + filename); } else if ((childEl.tagName() == "member") && ((childEl.attribute("kind") == "function") || (childEl.attribute("kind") == "slot") || (childEl.attribute("kind") == "signal") )) { TQString classname = parentEl.namedItem("name").firstChild().toText().data(); TQString membername = childEl.namedItem("name").firstChild().toText().data(); TQString anchor = childEl.namedItem("anchor").firstChild().toText().data(); TQString arglist = childEl.namedItem("arglist").firstChild().toText().data(); if (classname != membername) { IndexItemProto *indexItem = new IndexItemProto(this, item, index, membername,i18n("%1::%2%3 Member Reference").arg(classname).arg(membername).arg(arglist)); indexItem->addURL(KURL(prefix + "#" + anchor)); } } childEl = childEl.nextSibling().toElement(); } } ProjectDocumentationPlugin *DocDoxygenPlugin::projectDocumentationPlugin(ProjectDocType type) { if (type == APIDocs) return new ProjectDocumentationPlugin(this, type); return DocumentationPlugin::projectDocumentationPlugin(type); } TQStringList DocDoxygenPlugin::tagFiles(const TQString& path, int level) { TQStringList r; TQDir dir(path); if (level > 10) return r; if (!dir.isReadable()) return r; if (!dir.exists()) return r; TQStringList dirList; TQStringList fileList; TQStringList::Iterator it; dir.setFilter ( TQDir::Dirs); dirList = dir.entryList(); dirList.remove("."); dirList.remove(".."); dir.setFilter(TQDir::Files | TQDir::Hidden | TQDir::System); fileList = dir.entryList(); TQStringList::Iterator end = dirList.end(); for ( it = dirList.begin(); it != end; ++it ) { TQString name = *it; if (TQFileInfo( dir, *it ).isSymLink()) continue; r += tagFiles(path + name + "/", level + 1 ); } TQStringList::Iterator fend = fileList.end(); for ( it = fileList.begin(); it != fend; ++it ) { TQString name = *it; TQFileInfo fi( dir, *it ); if (fi.isSymLink() || !fi.isFile()) continue; if (TQDir::match(TQString("*.tag"), name)) r += (path+name); } return r; } #include "docdoxygenplugin.moc"