kformulacontainer.h 10.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* This file is part of the KDE project
   Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
	              Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.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 KFORMULACONTAINER_H
#define KFORMULACONTAINER_H

24
25
#include <QClipboard>
#include <QImage>
26
//#include <q3ptrlist.h>
27
#include <QObject>
28
#include <QStack>
29
#include <QString>
30
31
32
//Added by qt3to4:
#include <QTextStream>
#include <QKeyEvent>
Laurent Montel's avatar
Laurent Montel committed
33
#include <QDomElement>
34
35
36
#include <kcommand.h>
//#include <KoCommandHistory.h>
#include "kformuladefs.h"
Laurent Montel's avatar
Laurent Montel committed
37
#include <kformuladocument.h>
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
class QColorGroup;
class QKeyEvent;
class QPainter;

class KCommand;
class KPrinter;

KFORMULA_NAMESPACE_BEGIN

class BasicElement;
class Document;
class FormulaCursor;
class FormulaElement;
class IndexElement;
class PlainCommand;
class SymbolTable;


/**
 * The interface the elements expect from its document.
 *
 * Please don't mistake this class for Document.
 * This one represents one formula, the other one provides
 * the context in which the formulae exist.
 */
class FormulaDocument {
    // not allowed
    FormulaDocument( const FormulaDocument& ) {}
    FormulaDocument& operator=( const FormulaDocument& ) { return *this; }
public:

    FormulaDocument() {}
    virtual ~FormulaDocument() {}

    virtual void elementRemoval(BasicElement* /*child*/) {}
    virtual void changed() {}
    virtual void cursorHasMoved( FormulaCursor* ) {}
    virtual void moveOutLeft( FormulaCursor* ) {}
    virtual void moveOutRight( FormulaCursor* ) {}
    virtual void moveOutAbove( FormulaCursor* ) {}
    virtual void moveOutBelow( FormulaCursor* ) {}
    virtual void tell( const QString& /*msg*/ ) {}
    virtual void insertFormula( FormulaCursor* ) {}
    virtual void removeFormula( FormulaCursor* ) {}
    virtual void baseSizeChanged( int, bool ) {}
    virtual const SymbolTable& getSymbolTable() const = 0;
};


/**
 * The document. Actually only one part of the whole.
 * Provides everything to edit the formula.
 */
class KOFORMULA_EXPORT Container : public QObject, public FormulaDocument {
    friend class MimeSource;
    Q_OBJECT

    // no copying
    Container( const Container& );
    Container& operator= ( const Container& );

public:

    enum ViewActions { EXIT_LEFT, EXIT_RIGHT,
                       EXIT_ABOVE, EXIT_BELOW,
                       INSERT_FORMULA, REMOVE_FORMULA };

    /**
     * Constructs a new formula and register it with the document.
     *
     * @param doc the document we belong to.
     * @param pos the formulas position inside its document.
     * @param registerMe whether the formula is to be registered
     * with the document.
     */
    Container( Document* doc, int pos, bool registerMe=true );
    ~Container();

    /**
     * Needs to be called before anything else can be done with a
     * newly created formula! This is required to allow polymorphic
     * formulas. (The virtual method problem.)
     */
    void initialize();

    /**
     * Returns a new cursor. It points to the beginning of the
     * formula. The cursor gets no messages if the formula changes
     * so use this with care!
     */
    FormulaCursor* createCursor();

    /**
     * Gets called just before the child is removed from
     * the element tree.
     */
    void elementRemoval(BasicElement* child);

    /**
     * Gets called when ever something changes and we need to
     * recalc.
     */
    void changed();

    /**
     * Gets called when a request has the side effect of moving the
     * cursor. In the end any operation that moves the cursor should
     * call this.
     */
    void cursorHasMoved( FormulaCursor* );

    /**
     * Inside the formula occurred an event that must be handled
     * outside.
     */
    void moveOutLeft( FormulaCursor* );
    void moveOutRight( FormulaCursor* );
    void moveOutAbove( FormulaCursor* );
    void moveOutBelow( FormulaCursor* );
    void tell( const QString& msg );
    void removeFormula( FormulaCursor* );

    /**
     * Register and unregister this formula with its document.
     */
    void registerFormula( int pos=-1 );
    void unregisterFormula();

    /**
     * The base size changed. If not owned it uses the default one now.
     */
    void baseSizeChanged( int size, bool owned );

    /**
     * Draws the whole thing.
     */
    void draw( QPainter& painter, const QRect& r,
175
               const QPalette& palette, bool edit=false );
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
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

    /**
     * Draws the whole thing.
     */
    void draw( QPainter& painter, const QRect& r, bool edit=false );

    /**
     * Saves the data into the document.
     */
    void save( QDomElement &root );

    /**
     * Save formula as MathML.
     */
    void saveMathML( QTextStream& stream, bool oasisFormat = false );

    /**
     * Load function.
     * Load the formula from the specified file containing MathML .
     */
    bool loadMathML( const QDomDocument &doc, bool oasisFormat = false );

