|
|
|
/***************************************************************************
|
|
|
|
* 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 <unistd.h>
|
|
|
|
|
|
|
|
#include <tqdom.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqdialog.h>
|
|
|
|
|
|
|
|
#include <kurl.h>
|
|
|
|
#include <kaboutdata.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
|
|
|
|
#include <kdevgenericfactory.h>
|
|
|
|
#include <kdevplugininfo.h>
|
|
|
|
|
|
|
|
#include "../../../../config.h"
|
|
|
|
|
|
|
|
class DevHelpDocumentationCatalogItem: public DocumentationCatalogItem
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DevHelpDocumentationCatalogItem(const TQString &devHelpFile, DocumentationPlugin* plugin,
|
|
|
|
KListView *parent, const TQString &name)
|
|
|
|
:DocumentationCatalogItem(plugin, parent, 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<m_devHelpFile.length(); a++) {
|
|
|
|
checksum += (a+1) * (int)m_devHelpFile[a];
|
|
|
|
}
|
|
|
|
TQString str;
|
|
|
|
TQTextOStream( &str ) << checksum;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
private:
|
|
|
|
TQString m_devHelpFile;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static const KDevPluginInfo data("docdevhelpplugin");
|
|
|
|
typedef KDevGenericFactory<DocDevHelpPlugin> 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(KListView* contents, const TQString& title, const TQString& url)
|
|
|
|
{
|
|
|
|
return new DevHelpDocumentationCatalogItem(url, this, contents, title);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPair<KFile::Mode, TQString> DocDevHelpPlugin::catalogLocatorProps()
|
|
|
|
{
|
|
|
|
return TQPair<KFile::Mode, TQString>(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<TQString, TQString> entryMap = config->entryMap("Locations");
|
|
|
|
|
|
|
|
for (TQMap<TQString, TQString>::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<DevHelpDocumentationCatalogItem *>(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<TQString> 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<TQFileInfo> 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<TQString> &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<DevHelpDocumentationCatalogItem *>(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<DevHelpDocumentationCatalogItem *>(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<DevHelpDocumentationCatalogItem *>(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"
|