~ubuntu-branches/ubuntu/breezy/koffice/breezy

« back to all changes in this revision

Viewing changes to kword/kwformulaframe.cc

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
   Copyright (C) 2003 Ulrich Kuettler <ulrich.kuettler@gmx.de>
 
3
 
 
4
   This program is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU General Public
 
6
   License as published by the Free Software Foundation; either
 
7
   version 2 of the License, or (at your option) any later version.
 
8
 
 
9
   This program is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
   General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with this program; see the file COPYING.  If not, write to
 
16
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
   Boston, MA 02111-1307, USA.
 
18
*/
 
19
 
 
20
#include "kwdoc.h"
 
21
#include "kwview.h"
 
22
#include "kwviewmode.h"
 
23
#include "kwcanvas.h"
 
24
#include "kwcommand.h"
 
25
#include "kwframe.h"
 
26
#include "defs.h"
 
27
#include "kwtextframeset.h"
 
28
#include "kwtableframeset.h"
 
29
#include "kwanchor.h"
 
30
#include "resizehandles.h"
 
31
#include <kotextobject.h> // for customItemChar!
 
32
#include <qpopupmenu.h>
 
33
 
 
34
#include <kformulacontainer.h>
 
35
#include <kformuladocument.h>
 
36
#include <kformulaview.h>
 
37
 
 
38
#include <kcursor.h>
 
39
#include <klocale.h>
 
40
#include <kmessagebox.h>
 
41
#include <kparts/partmanager.h>
 
42
#include <kdebug.h>
 
43
#include <kdeversion.h>
 
44
#if ! KDE_IS_VERSION(3,1,90)
 
45
#include <kdebugclasses.h>
 
46
#endif
 
47
#include <float.h>
 
48
#include "KWordFrameSetIface.h"
 
49
#include <dcopobject.h>
 
50
#include "qdrawutil.h"
 
51
#include "KWordTextFrameSetEditIface.h"
 
52
#include "KWordFormulaFrameSetIface.h"
 
53
#include "KWordFormulaFrameSetEditIface.h"
 
54
#include "KWordPictureFrameSetIface.h"
 
55
#include "KWordHorizontalLineFrameSetIface.h"
 
56
 
 
57
#include "kwformulaframe.h"
 
58
 
 
59
#include <assert.h>
 
60
 
 
61
// #ifdef __GNUC__
 
62
// #undef k_funcinfo
 
63
// #define k_funcinfo "[\033[36m" << __PRETTY_FUNCTION__ << "\033[m] "
 
64
// #endif
 
65
 
 
66
/******************************************************************/
 
67
/* Class: KWFormulaFrameSet                                       */
 
68
/******************************************************************/
 
69
KWFormulaFrameSet::KWFormulaFrameSet( KWDocument *_doc, const QString & name )
 
70
    : KWFrameSet( _doc ), m_changed( false ), m_edit( 0 )
 
71
{
 
72
    kdDebug() << k_funcinfo << endl;
 
73
 
 
74
    // The newly created formula is not yet part of the formula
 
75
    // document. It will be added when a frame is created.
 
76
    formula = _doc->getFormulaDocument()->createFormula( -1, false );
 
77
 
 
78
    // With the new drawing scheme (drawFrame being called with translated painter)
 
79
    // there is no need to move the KFormulaContainer anymore, it remains at (0,0).
 
80
    formula->moveTo( 0, 0 );
 
81
 
 
82
    connect( formula, SIGNAL( formulaChanged( double, double ) ),
 
83
             this, SLOT( slotFormulaChanged( double, double ) ) );
 
84
    connect( formula, SIGNAL( errorMsg( const QString& ) ),
 
85
             this, SLOT( slotErrorMessage( const QString& ) ) );
 
86
    if ( name.isEmpty() )
 
87
        m_name = _doc->generateFramesetName( i18n( "Formula %1" ) );
 
88
    else
 
89
        m_name = name;
 
90
 
 
91
    /*
 
92
    if ( isFloating() ) {
 
93
        // we need to look for the anchor every time, don't cache this value.
 
94
        // undo/redo creates/deletes anchors
 
95
        KWAnchor * anchor = findAnchor( 0 );
 
96
        if ( anchor ) {
 
97
            KoTextFormat * format = anchor->format();
 
98
            formula->setFontSize( format->pointSize() );
 
99
        }
 
100
    }
 
101
    */
 
102
    QRect rect = formula->boundingRect();
 
103
    slotFormulaChanged(rect.width(), rect.height());
 
104
}
 