    /**
     * Loads a formula from the document.
     */
    bool load( const QDomElement &fe );

    /**
     * @returns Tex string for the formula
     */
    QString texString();

    QString formulaString();

    /**
     * Prints the formula.
     */
    void print(KPrinter& printer);

    /**
     * @returns an image that looks like out formula.
     */
    QImage drawImage( int width, int height );

    /**
     * @returns the cursor to be used for editing.
     */
    FormulaCursor* activeCursor();
    const FormulaCursor* activeCursor() const;

    /**
     * Sets the cursor that is to be used for any editing.
     *
     * The active cursor might 0. In this case you must not
     * request any change from the formula.
     */
    void setActiveCursor(FormulaCursor* cursor);

    /**
     * @returns the formula's size.
     */
    QRect boundingRect() const;

    /**
     * @returns the formula's size including its active cursor.
     */
    QRect coveredRect();

    double width() const;
    double height() const;

    /**
     * @returns the distance between the upper bound and the formulas
     * base line.
     */
    double baseline() const;

    /**
     * Moves the formula to a new location. This location will be the
     * upper left corner of the rectangle that is drawn by the painter.
     */
    void moveTo( int x, int y );

    /**
     * KWord uses a transformed painter to draw formulas, so every
     * formula has the internal position (0,0). But we might need to
     * sort our formulas according to their position inside the
     * document. (This is only needed for math formulas.)
     */
    virtual double getDocumentX() const { return -1; }
    virtual double getDocumentY() const { return -1; }
    virtual void setDocumentPosition( double /*x*/, double /*y*/ ) {}

    /**
     * Start the documents evaluation at this formula. This must be the
     * formula that changed. The formulas above it won't be affected
     * by this change.
     *
     * This has no meaning in not evaluating formulas.
     */
    virtual void startEvaluation() {}

    /**
     * Recalcs the formula and emits the .*Changed signals if needed.
     */
    void testDirty();

    /**
     * Recalc the formula.
     */
    virtual void recalc();

    /**
     * @returns true if there is no element.
     */
    bool isEmpty();

    /**
     * @returns the document this formula belongs to.
     */
    virtual Document* document() const;

    virtual const SymbolTable& getSymbolTable() const;

    int fontSize() const;

    /**
     * Sets the base font size of this formula.
     */
    void setFontSize( int pointSize, bool forPrint = false );

    void setFontSizeDirect( int pointSize );

    /**
        If the cursor is in a matrix, the matrix actions will be enabled, otherwise disabled.
    */
    void updateMatrixActions();

signals:

    /**
     * The cursor has been moved but the formula hasn't been
     * changed. The view that owns the cursor needs to know this.
     */
    void cursorMoved(FormulaCursor* cursor);

    /**
     * The cursor wants to leave this formula.
     */
    void leaveFormula( Container* formula, FormulaCursor* cursor, int cmd );

    /**
     * The formula has changed and needs to be redrawn.
     */
    void formulaChanged( int width, int height );
    void formulaChanged( double width, double height );

    /**
     * A message that might be a useful hint. Meant for the statusbar.
     */
    void statusMsg( const QString& msg );

    /**
     * A message that describes an error. Meant for a message box. (?)
     */
    void errorMsg( const QString& );

    /**
     * The element is going to leave the formula with and all its children.
     */
    void elementWillVanish(BasicElement* element);

    /**
     * Tells the cursors that we have just loaded a new formula.
     */
    void formulaLoaded(FormulaElement*);

    /**
     * We've got a new base size.
     */
    void baseSizeChanged( int );

public:

    /**
     * General input.
     */
    void input( QKeyEvent* event );

    void performRequest( Request* request );

    // There are a lot of thing we can do with the formula.

    /**
     * Insert data from the clipboard.
     */
    void paste();

    /**
     * Insert data from the document.
     */
    void paste( const QDomDocument& document, QString desc );

    /**
     * Copy the current selection to the clipboard.
     */
    void copy();

    /**
     * Copy and remove.
     */
    void cut();

protected:

Laurent Montel's avatar
Laurent Montel committed
391
    KCommandHistory* getHistory() const;
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

    /**
     * @returns the root of our element tree. That's the formula's structure.
     */
    FormulaElement* rootElement() const;

    /**
     * Factory method.
     */
    virtual FormulaElement* createMainSequence();

    void emitErrorMsg( const QString& );

private:

    /**
     * Execute the command if it makes sense.
     */
    void execute(KCommand *command);

    /**
     * Emits a signal if the cursor had moved.
     */
    void checkCursor();

    /**
     * @returns true if there is a cursor that is allowed to edit the formula.
     */
    bool hasValidCursor() const;

    struct Container_Impl;
    Container_Impl* impl;

    // debug
    friend class TestFormulaCursor;
    friend class TestFormulaElement;
    friend class TestIndexElement;
    friend class TestCommands;
};

KFORMULA_NAMESPACE_END

#endif // KFORMULACONTAINER_H