File: BasicElement.h

package info (click to toggle)
calligra 1%3A3.2.1%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 261,632 kB
  • sloc: cpp: 650,836; xml: 27,662; python: 6,044; perl: 2,724; yacc: 1,817; ansic: 1,325; sh: 1,277; lex: 1,107; ruby: 1,010; javascript: 495; makefile: 17
file content (345 lines) | stat: -rw-r--r-- 12,882 bytes parent folder | download | duplicates (2)
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/* This file is part of the KDE project
   Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
                      Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
   Copyright (C) 2006 Martin Pfeiffer <hubipete@gmx.net>
   Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
                 2009 Jeremias Epperlein <jeeree@web.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#ifndef BASICELEMENT_H
#define BASICELEMENT_H

#include "koformula_export.h"
#include "ElementFactory.h"

#include <QHash>
#include <QList>
#include <QString>
#include <QRectF>
#include <QLineF>
class QPainter;
class QVariant;
class KoXmlWriter;
#include "KoXmlReaderForward.h"
class AttributeManager;
class FormulaCursor;
class QPainterPath;
class TableDataElement;

/**
 * @short The base class for all elements of a formula
 *
 * The BasicElement class is constructed with a parent and normally an element in a
 * formula has a parent. The only exception is FormulaElement which is the root of
 * the element tree and has no parent element.
 * Most of the elements have children but the number of it can be fixed or variable
 * and the type of child element is not certain. So with the childElements() method you
 * can obtain a list of all direct children of an element. Note that the returned list
 * can be empty when the element is eg a token. This is also the reason why each class
 * inheriting BasicElement has to implement the childElements() method on its own.
 * With the childElementAt method you can test if the given point is in the element.
 * This method is generically implemented for all element types only once in
 * BasicElement.
 * The BasicElement knows its size and position in the formula. This data is normally
 * only used for drawing and stored in the m_boundingRect attribute.
 * To adapt both variables, size and coordinates, to fit in the formula each and every
 * BasicElement derived class has to implement layoutElement().
 *
 * For cursor movement, an element has to implement elementBefore, elementAfter,
 * lastCursorPosition and positionOfChild as well as
 * moveCursor (keyboard navigation) and setCursorTo (cursor placement by clicking).
 */
class KOFORMULA_EXPORT BasicElement {
public:
    /*
     * The standard constructor
     * @param parent pointer to the BasicElement's parent
     */
    explicit BasicElement(BasicElement *parent = 0);

    /// The standard destructor
    virtual ~BasicElement();

    /**
     * Get the element of the formula at the given point
     * @param p the point to look for 
     * @return a pointer to a BasicElement
     */
    BasicElement* childElementAt( const QPointF& p );

    /**
     * Obtain a list of all child elements of this element - sorted in saving order
     * @return a QList with pointers to all child elements
     */
    virtual const QList<BasicElement*> childElements() const;

    /**
     * Replace a child element
     * @param oldelement the child to replace
     * @param newelement the child @p oldelement is replaced with
     */ 
    virtual bool replaceChild( BasicElement* oldelement, BasicElement* newelement );

    /**
     * Render the element to the given QPainter
     * @param painter The QPainter to paint the element to
     * @param am AttributeManager containing style info
     */
    virtual void paint( QPainter& painter, AttributeManager* am );

    /**
     * Render the editing hints of the element to the given QPainter
     * @param painter The QPainter to paint the element to
     * @param am AttributeManager containing style info
     */
    virtual void paintEditingHints( QPainter& painter, AttributeManager* am );

    
    /**
     * Calculate the minimum size of the element and the positions of its children
     *
     * Laying out the items is done in two parts.
     *
     * First layout() is called for the topmost element, which in turn calls
     * layout() for its children, and so on. This sets the minimum size of all elements.
     *
     * Then stretch() is called for the topmost element, which in turn calls
     * stretch() for its children, and so on.  This stretches elements that
     * are stretchable, up to their maximum size.
     *
     * @param am The AttributeManager providing information about attributes values
     */
    virtual void layout( const AttributeManager* am );

    /**
     * Calculate the stretched size of the element.  This is called after layouting.
     */
    virtual void stretch();

    /**
     * Implement the cursor behaviour for the element
     * @param cursor the cursor we test
     * @return true, if the element accepts the cursor
     */
    virtual bool acceptCursor( const FormulaCursor& cursor );
    
    /**
     * Return the coordinates of the line, where the cursor should be drawn
     * in coordinates relative to the formula element (or the flake shape)
     * @param position The position of FormulaCursor
     * @return the cursor line
     */
    virtual QLineF cursorLine(int position) const;
    
    virtual QPainterPath selectionRegion(const int pos1, const int pos2) const;
    
    virtual QList<BasicElement*> elementsBetween(int pos1, int pos2) const;
    
    /**
     * Move the cursor in the direction specified in cursor
     * @param newcursor the cursor we move around
     * @param oldcursor the former cursor position
     * @return true, if we moved the cursor
     */
    virtual bool moveCursor(FormulaCursor& newcursor, FormulaCursor& oldcursor);
    
    /// @return The element's ElementType
    virtual ElementType elementType() const;

    /// Set the element's width to @p width
    void setWidth( qreal width );

    /// @return The width of the element
    qreal width() const;

    /// Set the element's height to @p height
    void setHeight( qreal height );

    /// @return The height of the element
    qreal height() const;

    /// @return The bounding rectangle of the element
    const QRectF& boundingRect() const;

