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.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Mar 11 11:47:39 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003