diff options
Diffstat (limited to 'parts/documentation/interfaces/tdevdocumentationplugin.cpp')
-rw-r--r-- | parts/documentation/interfaces/tdevdocumentationplugin.cpp | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/parts/documentation/interfaces/tdevdocumentationplugin.cpp b/parts/documentation/interfaces/tdevdocumentationplugin.cpp new file mode 100644 index 00000000..f3c20841 --- /dev/null +++ b/parts/documentation/interfaces/tdevdocumentationplugin.cpp @@ -0,0 +1,721 @@ +/* This file is part of the KDE project + Copyright (C) 2004 by Alexander Dymo <cloudtemple@mksat.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include "tdevdocumentationplugin.h" + +#include <tqfile.h> +#include <tqpainter.h> +#include <tqstyle.h> +#include <tqheader.h> +#include <tqtextstream.h> + +#include <kstandarddirs.h> +#include <kiconloader.h> +#include <tdeconfig.h> +#include <kdebug.h> +#include <kdirwatch.h> +#include <tdelocale.h> + +//class DocumentationItem + +DocumentationItem::DocumentationItem(DocumentationItem::Type type, TDEListView *parent, + const TQString &name) + :TDEListViewItem(parent, name), m_type(type) +{ + init(); +} + +DocumentationItem::DocumentationItem(DocumentationItem::Type type, TDEListViewItem *parent, + const TQString &name) + :TDEListViewItem(parent, name), m_type(type) +{ + init(); +} + +DocumentationItem::DocumentationItem(DocumentationItem::Type type, TDEListView *parent, + TDEListViewItem *after, const TQString &name) + :TDEListViewItem(parent, after, name), m_type(type) +{ + init(); +} + +DocumentationItem::DocumentationItem(DocumentationItem::Type type, TDEListViewItem * parent, + TDEListViewItem * after, const TQString & name ) + :TDEListViewItem(parent, after, name), m_type(type) +{ + init(); +} + + +void DocumentationItem::init( ) +{ + TQString icon; + + switch (m_type) + { + case Collection: + case Catalog: + icon = "folder"; + break; + case Book: + icon = "contents"; + break; + default: + icon = "document"; + } + + setPixmap(0, SmallIcon(icon)); +} + + + + + +//class DocumentationCatalogItem + + +DocumentationCatalogItem::DocumentationCatalogItem(DocumentationPlugin* plugin, + TDEListView *parent, const TQString &name) + :DocumentationItem(DocumentationItem::Catalog, parent, name), m_plugin(plugin), + isLoaded(false), isActivated(false), m_isProjectDocumentationItem(false) +{ + setExpandable(true); + m_plugin->addCatalog(this); +} + +DocumentationCatalogItem::DocumentationCatalogItem(DocumentationPlugin* plugin, + DocumentationItem *parent, const TQString &name) + :DocumentationItem(DocumentationItem::Catalog, parent, name), m_plugin(plugin), + isLoaded(false), isActivated(false), m_isProjectDocumentationItem(false) +{ + setExpandable(true); + m_plugin->addCatalog(this); +} + +DocumentationCatalogItem::~ DocumentationCatalogItem( ) +{ + m_plugin->clearCatalog(this); +} + +void DocumentationCatalogItem::setOpen(bool o) +{ + if (o) + { + load(); + } + DocumentationItem::setOpen(o); +} + +void DocumentationCatalogItem::load() +{ +if(isLoaded) +return; + + plugin()->createTOC(this); + isLoaded = true; +} + +void DocumentationCatalogItem::activate() +{ + if (!isActivated) + { + plugin()->setCatalogURL(this); + isActivated = true; + } + DocumentationItem::activate(); +} + + + + +//class IndexItemProto + +IndexItemProto::IndexItemProto(DocumentationPlugin *plugin, DocumentationCatalogItem *catalog, + IndexBox *listbox, const TQString &text, const TQString &description) + : m_listbox(listbox), m_text(text), m_description(description) +{ + plugin->indexes[catalog].append(this); + m_listbox->addIndexItem(this); +} + +IndexItemProto::~IndexItemProto() +{ + m_listbox->removeIndexItem(this); +} + + +//class IndexItem + +IndexItem::IndexItem(IndexBox *listbox, const TQString &text) + :TQListBoxText(listbox, text), m_listbox(listbox) +{ +} + +IndexItem::List IndexItem::urls() const +{ + List urlList; + TQValueList<IndexItemProto*> itemProtos = m_listbox->items[text()]; + for (TQValueList<IndexItemProto*>::const_iterator it = itemProtos.begin(); + it != itemProtos.end(); ++it) + urlList.append(tqMakePair((*it)->description(), (*it)->url())); + return urlList; +} + + + + +//class ConfigurationItem + +ConfigurationItem::ConfigurationItem(TQListView *parent, DocumentationPlugin * plugin, const TQString &title, const TQString &url, + bool indexPossible, bool fullTextSearchPossible) + :TQCheckListItem(parent, "", TQCheckListItem::CheckBox), m_title(title), m_url(url), + m_origTitle(title), m_contents(true), m_index(false), m_fullTextSearch(false), + m_indexPossible(indexPossible), m_fullTextSearchPossible(fullTextSearchPossible), + m_docPlugin( plugin ) +{ + setText(3, m_title); + setText(4, m_url); +} + +void ConfigurationItem::paintCell(TQPainter *p, const TQColorGroup &cg, int column, + int width, int align) +{ + if ( (column == 0) || (column == 1) || (column == 2) ) + { + if ( !p ) + return; + + TQListView *lv = listView(); + if ( !lv ) + return; + + const BackgroundMode bgmode = lv->viewport()->backgroundMode(); + const TQColorGroup::ColorRole crole = TQPalette::backgroundRoleFromMode( bgmode ); + p->fillRect(0, 0, width, height(), cg.brush(crole)); + + TQFontMetrics fm(lv->fontMetrics()); + int boxsize = lv->style().pixelMetric(TQStyle::PM_CheckListButtonSize, lv); + int marg = lv->itemMargin(); + int styleflags = TQStyle::Style_Default; + + if (((column == 0) && m_contents) || ((column == 1) && m_index) || ((column == 2) && m_fullTextSearch)) + styleflags |= TQStyle::Style_On; + else + styleflags |= TQStyle::Style_Off; + if ((column == 0) || ((column == 1) && m_indexPossible) || ((column == 2) && m_fullTextSearchPossible)) + styleflags |= TQStyle::Style_Enabled; + + int x = 0; + int y = 0; + x += 3; + if (align & AlignVCenter) + y = ((height() - boxsize) / 2) + marg; + else + y = (fm.height() + 2 + marg - boxsize) / 2; + + TQStyleOption opt(this); + lv->style().tqdrawPrimitive(TQStyle::PE_CheckListIndicator, p, + TQRect(x, y, boxsize, fm.height() + 2 + marg), cg, styleflags, opt); + + return; + } + TQListViewItem::paintCell(p, cg, column, width, align); +} + +int ConfigurationItem::width(const TQFontMetrics &fm, const TQListView *lv, int c) const +{ + if ((c == 0) || (c == 1) || (c == 2)) + return lv->style().pixelMetric(TQStyle::PM_CheckListButtonSize, lv) + 4; + return TQListViewItem::width(fm, lv, c); +} + + + + + + + + +//class DocumentationPlugin + +DocumentationPlugin::DocumentationPlugin(TDEConfig *pluginConfig, TQObject *parent, const char *name) + :TQObject(parent, name), config(pluginConfig), m_indexCreated(false) +{ +} + +DocumentationPlugin::~DocumentationPlugin() +{ +} + +void DocumentationPlugin::autoSetup() +{ + config->setGroup("General"); + if ( ! config->readBoolEntry("Autosetup", false) ) + { + autoSetupPlugin(); + config->setGroup("General"); + config->writeEntry("Autosetup", true); + config->sync(); + } +} + +void DocumentationPlugin::reload() +{ + clear(); + for (TQValueList<DocumentationCatalogItem *>::iterator it = catalogs.begin(); + it != catalogs.end(); ++it) + { + createTOC(*it); + } +} + +void DocumentationPlugin::clear() +{ + for (TQValueList<DocumentationCatalogItem *>::iterator it = catalogs.begin(); + it != catalogs.end(); ++it) + { + clearCatalog(*it); + } +} + +void DocumentationPlugin::clearCatalog(DocumentationCatalogItem *item) +{ + //clear named catalog map + for (TQMap<TQString, DocumentationCatalogItem*>::iterator it = namedCatalogs.begin(); + it != namedCatalogs.end(); ++it) + { + if (it.data() == item) + { + namedCatalogs.remove(it); + break; + } + } + //clear indexes for catalog + TQValueList<IndexItemProto *> idx = indexes[item]; + for (TQValueList<IndexItemProto *>::iterator it = idx.begin(); it != idx.end(); ++it) + { + delete *it; + } + indexes.remove(item); + + //remove catalog + catalogs.remove(item); +} + +void DocumentationPlugin::createIndex(IndexBox *index) +{ + if (m_indexCreated) + return; + + for (TQValueList<DocumentationCatalogItem *>::iterator it = catalogs.begin(); + it != catalogs.end(); ++it) + { + loadIndex(index, *it); + } + m_indexCreated = true; +} + +void DocumentationPlugin::cacheIndex(DocumentationCatalogItem *item) +{ + kdDebug() << "Creating index cache for " << item->text(0) << endl; + + TQString cacheName = locateLocal("data", TQString("tdevdocumentation/index/cache_") + item->text(0)); + TQFile cacheFile(cacheName); + if (!cacheFile.open(IO_WriteOnly)) + return; + + TQTextStream str(&cacheFile); + str.setEncoding(TQTextStream::Unicode); + str << CACHE_VERSION << endl; + + TQValueList<IndexItemProto*> catalogIndexes = indexes[item]; + for (TQValueList<IndexItemProto*>::const_iterator it = catalogIndexes.constBegin(); + it != catalogIndexes.constEnd(); ++it) + { + str << (*it)->text() << endl; + str << (*it)->description() << endl; + str << (*it)->url().url() << endl; + } + + cacheFile.close(); +} + +bool DocumentationPlugin::loadCachedIndex(IndexBox *index, DocumentationCatalogItem *item) +{ + TQString cacheName = locateLocal("data", TQString("tdevdocumentation/index/cache_") + item->cacheVersion() + item->text(0)); + TQFile cacheFile(cacheName); + if (!cacheFile.open(IO_ReadOnly)) + return false; + + kdDebug() << "Using cached index for item: " << item->text(0) << endl; + + TQTextStream str(&cacheFile); + str.setEncoding(TQTextStream::Unicode); + TQString cache = str.read(); + TQStringList cacheList = TQStringList::split("\n", cache, true); + TQString ver = cacheList.first(); + if (ver != CACHE_VERSION) + { + kdDebug() << "Wrong cache version: " << ver << endl; + return false; + } + TQStringList::const_iterator it = cacheList.begin(); + it++; + TQString s[3]; int c = 0; + for (; it != cacheList.end(); ++it) + { + s[c] = *it; + if (c == 2) + { + IndexItemProto *ii = new IndexItemProto(this, item, index, s[0], s[1]); + ii->addURL(KURL(s[2])); + c = 0; + } + else c++; + } + cacheFile.close(); + + return true; +} + +void DocumentationPlugin::addCatalog(DocumentationCatalogItem *item) +{ + catalogs.append(item); + namedCatalogs[item->text(0)] = item; +// indexes[item] = TQValueList<IndexItem*>(); +} + +void DocumentationPlugin::addCatalogConfiguration(TDEListView *configurationView, + const TQString &title, const TQString &url) +{ + new ConfigurationItem(configurationView, this, title, url, + hasCapability(Index), hasCapability(FullTextSearch)); +} + +void DocumentationPlugin::editCatalogConfiguration(ConfigurationItem *configurationItem, + const TQString &title, const TQString &url) +{ + configurationItem->setTitle(title); + configurationItem->setURL(url); +} + +void DocumentationPlugin::deleteCatalogConfiguration(const ConfigurationItem *const configurationItem) +{ + deletedConfigurationItems << configurationItem->title(); +} + +void DocumentationPlugin::clearCatalogIndex(DocumentationCatalogItem *item) +{ + //clear indexes for catalog + TQValueList<IndexItemProto *> idx = indexes[item]; + for (TQValueList<IndexItemProto *>::iterator it = idx.begin(); it != idx.end(); ++it) + { + delete *it; + } + indexes.remove(item); +} + +void DocumentationPlugin::loadIndex(IndexBox *index, DocumentationCatalogItem *item) +{ + if (!indexEnabled(item)) + return; + if (!needRefreshIndex(item) && loadCachedIndex(index, item)) + return; + createIndex(index, item); + cacheIndex(item); +} + +void DocumentationPlugin::init(TDEListView *contents) +{ + config->setGroup("Locations"); + TQMap<TQString, TQString> entryMap = config->entryMap("Locations"); + + for (TQMap<TQString, TQString>::const_iterator it = entryMap.begin(); + it != entryMap.end(); ++it) + { + if (catalogEnabled(it.key())) + createCatalog(contents, it.key(), config->readPathEntry(it.key())); + } +} + +void DocumentationPlugin::reinit(TDEListView *contents, IndexBox *index, TQStringList restrictions) +{ + config->setGroup("Locations"); + TQMap<TQString, TQString> entryMap = config->entryMap("Locations"); + + //remove deleted in configuration catalogs + for (TQStringList::const_iterator it = deletedConfigurationItems.constBegin(); + it != deletedConfigurationItems.constEnd(); ++it) + { + if (namedCatalogs.contains(*it)) + delete namedCatalogs[*it]; + } + deletedConfigurationItems.clear(); + + //update configuration + for (TQMap<TQString, TQString>::const_iterator it = entryMap.begin(); + it != entryMap.end(); ++it) + { + config->setGroup("Locations"); + if (restrictions.contains(it.key()) || (!catalogEnabled(it.key()))) + { + if (namedCatalogs.contains(it.key())) + delete namedCatalogs[it.key()]; + } + else + { + kdDebug() << "updating 1" << endl; + if (!namedCatalogs.contains(it.key())) //create catalog if it does not exist + { + DocumentationCatalogItem * item = createCatalog(contents, it.key(), config->readPathEntry(it.key())); + loadIndex(index, item); + index->setDirty(true); +// index->refill(indexes[item]); + } + else if (!indexEnabled(namedCatalogs[it.key()])) //clear index if it is disabled in configuration + { + kdDebug() << " updating: clearCatalogIndex" << endl; + clearCatalogIndex(namedCatalogs[it.key()]); + } + else if ( (indexEnabled(namedCatalogs[it.key()])) //index is requested in configuration but does not yet exist + && (!indexes.contains(namedCatalogs[it.key()])) ) + { + kdDebug() << " index requested " << endl; + loadIndex(index, namedCatalogs[it.key()]); + index->setDirty(true); + } + m_indexCreated = true; + } + } +} + +void DocumentationPlugin::loadCatalogConfiguration(TDEListView *configurationView) +{ + config->setGroup("Locations"); + TQMap<TQString, TQString> entryMap = config->entryMap("Locations"); + + for (TQMap<TQString, TQString>::const_iterator it = entryMap.begin(); + it != entryMap.end(); ++it) + { + if (namedCatalogs.contains(it.key()) + && namedCatalogs[it.key()]->isProjectDocumentationItem()) + continue; + + config->setGroup("Locations"); + ConfigurationItem *item = new ConfigurationItem(configurationView, this, it.key(), + config->readPathEntry(it.key()), + hasCapability(Index), hasCapability(FullTextSearch)); + config->setGroup("TOC Settings"); + item->setContents(config->readBoolEntry(item->title(), true)); + config->setGroup("Index Settings"); + item->setIndex(config->readBoolEntry(item->title(), false)); + config->setGroup("Search Settings"); + item->setFullTextSearch(config->readBoolEntry(item->title(), false)); + } +} + +void DocumentationPlugin::saveCatalogConfiguration(TDEListView *configurationView) +{ + config->setGroup("Locations"); + + for (TQStringList::const_iterator it = deletedConfigurationItems.constBegin(); + it != deletedConfigurationItems.constEnd(); ++it) + { + config->deleteEntry(*it); + } + + TQListViewItemIterator it(configurationView); + while (it.current()) + { + ConfigurationItem *confItem = dynamic_cast<ConfigurationItem*>(it.current()); + if ( confItem->docPlugin() != this ) + { + ++it; + continue; + } + + config->setGroup("Locations"); + if (confItem->isChanged()) + config->deleteEntry(confItem->origTitle()); + config->writePathEntry(confItem->title(), confItem->url()); + + config->setGroup("TOC Settings"); + if (confItem->isChanged()) + config->deleteEntry(confItem->origTitle()); + config->writeEntry(confItem->title(), confItem->contents()); + + config->setGroup("Index Settings"); + if (confItem->isChanged()) + config->deleteEntry(confItem->origTitle()); + config->writeEntry(confItem->title(), confItem->index()); + + config->setGroup("Search Settings"); + if (confItem->isChanged()) + config->deleteEntry(confItem->origTitle()); + config->writeEntry(confItem->title(), confItem->fullTextSearch()); + + ++it; + } + config->sync(); +} + +void DocumentationPlugin::setIndexEnabled( DocumentationCatalogItem * item, bool e ) +{ + TQString group = config->group(); + config->setGroup("Index Settings"); + config->writeEntry(item->text(0), e); + config->setGroup(group); +} + +bool DocumentationPlugin::indexEnabled( DocumentationCatalogItem * item ) const +{ + TQString group = config->group(); + config->setGroup("Index Settings"); + bool b = config->readBoolEntry(item->text(0), false); + config->setGroup(group); + return b; +} + +bool DocumentationPlugin::catalogEnabled(const TQString &name) const +{ + TQString group = config->group(); + config->setGroup("TOC Settings"); + bool b = config->readBoolEntry(name, true); + config->setGroup(group); + return b; +} + +void DocumentationPlugin::setCatalogEnabled(const TQString &name, bool e) +{ + TQString group = config->group(); + config->setGroup("TOC Settings"); + config->writeEntry(name, e); + config->setGroup(group); +} + + + + +//class IndexBox + +IndexBox::IndexBox(TQWidget *parent, const char *name) + :TDEListBox(parent, name), m_dirty(false) +{ +} + +void IndexBox::addIndexItem(IndexItemProto *item) +{ + items[item->text()].append(item); +} + +void IndexBox::removeIndexItem(IndexItemProto *item) +{ + TQString text = item->text(); + items[text].remove(item); + if (items[text].count() == 0) + { + items.remove(text); + TQListBoxItem *item = findItem(text, TQt::CaseSensitive | TQt::ExactMatch); + if (item) + delete item; + } +} + +void IndexBox::fill() +{ + for (TQMap<TQString, TQValueList<IndexItemProto*> >::const_iterator it = items.begin(); + it != items.end(); ++it) + { + new IndexItem(this, it.key()); + } +} + +void IndexBox::setDirty(bool dirty) +{ + m_dirty = dirty; +} + +void IndexBox::refill() +{ + if (m_dirty) + { + clear(); + fill(); + setDirty(false); + } +} + + +ProjectDocumentationPlugin::ProjectDocumentationPlugin(DocumentationPlugin *docPlugin, DocumentationPlugin::ProjectDocType type) + :TQObject(0, 0), m_docPlugin(docPlugin), m_catalog(0), m_type(type), m_contents(0), m_index(0) +{ + kdDebug() << "ProjectDocumentationPlugin::ProjectDocumentationPlugin for type " << type << endl; + + m_watch = new KDirWatch(this); + connect(m_watch, TQT_SIGNAL(dirty(const TQString&)), this, TQT_SLOT(reinit())); + m_watch->startScan(); +} + +ProjectDocumentationPlugin::~ProjectDocumentationPlugin() +{ + deinit(); +} + +void ProjectDocumentationPlugin::init(TDEListView *contents, IndexBox *index, const TQString &url) +{ + m_contents = contents; + m_index = index; + m_url = url; + + if (m_catalog) + deinit(); + m_catalog = m_docPlugin->createCatalog(contents, + m_type == DocumentationPlugin::APIDocs ? i18n("Project API Documentation") + : i18n("Project User Manual"), url); + if (m_catalog) + { + m_catalog->setProjectDocumentationItem(true); + m_watch->addFile(url); + } +} + +void ProjectDocumentationPlugin::reinit() +{ + deinit(); + if (m_contents != 0 && m_index != 0 && m_url != 0) + init(m_contents, m_index, m_url); +} + +void ProjectDocumentationPlugin::deinit() +{ + m_watch->removeFile(m_url); + delete m_catalog; + m_catalog = 0; +} + +TQString ProjectDocumentationPlugin::pluginName() const +{ + return m_docPlugin->pluginName(); +} + +TQString ProjectDocumentationPlugin::catalogURL() const +{ + return m_url; +} + +#include "tdevdocumentationplugin.moc" |