    /// @return The absolute bounding rectangle of the element
    const QRectF absoluteBoundingRect() const;

    /**
     * place the cursor at the given point
     * the point should be placed a the position in the element 
     * (or it's child) that is closest to the point
     * in particular the point doesn't have to be within 
     * boundingBox()
     * @param cursor The FormulaCursor to modify
     * @param point The point in coordinates relative to the elements local coordinate system
     * @return true, iff the cursor could be placed
     **/
    virtual bool setCursorTo(FormulaCursor& cursor, QPointF point);

    /// @return The bounding rectangle of the children, relative to the element
    const QRectF& childrenBoundingRect() const;

    /// Set the bounding rectangle of the children, relative to the element
    void setChildrenBoundingRect(const QRectF &rect);

    /// Set the element's baseline to @p baseLine
    void setBaseLine( qreal baseLine );

    /// @return The baseline of the element
    qreal baseLine() const;

    /// Set the element's origin inside the m_parentElement to @p origin
    void setOrigin( QPointF origin );

    /// @return The element's origin 
    QPointF origin() const;

    /// Set the element's m_parentElement to @p parent
    void setParentElement( BasicElement* parent );

    /// @return The parent element of this BasicElement
    BasicElement* parentElement() const;

    /// @return The last cursor position (number of available cursor positions - 1)
    virtual int endPosition() const;
    
    /** 
     * @return the cursor position before the child in this element and -1 if it isn't a child
     * @param child  the childelement we are looking for
     */
    virtual int positionOfChild(BasicElement* child) const;
        
    /// @return the element right before the cursor position @p position and 0 if there is none
    virtual BasicElement* elementBefore(int position) const;
    
    /// @return the element right after the cursor position @p position and 0 if there is none
    virtual BasicElement* elementAfter(int position) const;
    
    /// Set the element's m_scaleFactor to @p scaleFactor
    void setScaleFactor( qreal scaleFactor );

    /// @return The elements scale factor
    qreal scaleFactor() const;

    /// Set the elements scale level and sets the scale factor
    void setScaleLevel( int scaleLevel );

    /// @return The elements scale level
    int scaleLevel() const;

    /**
     * Set an attribute's value
     * @param name The name of the attribute to be set
     * @param value The value to set for the attribute
     */
    void setAttribute( const QString& name, const QVariant& value );

    /// @return The value of the attribute if it is set for this element
    QString attribute( const QString& attribute ) const;

    /// @return The value of the attribute if it is inherited
    virtual QString inheritsAttribute( const QString& attribute ) const;

    /// @return The default value of the attribute for this element
    virtual QString attributesDefaultValue( const QString& attribute ) const;

    /// Whether displaystyle is set
    bool displayStyle() const;
    
    /// Whether displaystyle is set.  This is updated by FormulaRenderer
    void setDisplayStyle(bool displayStyle);

    /// Read the element from MathML
    bool readMathML( const KoXmlElement& element );

    /// Save the element to MathML 
    void writeMathML( KoXmlWriter* writer, const QString& ns = "math" ) const;

    /// @return true, if @p other is a descendant of this element
    bool hasDescendant(BasicElement* other) const;

    /// @return first empty element, that is a descendant of this element, if there is one
    BasicElement* emptyDescendant();

    /// @return true, when the element is empty
    virtual bool isEmpty() const;

    /// @return true, if the element is an inferred mrow
    virtual bool isInferredRow() const;

    /// @return the formula element that is a descendant of this element
    BasicElement* formulaElement();

    /** writes the child element tree to qDebug()
     *  only for debugging purpose
     *  @param wrong indicates, if the parent is set wrong
     *  @param indent indention level
     */
    virtual void writeElementTree(int indent=0, bool wrong=false) const;

    /// return the content of the element to qDebug(), only for debugging
    virtual const QString writeElementContent() const;
    
    /// @return the first TableDataElement among the elements ancestors or 0 if there is none
    TableDataElement* parentTableData();

protected:
    /// Read all attributes loaded and add them to the m_attributes map 
    virtual bool readMathMLAttributes( const KoXmlElement& element );

    /// Read all content from the node - reimplemented by child elements
    virtual bool readMathMLContent( const KoXmlElement& element );

    /// Write all attributes of m_attributes to @p writer
    virtual void writeMathMLAttributes( KoXmlWriter* writer ) const;

    /// Write all content to the KoXmlWriter - reimplemented by the child elements
    virtual void writeMathMLContent( KoXmlWriter* writer, const QString& ns ) const;

    static void cleanElementTree(BasicElement* element);
    
private:
    /// The element's parent element - might not be null except of FormulaElement
    BasicElement* m_parentElement;

    /// A hash map of all attributes where attribute name is assigned to a value
    QHash<QString,QString> m_attributes;

    /// The boundingRect storing the element's width, height, x and y
    QRectF m_boundingRect;
    
    /** The boundingRect storing the child element's width, height, x and y
     *  The bottomRight hand corner will always be small that then size of
     *  m_boundingRect
     */
    QRectF m_childrenBoundingRect;

    /// The position of our base line from the upper border
    qreal m_baseLine;

    /// Factor with which this element is scaled down by
    qreal m_scaleFactor;

    /// Scale level with which this element is scaled down by
    qreal m_scaleLevel;

    /// Indicates whether this element has displaystyle set
    bool m_displayStyle;
};

#endif // BASICELEMENT_H