105
 
 
106
KWordFrameSetIface* KWFormulaFrameSet::dcopObject()
 
107
{
 
108
    if ( !m_dcop )
 
109
        m_dcop = new KWordFormulaFrameSetIface( this );
 
110
 
 
111
    return m_dcop;
 
112
}
 
113
 
 
114
KWFormulaFrameSet::~KWFormulaFrameSet()
 
115
{
 
116
    kdDebug() << k_funcinfo << endl;
 
117
    delete formula;
 
118
}
 
119
 
 
120
void KWFormulaFrameSet::addFrame( KWFrame *_frame, bool recalc )
 
121
{
 
122
    kdDebug() << k_funcinfo << endl;
 
123
    if ( formula ) {
 
124
        _frame->setWidth( formula->width() );
 
125
        _frame->setHeight( formula->height() );
 
126
    }
 
127
    KWFrameSet::addFrame( _frame, recalc );
 
128
    if ( formula ) {
 
129
        formula->registerFormula();
 
130
    }
 
131
}
 
132
 
 
133
void KWFormulaFrameSet::delFrame( unsigned int _num, bool remove, bool recalc )
 
134
{
 
135
    kdDebug() << k_funcinfo << endl;
 
136
    assert( _num == 0 );
 
137
    KWFrameSet::delFrame( _num, remove, recalc );
 
138
    formula->unregisterFormula();
 
139
}
 
140
 
 
141
 
 
142
void KWFormulaFrameSet::moveFrame( KWFrame* frame )
 
143
{
 
144
    formula->setDocumentPosition( frame->x(), frame->y()+formula->baseline() );
 
145
}
 
146
 
 
147
 
 
148
KWFrameSetEdit* KWFormulaFrameSet::createFrameSetEdit(KWCanvas* canvas)
 
149
{
 
150
    return new KWFormulaFrameSetEdit(this, canvas);
 
151
}
 
152
 
 
153
void KWFormulaFrameSet::drawFrameContents( KWFrame* /*frame*/,
 
154
                                           QPainter* painter, const QRect& crect,
 
155
                                           const QColorGroup& cg, bool onlyChanged,
 
156
                                           bool resetChanged,
 
157
                                           KWFrameSetEdit */*edit*/, KWViewMode * )
 
158
{
 
159
    if ( m_changed || !onlyChanged )
 
160
    {
 
161
        if ( resetChanged )
 
162
            m_changed = false;
 
163
 
 
164
        bool printing = painter->device()->devType() == QInternal::Printer;
 
165
        bool clipping = true;
 
166
        QPainter *p;
 
167
        QPixmap* pix = 0L;
 
168
        if ( printing ) {
 
169
            p = painter;
 
170
            clipping = painter->hasClipping();
 
171
 
 
172
            // That's unfortunate for formulas wider than the page.
 
173
            // However it helps a lot with ordinary formulas.
 
174
            painter->setClipping( false );
 
175
        }
 
176
        else {
 
177
            pix = doubleBufferPixmap( crect.size() );
 
178
            p = new QPainter( pix );
 
179
            p->translate( -crect.x(), -crect.y() );
 
180
        }
 
181
 
 
182
        if ( m_edit ) {
 
183
            //KWFormulaFrameSetEdit * formulaEdit = static_cast<KWFormulaFrameSetEdit *>(edit);
 
184
            if ( m_edit->getFormulaView() ) {
 
185
                m_edit->getFormulaView()->draw( *p, crect, cg );
 
186
            }
 
187
            else {
 
188
                formula->draw( *p, crect, cg );
 
189
            }
 
190
        }
 
191
        else {
 
192
            formula->draw( *p, crect, cg );
 
193
        }
 
194
 
 
195
        if ( !printing ) {
 
196
            p->end();
 
197
            delete p;
 
198
            painter->drawPixmap( crect.topLeft(), *pix );
 
199
        }
 
200
        else {
 
201
            painter->setClipping( clipping );
 
202
        }
 
203
    }
 
204
}
 
