lib Library API Documentation

kformulacontainer.cc

00001 /* This file is part of the KDE project 00002 Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org> 00003 Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include <qapplication.h> 00022 #include <qdom.h> 00023 #include <qevent.h> 00024 #include <qfile.h> 00025 #include <qpainter.h> 00026 #include <qpixmap.h> 00027 #include <qstring.h> 00028 #include <qtextstream.h> 00029 00030 #include <kdebug.h> 00031 #include <klocale.h> 00032 #include <kprinter.h> 00033 00034 #include "bracketelement.h" 00035 #include "contextstyle.h" 00036 #include "formulacursor.h" 00037 #include "formulaelement.h" 00038 #include "fractionelement.h" 00039 #include "indexelement.h" 00040 #include "kformulacommand.h" 00041 #include "kformulacompatibility.h" 00042 #include "kformulacontainer.h" 00043 #include "kformuladocument.h" 00044 #include "kformulamathmlread.h" 00045 #include "kformulamimesource.h" 00046 #include "matrixelement.h" 00047 #include "rootelement.h" 00048 #include "sequenceelement.h" 00049 #include "symbolelement.h" 00050 #include "symboltable.h" 00051 #include "spaceelement.h" 00052 #include "textelement.h" 00053 00054 #include <assert.h> 00055 00056 KFORMULA_NAMESPACE_BEGIN 00057 using namespace std; 00058 00059 00060 struct Container::Container_Impl { 00061 00062 Container_Impl( Document* doc ) 00063 : dirty( true ), cursorMoved( false ), document( doc ) 00064 { 00065 } 00066 00067 ~Container_Impl() 00068 { 00069 delete internCursor; 00070 delete rootElement; 00071 document = 0; 00072 } 00073 00077 bool dirty; 00078 00082 bool cursorMoved; 00083 00087 FormulaElement* rootElement; 00088 00092 FormulaCursor* activeCursor; 00093 00097 FormulaCursor* internCursor; 00098 00102 Document* document; 00103 }; 00104 00105 00106 FormulaElement* Container::rootElement() const { return impl->rootElement; } 00107 Document* Container::document() const { return impl->document; } 00108 00109 Container::Container( Document* doc, int pos, bool registerMe ) 00110 { 00111 impl = new Container_Impl( doc ); 00112 impl->rootElement = 0; 00113 if ( registerMe ) { 00114 registerFormula( pos ); 00115 } 00116 } 00117 00118 Container::~Container() 00119 { 00120 unregisterFormula(); 00121 delete impl; 00122 impl = 0; 00123 } 00124 00125 00126 void Container::initialize() 00127 { 00128 assert( impl->rootElement == 0 ); 00129 impl->rootElement = createMainSequence(); 00130 impl->activeCursor = impl->internCursor = createCursor(); 00131 recalc(); 00132 } 00133 00134 00135 FormulaElement* Container::createMainSequence() 00136 { 00137 return new FormulaElement( this ); 00138 } 00139 00140 00141 FormulaCursor* Container::createCursor() 00142 { 00143 return new FormulaCursor(rootElement()); 00144 } 00145 00146 00147 KoCommandHistory* Container::getHistory() const 00148 { 00149 return document()->getHistory(); 00150 } 00151 00152 00157 void Container::elementRemoval(BasicElement* child) 00158 { 00159 emit elementWillVanish(child); 00160 } 00161 00166 void Container::changed() 00167 { 00168 impl->dirty = true; 00169 } 00170 00171 void Container::cursorHasMoved( FormulaCursor* ) 00172 { 00173 impl->cursorMoved = true; 00174 } 00175 00176 void Container::moveOutLeft( FormulaCursor* cursor ) 00177 { 00178 emit leaveFormula( this, cursor, EXIT_LEFT ); 00179 } 00180 00181 void Container::moveOutRight( FormulaCursor* cursor ) 00182 { 00183 emit leaveFormula( this, cursor, EXIT_RIGHT ); 00184 } 00185 00186 void Container::moveOutAbove( FormulaCursor* cursor ) 00187 { 00188 emit leaveFormula( this, cursor, EXIT_ABOVE ); 00189 } 00190 00191 void Container::moveOutBelow( FormulaCursor* cursor ) 00192 { 00193 emit leaveFormula( this, cursor, EXIT_BELOW ); 00194 } 00195 00196 void Container::tell( const QString& msg ) 00197 { 00198 emit statusMsg( msg ); 00199 } 00200 00201 void Container::removeFormula( FormulaCursor* cursor ) 00202 { 00203 emit leaveFormula( this, cursor, REMOVE_FORMULA ); 00204 } 00205 00206 00207 void Container::registerFormula( int pos ) 00208 { 00209 document()->registerFormula( this, pos ); 00210 } 00211 00212 void Container::unregisterFormula() 00213 { 00214 document()->unregisterFormula( this ); 00215 } 00216 00217 00218 void Container::baseSizeChanged( int size, bool owned ) 00219 { 00220 if ( owned ) { 00221 emit baseSizeChanged( size ); 00222 } 00223 else { 00224 const ContextStyle& context = document()->getContextStyle(); 00225 emit baseSizeChanged( context.baseSize() ); 00226 } 00227 } 00228 00229 FormulaCursor* Container::activeCursor() 00230 { 00231 return impl->activeCursor; 00232 } 00233 00234 const FormulaCursor* Container::activeCursor() const 00235 { 00236 return impl->activeCursor; 00237 } 00238 00239 00244 void Container::setActiveCursor(FormulaCursor* cursor) 00245 { 00246 document()->activate(this); 00247 if (cursor != 0) { 00248 impl->activeCursor = cursor; 00249 } 00250 else { 00251 *(impl->internCursor) = *(impl->activeCursor); 00252 impl->activeCursor = impl->internCursor; 00253 } 00254 } 00255 00256 00257 bool Container::hasValidCursor() const 00258 { 00259 return (impl->activeCursor != 0) && !impl->activeCursor->isReadOnly(); 00260 } 00261 00262 void Container::testDirty() 00263 { 00264 if (impl->dirty) { 00265 recalc(); 00266 } 00267 } 00268 00269 void Container::recalc() 00270 { 00271 impl->dirty = false; 00272 ContextStyle& context = impl->document->getContextStyle(); 00273 rootElement()->calcSizes( context ); 00274 00275 emit formulaChanged( context.layoutUnitToPixelX( rootElement()->getWidth() ), 00276 context.layoutUnitToPixelY( rootElement()->getHeight() ) ); 00277 emit formulaChanged( context.layoutUnitPtToPt( context.pixelXToPt( rootElement()->getWidth() ) ), 00278 context.layoutUnitPtToPt( context.pixelYToPt( rootElement()->getHeight() ) ) ); 00279 emit cursorMoved( activeCursor() ); 00280 } 00281 00282 bool Container::isEmpty() 00283 { 00284 return rootElement()->countChildren() == 0; 00285 } 00286 00287 00288 const SymbolTable& Container::getSymbolTable() const 00289 { 00290 return document()->getSymbolTable(); 00291 } 00292 00293 00294 void Container::draw( QPainter& painter, const QRect& r, const QColorGroup& cg, bool edit ) 00295 { 00296 painter.fillRect( r, cg.base() ); 00297 draw( painter, r, edit ); 00298 } 00299 00300 00301 void Container::draw( QPainter& painter, const QRect& r, bool edit ) 00302 { 00303 //ContextStyle& context = document()->getContextStyle( painter.device()->devType() == QInternal::Printer ); 00304 ContextStyle& context = document()->getContextStyle( edit ); 00305 rootElement()->draw( painter, context.pixelToLayoutUnit( r ), context ); 00306 } 00307 00308 00309 void Container::checkCursor() 00310 { 00311 if ( impl->cursorMoved ) { 00312 impl->cursorMoved = false; 00313 emit cursorMoved( activeCursor() ); 00314 } 00315 } 00316 00317 void Container::input( QKeyEvent* event ) 00318 { 00319 //if ( !hasValidCursor() ) 00320 if ( impl->activeCursor == 0 ) { 00321 return; 00322 } 00323 execute( activeCursor()->getElement()->input( this, event ) ); 00324 checkCursor(); 00325 } 00326 00327 00328 void Container::performRequest( Request* request ) 00329 { 00330 if ( !hasValidCursor() ) 00331 return; 00332 execute( activeCursor()->getElement()->buildCommand( this, request ) ); 00333 checkCursor(); 00334 } 00335 00336 00337 void Container::paste() 00338 { 00339 if (!hasValidCursor()) 00340 return; 00341 QClipboard* clipboard = QApplication::clipboard(); 00342 const QMimeSource* source = clipboard->data(); 00343 if (source->provides( MimeSource::selectionMimeType() )) { 00344 QByteArray data = source->encodedData( MimeSource::selectionMimeType() ); 00345 QDomDocument formula; 00346 formula.setContent(data); 00347 paste( formula, i18n("Paste") ); 00348 } 00349 } 00350 00351 void Container::paste( QDomDocument document, QString desc ) 00352 { 00353 FormulaCursor* cursor = activeCursor(); 00354 QPtrList<BasicElement> list; 00355 list.setAutoDelete( true ); 00356 if ( cursor->buildElementsFromDom( document.documentElement(), list ) ) { 00357 uint count = list.count(); 00358 // You must not execute an add command that adds nothing. 00359 if (count > 0) { 00360 KFCReplace* command = new KFCReplace( desc, this ); 00361 for (uint i = 0; i < count; i++) { 00362 command->addElement(list.take(0)); 00363 } 00364 execute(command); 00365 } 00366 } 00367 } 00368 00369 void Container::copy() 00370 { 00371 // read-only cursors are fine for copying. 00372 FormulaCursor* cursor = activeCursor(); 00373 if (cursor != 0) { 00374 QDomDocument formula = document()->createDomDocument(); 00375 cursor->copy( formula ); 00376 QClipboard* clipboard = QApplication::clipboard(); 00377 clipboard->setData(new MimeSource(document(), formula)); 00378 } 00379 } 00380 00381 void Container::cut() 00382 { 00383 if (!hasValidCursor()) 00384 return; 00385 FormulaCursor* cursor = activeCursor(); 00386 if (cursor->isSelection()) { 00387 copy(); 00388 DirectedRemove r( req_remove, beforeCursor ); 00389 performRequest( &r ); 00390 } 00391 } 00392 00393 00394 void Container::emitErrorMsg( const QString& msg ) 00395 { 00396 emit errorMsg( msg ); 00397 } 00398 00399 void Container::execute(KCommand* command) 00400 { 00401 if ( command != 0 ) { 00402 getHistory()->addCommand(command); 00403 } 00404 } 00405 00406 00407 QRect Container::boundingRect() const 00408 { 00409 const ContextStyle& context = document()->getContextStyle(); 00410 return QRect( context.layoutUnitToPixelX( rootElement()->getX() ), 00411 context.layoutUnitToPixelY( rootElement()->getY() ), 00412 context.layoutUnitToPixelX( rootElement()->getWidth() ), 00413 context.layoutUnitToPixelY( rootElement()->getHeight() ) ); 00414 } 00415 00416 QRect Container::coveredRect() 00417 { 00418 if ( impl->activeCursor != 0 ) { 00419 const ContextStyle& context = document()->getContextStyle(); 00420 const LuPixelRect& cursorRect = impl->activeCursor->getCursorSize(); 00421 return QRect( context.layoutUnitToPixelX( rootElement()->getX() ), 00422 context.layoutUnitToPixelY( rootElement()->getY() ), 00423 context.layoutUnitToPixelX( rootElement()->getWidth() ), 00424 context.layoutUnitToPixelY( rootElement()->getHeight() ) ) | 00425 QRect( context.layoutUnitToPixelX( cursorRect.x() ), 00426 context.layoutUnitToPixelY( cursorRect.y() ), 00427 context.layoutUnitToPixelX( cursorRect.width() ), 00428 context.layoutUnitToPixelY( cursorRect.height() ) ); 00429 } 00430 return boundingRect(); 00431 } 00432 00433 double Container::width() const 00434 { 00435 const ContextStyle& context = document()->getContextStyle(); 00436 return context.layoutUnitPtToPt( context.pixelXToPt( rootElement()->getWidth() ) ); 00437 } 00438 00439 double Container::height() const 00440 { 00441 const ContextStyle& context = document()->getContextStyle(); 00442 return context.layoutUnitPtToPt( context.pixelYToPt( rootElement()->getHeight() ) ); 00443 } 00444 00445 double Container::baseline() const 00446 { 00447 const ContextStyle& context = document()->getContextStyle(); 00448 //return context.layoutUnitToPixelY( rootElement()->getBaseline() ); 00449 return context.layoutUnitPtToPt( context.pixelYToPt( rootElement()->getBaseline() ) ); 00450 } 00451 00452 void Container::moveTo( int x, int y ) 00453 { 00454 const ContextStyle& context = document()->getContextStyle(); 00455 rootElement()->setX( context.pixelToLayoutUnitX( x ) ); 00456 rootElement()->setY( context.pixelToLayoutUnitY( y ) ); 00457 } 00458 00459 int Container::fontSize() const 00460 { 00461 if ( rootElement()->hasOwnBaseSize() ) { 00462 return rootElement()->getBaseSize(); 00463 } 00464 else { 00465 const ContextStyle& context = document()->getContextStyle(); 00466 return qRound( context.baseSize() ); 00467 } 00468 } 00469 00470 void Container::setFontSize( int pointSize, bool /*forPrint*/ ) 00471 { 00472 if ( rootElement()->getBaseSize() != pointSize ) { 00473 execute( new KFCChangeBaseSize( i18n( "Base Size Change" ), this, rootElement(), pointSize ) ); 00474 } 00475 } 00476 00477 void Container::setFontSizeDirect( int pointSize ) 00478 { 00479 rootElement()->setBaseSize( pointSize ); 00480 recalc(); 00481 } 00482 00483 00484 void Container::save( QDomElement root ) 00485 { 00486 QDomDocument ownerDoc = root.ownerDocument(); 00487 root.appendChild(rootElement()->getElementDom(ownerDoc)); 00488 } 00489 00490 00494 bool Container::load( QDomElement fe ) 00495 { 00496 if (!fe.isNull()) { 00497 FormulaElement* root = createMainSequence(); 00498 if (root->buildFromDom(fe)) { 00499 delete impl->rootElement; 00500 impl->rootElement = root; 00501 emit formulaLoaded(rootElement()); 00502 00503 recalc(); 00504 return true; 00505 } 00506 else { 00507 delete root; 00508 kdWarning( DEBUGID ) << "Error constructing element tree." << endl; 00509 } 00510 } 00511 else { 00512 kdWarning( DEBUGID ) << "Empty element." << endl; 00513 } 00514 return false; 00515 } 00516 00517 00518 void Container::saveMathML( QTextStream& stream ) 00519 { 00520 QDomDocumentType dt = QDomImplementation().createDocumentType( "math", 00521 "-//W3C//DTD MathML 2.0//EN", 00522 "http://www.w3.org/TR/MathML2/dtd/mathml2.dtd"); 00523 QDomDocument doc( dt ); 00524 rootElement()->writeMathML( doc, doc ); 00525 doc.save( stream, 2 ); 00526 } 00527 00528 bool Container::loadMathML( QDomDocument doc ) 00529 { 00530 const ContextStyle& context = document()->getContextStyle(); 00531 MathML2KFormula filter( doc, context ); 00532 filter.startConversion(); 00533 00534 if ( load( filter.getKFormulaDom().documentElement() ) ) { 00535 getHistory()->clear(); 00536 return true; 00537 } 00538 return false; 00539 } 00540 00541 00542 void Container::print(KPrinter& printer) 00543 { 00544 //printer.setFullPage(true); 00545 QPainter painter; 00546 if (painter.begin(&printer)) { 00547 rootElement()->draw( painter, LuPixelRect( rootElement()->getX(), 00548 rootElement()->getY(), 00549 rootElement()->getWidth(), 00550 rootElement()->getHeight() ), 00551 document()->getContextStyle( false ) ); 00552 } 00553 } 00554 00555 QImage Container::drawImage( int width, int height ) 00556 { 00557 ContextStyle& context = document()->getContextStyle( false ); 00558 QRect rect(impl->rootElement->getX(), impl->rootElement->getY(), 00559 impl->rootElement->getWidth(), impl->rootElement->getHeight()); 00560 00561 int realWidth = context.layoutUnitToPixelX( impl->rootElement->getWidth() ); 00562 int realHeight = context.layoutUnitToPixelY( impl->rootElement->getHeight() ); 00563 00564 double f = QMAX( static_cast<double>( width )/static_cast<double>( realWidth ), 00565 static_cast<double>( height )/static_cast<double>( realHeight ) ); 00566 00567 int oldZoom = context.zoom(); 00568 context.setZoomAndResolution( qRound( oldZoom*f ), QPaintDevice::x11AppDpiX(), QPaintDevice::x11AppDpiY() ); 00569 00570 kdDebug( DEBUGID ) << "Container::drawImage " 00571 << "(" << width << " " << height << ")" 00572 << "(" << context.layoutUnitToPixelX( impl->rootElement->getWidth() ) 00573 << " " << context.layoutUnitToPixelY( impl->rootElement->getHeight() ) << ")" 00574 << endl; 00575 00576 QPixmap pm( context.layoutUnitToPixelX( impl->rootElement->getWidth() ), 00577 context.layoutUnitToPixelY( impl->rootElement->getHeight() ) ); 00578 pm.fill(); 00579 QPainter paint(&pm); 00580 impl->rootElement->draw(paint, rect, context); 00581 paint.end(); 00582 context.setZoomAndResolution( oldZoom, QPaintDevice::x11AppDpiX(), QPaintDevice::x11AppDpiY() ); 00583 //return pm.convertToImage().smoothScale( width, height ); 00584 return pm.convertToImage(); 00585 } 00586 00587 QString Container::texString() 00588 { 00589 return rootElement()->toLatex(); 00590 } 00591 00592 QString Container::formulaString() 00593 { 00594 return rootElement()->formulaString(); 00595 } 00596 00597 KFORMULA_NAMESPACE_END 00598 00599 using namespace KFormula; 00600 #include "kformulacontainer.moc"
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:22 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003