diff options
Diffstat (limited to 'parts/documentation/interfaces/kdevdocumentationplugin.cpp')
| -rw-r--r-- | parts/documentation/interfaces/kdevdocumentationplugin.cpp | 721 | 
1 files changed, 721 insertions, 0 deletions
| diff --git a/parts/documentation/interfaces/kdevdocumentationplugin.cpp b/parts/documentation/interfaces/kdevdocumentationplugin.cpp new file mode 100644 index 00000000..afc9abad --- /dev/null +++ b/parts/documentation/interfaces/kdevdocumentationplugin.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 "kdevdocumentationplugin.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("kdevdocumentation/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("kdevdocumentation/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 "kdevdocumentationplugin.moc" | 