205
 
 
206
 
 
207
void KWFormulaFrameSet::slotFormulaChanged( double width, double height )
 
208
{
 
209
    if ( frames.isEmpty() )
 
210
        return;
 
211
 
 
212
    double oldWidth = frames.first()->width();
 
213
    double oldHeight = frames.first()->height();
 
214
 
 
215
    frames.first()->setWidth( width );
 
216
    frames.first()->setHeight( height );
 
217
 
 
218
    updateFrames();
 
219
    kWordDocument()->layout();
 
220
    if ( ( oldWidth != width ) || ( oldHeight != height ) ) {
 
221
        kWordDocument()->repaintAllViews( false );
 
222
        kWordDocument()->updateRulerFrameStartEnd();
 
223
    }
 
224
 
 
225
    m_changed = true;
 
226
 
 
227
    if ( !m_edit ) {
 
228
        // A change without a FrameSetEdit! This must be the result of
 
229
        // an undo. We need to evaluate.
 
230
        formula->startEvaluation();
 
231
    }
 
232
}
 
233
 
 
234
void KWFormulaFrameSet::slotErrorMessage( const QString& msg )
 
235
{
 
236
    KMessageBox::error( /*m_widget*/ 0, msg );
 
237
}
 
238
 
 
239
QDomElement KWFormulaFrameSet::save(QDomElement& parentElem, bool saveFrames)
 
240
{
 
241
    if ( frames.isEmpty() ) // Deleted frameset -> don't save
 
242
        return QDomElement();
 
243
    QDomElement framesetElem = parentElem.ownerDocument().createElement("FRAMESET");
 
244
    parentElem.appendChild(framesetElem);
 
245
 
 
246
    KWFrameSet::saveCommon(framesetElem, saveFrames);
 
247
 
 
248
    QDomElement formulaElem = parentElem.ownerDocument().createElement("FORMULA");
 
249
    framesetElem.appendChild(formulaElem);
 
250
    formula->save(formulaElem);
 
251
    return framesetElem;
 
252
}
 
253
 
 
254
void KWFormulaFrameSet::load(QDomElement& attributes, bool loadFrames)
 
255
{
 
256
    KWFrameSet::load(attributes, loadFrames);
 
257
    QDomElement formulaElem = attributes.namedItem("FORMULA").toElement();
 
258
    paste( formulaElem );
 
259
}
 
260
 
 
261
void KWFormulaFrameSet::paste( QDomNode& formulaElem )
 
262
{
 
263
    if (!formulaElem.isNull()) {
 
264
        if (formula == 0) {
 
265
            formula = m_doc->getFormulaDocument()->createFormula( -1, false );
 
266
            connect(formula, SIGNAL(formulaChanged(double, double)),
 
267
                    this, SLOT(slotFormulaChanged(double, double)));
 
268
            connect( formula, SIGNAL( errorMsg( const QString& ) ),
 
269
                     this, SLOT( slotErrorMessage( const QString& ) ) );
 
270
        }
 
271
        if ( !formula->load( formulaElem.firstChild().toElement() ) ) {
 
272
            kdError(32001) << "Error loading formula" << endl;
 
273
        }
 
274
    }
 
275
    else {
 
276
        kdError(32001) << "Missing FORMULA tag in FRAMESET" << endl;
 
277
    }
 
278
}
 
279
 
 
280
void KWFormulaFrameSet::zoom( bool forPrint )
 
