File: custom_qtextobject.dox

package info (click to toggle)
grantlee5 5.1.0-2.1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 4,152 kB
  • sloc: cpp: 24,299; python: 413; sh: 108; ruby: 24; makefile: 20
file content (131 lines) | stat: -rw-r--r-- 4,493 bytes parent folder | download | duplicates (5)
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

namespace Grantlee
{

/**
  @page custom_qtextobject Handling custom QTextObjects

  It is possible using the QTextObjectInterface API to construct QTextDocuments containing custom text objects. If processing a QTextDocument
  containing custom objects through the MarkupDirector and AbstractMarkupBuilder classes, it is necessary to implement support for the custom types
  in %Grantlee.

  In this example, we create a builder with a new method <tt>addAudioTag</tt>. As it may be desired to implement multiple builders
  with support for the <tt>addAudioTag</tt> method, it makes sense to put that call into an interface.

  @code
    class AbstractAudioBuilder : virtual public Grantlee::AbstractMarkupBuilder
    {
    public:
      virtual void addAudioTag( const QString &source ) = 0;
    };
  @endcode

  We create a small interface for supporting the addition of audio markup. The interface should inherit virtually from the
  AbstractMarkupBuilder interface, so that functionality from through that interface is also available.

  Customized builders inheriting from an existing builder and the new interface can then be created.

  @code
    class AudioTextHtmlBuilder : public Grantlee::TextHTMLBuilder, public AbstractAudioBuilder
    {
    public:
      AudioTextHtmlBuilder();

      /* reimp */ void addAudioTag( const QString &source );
    };

    class AudioPlainTextBuilder : public Grantlee::PlainTextMarkupBuilder, public AbstractAudioBuilder
    {
    public:
      AudioPlainTextBuilder();

      /* reimp */ void addAudioTag( const QString &source );
    };
  @endcode

  The implementation of each concrete builder is appropriate to the type of markup being created.

  @code
    void AudioTextHtmlBuilder::addAudioTag( const QString &source )
    {
      appendRawText( QString( "<audio src=\"%1\" />").arg( source ) );
    }

    void AudioPlainTextBuilder::addAudioTag(const QString& source)
    {
      int ref = addReference( source );
      appendRawText( QString( "[%1]" ).arg( ref ) );
    }
  @endcode

  The final part to be implemented is support for the custom type in a MarkupDirector.
  The MarkupDirector::processCustomFragment method is called for any QTextFragments with custom QTextFormat types. This method can be implemented
  to instruct the builder to create appropriate output for the type.

  @code
    class AudioTextDocumentDirector : public Grantlee::MarkupDirector
    {
    public:

      AudioTextDocumentDirector(AbstractAudioBuilder* builder);

      /* reimp */ void processCustomFragment( const QTextFragment& fragment, const QTextDocument* doc);

    private:
      AbstractAudioBuilder *m_builder;
    };
  @endcode

  We create a subclass of Grantlee::MarkupDirector to take our new <tt>AbstractAudioBuilder</tt> interface and implement the processCustomFragment method to handle QTextFragments with our custom format type. The name of the audio file referenced in the document is then extracted and used as a parameter in the <tt>addAudioTag</tt> method.

  @code
    AudioTextDocumentDirector::AudioTextDocumentDirector(AbstractAudioBuilder* builder)
      : MarkupDirector(builder), m_builder(builder)
    {

    }

    void AudioTextDocumentDirector::processCustomFragment(const QTextFragment& fragment, const QTextDocument* doc)
    {
      if ( fragment.charFormat().objectType() != AudioType )
        return Grantlee::MarkupDirector::processCustomFragment( fragment, doc );

      QString name = fragment.charFormat().property( AudioProperty ).toString();

      m_builder->addAudioTag( name );
    }
  @endcode

  The custom AudioTextDocumentDirector and builders can then be used to create output including markup for custom types.

  @code
    AudioTextHtmlBuilder *builder = new AudioTextHtmlBuilder();
    AudioTextDocumentDirector *director = new AudioTextDocumentDirector(builder);

    director->processDocument(document);
    QString result = builder->getResult();
  @endcode

  In a simple case, this could create output such as:

  @verbatim
    <p>Here is a paragraph with an inline audio element: <audio src="http://www.example.com/mysound.ogg" />.

    <p>And another paragraph.
  @endverbatim

  or if the AudioPlainTextBuilder was used instead:

  @verbatim
    Here is a paragraph with an inline audio element: [1].

    And another paragraph.

    ----
    [1] http://www.example.com/mysound.ogg
  @endverbatim

  The textedit example in the %Grantlee source distribution implements this feature.
*/

}