00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qfile.h>
00021
00022 #include "KWFormulaFrameSet.h"
00023
00024 #include "KWDocument.h"
00025 #include "KWView.h"
00026 #include "KWViewMode.h"
00027 #include "KWCanvas.h"
00028 #include "KWFrame.h"
00029 #include "defs.h"
00030
00031 #include <kformulacontainer.h>
00032 #include <kformuladocument.h>
00033 #include <kformulaview.h>
00034 #include <KoOasisContext.h>
00035 #include <KoXmlNS.h>
00036 #include <KoXmlWriter.h>
00037
00038 #include <klocale.h>
00039 #include <kmessagebox.h>
00040 #include <kdebug.h>
00041 #include <ktempfile.h>
00042 #include <dcopobject.h>
00043 #include "KWordFormulaFrameSetIface.h"
00044 #include "KWordFormulaFrameSetEditIface.h"
00045
00046 #include <assert.h>
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 KWFormulaFrameSet::KWFormulaFrameSet( KWDocument *doc, const QString & name )
00057 : KWFrameSet( doc ), m_changed( false ), m_edit( 0 )
00058 {
00059 if ( name.isEmpty() )
00060 m_name = doc->generateFramesetName( i18n( "Formula %1" ) );
00061 else
00062 m_name = name;
00063
00064 init();
00065 }
00066
00067 KWFormulaFrameSet::KWFormulaFrameSet( KWDocument* doc, const QDomElement& frameTag,
00068 const QDomElement& mathTag, KoOasisContext& context )
00069 : KWFrameSet( doc ), m_changed( false ), m_edit( 0 )
00070 {
00071 m_name = frameTag.attributeNS( KoXmlNS::draw, "name", QString::null );
00072 if ( doc->frameSetByName( m_name ) )
00073 m_name = doc->generateFramesetName( m_name + " %1" );
00074
00075 init();
00076
00077 context.styleStack().save();
00078 context.fillStyleStack( frameTag, KoXmlNS::draw, "style-name", "graphic" );
00079 loadOasisFrame( frameTag, context );
00080 context.styleStack().restore();
00081
00082 formula->loadMathML( mathTag );
00083 }
00084
00085 void KWFormulaFrameSet::init()
00086 {
00087
00088
00089 formula = m_doc->formulaDocument()->createFormula( -1, false );
00090
00091
00092
00093 formula->moveTo( 0, 0 );
00094
00095 connect( formula, SIGNAL( formulaChanged( double, double ) ),
00096 this, SLOT( slotFormulaChanged( double, double ) ) );
00097 connect( formula, SIGNAL( errorMsg( const QString& ) ),
00098 this, SLOT( slotErrorMessage( const QString& ) ) );
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 QRect rect = formula->boundingRect();
00112 slotFormulaChanged(rect.width(), rect.height());
00113 }
00114
00115 KWordFrameSetIface* KWFormulaFrameSet::dcopObject()
00116 {
00117 if ( !m_dcop )
00118 m_dcop = new KWordFormulaFrameSetIface( this );
00119
00120 return m_dcop;
00121 }
00122
00123 KWFormulaFrameSet::~KWFormulaFrameSet()
00124 {
00125 kdDebug() << k_funcinfo << endl;
00126 delete formula;
00127 }
00128
00129 void KWFormulaFrameSet::addFrame( KWFrame *frame, bool recalc )
00130 {
00131 kdDebug() << k_funcinfo << endl;
00132 if ( formula ) {
00133 frame->setWidth( formula->width() );
00134 frame->setHeight( formula->height() );
00135 }
00136 KWFrameSet::addFrame( frame, recalc );
00137 if ( formula ) {
00138 formula->registerFormula();
00139 }
00140 }
00141
00142 void KWFormulaFrameSet::deleteFrame( unsigned int num, bool remove, bool recalc )
00143 {
00144 kdDebug() << k_funcinfo << endl;
00145 assert( num == 0 );
00146 KWFrameSet::deleteFrame( num, remove, recalc );
00147 formula->unregisterFormula();
00148 }
00149
00150
00151 KWFrameSetEdit* KWFormulaFrameSet::createFrameSetEdit(KWCanvas* canvas)
00152 {
00153 return new KWFormulaFrameSetEdit(this, canvas);
00154 }
00155
00156 void KWFormulaFrameSet::drawFrameContents( KWFrame* ,
00157 QPainter* painter, const QRect& crect,
00158 const QColorGroup& cg, bool onlyChanged,
00159 bool resetChanged,
00160 KWFrameSetEdit* , KWViewMode * )
00161 {
00162 if ( m_changed || !onlyChanged )
00163 {
00164 if ( resetChanged )
00165 m_changed = false;
00166
00167 bool printing = painter->device()->devType() == QInternal::Printer;
00168 bool clipping = true;
00169 QPainter *p;
00170 QPixmap* pix = 0L;
00171 if ( printing ) {
00172 p = painter;
00173 clipping = painter->hasClipping();
00174
00175
00176
00177 painter->setClipping( false );
00178 }
00179 else {
00180 pix = doubleBufferPixmap( crect.size() );
00181 p = new QPainter( pix );
00182 p->translate( -crect.x(), -crect.y() );
00183 }
00184
00185 if ( m_edit ) {
00186
00187 if ( m_edit->getFormulaView() ) {
00188 m_edit->getFormulaView()->draw( *p, crect, cg );
00189 }
00190 else {
00191 formula->draw( *p, crect, cg );
00192 }
00193 }
00194 else {
00195 formula->draw( *p, crect, cg );
00196 }
00197
00198 if ( !printing ) {
00199 p->end();
00200 delete p;
00201 painter->drawPixmap( crect.topLeft(), *pix );
00202 }
00203 else {
00204 painter->setClipping( clipping );
00205 }
00206 }
00207 }
00208
00209
00210 void KWFormulaFrameSet::slotFormulaChanged( double width, double height )
00211 {
00212 if ( m_frames.isEmpty() )
00213 return;
00214
00215 double oldWidth = m_frames.first()->width();
00216 double oldHeight = m_frames.first()->height();
00217
00218 m_frames.first()->setWidth( width );
00219 m_frames.first()->setHeight( height );
00220
00221 updateFrames();
00222 kWordDocument()->layout();
00223 if ( ( oldWidth != width ) || ( oldHeight != height ) ) {
00224 kWordDocument()->repaintAllViews( false );
00225 kWordDocument()->updateRulerFrameStartEnd();
00226 }
00227
00228 m_changed = true;
00229
00230 if ( !m_edit ) {
00231
00232
00233 formula->startEvaluation();
00234 }
00235 }
00236
00237 void KWFormulaFrameSet::slotErrorMessage( const QString& msg )
00238 {
00239 KMessageBox::error( 0, msg );
00240 }
00241
00242 MouseMeaning KWFormulaFrameSet::getMouseMeaningInsideFrame( const KoPoint& )
00243 {
00244 return MEANING_MOUSE_INSIDE_TEXT;
00245 }
00246
00247 QDomElement KWFormulaFrameSet::save(QDomElement& parentElem, bool saveFrames)
00248 {
00249 if ( m_frames.isEmpty() )
00250 return QDomElement();
00251 QDomElement framesetElem = parentElem.ownerDocument().createElement("FRAMESET");
00252 parentElem.appendChild(framesetElem);
00253
00254 KWFrameSet::saveCommon(framesetElem, saveFrames);
00255
00256 QDomElement formulaElem = parentElem.ownerDocument().createElement("FORMULA");
00257 framesetElem.appendChild(formulaElem);
00258 formula->save(formulaElem);
00259 return framesetElem;
00260 }
00261
00262 void KWFormulaFrameSet::saveOasis(KoXmlWriter& writer, KoSavingContext& context, bool) const
00263 {
00264 KWFrame *frame = m_frames.getFirst();
00265 frame->startOasisFrame( writer, context.mainStyles(), name() );
00266
00267 KTempFile contentTmpFile;
00268 contentTmpFile.setAutoDelete( true );
00269 QFile* tmpFile = contentTmpFile.file();
00270
00271 QTextStream stream(tmpFile);
00272 stream.setEncoding( QTextStream::UnicodeUTF8 );
00273 formula->saveMathML( stream, true );
00274 tmpFile->close();
00275
00276 writer.startElement( "draw:object" );
00277 writer.startElement( "math:math" );
00278 writer.addCompleteElement( tmpFile );
00279 writer.endElement();
00280 writer.endElement();
00281 writer.endElement();
00282 }
00283
00284 void KWFormulaFrameSet::load(QDomElement& attributes, bool loadFrames)
00285 {
00286 KWFrameSet::load(attributes, loadFrames);
00287 QDomElement formulaElem = attributes.namedItem("FORMULA").toElement();
00288 paste( formulaElem );
00289 }
00290
00291 void KWFormulaFrameSet::paste( QDomNode& formulaElem )
00292 {
00293 if (!formulaElem.isNull()) {
00294 if (formula == 0) {
00295 formula = m_doc->formulaDocument()->createFormula( -1, false );
00296 connect(formula, SIGNAL(formulaChanged(double, double)),
00297 this, SLOT(slotFormulaChanged(double, double)));
00298 connect( formula, SIGNAL( errorMsg( const QString& ) ),
00299 this, SLOT( slotErrorMessage( const QString& ) ) );
00300 }
00301 m_doc->formulaDocument()->setCreationStrategy( "Oasis" );
00302 if ( !formula->loadMathML( formulaElem.firstChild().toElement() ) ) {
00303 kdError(32001) << "Error loading formula" << endl;
00304 }
00305 }
00306 else {
00307 kdError(32001) << "Missing math tag in FRAMESET" << endl;
00308 }
00309 }
00310
00311 void KWFormulaFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
00312 {
00313 kdDebug() << k_funcinfo << endl;
00314 KWFrameSet::moveFloatingFrame( frameNum, position );
00315 if ( !m_frames.isEmpty() ) {
00316 formula->setDocumentPosition( position.x(), position.y()+formula->baseline() );
00317 }
00318 }
00319
00320 int KWFormulaFrameSet::floatingFrameBaseline( int )
00321 {
00322 if ( !m_frames.isEmpty() )
00323 {
00324 return m_doc->ptToLayoutUnitPixY( formula->baseline() );
00325 }
00326 return -1;
00327 }
00328
00329 void KWFormulaFrameSet::setAnchorFormat( KoTextFormat* format, int )
00330 {
00331 if ( !m_frames.isEmpty() ) {
00332 formula->setFontSizeDirect( format->pointSize() );
00333 }
00334 }
00335
00336
00337 QPixmap* KWFormulaFrameSet::m_bufPixmap = 0;
00338
00339
00340
00341
00342 QPixmap* KWFormulaFrameSet::doubleBufferPixmap( const QSize& s )
00343 {
00344 if ( !m_bufPixmap ) {
00345 int w = QABS( s.width() );
00346 int h = QABS( s.height() );
00347 m_bufPixmap = new QPixmap( w, h );
00348 } else {
00349 if ( m_bufPixmap->width() < s.width() ||
00350 m_bufPixmap->height() < s.height() ) {
00351 m_bufPixmap->resize( QMAX( s.width(), m_bufPixmap->width() ),
00352 QMAX( s.height(), m_bufPixmap->height() ) );
00353 }
00354 }
00355
00356 return m_bufPixmap;
00357 }
00358
00359
00360 KWFormulaFrameSetEdit::KWFormulaFrameSetEdit(KWFormulaFrameSet* fs, KWCanvas* canvas)
00361 : KWFrameSetEdit(fs, canvas)
00362 {
00363 formulaView = new KFormula::View( fs->getFormula() );
00364
00365 connect( formulaView, SIGNAL( cursorChanged( bool, bool ) ),
00366 this, SLOT( cursorChanged( bool, bool ) ) );
00367 connect( fs->getFormula(), SIGNAL( leaveFormula( Container*, FormulaCursor*, int ) ),
00368 this, SLOT( slotLeaveFormula( Container*, FormulaCursor*, int ) ) );
00369
00370 fs->m_edit = this;
00371
00372 m_canvas->gui()->getView()->showFormulaToolbar(true);
00373 focusInEvent();
00374 dcop=0;
00375 }
00376
00377 DCOPObject* KWFormulaFrameSetEdit::dcopObject()
00378 {
00379 if ( !dcop )
00380 dcop = new KWordFormulaFrameSetEditIface( this );
00381 return dcop;
00382 }
00383
00384 KWFormulaFrameSetEdit::~KWFormulaFrameSetEdit()
00385 {
00386 formulaFrameSet()->m_edit = 0;
00387 focusOutEvent();
00388
00389 m_canvas->gui()->getView()->showFormulaToolbar(false);
00390 delete formulaView;
00391 formulaView = 0;
00392 formulaFrameSet()->getFormula()->startEvaluation();
00393 formulaFrameSet()->setChanged();
00394 m_canvas->repaintChanged( formulaFrameSet(), true );
00395 delete dcop;
00396 }
00397
00398 const KFormula::View* KWFormulaFrameSetEdit::getFormulaView() const { return formulaView; }
00399 KFormula::View* KWFormulaFrameSetEdit::getFormulaView() { return formulaView; }
00400
00401 void KWFormulaFrameSetEdit::keyPressEvent( QKeyEvent* event )
00402 {
00403
00404 formulaView->keyPressEvent( event );
00405 }
00406
00407 void KWFormulaFrameSetEdit::mousePressEvent( QMouseEvent* event,
00408 const QPoint&,
00409 const KoPoint& pos )
00410 {
00411
00412 KoPoint tl = m_currentFrame->topLeft();
00413 formulaView->mousePressEvent( event, pos-tl );
00414 }
00415
00416 void KWFormulaFrameSetEdit::mouseMoveEvent( QMouseEvent* event,
00417 const QPoint&,
00418 const KoPoint& pos )
00419 {
00420 KoPoint tl = m_currentFrame->topLeft();
00421 formulaView->mouseMoveEvent( event, pos-tl );
00422 }
00423
00424 void KWFormulaFrameSetEdit::mouseReleaseEvent( QMouseEvent* event,
00425 const QPoint&,
00426 const KoPoint& pos )
00427 {
00428 KoPoint tl = m_currentFrame->topLeft();
00429 formulaView->mouseReleaseEvent( event, pos-tl );
00430 }
00431
00432 void KWFormulaFrameSetEdit::focusInEvent()
00433 {
00434
00435 if ( formulaView != 0 ) {
00436 formulaView->focusInEvent(0);
00437 }
00438 }
00439
00440 void KWFormulaFrameSetEdit::focusOutEvent()
00441 {
00442
00443
00444 if ( formulaView != 0 ) {
00445 formulaView->focusOutEvent(0);
00446 }
00447 }
00448
00449 void KWFormulaFrameSetEdit::copy()
00450 {
00451 formulaView->getDocument()->copy();
00452 }
00453
00454 void KWFormulaFrameSetEdit::cut()
00455 {
00456 formulaView->getDocument()->cut();
00457 }
00458
00459 void KWFormulaFrameSetEdit::paste()
00460 {
00461 formulaView->getDocument()->paste();
00462 }
00463
00464 void KWFormulaFrameSetEdit::pasteData( QMimeSource* , int , bool )
00465 {
00466 paste();
00467 }
00468
00469 void KWFormulaFrameSetEdit::selectAll()
00470 {
00471 formulaView->slotSelectAll();
00472 }
00473
00474 void KWFormulaFrameSetEdit::moveHome()
00475 {
00476 formulaView->moveHome( KFormula::WordMovement );
00477 }
00478 void KWFormulaFrameSetEdit::moveEnd()
00479 {
00480 formulaView->moveEnd( KFormula::WordMovement );
00481 }
00482
00483 void KWFormulaFrameSetEdit::removeFormula()
00484 {
00485 if ( formulaFrameSet()->isFloating() ) {
00486 KWCanvas* canvas = m_canvas;
00487
00488
00489 exitRight();
00490
00491 QKeyEvent keyEvent( QEvent::KeyPress, Key_Backspace, 0, 0 );
00492 canvas->currentFrameSetEdit()->keyPressEvent( &keyEvent );
00493 }
00494 }
00495
00496 void KWFormulaFrameSetEdit::cursorChanged( bool visible, bool )
00497 {
00498 if ( visible ) {
00499 if ( m_currentFrame )
00500 {
00501
00502 QPoint nPoint = frameSet()->kWordDocument()->zoomPoint( m_currentFrame->topLeft() );
00503 nPoint += formulaView->getCursorPoint();
00504
00505 QPoint p = m_canvas->viewMode()->normalToView( nPoint );
00506 m_canvas->ensureVisible( p.x(), p.y() );
00507 }
00508 }
00509 formulaFrameSet()->setChanged();
00510 m_canvas->repaintChanged( formulaFrameSet(), true );
00511 }
00512
00513 void KWFormulaFrameSetEdit::slotLeaveFormula( KFormula::Container*,
00514 KFormula::FormulaCursor* cursor,
00515 int cmd )
00516 {
00517 kdDebug() << k_funcinfo << endl;
00518
00519 if ( cursor == formulaView->getCursor() ) {
00520 switch ( cmd ) {
00521 case KFormula::Container::EXIT_LEFT:
00522 exitLeft();
00523 break;
00524 case KFormula::Container::EXIT_RIGHT:
00525 exitRight();
00526 break;
00527 case KFormula::Container::EXIT_ABOVE:
00528 exitLeft();
00529 break;
00530 case KFormula::Container::EXIT_BELOW:
00531 exitRight();
00532 break;
00533 case KFormula::Container::REMOVE_FORMULA:
00534 removeFormula();
00535 break;
00536 }
00537 }
00538 }
00539
00540 #include "KWFormulaFrameSet.moc"