281
{
 
282
    if ( !frames.isEmpty() ) {
 
283
        KWFrameSet::zoom( forPrint );
 
284
    }
 
285
}
 
286
 
 
287
void KWFormulaFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
 
288
{
 
289
    kdDebug() << k_funcinfo << endl;
 
290
    KWFrameSet::moveFloatingFrame( frameNum, position );
 
291
    if ( !frames.isEmpty() ) {
 
292
        formula->setDocumentPosition( position.x(), position.y()+formula->baseline() );
 
293
    }
 
294
}
 
295
 
 
296
int KWFormulaFrameSet::floatingFrameBaseline( int /*frameNum*/ )
 
297
{
 
298
    if ( !frames.isEmpty() )
 
299
    {
 
300
        return m_doc->ptToLayoutUnitPixY( formula->baseline() );
 
301
    }
 
302
    return -1;
 
303
}
 
304
 
 
305
void KWFormulaFrameSet::setAnchorFormat( KoTextFormat* format, int /*frameNum*/ )
 
306
{
 
307
    if ( !frames.isEmpty() ) {
 
308
        formula->setFontSizeDirect( format->pointSize() );
 
309
    }
 
310
}
 
311
 
 
312
void KWFormulaFrameSet::showPopup( KWFrame *, KWView *view, const QPoint &point )
 
313
{
 
314
    QPopupMenu * popup = view->popupMenu("Formula");
 
315
    Q_ASSERT(popup);
 
316
    if (popup)
 
317
        popup->popup( point );
 
318
}
 
319
 
 
320
 
 
321
QPixmap* KWFormulaFrameSet::m_bufPixmap = 0;
 
322
 
 
323
// stolen from KWDocument
 
324
// However, I don't see if a formula frame can be an underlying
 
325
// frame. That is why I use my own buffer.
 
326
QPixmap* KWFormulaFrameSet::doubleBufferPixmap( const QSize& s )
 
327
{
 
328
    if ( !m_bufPixmap ) {
 
329
        int w = QABS( s.width() );
 
330
        int h = QABS( s.height() );
 
331
        m_bufPixmap = new QPixmap( w, h );
 
332
    } else {
 
333
        if ( m_bufPixmap->width() < s.width() ||
 
334
             m_bufPixmap->height() < s.height() ) {
 
335
            m_bufPixmap->resize( QMAX( s.width(), m_bufPixmap->width() ),
 
336
                                 QMAX( s.height(), m_bufPixmap->height() ) );
 
337
        }
 
338
    }
 
339
 
 
340
    return m_bufPixmap;
 
341
}
 
342
 
 
343
 
 
344
KWFormulaFrameSetEdit::KWFormulaFrameSetEdit(KWFormulaFrameSet* fs, KWCanvas* canvas)
 
345
        : KWFrameSetEdit(fs, canvas)
 
346
{
 
347
    formulaView = new KFormula::View( fs->getFormula() );
 
348
 
 
349
    connect( formulaView, SIGNAL( cursorChanged( bool, bool ) ),
 
350
             this, SLOT( cursorChanged( bool, bool ) ) );
 
351
    connect( fs->getFormula(), SIGNAL( leaveFormula( Container*, FormulaCursor*, int ) ),
 
352
             this, SLOT( slotLeaveFormula( Container*, FormulaCursor*, int ) ) );
 
353
 
 
354
    fs->m_edit = this;
 
355
 
 
356
    m_canvas->gui()->getView()->showFormulaToolbar(true);
 
357
    focusInEvent();
 
358
    dcop=0;
 
359
}
 
360
 
 
361
DCOPObject* KWFormulaFrameSetEdit::dcopObject()
 
362
{
 
363
    if ( !dcop )
 
364
        dcop = new KWordFormulaFrameSetEditIface( this );
 
365
    return dcop;
 
366
}
 
367
 
 
368
KWFormulaFrameSetEdit::~KWFormulaFrameSetEdit()
 
