/*************************************************************************** * 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 "docdevhelpplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../../../../config.h" class DevHelpDocumentationCatalogItem: public DocumentationCatalogItem { public: DevHelpDocumentationCatalogItem(const TQString &devHelpFile, DocumentationPlugin* plugin, TDEListView *parent, TDEListViewItem *after, const TQString &name) :DocumentationCatalogItem(plugin, parent, after, name), m_devHelpFile(devHelpFile) { } DevHelpDocumentationCatalogItem(const TQString &devHelpFile, DocumentationPlugin* plugin, DocumentationItem *parent, const TQString &name) :DocumentationCatalogItem(plugin, parent, name), m_devHelpFile(devHelpFile) { } TQString devHelpFile() const { return m_devHelpFile; } virtual TQString cacheVersion() const { unsigned int checksum=0; for(int a=0;a DocDevHelpPluginFactory; K_EXPORT_COMPONENT_FACTORY( libdocdevhelpplugin, DocDevHelpPluginFactory(data) ) DocDevHelpPlugin::DocDevHelpPlugin(TQObject* parent, const char* name, const TQStringList /*args*/) :DocumentationPlugin(DocDevHelpPluginFactory::instance()->config(), parent, name) { setCapabilities(Index | FullTextSearch | ProjectDocumentation); autoSetup(); } DocDevHelpPlugin::~DocDevHelpPlugin() { } DocumentationCatalogItem* DocDevHelpPlugin::createCatalog(TDEListView* contents, TDEListViewItem *after, const TQString& title, const TQString& url) { return new DevHelpDocumentationCatalogItem(url, this, contents, after, title); } TQPair DocDevHelpPlugin::catalogLocatorProps() { return TQPair(KFile::File, "*.devhelp"); } TQString DocDevHelpPlugin::catalogTitle(const TQString& url) { TQFileInfo fi(url); if (!fi.exists()) return TQString(); TQFile f(url); if (!f.open(IO_ReadOnly)) return TQString(); TQDomDocument doc; if (!doc.setContent(&f)) return TQString(); f.close(); TQDomElement docEl = doc.documentElement(); return docEl.attribute("title", TQString()); } TQString DocDevHelpPlugin::pluginName() const { return i18n("Devhelp Documentation Collection"); } TQStringList DocDevHelpPlugin::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; } bool DocDevHelpPlugin::needRefreshIndex(DocumentationCatalogItem* item) { DevHelpDocumentationCatalogItem *dhItem = dynamic_cast(item); if (!dhItem) return false; TQFileInfo fi(dhItem->devHelpFile()); config->setGroup("Index"); if (fi.lastModified() > config->readDateTimeEntry(dhItem->text(0), new TQDateTime())) { kdDebug() << "need rebuild index for " << dhItem->text(0) << endl; config->writeEntry(item->text(0), fi.lastModified()); return true; } else return false; } void DocDevHelpPlugin::autoSetupPlugin() { TQValueStack scanStack; pushToScanStack(scanStack, getenv("DEVHELP_SEARCH_PATH")); pushToScanStack(scanStack, TQString(getenv("HOME")) + "/.devhelp/books"); TQString dhexepath = DocDevHelpPluginFactory::instance()->dirs()->findExe("devhelp"); if (!dhexepath.isEmpty()) { TQFileInfo fi(dhexepath); TQString path = KURL(fi.dirPath(true)).upURL().path(1); pushToScanStack(scanStack, path + "share/devhelp/books"); pushToScanStack(scanStack, path + "share/gtk-doc/html"); } pushToScanStack(scanStack, "/usr/share/gtk-doc/html"); pushToScanStack(scanStack, "/usr/share/devhelp/books/"); pushToScanStack(scanStack, "/usr/local/share/devhelp/books"); pushToScanStack(scanStack, "/usr/local/share/gtk-doc/html"); pushToScanStack(scanStack, "/opt/gnome/share/devhelp/books"); pushToScanStack(scanStack, "/opt/gnome/share/gtk-doc/html"); pushToScanStack(scanStack, "/opt/gnome2/share/devhelp/books"); pushToScanStack(scanStack, "/opt/gnome2/share/gtk-doc/html"); //fill the list of scan dirs (with subdirectories) TQStringList scanList; TQDir dir; do { dir.setPath(scanStack.pop()); if (!dir.exists()) continue; scanList << dir.path(); const TQFileInfoList *dirEntries = dir.entryInfoList(); if ( !dirEntries ) continue; TQPtrListIterator it(*dirEntries); for (; it.current(); ++it) { TQString fileName = it.current()->fileName(); if (fileName == "." || fileName == "..") continue; TQString path = it.current()->absFilePath(); if (it.current()->isDir()) { scanStack.push(path); } } } while (!scanStack.isEmpty()); for (TQStringList::const_iterator it = scanList.begin(); it != scanList.end(); ++it) { scanDevHelpDir(*it); } } void DocDevHelpPlugin::scanDevHelpDir(const TQString &path) { TQDir d(path); if (! d.exists() || !d.isReadable()) return; d.setFilter(TQDir::Files); //scan for *.devhelp files const TQFileInfoList *list = d.entryInfoList(); TQFileInfoListIterator it( *list ); TQFileInfo *fi; while ( (fi = it.current()) != 0 ) { if (fi->extension() == "devhelp") { config->setGroup("Locations"); config->writePathEntry(catalogTitle(fi->absFilePath()), fi->absFilePath()); } ++it; } } void DocDevHelpPlugin::pushToScanStack(TQValueStack &stack, const TQString &value) { if ( (!value.isEmpty()) && (!stack.contains(value)) ) { stack << value; kdDebug() << "Devhelp scan stack: +: " << value << endl; } } void DocDevHelpPlugin::createIndex(IndexBox* index, DocumentationCatalogItem* item) { DevHelpDocumentationCatalogItem *dhItem = dynamic_cast(item); if (!dhItem) return; TQFileInfo fi(dhItem->devHelpFile()); TQFile f(dhItem->devHelpFile()); if (!f.open(IO_ReadOnly)) { kdDebug(9002) << "Could not read" << dhItem->devHelpFile() << endl; return; } TQDomDocument doc; if (!doc.setContent(&f)) { kdDebug() << "Not a valid devhelp file: " << dhItem->devHelpFile() << endl; return; } f.close(); TQString baseUrl = KURL(dhItem->devHelpFile()).directory(); TQDomElement docEl = doc.documentElement(); TQDomElement chaptersEl = docEl.namedItem("functions").toElement(); TQDomElement childEl = chaptersEl.firstChild().toElement(); while (!childEl.isNull()) { if (childEl.tagName() == "function") { TQString name = childEl.attribute("name"); TQString url = childEl.attribute("link"); IndexItemProto *ii = new IndexItemProto(this, item, index, name, item->text(0)); ii->addURL(KURL(baseUrl+"/"+url)); } childEl = childEl.nextSibling().toElement(); } } void DocDevHelpPlugin::createTOC(DocumentationCatalogItem* item) { DevHelpDocumentationCatalogItem *dhItem = dynamic_cast(item); if (!dhItem) return; TQFileInfo fi(dhItem->devHelpFile()); TQFile f(dhItem->devHelpFile()); if (!f.open(IO_ReadOnly)) { kdDebug(9002) << "Could not read" << dhItem->devHelpFile() << endl; return; } TQDomDocument doc; if (!doc.setContent(&f)) { kdDebug() << "Not a valid devhelp file: " << dhItem->devHelpFile() << endl; return; } f.close(); TQDomElement docEl = doc.documentElement(); TQDomElement chaptersEl = docEl.namedItem("chapters").toElement(); TQDomElement childEl = chaptersEl.lastChild().toElement(); TQString baseUrl = KURL(dhItem->devHelpFile()).directory(); addTocSect(dhItem, childEl, baseUrl, true); } void DocDevHelpPlugin::addTocSect(DocumentationItem *parent, TQDomElement childEl, TQString baseUrl, bool book) { while (!childEl.isNull()) { if ( (childEl.tagName() == "sub") || (childEl.tagName() == "chapter")) { TQString name = childEl.attribute("name"); TQString url = childEl.attribute("link"); if (name.isEmpty() && url.contains("ix")) name = "Index"; DocumentationItem *item = new DocumentationItem( book ? DocumentationItem::Book : DocumentationItem::Document, parent, name); item->setURL(KURL(baseUrl+"/"+url)); TQDomElement grandchildEl = childEl.lastChild().toElement(); addTocSect(item, grandchildEl, baseUrl); } childEl = childEl.previousSibling().toElement(); } } void DocDevHelpPlugin::setCatalogURL(DocumentationCatalogItem* item) { DevHelpDocumentationCatalogItem *dhItem = dynamic_cast(item); if (!dhItem) return; TQFileInfo fi(dhItem->devHelpFile()); TQFile f(dhItem->devHelpFile()); if (!f.open(IO_ReadOnly)) { kdDebug(9002) << "Could not read" << dhItem->devHelpFile() << endl; return; } TQDomDocument doc; if (!doc.setContent(&f)) { kdDebug(9002) << "Not a valid Devhelp file: " << dhItem->devHelpFile() << endl; return; } f.close(); TQDomElement docEl = doc.documentElement(); TQDomElement titleEl = docEl.namedItem("book").toElement(); if (item->url().isEmpty()) { KURL url(fi.dirPath(true) + "/" + docEl.attribute("link", TQString())); item->setURL(url); } } ProjectDocumentationPlugin *DocDevHelpPlugin::projectDocumentationPlugin(ProjectDocType type) { if (type == APIDocs) return new ProjectDocumentationPlugin(this, type); return DocumentationPlugin::projectDocumentationPlugin(type); } #include "docdevhelpplugin.moc"