/***************************************************************************
 *   Copyright (C) 2004-2006 by Albert Astals Cid <tsdgeos@terra.es>       *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/

// qt/kde includes
#include <tqheader.h>
#include <tqvariant.h>
#include <tdelocale.h>

// local includes
#include "toc.h"
#include "core/link.h"
#include "core/page.h"

// uncomment following to enable a 2nd column showing the page referred
// by each tree entry note: PDF uses often references to viewports and
// they're slow when converted to page number. drop the 2nd column idea.
//#define TOC_ENABLE_PAGE_COLUMN

class TOCItem : public TDEListViewItem
{
    public:
        TOCItem( TDEListView *parent, TOCItem *after, const TQDomElement & e )
            : TDEListViewItem( parent, after, e.tagName() ), m_element( e )
        {
#ifdef TOC_ENABLE_PAGE_COLUMN
            if ( e.hasAttribute( "Page" ) )
                setText( 1, e.attribute( "Page" ) );
#endif
            setMultiLinesEnabled(true);
        }

        TOCItem( TDEListViewItem *parent, TOCItem *after, const TQDomElement & e )
            : TDEListViewItem( parent, after, e.tagName() ), m_element( e )
        {
#ifdef TOC_ENABLE_PAGE_COLUMN
            if ( e.hasAttribute( "Page" ) )
                setText( 1, e.attribute( "Page" ) );
#endif
            setMultiLinesEnabled(true);
        }

        const TQDomElement & element() const
        {
            return m_element;
        }

    private:
        TQDomElement m_element;
};

TOC::TOC(TQWidget *parent, KPDFDocument *document) : TDEListView(parent), m_document(document)
{
    addColumn( i18n("Topic") );
#ifdef TOC_ENABLE_PAGE_COLUMN
    addColumn( i18n("Page") );
#else
    header() -> hide();
#endif
    setSorting(-1);
    setRootIsDecorated(true);
    // the next line causes bug:147233
//    setResizeMode(AllColumns);
    setAllColumnsShowFocus(true);
    connect(this, TQT_SIGNAL(clicked(TQListViewItem *)), this, TQT_SLOT(slotExecuted(TQListViewItem *)));
    connect(this, TQT_SIGNAL(returnPressed(TQListViewItem *)), this, TQT_SLOT(slotExecuted(TQListViewItem *)));
}

TOC::~TOC()
{
    m_document->removeObserver( this );
}

uint TOC::observerId() const
{
    return TOC_ID;
}

void TOC::notifySetup( const TQValueVector< KPDFPage * > & /*pages*/, bool documentChanged )
{
    if ( !documentChanged )
        return;

    // clear contents
    clear();

    // request synopsis description (is a dom tree)
    const DocumentSynopsis * syn = m_document->documentSynopsis();

    // if not present, disable the contents tab
    if ( !syn )
    {
        emit hasTOC( false );
        return;
    }

    // else populate the listview and enable the tab
    addChildren( *syn );
    emit hasTOC( true );
}

void TOC::addChildren( const TQDomNode & parentNode, TDEListViewItem * parentItem )
{
    // keep track of the current listViewItem
    TOCItem * currentItem = 0;
    TQDomNode n = parentNode.firstChild();
    while( !n.isNull() )
    {
        // convert the node to an element (sure it is)
        TQDomElement e = n.toElement();

        // insert the entry as top level (listview parented) or 2nd+ level
        if ( !parentItem )
            currentItem = new TOCItem( this, currentItem, e );
        else
            currentItem = new TOCItem( parentItem, currentItem, e );

        // descend recursively and advance to the next node
        if ( e.hasChildNodes() )
            addChildren( n, currentItem );

        // open/keep close the item
        bool isOpen = false;
        if ( e.hasAttribute( "Open" ) )
            isOpen = TQVariant( e.attribute( "Open" ) ).toBool();
        currentItem->setOpen( isOpen );

        n = n.nextSibling();
    }
}

void TOC::slotExecuted( TQListViewItem *i )
{
    TOCItem* tocItem = dynamic_cast<TOCItem*>( i );
    // that filters clicks on [+] that for a strange reason don't seem to be TOCItem*
    if (tocItem == NULL)
        return;
    const TQDomElement & e = tocItem->element();

    TQString externalFileName = e.attribute( "ExternalFileName" );
    if ( !externalFileName.isEmpty() )
    {
        KPDFLinkGoto link( externalFileName, getViewport( e ) );
        m_document->processLink( &link );
    }
    else
    {
        m_document->setViewport( getViewport( e ), TOC_ID );
    }
}

DocumentViewport TOC::getViewport( const TQDomElement &e ) const
{
    if ( e.hasAttribute( "Viewport" ) )
    {
        // if the node has a viewport, set it
        return DocumentViewport( e.attribute( "Viewport" ) );
    }
    else if ( e.hasAttribute( "ViewportName" ) )
    {
        // if the node references a viewport, get the reference and set it
        const TQString & page = e.attribute( "ViewportName" );
        const TQString & viewport = m_document->getMetaData( "NamedViewport", page );
        if ( !viewport.isNull() )
            return DocumentViewport( viewport );
    }
    return DocumentViewport();
}

#include "toc.moc"
