summaryrefslogtreecommitdiff
path: root/src/backend/rendering/cbookdisplay.cpp
blob: 259e904739ea037267bd07d7937ccc441506d010 (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
/*********
*
* This file is part of BibleTime's source code, http://www.bibletime.info/.
*
* Copyright 1999-2011 by the BibleTime developers.
* The BibleTime source code is licensed under the GNU General Public License version 2.0.
*
**********/

#include "backend/rendering/cbookdisplay.h"

#include <QSharedPointer>
#include <QtAlgorithms>

#include "backend/drivers/cswordbookmoduleinfo.h"
#include "backend/keys/cswordtreekey.h"
#include "backend/rendering/cdisplayrendering.h"


const QString Rendering::CBookDisplay::text(
        const QList<const CSwordModuleInfo*> &modules,
        const QString &keyName,
        const DisplayOptions &displayOptions,
        const FilterOptions &filterOptions)
{
    typedef CSwordBookModuleInfo CSBMI;

    const CSBMI* book = dynamic_cast<const CSBMI*>(modules.first());
    Q_ASSERT(book);

    DisplayOptions dOpts = displayOptions;
    dOpts.lineBreaks = true; //books should render with blocks, not with inlined sections

    CDisplayRendering render(dOpts, filterOptions);
    CDisplayRendering::KeyTree tree;
    CDisplayRendering::KeyTreeItem::Settings itemSettings;

    // the number of levels which should be display together, 1 means display no entries together
    int displayLevel = book->config( CSwordModuleInfo::DisplayLevel ).toInt();

    QSharedPointer<CSwordTreeKey> key (
        dynamic_cast<CSwordTreeKey*>( CSwordKey::createInstance(book) )
    );
    key->setKey(keyName); //set the key to position we'd like to get

    const unsigned long offset = key->getOffset();

    // standard of DisplayLevel, display nothing together
    // if the current key is the root entry don't display anything together!

    if ((displayLevel <= 1) || (key->key().isEmpty() || (key->key() == "/") )) {
        tree.append( new CDisplayRendering::KeyTreeItem( key->key(), modules, itemSettings ) );

        const QString renderedText = render.renderKeyTree(tree);
        key->setOffset( offset );

        qDeleteAll(tree);      // Dispose of the heap allocated objects pointed to in tree.
        return renderedText;
    };

    /**
    * Check whether displaying displayLevel levels together is possible.
    * For this count the childs and parents
    * of the required position
    */

    int possibleLevels = 1; //we start with the default value of displayLevel, which means no entries together

    while ( key->sword::TreeKeyIdx::parent() && (key->key() != "/") && !key->key().isEmpty() ) {//add parents
        ++possibleLevels;
    };

    //   key->key(keyName); //set the key to the start position

    key->setOffset( offset );

    while ( key->firstChild( )) { //add childs
        ++possibleLevels;
    };

    if (possibleLevels < displayLevel) { //too few levels available!
        //display current level, we could also decide to display the available levels together
        tree.append( new CDisplayRendering::KeyTreeItem( key->key(), modules, itemSettings ) );

        const QString renderedText = render.renderKeyTree(tree);
        key->setOffset( offset );
        qDeleteAll(tree);      // Dispose of the heap allocated objects pointed to in tree.
        return renderedText;
    };

    if ((displayLevel > 2) && (displayLevel == possibleLevels)) { //fix not to diplay the whole module
        --displayLevel;
    }

    // at this point we're sure that we can display the required levels toogether
    // at the moment we're at the lowest level, so we only have to go up!
    for (int currentLevel = 1; currentLevel < displayLevel; ++currentLevel) { //we start again with 1 == standard of displayLevel

        if ( !key->sword::TreeKeyIdx::parent() ) { //something went wrong although we checked before! Be safe and return entry's text
            tree.append( new CDisplayRendering::KeyTreeItem( key->key(), modules, itemSettings ) );

            const QString renderedText = render.renderKeyTree(tree);
            key->setOffset( offset );
            qDeleteAll(tree);      // Dispose of the heap allocated objects pointed to in tree.
            return renderedText;
        };
    };

    // no we can display all sub levels together! We checked before that this is possible!
    itemSettings.highlight = (key->key() == keyName);

    tree.append( new CDisplayRendering::KeyTreeItem( key->key(), modules, itemSettings ) );

    //const bool hasToplevelText = !key->strippedText().isEmpty();
    key->firstChild(); //go to the first sibling on the same level

    setupRenderTree(key.data(), &tree, keyName);

    const QString renderedText = render.renderKeyTree(tree);

    key->setOffset( offset ); //restore key

    qDeleteAll(tree);      // Dispose of the heap allocated objects pointed to in tree.
    return renderedText;
}

void Rendering::CBookDisplay::setupRenderTree(CSwordTreeKey * swordTree, CTextRendering::KeyTree * renderTree, const QString& highlightKey) {

    const QString key = swordTree->key();
    const unsigned long offset = swordTree->getOffset();

    CTextRendering::KeyTreeItem::Settings settings;
    settings.highlight = (key == highlightKey);

    /// \todo Check whether this is correct:
    CTextRendering::KeyTreeItem *item = new CTextRendering::KeyTreeItem(
            key, swordTree->module(), settings);
    renderTree->append( item );

    if (swordTree->hasChildren()) { //print tree for the child items
        swordTree->firstChild();
        setupRenderTree(swordTree, item->childList(), highlightKey);
        swordTree->setOffset( offset ); //go back where we came from
    }

    if (swordTree->nextSibling()) { //print tree for next entry on the same depth
        setupRenderTree(swordTree, renderTree, highlightKey);
        swordTree->setOffset( offset ); //return to the value we had at the beginning of this block!
    }
}