summaryrefslogtreecommitdiffstats
path: root/kpdf/ui/toc.cpp
blob: 015ba313a797c8c49e6908d30858f4558dc9a438 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/***************************************************************************
 *   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 <klocale.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 KListViewItem
{
    public:
        TOCItem( KListView *parent, TOCItem *after, const TQDomElement & e )
            : KListViewItem( 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( KListViewItem *parent, TOCItem *after, const TQDomElement & e )
            : KListViewItem( 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) : KListView(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, KListViewItem * 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"