369
{
 
370
    formulaFrameSet()->m_edit = 0;
 
371
    focusOutEvent();
 
372
    // this causes a core dump on quit
 
373
    m_canvas->gui()->getView()->showFormulaToolbar(false);
 
374
    delete formulaView;
 
375
    formulaView = 0;
 
376
    formulaFrameSet()->getFormula()->startEvaluation();
 
377
    formulaFrameSet()->setChanged();
 
378
    m_canvas->repaintChanged( formulaFrameSet(), true );
 
379
    delete dcop;
 
380
}
 
381
 
 
382
const KFormula::View* KWFormulaFrameSetEdit::getFormulaView() const { return formulaView; }
 
383
KFormula::View* KWFormulaFrameSetEdit::getFormulaView() { return formulaView; }
 
384
 
 
385
void KWFormulaFrameSetEdit::keyPressEvent( QKeyEvent* event )
 
386
{
 
387
    //kdDebug(32001) << "KWFormulaFrameSetEdit::keyPressEvent" << endl;
 
388
    formulaView->keyPressEvent( event );
 
389
}
 
390
 
 
391
void KWFormulaFrameSetEdit::mousePressEvent( QMouseEvent* event,
 
392
                                             const QPoint&,
 
393
                                             const KoPoint& pos )
 
394
{
 
395
    // [Note that this method is called upon RMB and MMB as well, now]
 
396
    KoPoint tl = m_currentFrame->topLeft();
 
397
    formulaView->mousePressEvent( event, pos-tl );
 
398
}
 
399
 
 
400
void KWFormulaFrameSetEdit::mouseMoveEvent( QMouseEvent* event,
 
401
                                            const QPoint&,
 
402
                                            const KoPoint& pos )
 
403
{
 
404
    KoPoint tl = m_currentFrame->topLeft();
 
405
    formulaView->mouseMoveEvent( event, pos-tl );
 
406
}
 
407
 
 
408
void KWFormulaFrameSetEdit::mouseReleaseEvent( QMouseEvent* event,
 
409
                                               const QPoint&,
 
410
                                               const KoPoint& pos )
 
411
{
 
412
    KoPoint tl = m_currentFrame->topLeft();
 
413
    formulaView->mouseReleaseEvent( event, pos-tl );
 
414
}
 
415
 
 
416
void KWFormulaFrameSetEdit::focusInEvent()
 
417
{
 
418
    //kdDebug(32001) << "KWFormulaFrameSetEdit::focusInEvent" << endl;
 
419
    if ( formulaView != 0 ) {
 
420
        formulaView->focusInEvent(0);
 
421
    }
 
422
}
 
423
 
 
424
void KWFormulaFrameSetEdit::focusOutEvent()
 
425
{
 
426
    //kdDebug(32001) << "KWFormulaFrameSetEdit::focusOutEvent" <<
 
427
    //endl;
 
428
    if ( formulaView != 0 ) {
 
429
        formulaView->focusOutEvent(0);
 
430
    }
 
431
}
 
432
 
 
433
void KWFormulaFrameSetEdit::copy()
 
434
{
 
435
    formulaView->getDocument()->copy();
 
436
}
 
437
 
 
438
void KWFormulaFrameSetEdit::cut()
 
439
{
 
440
    formulaView->getDocument()->cut();
 
441
}
 
442
 
 
443
void KWFormulaFrameSetEdit::paste()
 
444
{
 
445
    formulaView->getDocument()->paste();
 
446
}
 
447
 
 
448
void KWFormulaFrameSetEdit::selectAll()
 
449
{
 
450
    formulaView->slotSelectAll();
 
451
}
 
452
 
 
453
void KWFormulaFrameSetEdit::moveHome()
 
454
{
 
455
    formulaView->moveHome( KFormula::WordMovement );
 
456
}
 
457
void KWFormulaFrameSetEdit::moveEnd()
 
458
{
 
459
    formulaView->moveEnd( KFormula::WordMovement );
 
460
}
 
461
 
 
462
void KWFormulaFrameSetEdit::exitLeft()
 
463
{
 
464
    if ( formulaFrameSet()->isFloating() ) {
 
465
        KWAnchor* anchor = formulaFrameSet()->findAnchor( 0 );
 
466
        int index = anchor->index();
 
467
        KoTextParag *parag = static_cast<KoTextParag*>( anchor->paragraph() );
 
468
        m_canvas->editTextFrameSet( formulaFrameSet()->anchorFrameset(), parag, index );
 
469
    }
 
470
}
 
471
 
 
472
void KWFormulaFrameSetEdit::exitRight()
 
473
{
 
474
    if ( formulaFrameSet()->isFloating() ) {
 
475
        KWAnchor* anchor = formulaFrameSet()->findAnchor( 0 );
 
476
        int index = anchor->index();
 
477
        KoTextParag *parag = static_cast<KoTextParag*>( anchor->paragraph() );
 
478
        m_canvas->editTextFrameSet( formulaFrameSet()->anchorFrameset(), parag, index+1 );
 
479
    }
 
480
}
 
481
 
 
482
 
 
483
void KWFormulaFrameSetEdit::exitAbove()
 
484
{
 
485
    exitLeft();
 
486
}
 
487
 
 
488
 
 
489
void KWFormulaFrameSetEdit::exitBelow()
 
490
{
 
491
    exitRight();
 
492
}
 
493
 
 
494
 
 
495
void KWFormulaFrameSetEdit::removeFormula()
 
496
{
 
497
    if ( formulaFrameSet()->isFloating() ) {
 
498
        KWCanvas* canvas = m_canvas;
 
499
 
 
500
        // This call will destroy us! We cannot use 'this' afterwards!
 
501
        exitRight();
 
502
 
 
503
        QKeyEvent keyEvent( QEvent::KeyPress, Key_Backspace, 0, 0 );
 
504
        canvas->currentFrameSetEdit()->keyPressEvent( &keyEvent );
 
505
    }
 
506
}
 
507
 
 
508
void KWFormulaFrameSetEdit::cursorChanged( bool visible, bool /*selecting*/ )
 
509
{
 
510
    if ( visible ) {
 
511
        if ( m_currentFrame )
 
512
        {
 
513
            // Add the cursor position to the (zoomed) frame position
 
514
            QPoint nPoint = frameSet()->kWordDocument()->zoomPoint( m_currentFrame->topLeft() );
 
515
            nPoint += formulaView->getCursorPoint();
 
516
            // Apply viewmode conversion
 
517
            QPoint p = m_canvas->viewMode()->normalToView( nPoint );
 
518
            m_canvas->ensureVisible( p.x(), p.y() );
 
519
        }
 
520
    }
 
521
    formulaFrameSet()->setChanged();
 
522
    m_canvas->repaintChanged( formulaFrameSet(), true );
 
523
}
 
524
 
 
525
void KWFormulaFrameSetEdit::slotLeaveFormula( KFormula::Container*,
 
526
                                              KFormula::FormulaCursor* cursor,
 
527
                                              int cmd )
 
528
{
 
529
    kdDebug() << k_funcinfo << endl;
 
530
 
 
531
    if ( cursor == formulaView->getCursor() ) {
 
532
        switch ( cmd ) {
 
533
        case KFormula::Container::EXIT_LEFT:
 
534
            exitLeft();
 
535
            break;
 
536
        case KFormula::Container::EXIT_RIGHT:
 
537
            exitRight();
 
538
            break;
 
539
        case KFormula::Container::EXIT_ABOVE:
 
540
            exitAbove();
 
541
            break;
 
542
        case KFormula::Container::EXIT_BELOW:
 
543
            exitBelow();
 
544
            break;
 
545
        case KFormula::Container::REMOVE_FORMULA:
 
546
            removeFormula();
 
547
            break;
 
548
        }
 
549
    }
 
550
}
 
551
 
 
552
#include "kwformulaframe.moc"