1
/* This file is part of the KDE project
2
Copyright (C) 2003 Ulrich Kuettler <ulrich.kuettler@gmx.de>
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.
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.
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.
22
#include "kwviewmode.h"
24
#include "kwcommand.h"
27
#include "kwtextframeset.h"
28
#include "kwtableframeset.h"
30
#include "resizehandles.h"
31
#include <kotextobject.h> // for customItemChar!
32
#include <qpopupmenu.h>
34
#include <kformulacontainer.h>
35
#include <kformuladocument.h>
36
#include <kformulaview.h>
40
#include <kmessagebox.h>
41
#include <kparts/partmanager.h>
43
#include <kdeversion.h>
44
#if ! KDE_IS_VERSION(3,1,90)
45
#include <kdebugclasses.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"
57
#include "kwformulaframe.h"
63
// #define k_funcinfo "[\033[36m" << __PRETTY_FUNCTION__ << "\033[m] "
66
/******************************************************************/
67
/* Class: KWFormulaFrameSet */
68
/******************************************************************/
69
KWFormulaFrameSet::KWFormulaFrameSet( KWDocument *_doc, const QString & name )
70
: KWFrameSet( _doc ), m_changed( false ), m_edit( 0 )
72
kdDebug() << k_funcinfo << endl;
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 );
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 );
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& ) ) );
87
m_name = _doc->generateFramesetName( i18n( "Formula %1" ) );
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 );
97
KoTextFormat * format = anchor->format();
98
formula->setFontSize( format->pointSize() );
102
QRect rect = formula->boundingRect();
103
slotFormulaChanged(rect.width(), rect.height());
106
KWordFrameSetIface* KWFormulaFrameSet::dcopObject()
109
m_dcop = new KWordFormulaFrameSetIface( this );
114
KWFormulaFrameSet::~KWFormulaFrameSet()
116
kdDebug() << k_funcinfo << endl;
120
void KWFormulaFrameSet::addFrame( KWFrame *_frame, bool recalc )
122
kdDebug() << k_funcinfo << endl;
124
_frame->setWidth( formula->width() );
125
_frame->setHeight( formula->height() );
127
KWFrameSet::addFrame( _frame, recalc );
129
formula->registerFormula();
133
void KWFormulaFrameSet::delFrame( unsigned int _num, bool remove, bool recalc )
135
kdDebug() << k_funcinfo << endl;
137
KWFrameSet::delFrame( _num, remove, recalc );
138
formula->unregisterFormula();
142
void KWFormulaFrameSet::moveFrame( KWFrame* frame )
144
formula->setDocumentPosition( frame->x(), frame->y()+formula->baseline() );
148
KWFrameSetEdit* KWFormulaFrameSet::createFrameSetEdit(KWCanvas* canvas)
150
return new KWFormulaFrameSetEdit(this, canvas);
153
void KWFormulaFrameSet::drawFrameContents( KWFrame* /*frame*/,
154
QPainter* painter, const QRect& crect,
155
const QColorGroup& cg, bool onlyChanged,
157
KWFrameSetEdit */*edit*/, KWViewMode * )
159
if ( m_changed || !onlyChanged )
164
bool printing = painter->device()->devType() == QInternal::Printer;
165
bool clipping = true;
170
clipping = painter->hasClipping();
172
// That's unfortunate for formulas wider than the page.
173
// However it helps a lot with ordinary formulas.
174
painter->setClipping( false );
177
pix = doubleBufferPixmap( crect.size() );
178
p = new QPainter( pix );
179
p->translate( -crect.x(), -crect.y() );
183
//KWFormulaFrameSetEdit * formulaEdit = static_cast<KWFormulaFrameSetEdit *>(edit);
184
if ( m_edit->getFormulaView() ) {
185
m_edit->getFormulaView()->draw( *p, crect, cg );
188
formula->draw( *p, crect, cg );
192
formula->draw( *p, crect, cg );
198
painter->drawPixmap( crect.topLeft(), *pix );
201
painter->setClipping( clipping );
207
void KWFormulaFrameSet::slotFormulaChanged( double width, double height )
209
if ( frames.isEmpty() )
212
double oldWidth = frames.first()->width();
213
double oldHeight = frames.first()->height();
215
frames.first()->setWidth( width );
216
frames.first()->setHeight( height );
219
kWordDocument()->layout();
220
if ( ( oldWidth != width ) || ( oldHeight != height ) ) {
221
kWordDocument()->repaintAllViews( false );
222
kWordDocument()->updateRulerFrameStartEnd();
228
// A change without a FrameSetEdit! This must be the result of
229
// an undo. We need to evaluate.
230
formula->startEvaluation();
234
void KWFormulaFrameSet::slotErrorMessage( const QString& msg )
236
KMessageBox::error( /*m_widget*/ 0, msg );
239
QDomElement KWFormulaFrameSet::save(QDomElement& parentElem, bool saveFrames)
241
if ( frames.isEmpty() ) // Deleted frameset -> don't save
242
return QDomElement();
243
QDomElement framesetElem = parentElem.ownerDocument().createElement("FRAMESET");
244
parentElem.appendChild(framesetElem);
246
KWFrameSet::saveCommon(framesetElem, saveFrames);
248
QDomElement formulaElem = parentElem.ownerDocument().createElement("FORMULA");
249
framesetElem.appendChild(formulaElem);
250
formula->save(formulaElem);
254
void KWFormulaFrameSet::load(QDomElement& attributes, bool loadFrames)
256
KWFrameSet::load(attributes, loadFrames);
257
QDomElement formulaElem = attributes.namedItem("FORMULA").toElement();
258
paste( formulaElem );
261
void KWFormulaFrameSet::paste( QDomNode& formulaElem )
263
if (!formulaElem.isNull()) {
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& ) ) );
271
if ( !formula->load( formulaElem.firstChild().toElement() ) ) {
272
kdError(32001) << "Error loading formula" << endl;
276
kdError(32001) << "Missing FORMULA tag in FRAMESET" << endl;
280
void KWFormulaFrameSet::zoom( bool forPrint )
282
if ( !frames.isEmpty() ) {
283
KWFrameSet::zoom( forPrint );
287
void KWFormulaFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
289
kdDebug() << k_funcinfo << endl;
290
KWFrameSet::moveFloatingFrame( frameNum, position );
291
if ( !frames.isEmpty() ) {
292
formula->setDocumentPosition( position.x(), position.y()+formula->baseline() );
296
int KWFormulaFrameSet::floatingFrameBaseline( int /*frameNum*/ )
298
if ( !frames.isEmpty() )
300
return m_doc->ptToLayoutUnitPixY( formula->baseline() );
305
void KWFormulaFrameSet::setAnchorFormat( KoTextFormat* format, int /*frameNum*/ )
307
if ( !frames.isEmpty() ) {
308
formula->setFontSizeDirect( format->pointSize() );
312
void KWFormulaFrameSet::showPopup( KWFrame *, KWView *view, const QPoint &point )
314
QPopupMenu * popup = view->popupMenu("Formula");
317
popup->popup( point );
321
QPixmap* KWFormulaFrameSet::m_bufPixmap = 0;
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 )
328
if ( !m_bufPixmap ) {
329
int w = QABS( s.width() );
330
int h = QABS( s.height() );
331
m_bufPixmap = new QPixmap( w, h );
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() ) );
344
KWFormulaFrameSetEdit::KWFormulaFrameSetEdit(KWFormulaFrameSet* fs, KWCanvas* canvas)
345
: KWFrameSetEdit(fs, canvas)
347
formulaView = new KFormula::View( fs->getFormula() );
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 ) ) );
356
m_canvas->gui()->getView()->showFormulaToolbar(true);
361
DCOPObject* KWFormulaFrameSetEdit::dcopObject()
364
dcop = new KWordFormulaFrameSetEditIface( this );
368
KWFormulaFrameSetEdit::~KWFormulaFrameSetEdit()
370
formulaFrameSet()->m_edit = 0;
372
// this causes a core dump on quit
373
m_canvas->gui()->getView()->showFormulaToolbar(false);
376
formulaFrameSet()->getFormula()->startEvaluation();
377
formulaFrameSet()->setChanged();
378
m_canvas->repaintChanged( formulaFrameSet(), true );
382
const KFormula::View* KWFormulaFrameSetEdit::getFormulaView() const { return formulaView; }
383
KFormula::View* KWFormulaFrameSetEdit::getFormulaView() { return formulaView; }
385
void KWFormulaFrameSetEdit::keyPressEvent( QKeyEvent* event )
387
//kdDebug(32001) << "KWFormulaFrameSetEdit::keyPressEvent" << endl;
388
formulaView->keyPressEvent( event );
391
void KWFormulaFrameSetEdit::mousePressEvent( QMouseEvent* event,
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 );
400
void KWFormulaFrameSetEdit::mouseMoveEvent( QMouseEvent* event,
404
KoPoint tl = m_currentFrame->topLeft();
405
formulaView->mouseMoveEvent( event, pos-tl );
408
void KWFormulaFrameSetEdit::mouseReleaseEvent( QMouseEvent* event,
412
KoPoint tl = m_currentFrame->topLeft();
413
formulaView->mouseReleaseEvent( event, pos-tl );
416
void KWFormulaFrameSetEdit::focusInEvent()
418
//kdDebug(32001) << "KWFormulaFrameSetEdit::focusInEvent" << endl;
419
if ( formulaView != 0 ) {
420
formulaView->focusInEvent(0);
424
void KWFormulaFrameSetEdit::focusOutEvent()
426
//kdDebug(32001) << "KWFormulaFrameSetEdit::focusOutEvent" <<
428
if ( formulaView != 0 ) {
429
formulaView->focusOutEvent(0);
433
void KWFormulaFrameSetEdit::copy()
435
formulaView->getDocument()->copy();
438
void KWFormulaFrameSetEdit::cut()
440
formulaView->getDocument()->cut();
443
void KWFormulaFrameSetEdit::paste()
445
formulaView->getDocument()->paste();
448
void KWFormulaFrameSetEdit::selectAll()
450
formulaView->slotSelectAll();
453
void KWFormulaFrameSetEdit::moveHome()
455
formulaView->moveHome( KFormula::WordMovement );
457
void KWFormulaFrameSetEdit::moveEnd()
459
formulaView->moveEnd( KFormula::WordMovement );
462
void KWFormulaFrameSetEdit::exitLeft()
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 );
472
void KWFormulaFrameSetEdit::exitRight()
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 );
483
void KWFormulaFrameSetEdit::exitAbove()
489
void KWFormulaFrameSetEdit::exitBelow()
495
void KWFormulaFrameSetEdit::removeFormula()
497
if ( formulaFrameSet()->isFloating() ) {
498
KWCanvas* canvas = m_canvas;
500
// This call will destroy us! We cannot use 'this' afterwards!
503
QKeyEvent keyEvent( QEvent::KeyPress, Key_Backspace, 0, 0 );
504
canvas->currentFrameSetEdit()->keyPressEvent( &keyEvent );
508
void KWFormulaFrameSetEdit::cursorChanged( bool visible, bool /*selecting*/ )
511
if ( m_currentFrame )
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() );
521
formulaFrameSet()->setChanged();
522
m_canvas->repaintChanged( formulaFrameSet(), true );
525
void KWFormulaFrameSetEdit::slotLeaveFormula( KFormula::Container*,
526
KFormula::FormulaCursor* cursor,
529
kdDebug() << k_funcinfo << endl;
531
if ( cursor == formulaView->getCursor() ) {
533
case KFormula::Container::EXIT_LEFT:
536
case KFormula::Container::EXIT_RIGHT:
539
case KFormula::Container::EXIT_ABOVE:
542
case KFormula::Container::EXIT_BELOW:
545
case KFormula::Container::REMOVE_FORMULA:
552
#include "kwformulaframe.moc"