Changeset 60

Show
Ignore:
Timestamp:
04/14/06 12:08:30 (2 years ago)
Author:
jordi
Message:

The document's outlines are now loaded correctly, although I don't like the way is set up now...

Location:
trunk
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/DocumentOutline.cxx

    r58 r60  
    1717 
    1818#include <config.h> 
     19 
     20// Poppler headers 
     21#include <goo/GooList.h> 
     22#include <Outline.h> 
     23#include <PDFDoc.h> 
     24#include <Link.h> 
     25 
    1926#include "epdfview.h" 
    2027 
    2128using namespace ePDFView; 
    2229 
     30/// Forward declarations. 
     31static void deleteChild (gpointer child, gpointer userData); 
     32 
    2333/// 
    2434/// @brief Constructs a new DocumentOutline. 
    2535/// 
    26 DocumentOutline::DocumentOutline () 
    27 { 
     36DocumentOutline::DocumentOutline (PDFDoc *document) 
     37{ 
     38    m_Destination = 1; 
     39    m_Document = document; 
     40    m_Children = NULL; 
     41    m_LastReturnedChild = NULL; 
     42    m_Parent = NULL; 
     43    m_Title = NULL; 
    2844} 
    2945 
     
    3349DocumentOutline::~DocumentOutline () 
    3450{ 
     51    m_Document = NULL; 
     52    m_Parent = NULL; 
     53    g_free (m_Title); 
     54    /// Delete the children. 
     55    g_list_foreach (m_Children, deleteChild, NULL); 
     56    g_list_free (m_Children); 
    3557} 
    3658 
     
    5072DocumentOutline::getDestinationPage () 
    5173{ 
    52     return 1; 
     74    return m_Destination; 
    5375} 
    5476 
     
    6284DocumentOutline::getFirstChild () 
    6385{ 
     86    m_LastReturnedChild = g_list_first (m_Children); 
     87    if ( NULL != m_LastReturnedChild ) 
     88    { 
     89        return (DocumentOutline *)m_LastReturnedChild->data; 
     90    } 
     91    return NULL; 
     92} 
     93 
     94/// 
     95/// @brief Gets the next outline's child. 
     96/// 
     97/// @returns The next child after the one returned by the last call to  
     98///          getFirstChild() or getNextChild(). 
     99///          If no child has been returned yet (i.e., getFirstChild() hasn't 
     100///          been called yet) or there's no next child returns NULL. 
     101/// 
     102DocumentOutline * 
     103DocumentOutline::getNextChild () 
     104{ 
     105    m_LastReturnedChild = g_list_next (m_LastReturnedChild); 
     106    if ( NULL != m_LastReturnedChild ) 
     107    { 
     108        return (DocumentOutline *)m_LastReturnedChild->data; 
     109    } 
    64110    return NULL; 
    65111} 
     
    73119DocumentOutline::getNumChildren () 
    74120{ 
    75     return 0; 
     121    return g_list_length (m_Children); 
    76122} 
    77123 
     
    85131DocumentOutline::getTitle () 
    86132{ 
    87     return ""; 
    88 } 
     133    if ( NULL == m_Title ) 
     134    { 
     135        return ""; 
     136    } 
     137    return m_Title; 
     138} 
     139 
     140void 
     141DocumentOutline::setDestination (gint destination) 
     142{ 
     143    m_Destination = destination; 
     144} 
     145 
     146void 
     147DocumentOutline::setChildren (GooList *childrenList) 
     148{ 
     149    if ( NULL != childrenList ) 
     150    { 
     151        int numChildren = childrenList->getLength (); 
     152        for ( int childIndex = 0; childIndex < numChildren; childIndex++) 
     153        { 
     154            OutlineItem *item = (OutlineItem *)childrenList->get (childIndex); 
     155            // Get the title. 
     156            gchar *title = g_ucs4_to_utf8 (item->getTitle (),  
     157                                           item->getTitleLength (), 
     158                                           NULL, NULL, NULL);             
     159            // The page destination. 
     160            gint destination = 1; 
     161            LinkAction *action = item->getAction (); 
     162            if ( NULL != action ) 
     163            { 
     164                if ( action->isOk () && actionGoTo == action->getKind () ) 
     165                { 
     166                    LinkDest *dest = ((LinkGoTo *)action)->getDest (); 
     167                    if ( dest->isOk () && dest->isPageRef () ) 
     168                    { 
     169                        Ref ref = dest->getPageRef (); 
     170                        destination = m_Document->findPage (ref.num, ref.gen); 
     171                    } 
     172                    else if ( dest->isOk () ) 
     173                    { 
     174                        destination = dest->getPageNum (); 
     175                    } 
     176                } 
     177            } 
     178            // Create the child. 
     179            DocumentOutline *child = new DocumentOutline (m_Document); 
     180            child->setParent (this); 
     181            child->setTitle (title); 
     182            g_free (title); 
     183            child->setDestination (destination); 
     184            // Add to the list of children. 
     185            m_Children = g_list_append (m_Children, child); 
     186            // And add its own children. 
     187            if ( item->hasKids () ) 
     188            { 
     189                // I need to open the outline because if it's not  
     190                // open then the getKids() function returns NULL. 
     191                item->open (); 
     192                child->setChildren (item->getKids ()); 
     193            } 
     194        } 
     195    } 
     196} 
     197 
     198/// 
     199/// @brief Sets the outline. 
     200/// 
     201/// This is only called for the root outline element when loading a document. 
     202/// Fills in the list of outline items from the document. 
     203/// 
     204/// @param outline The outline from the documents. 
     205/// 
     206void 
     207DocumentOutline::setOutline (Outline *outline) 
     208{ 
     209    g_assert (NULL != outline && "Tried to set a NULL outline."); 
     210     
     211    setTitle (""); 
     212    setDestination (1); 
     213         
     214    setChildren (outline->getItems ()); 
     215} 
     216 
     217void 
     218DocumentOutline::setParent (DocumentOutline *parent) 
     219{ 
     220    m_Parent = parent; 
     221} 
     222 
     223void 
     224DocumentOutline::setTitle (const char *title) 
     225{ 
     226    g_assert (NULL != title && "Tried to set a NULL title."); 
     227 
     228    g_free (m_Title); 
     229    m_Title = g_strdup (title); 
     230} 
     231 
     232void 
     233deleteChild (gpointer child, gpointer userData) 
     234{ 
     235    g_assert ( NULL != child && "An outline's child is NULL!"); 
     236     
     237    DocumentOutline *outline = (DocumentOutline *)child; 
     238    delete outline; 
     239} 
  • trunk/src/DocumentOutline.h

    r58 r60  
    1919#define __DOCUMENT_OUTLINE_H__ 
    2020 
     21// Forward declarations. 
     22class PDFDoc; 
     23class Outline; 
     24class GooList; 
     25 
    2126namespace ePDFView 
    2227{ 
     
    3742    { 
    3843        public: 
    39             DocumentOutline (void); 
     44            DocumentOutline (PDFDoc *document); 
    4045            ~DocumentOutline (void); 
    4146 
    4247            gint getDestinationPage (void); 
    4348            DocumentOutline *getFirstChild (void); 
     49            DocumentOutline *getNextChild (void); 
    4450            gint getNumChildren (void); 
    4551            const gchar *getTitle (void); 
     52            void setOutline (Outline *outline); 
     53 
     54        private: 
     55            GList *m_Children; 
     56            gint m_Destination; 
     57            PDFDoc *m_Document; 
     58            GList *m_LastReturnedChild; 
     59            DocumentOutline *m_Parent; 
     60            gchar *m_Title; 
     61 
     62            void setChildren (GooList *childrenList); 
     63            void setParent (DocumentOutline *parent); 
     64            void setTitle (const gchar *title); 
     65            void setDestination (gint destination); 
    4666    }; 
    4767} 
  • trunk/src/IDocument.cxx

    r58 r60  
    127127    m_Creator = NULL; 
    128128    m_CurrentPage = 0; 
    129     m_Outline = new DocumentOutline (); 
     129    m_Outline = NULL; 
    130130    m_FileName = NULL; 
    131131    m_Format = NULL; 
  • trunk/src/PDFDocument.cxx

    r58 r60  
    124124    delete m_Document; 
    125125    m_Document = newDocument; 
     126    // Load the document's information and outline. 
    126127    loadMetadata (); 
     128    m_Outline = new DocumentOutline (m_Document); 
     129    m_Outline->setOutline (m_Document->getOutline ()); 
    127130    // Set the output device. 
    128131    delete m_OutputDevice; 
  • trunk/tests/DocumentOutlineTest.cxx

    r59 r60  
    5151{ 
    5252    CPPUNIT_ASSERT ( !m_Document->isLoaded ()); 
    53     DocumentOutline *outline = m_Document->getOutline (); 
    54     // The initial state of the outline is no outline at all. 
    55     CPPUNIT_ASSERT_EQUAL (0, outline->getNumChildren ()); 
    56     CPPUNIT_ASSERT (0 == g_ascii_strcasecmp ("", outline->getTitle ())); 
    57     CPPUNIT_ASSERT_EQUAL (1, outline->getDestinationPage ()); 
    58     CPPUNIT_ASSERT (NULL == outline->getFirstChild ()); 
     53    CPPUNIT_ASSERT ( NULL == m_Document->getOutline ()); 
    5954} 
    6055 
     
    6358/// 
    6459/// When a loaded document doesn't have an outline, the DocumentOutline's 
    65 /// behaviour is exactly the same as the initial status. 
     60/// is empty. 
    6661/// 
    6762void 
     
    7267    CPPUNIT_ASSERT (m_Document->isLoaded ()); 
    7368    DocumentOutline *outline = m_Document->getOutline (); 
     69    CPPUNIT_ASSERT ( NULL != outline ); 
    7470    CPPUNIT_ASSERT_EQUAL (0, outline->getNumChildren ()); 
    7571    CPPUNIT_ASSERT (0 == g_ascii_strcasecmp ("", outline->getTitle ())); 
    7672    CPPUNIT_ASSERT_EQUAL (1, outline->getDestinationPage ()); 
    7773    CPPUNIT_ASSERT (NULL == outline->getFirstChild ()); 
     74    CPPUNIT_ASSERT (NULL == outline->getNextChild ()); 
    7875} 
     76 
     77/// 
     78/// @brief Test a file that has outline. 
     79/// 
     80/// The document I've gone test has the following outline: 
     81/// 
     82///  * 
     83///  | 
     84///  +- Test PDF 1 / page 3 
     85///  | 
     86///  +- Table of Contents / page 4 
     87///  | 
     88///  +- Chapter 1. First Chapter / page 5 
     89///     | 
     90///     + First Section / page 5 
     91/// 
     92void 
     93DocumentOutlineTest::hasOutline () 
     94{ 
     95    CPPUNIT_ASSERT (m_Document->loadFile (TEST_DATA_DIR "test1.pdf", 
     96                                          NULL, NULL)); 
     97    CPPUNIT_ASSERT (m_Document->isLoaded ()); 
     98    DocumentOutline *outline = m_Document->getOutline (); 
     99    CPPUNIT_ASSERT ( NULL != outline ); 
     100    // The root outline must be the same empy one, except it has children. 
     101    CPPUNIT_ASSERT_EQUAL (3, outline->getNumChildren ()); 
     102    CPPUNIT_ASSERT (0 == g_ascii_strcasecmp ("", outline->getTitle ())); 
     103    CPPUNIT_ASSERT_EQUAL (1, outline->getDestinationPage ()); 
     104 
     105    { 
     106        DocumentOutline *child = outline->getFirstChild(); 
     107        CPPUNIT_ASSERT ( NULL != child ); 
     108        CPPUNIT_ASSERT_EQUAL (0, child->getNumChildren ()); 
     109        CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp ("Test PDF 1",  
     110                                                     child->getTitle ())); 
     111        CPPUNIT_ASSERT_EQUAL (3, child->getDestinationPage ()); 
     112    } 
     113     
     114    { 
     115        DocumentOutline *child = outline->getNextChild(); 
     116        CPPUNIT_ASSERT ( NULL != child ); 
     117        CPPUNIT_ASSERT_EQUAL (0, child->getNumChildren ()); 
     118        CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp ("Table of Contents",  
     119                                                     child->getTitle ())); 
     120        CPPUNIT_ASSERT_EQUAL (4, child->getDestinationPage ()); 
     121    } 
     122 
     123    { 
     124        DocumentOutline *child = outline->getNextChild(); 
     125        CPPUNIT_ASSERT ( NULL != child ); 
     126        CPPUNIT_ASSERT_EQUAL (1, child->getNumChildren ()); 
     127        CPPUNIT_ASSERT_EQUAL (0, 
     128                              g_ascii_strcasecmp ("Chapter 1. First Chapter", 
     129                                                  child->getTitle ())); 
     130        CPPUNIT_ASSERT_EQUAL (5, child->getDestinationPage ()); 
     131 
     132        DocumentOutline *greatChild = child->getFirstChild (); 
     133        CPPUNIT_ASSERT ( NULL != greatChild ); 
     134        CPPUNIT_ASSERT_EQUAL (0, greatChild->getNumChildren ()); 
     135        CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp ("First Section", 
     136                                                     greatChild->getTitle ())); 
     137        CPPUNIT_ASSERT_EQUAL (5, greatChild->getDestinationPage ()); 
     138    } 
     139 
     140    // After the last child, it should return NULL. 
     141    CPPUNIT_ASSERT (NULL == outline->getNextChild ()); 
     142 
     143    // Try again the "no outlined" file. 
     144    noOutline (); 
     145} 
  • trunk/tests/DocumentOutlineTest.h

    r59 r60  
    2828        CPPUNIT_TEST (initialStatus); 
    2929        CPPUNIT_TEST (noOutline); 
     30        CPPUNIT_TEST (hasOutline); 
    3031        CPPUNIT_TEST_SUITE_END (); 
    3132 
     
    3637            void initialStatus (void); 
    3738            void noOutline (void); 
     39            void hasOutline (void); 
    3840 
    3941        protected: