00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <math.h>
00023
00024 #include <qpainter.h>
00025 #include <qpaintdevice.h>
00026 #include <qvaluestack.h>
00027
00028 #include <kcommand.h>
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031
00032
00033
00034 #include "MatrixDialog.h"
00035 #include "bracketelement.h"
00036 #include "creationstrategy.h"
00037 #include "elementtype.h"
00038 #include "elementvisitor.h"
00039 #include "formulacursor.h"
00040 #include "formulaelement.h"
00041 #include "fractionelement.h"
00042 #include "indexelement.h"
00043 #include "kformulacommand.h"
00044 #include "kformulacontainer.h"
00045 #include "kformuladocument.h"
00046 #include "matrixelement.h"
00047 #include "rootelement.h"
00048 #include "sequenceelement.h"
00049 #include "sequenceparser.h"
00050 #include "spaceelement.h"
00051 #include "symbolelement.h"
00052 #include "symboltable.h"
00053 #include "textelement.h"
00054
00055 #include <assert.h>
00056
00057 KFORMULA_NAMESPACE_BEGIN
00058
00059
00060 ElementCreationStrategy* SequenceElement::creationStrategy = 0;
00061
00062 void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy )
00063 {
00064 creationStrategy = strategy;
00065 }
00066
00067
00068 SequenceElement::SequenceElement(BasicElement* parent)
00069 : BasicElement(parent), parseTree(0), textSequence(true),singlePipe(true)
00070 {
00071 assert( creationStrategy != 0 );
00072 children.setAutoDelete(true);
00073 }
00074
00075
00076 SequenceElement::~SequenceElement()
00077 {
00078 delete parseTree;
00079 }
00080
00081 SequenceElement::SequenceElement( const SequenceElement& other )
00082 : BasicElement( other )
00083 {
00084 children.setAutoDelete(true);
00085 uint count = other.children.count();
00086 for (uint i = 0; i < count; i++) {
00087 BasicElement* child = children.at(i)->clone();
00088 child->setParent( this );
00089 children.append( child );
00090 }
00091 }
00092
00093
00094 bool SequenceElement::accept( ElementVisitor* visitor )
00095 {
00096 return visitor->visit( this );
00097 }
00098
00099
00100 bool SequenceElement::readOnly( const FormulaCursor* ) const
00101 {
00102 return getParent()->readOnly( this );
00103 }
00104
00105
00109 BasicElement* SequenceElement::goToPos( FormulaCursor* cursor, bool& handled,
00110 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00111 {
00112 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00113 if (e != 0) {
00114 LuPixelPoint myPos(parentOrigin.x() + getX(),
00115 parentOrigin.y() + getY());
00116
00117 uint count = children.count();
00118 for (uint i = 0; i < count; i++) {
00119 BasicElement* child = children.at(i);
00120 e = child->goToPos(cursor, handled, point, myPos);
00121 if (e != 0) {
00122 if (!handled) {
00123 handled = true;
00124 if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) {
00125 cursor->setTo(this, children.find(e));
00126 }
00127 else {
00128 cursor->setTo(this, children.find(e)+1);
00129 }
00130 }
00131 return e;
00132 }
00133 }
00134
00135 luPixel dx = point.x() - myPos.x();
00136
00137
00138 for (uint i = 0; i < count; i++) {
00139 BasicElement* child = children.at(i);
00140 if (dx < child->getX()) {
00141 cursor->setTo( this, i );
00142 handled = true;
00143 return children.at( i );
00144 }
00145 }
00146
00147 cursor->setTo(this, countChildren());
00148 handled = true;
00149 return this;
00150 }
00151 return 0;
00152 }
00153
00154
00155 bool SequenceElement::isEmpty()
00156 {
00157 uint count = children.count();
00158 for (uint i = 0; i < count; i++) {
00159 BasicElement* child = children.at(i);
00160 if (!child->isInvisible()) {
00161 return false;
00162 }
00163 }
00164 return true;
00165 }
00166
00167
00172 void SequenceElement::calcSizes(const ContextStyle& style,
00173 ContextStyle::TextStyle tstyle,
00174 ContextStyle::IndexStyle istyle)
00175 {
00176 if (!isEmpty()) {
00177 luPixel width = 0;
00178 luPixel toBaseline = 0;
00179 luPixel fromBaseline = 0;
00180
00181
00182 QPtrListIterator<BasicElement> it( children );
00183 for ( ; it.current(); ++it ) {
00184 BasicElement* child = it.current();
00185
00186 luPixel spaceBefore = 0;
00187 if ( isFirstOfToken( child ) ) {
00188 spaceBefore =
00189 style.ptToPixelX( child->getElementType()->getSpaceBefore( style,
00190 tstyle ) );
00191 }
00192
00193 if ( !child->isInvisible() ) {
00194 child->calcSizes( style, tstyle, istyle );
00195 child->setX( width + spaceBefore );
00196 width += child->getWidth() + spaceBefore;
00197
00198 luPixel childBaseline = child->getBaseline();
00199 if ( childBaseline > -1 ) {
00200 toBaseline = QMAX( toBaseline, childBaseline );
00201 fromBaseline = QMAX( fromBaseline,
00202 child->getHeight() - childBaseline );
00203 }
00204 else {
00205 luPixel bl = child->getHeight()/2 + style.axisHeight( tstyle );
00206 toBaseline = QMAX( toBaseline, bl );
00207 fromBaseline = QMAX( fromBaseline, child->getHeight() - bl );
00208 }
00209 }
00210 else {
00211 width += spaceBefore;
00212 child->setX( width );
00213 }
00214 }
00215
00216 setWidth(width);
00217 setHeight(toBaseline+fromBaseline);
00218 setBaseline(toBaseline);
00219
00220 setChildrenPositions();
00221 }
00222 else {
00223 luPixel w = style.getEmptyRectWidth();
00224 luPixel h = style.getEmptyRectHeight();
00225 setWidth( w );
00226 setHeight( h );
00227 setBaseline( h );
00228
00229 }
00230 }
00231
00232
00233 void SequenceElement::setChildrenPositions()
00234 {
00235 QPtrListIterator<BasicElement> it( children );
00236 for ( ; it.current(); ++it ) {
00237 BasicElement* child = it.current();
00238 child->setY(getBaseline() - child->getBaseline());
00239 }
00240 }
00241
00242
00248 void SequenceElement::draw( QPainter& painter, const LuPixelRect& r,
00249 const ContextStyle& context,
00250 ContextStyle::TextStyle tstyle,
00251 ContextStyle::IndexStyle istyle,
00252 const LuPixelPoint& parentOrigin )
00253 {
00254 LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
00255
00256
00257
00258
00259
00260 if (!isEmpty()) {
00261 QPtrListIterator<BasicElement> it( children );
00262 for ( ; it.current(); ) {
00263 BasicElement* child = it.current();
00264 if (!child->isInvisible()) {
00265 child->draw(painter, r, context, tstyle, istyle, myPos);
00266
00267
00268
00269 ElementType* token = child->getElementType();
00270 if ( token != 0 ) {
00271 it += token->end() - token->start();
00272 }
00273 else {
00274 ++it;
00275 }
00276 }
00277 else {
00278 ++it;
00279 }
00280 }
00281 }
00282 else {
00283 drawEmptyRect( painter, context, myPos );
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 }
00299
00300
00301 void SequenceElement::dispatchFontCommand( FontCommand* cmd )
00302 {
00303 QPtrListIterator<BasicElement> it( children );
00304 for ( ; it.current(); ++it ) {
00305 BasicElement* child = it.current();
00306 child->dispatchFontCommand( cmd );
00307 }
00308 }
00309
00310
00311 void SequenceElement::drawEmptyRect( QPainter& painter, const ContextStyle& context,
00312 const LuPixelPoint& upperLeft )
00313 {
00314 if ( context.edit() ) {
00315 painter.setBrush(Qt::NoBrush);
00316 painter.setPen( QPen( context.getEmptyColor(),
00317 context.layoutUnitToPixelX( context.getLineWidth() ) ) );
00318 painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ),
00319 context.layoutUnitToPixelY( upperLeft.y() ),
00320 context.layoutUnitToPixelX( getWidth() ),
00321 context.layoutUnitToPixelY( getHeight() ) );
00322 }
00323 }
00324
00325 void SequenceElement::calcCursorSize( const ContextStyle& context,
00326 FormulaCursor* cursor, bool smallCursor )
00327 {
00328 LuPixelPoint point = widgetPos();
00329 uint pos = cursor->getPos();
00330
00331 luPixel posX = getChildPosition( context, pos );
00332 luPixel height = getHeight();
00333
00334 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
00335 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
00336
00337
00338
00339 if ( cursor->isSelection() ) {
00340 uint mark = cursor->getMark();
00341 luPixel markX = getChildPosition( context, mark );
00342 luPixel x = QMIN(posX, markX);
00343 luPixel width = abs(posX - markX);
00344
00345 if ( smallCursor ) {
00346 cursor->cursorSize.setRect( point.x()+x, point.y(), width, height );
00347 }
00348 else {
00349 cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY,
00350 width + unitX, height + 4*unitY );
00351 }
00352 }
00353 else {
00354 if ( smallCursor ) {
00355 cursor->cursorSize.setRect( point.x()+posX, point.y(),
00356 unitX, height );
00357 }
00358 else {
00359 cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY,
00360 getWidth() + unitX, height + 4*unitY );
00361 }
00362 }
00363
00364 cursor->cursorPoint.setX( point.x()+posX );
00365 cursor->cursorPoint.setY( point.y()+getHeight()/2 );
00366 }
00367
00368
00372 void SequenceElement::drawCursor( QPainter& painter, const ContextStyle& context,
00373 FormulaCursor* cursor, bool smallCursor,
00374 bool activeCursor )
00375 {
00376 painter.setRasterOp( Qt::XorROP );
00377 if ( cursor->isSelection() ) {
00378 const LuPixelRect& r = cursor->cursorSize;
00379 painter.fillRect( context.layoutUnitToPixelX( r.x() ),
00380 context.layoutUnitToPixelY( r.y() ),
00381 context.layoutUnitToPixelX( r.width() ),
00382 context.layoutUnitToPixelY( r.height() ),
00383 Qt::white );
00384 }
00385 painter.setPen( QPen( Qt::white,
00386 context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
00387 const LuPixelPoint& point = cursor->getCursorPoint();
00388 const LuPixelRect& size = cursor->getCursorSize();
00389 if ( activeCursor )
00390 {
00391 int offset = 0;
00392 if ( cursor->isSelection() && cursor->getPos() > cursor->getMark() )
00393 offset = -1;
00394 painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset,
00395 context.layoutUnitToPixelY( size.top() ),
00396 context.layoutUnitToPixelX( point.x() ) + offset,
00397 context.layoutUnitToPixelY( size.bottom() )-1 );
00398 painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset + 1,
00399 context.layoutUnitToPixelY( size.top() ),
00400 context.layoutUnitToPixelX( point.x() ) + offset + 1,
00401 context.layoutUnitToPixelY( size.bottom() )-1 );
00402 }
00403 if ( !smallCursor && !cursor->isSelection() )
00404 painter.drawLine( context.layoutUnitToPixelX( size.left() ),
00405 context.layoutUnitToPixelY( size.bottom() )-1,
00406 context.layoutUnitToPixelX( size.right() )-1,
00407 context.layoutUnitToPixelY( size.bottom() )-1 );
00408
00409 painter.setRasterOp( Qt::CopyROP );
00410 }
00411
00412
00413 luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
00414 {
00415 if (child < children.count()) {
00416 return children.at(child)->getX();
00417 }
00418 else {
00419 if (children.count() > 0) {
00420 return children.at(child-1)->getX() + children.at(child-1)->getWidth();
00421 }
00422 else {
00423 return context.ptToLayoutUnitPixX( 2 );
00424 }
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00442 void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00443 {
00444
00445 if (from == getParent()) {
00446 cursor->setTo(this, children.count());
00447 from->entered( this );
00448 }
00449
00450
00451 else if (from == this) {
00452 if (cursor->getPos() > 0) {
00453 if (cursor->isSelectionMode()) {
00454 cursor->setTo(this, cursor->getPos()-1);
00455
00456
00457 if (children.at(cursor->getPos())->isInvisible()) {
00458 moveLeft(cursor, this);
00459 }
00460 }
00461 else {
00462 children.at(cursor->getPos()-1)->moveLeft(cursor, this);
00463 }
00464 }
00465 else {
00466
00467 if (getParent() != 0) {
00468 getParent()->moveLeft(cursor, this);
00469 }
00470 else {
00471 formula()->moveOutLeft( cursor );
00472 }
00473 }
00474 }
00475
00476
00477
00478 else {
00479 int fromPos = children.find(from);
00480 cursor->setTo(this, fromPos);
00481 if (cursor->isSelectionMode()) {
00482 cursor->setMark(fromPos+1);
00483 }
00484
00485
00486 if (from->isInvisible()) {
00487 moveLeft(cursor, this);
00488 }
00489 formula()->tell( "" );
00490 }
00491 }
00492
00498 void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00499 {
00500
00501 if (from == getParent()) {
00502 cursor->setTo(this, 0);
00503 from->entered( this );
00504 }
00505
00506
00507 else if (from == this) {
00508 uint pos = cursor->getPos();
00509 if (pos < children.count()) {
00510 if (cursor->isSelectionMode()) {
00511 cursor->setTo(this, pos+1);
00512
00513
00514 if (children.at(pos)->isInvisible()) {
00515 moveRight(cursor, this);
00516 }
00517 }
00518 else {
00519 children.at(pos)->moveRight(cursor, this);
00520 }
00521 }
00522 else {
00523
00524 if (getParent() != 0) {
00525 getParent()->moveRight(cursor, this);
00526 }
00527 else {
00528 formula()->moveOutRight( cursor );
00529 }
00530 }
00531 }
00532
00533
00534
00535 else {
00536 int fromPos = children.find(from);
00537 cursor->setTo(this, fromPos+1);
00538 if (cursor->isSelectionMode()) {
00539 cursor->setMark(fromPos);
00540 }
00541
00542
00543 if (from->isInvisible()) {
00544 moveRight(cursor, this);
00545 }
00546 formula()->tell( "" );
00547 }
00548 }
00549
00550
00551 void SequenceElement::moveWordLeft(FormulaCursor* cursor)
00552 {
00553 uint pos = cursor->getPos();
00554 if (pos > 0) {
00555 ElementType* type = children.at(pos-1)->getElementType();
00556 if (type != 0) {
00557 cursor->setTo(this, type->start());
00558 }
00559 }
00560 else {
00561 moveLeft(cursor, this);
00562 }
00563 }
00564
00565
00566 void SequenceElement::moveWordRight(FormulaCursor* cursor)
00567 {
00568 uint pos = cursor->getPos();
00569 if (pos < children.count()) {
00570 ElementType* type = children.at(pos)->getElementType();
00571 if (type != 0) {
00572 cursor->setTo(this, type->end());
00573 }
00574 }
00575 else {
00576 moveRight(cursor, this);
00577 }
00578 }
00579
00580
00586 void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00587 {
00588 if (from == getParent()) {
00589 moveRight(cursor, this);
00590 }
00591 else {
00592 if (getParent() != 0) {
00593 getParent()->moveUp(cursor, this);
00594 }
00595 else {
00596 formula()->moveOutAbove( cursor );
00597 }
00598 }
00599 }
00600
00606 void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00607 {
00608 if (from == getParent()) {
00609 moveRight(cursor, this);
00610 }
00611 else {
00612 if (getParent() != 0) {
00613 getParent()->moveDown(cursor, this);
00614 }
00615 else {
00616 formula()->moveOutBelow( cursor );
00617 }
00618 }
00619 }
00620
00625 void SequenceElement::moveHome(FormulaCursor* cursor)
00626 {
00627 if (cursor->isSelectionMode()) {
00628 BasicElement* element = cursor->getElement();
00629 if (element != this) {
00630 while (element->getParent() != this) {
00631 element = element->getParent();
00632 }
00633 cursor->setMark(children.find(element)+1);
00634 }
00635 }
00636 cursor->setTo(this, 0);
00637 }
00638
00643 void SequenceElement::moveEnd(FormulaCursor* cursor)
00644 {
00645 if (cursor->isSelectionMode()) {
00646 BasicElement* element = cursor->getElement();
00647 if (element != this) {
00648 while (element->getParent() != this) {
00649 element = element->getParent();
00650 if (element == 0) {
00651 cursor->setMark(children.count());
00652 break;
00653 }
00654 }
00655 if (element != 0) {
00656 cursor->setMark(children.find(element));
00657 }
00658 }
00659 }
00660 cursor->setTo(this, children.count());
00661 }
00662
00667 void SequenceElement::goInside(FormulaCursor* cursor)
00668 {
00669 cursor->setSelection(false);
00670 cursor->setTo(this, 0);
00671 }
00672
00673
00674
00675
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00706 void SequenceElement::insert(FormulaCursor* cursor,
00707 QPtrList<BasicElement>& newChildren,
00708 Direction direction)
00709 {
00710 int pos = cursor->getPos();
00711 uint count = newChildren.count();
00712 for (uint i = 0; i < count; i++) {
00713 BasicElement* child = newChildren.take(0);
00714 child->setParent(this);
00715 children.insert(pos+i, child);
00716 }
00717 if (direction == beforeCursor) {
00718 cursor->setTo(this, pos+count, pos);
00719 }
00720 else {
00721 cursor->setTo(this, pos, pos+count);
00722 }
00723
00724 formula()->changed();
00725 parse();
00726 }
00727
00728
00735 void SequenceElement::remove(FormulaCursor* cursor,
00736 QPtrList<BasicElement>& removedChildren,
00737 Direction direction)
00738 {
00739 if (cursor->isSelection()) {
00740 int from = cursor->getSelectionStart();
00741 int to = cursor->getSelectionEnd();
00742 for (int i = from; i < to; i++) {
00743 removeChild(removedChildren, from);
00744 }
00745 cursor->setTo(this, from);
00746 cursor->setSelection(false);
00747 }
00748 else {
00749 if (direction == beforeCursor) {
00750 int pos = cursor->getPos() - 1;
00751 if (pos >= 0) {
00752 while (pos >= 0) {
00753 BasicElement* child = children.at(pos);
00754 formula()->elementRemoval(child);
00755 children.take(pos);
00756 removedChildren.prepend(child);
00757 if (!child->isInvisible()) {
00758 break;
00759 }
00760 pos--;
00761 }
00762 cursor->setTo(this, pos);
00763 formula()->changed();
00764 }
00765 }
00766 else {
00767 uint pos = cursor->getPos();
00768 if (pos < children.count()) {
00769 while (pos < children.count()) {
00770 BasicElement* child = children.at(pos);
00771 formula()->elementRemoval(child);
00772 children.take(pos);
00773 removedChildren.append(child);
00774 if (!child->isInvisible()) {
00775 break;
00776 }
00777 }
00778
00779
00780
00781 cursor->setTo(this, pos);
00782 formula()->changed();
00783 }
00784 }
00785 }
00786 parse();
00787 }
00788
00789
00793 void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
00794 {
00795 BasicElement* child = children.at(pos);
00796 formula()->elementRemoval(child);
00797 children.take(pos);
00798 removedChildren.append(child);
00799
00800 formula()->changed();
00801 }
00802
00803
00808 void SequenceElement::normalize(FormulaCursor* cursor, Direction)
00809 {
00810 cursor->setSelection(false);
00811 }
00812
00813
00818 BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction )
00819 {
00820 if ( direction == beforeCursor ) {
00821 if ( cursor->getPos() > 0 ) {
00822 return children.at( cursor->getPos() - 1 );
00823 }
00824 }
00825 else {
00826 if ( cursor->getPos() < qRound( children.count() ) ) {
00827 return children.at( cursor->getPos() );
00828 }
00829 }
00830 return 0;
00831 }
00832
00833
00838 void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00839 {
00840 int pos = children.find(child);
00841 if (pos > -1) {
00842 cursor->setTo(this, pos+1, pos);
00843 }
00844 }
00845
00846 void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
00847 {
00848 int childPos = children.find(child);
00849 if (childPos > -1) {
00850 int pos = cursor->getPos();
00851 if (pos > childPos) {
00852 pos--;
00853 }
00854 int mark = cursor->getMark();
00855 if (mark > childPos) {
00856 mark--;
00857 }
00858 cursor->setTo(this, pos, mark);
00859 }
00860 }
00861
00862
00866 void SequenceElement::selectAllChildren(FormulaCursor* cursor)
00867 {
00868 cursor->setTo(this, children.count(), 0);
00869 }
00870
00871 bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
00872 {
00873 if ( cursor->isSelection() ) {
00874 uint from = QMIN( cursor->getPos(), cursor->getMark() );
00875 uint to = QMAX( cursor->getPos(), cursor->getMark() );
00876 for ( uint i = from; i < to; i++ ) {
00877 BasicElement* element = getChild( i );
00878 if ( element->getCharacter() == QChar::null ) {
00879 return false;
00880 }
00881 }
00882 }
00883 return true;
00884 }
00885
00886
00887 KCommand* SequenceElement::buildCommand( Container* container, Request* request )
00888 {
00889 FormulaCursor* cursor = container->activeCursor();
00890 if ( cursor->isReadOnly() ) {
00891 formula()->tell( i18n( "write protection" ) );
00892 return 0;
00893 }
00894
00895 switch ( *request ) {
00896 case req_addText: {
00897 KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00898 TextRequest* tr = static_cast<TextRequest*>( request );
00899 for ( uint i = 0; i < tr->text().length(); i++ ) {
00900 command->addElement( creationStrategy->createTextElement( tr->text()[i] ) );
00901 }
00902 return command;
00903 }
00904 case req_addTextChar: {
00905 KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00906 TextCharRequest* tr = static_cast<TextCharRequest*>( request );
00907 TextElement* element = creationStrategy->createTextElement( tr->ch(), tr->isSymbol() );
00908 command->addElement( element );
00909 return command;
00910 }
00911 case req_addEmptyBox: {
00912 EmptyElement* element = creationStrategy->createEmptyElement();
00913 if ( element != 0 ) {
00914 KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
00915 command->addElement( element );
00916 return command;
00917 }
00918 break;
00919 }
00920 case req_addNameSequence:
00921 if ( onlyTextSelected( container->activeCursor() ) ) {
00922 NameSequence* nameSequence = creationStrategy->createNameSequence();
00923 if ( nameSequence != 0 ) {
00924 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
00925 command->setElement( nameSequence );
00926 return command;
00927 }
00928 }
00929 break;
00930 case req_addBracket: {
00931 BracketRequest* br = static_cast<BracketRequest*>( request );
00932 BracketElement* bracketElement =
00933 creationStrategy->createBracketElement( br->left(), br->right() );
00934 if ( bracketElement != 0 ) {
00935 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
00936 command->setElement( bracketElement );
00937 return command;
00938 }
00939 break;
00940 }
00941 case req_addOverline: {
00942 OverlineElement* overline = creationStrategy->createOverlineElement();
00943 if ( overline != 0 ) {
00944 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
00945 command->setElement( overline );
00946 return command;
00947 }
00948 break;
00949 }
00950 case req_addUnderline: {
00951 UnderlineElement* underline = creationStrategy->createUnderlineElement();
00952 if ( underline != 0 ) {
00953 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
00954 command->setElement( underline );
00955 return command;
00956 }
00957 break;
00958 }
00959 case req_addMultiline: {
00960 MultilineElement* multiline = creationStrategy->createMultilineElement();
00961 if ( multiline != 0 ) {
00962 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
00963 command->setElement( multiline );
00964 return command;
00965 }
00966 break;
00967 }
00968 case req_addSpace: {
00969 SpaceRequest* sr = static_cast<SpaceRequest*>( request );
00970 SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
00971 if ( element != 0 ) {
00972 KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
00973 command->addElement( element );
00974 return command;
00975 }
00976 break;
00977 }
00978 case req_addFraction: {
00979 FractionElement* fraction = creationStrategy->createFractionElement();
00980 if ( fraction != 0 ) {
00981 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
00982 command->setElement( fraction );
00983 return command;
00984 }
00985 break;
00986 }
00987 case req_addRoot: {
00988 RootElement* root = creationStrategy->createRootElement();
00989 if ( root != 0 ) {
00990 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
00991 command->setElement( root );
00992 return command;
00993 }
00994 break;
00995 }
00996 case req_addSymbol: {
00997 SymbolRequest* sr = static_cast<SymbolRequest*>( request );
00998 SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
00999 if ( symbol != 0 ) {
01000 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
01001 command->setElement( symbol );
01002 return command;
01003 }
01004 break;
01005 }
01006 case req_addOneByTwoMatrix: {
01007 FractionElement* element = creationStrategy->createFractionElement();
01008 if ( element != 0 ) {
01009 KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
01010 element->showLine(false);
01011 command->setElement(element);
01012 return command;
01013 }
01014 }
01015 case req_addMatrix: {
01016 MatrixRequest* mr = static_cast<MatrixRequest*>( request );
01017 uint rows = mr->rows(), cols = mr->columns();
01018 if ( ( rows == 0 ) || ( cols == 0 ) ) {
01019 MatrixDialog* dialog = new MatrixDialog( 0 );
01020 if ( dialog->exec() ) {
01021 rows = dialog->h;
01022 cols = dialog->w;
01023 }
01024 delete dialog;
01025 }
01026
01027 if ( ( rows != 0 ) && ( cols != 0 ) ) {
01028 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
01029 command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
01030 return command;
01031 }
01032 else
01033 return 0L;
01034 }
01035 case req_addIndex: {
01036 if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
01037 IndexElement* element =
01038 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
01039 if ( element != 0 ) {
01040 element->getMainChild()->goInside( cursor );
01041 return element->getMainChild()->buildCommand( container, request );
01042 }
01043 }
01044 IndexElement* element = creationStrategy->createIndexElement();
01045 if ( element != 0 ) {
01046 if ( !cursor->isSelection() ) {
01047 cursor->moveLeft( SelectMovement | WordMovement );
01048 }
01049 IndexRequest* ir = static_cast<IndexRequest*>( request );
01050 KFCAddIndex* command = new KFCAddIndex( container, element,
01051 element->getIndex( ir->index() ) );
01052 return command;
01053 }
01054 break;
01055 }
01056 case req_removeEnclosing: {
01057 if ( !cursor->isSelection() ) {
01058 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01059 KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
01060 return command;
01061 }
01062 }
01063 case req_remove: {
01064 SequenceElement* sequence = cursor->normal();
01065 if ( sequence &&
01066 ( sequence == sequence->formula() ) &&
01067 ( sequence->countChildren() == 0 ) ) {
01068 sequence->formula()->removeFormula( cursor );
01069 return 0;
01070 }
01071 else {
01072 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01073
01074
01075 if ( !cursor->isSelection() ) {
01076 if ( countChildren() > 0 ) {
01077 if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
01078 return 0;
01079 }
01080 if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
01081 return 0;
01082 }
01083 }
01084 else if ( getParent() == 0 ) {
01085 return 0;
01086 }
01087 }
01088
01089 KFCRemove* command = new KFCRemove( container, dr->direction() );
01090 return command;
01091 }
01092 }
01093 case req_compactExpression: {
01094 cursor->moveEnd();
01095 cursor->moveRight();
01096 formula()->cursorHasMoved( cursor );
01097 break;
01098 }
01099 case req_makeGreek: {
01100 TextElement* element = cursor->getActiveTextElement();
01101 if ((element != 0) && !element->isSymbol()) {
01102 cursor->selectActiveElement();
01103 const SymbolTable& table = container->document()->getSymbolTable();
01104 if (table.greekLetters().find(element->getCharacter()) != -1) {
01105 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
01106 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
01107 command->addElement( symbol );
01108 return command;
01109 }
01110 cursor->setSelection( false );
01111 }
01112 break;
01113 }
01114 case req_paste:
01115 case req_copy:
01116 case req_cut:
01117 break;
01118 case req_formatBold:
01119 case req_formatItalic: {
01120 if ( cursor->isSelection() ) {
01121 CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
01122 CharStyle cs = normalChar;
01123 if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
01124 if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
01125 CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
01126 int end = cursor->getSelectionEnd();
01127 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01128 cmd->addElement( children.at( i ) );
01129 }
01130 return cmd;
01131 }
01132 break;
01133 }
01134 case req_formatFamily: {
01135 if ( cursor->isSelection() ) {
01136 CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
01137 CharFamily cf = cfr->charFamily();
01138 CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
01139 int end = cursor->getSelectionEnd();
01140 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01141 cmd->addElement( children.at( i ) );
01142 }
01143 return cmd;
01144 }
01145 break;
01146 }
01147 default:
01148 break;
01149 }
01150 return 0;
01151 }
01152
01153
01154 KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
01155 {
01156 QChar ch = event->text().at( 0 );
01157 if ( ch.isPrint() ) {
01158 return input( container, ch );
01159 }
01160 else {
01161 int action = event->key();
01162 int state = event->state();
01163 MoveFlag flag = movementFlag(state);
01164
01165 switch ( action ) {
01166 case Qt::Key_BackSpace: {
01167 DirectedRemove r( req_remove, beforeCursor );
01168 return buildCommand( container, &r );
01169 }
01170 case Qt::Key_Delete: {
01171 DirectedRemove r( req_remove, afterCursor );
01172 return buildCommand( container, &r );
01173 }
01174 case Qt::Key_Left: {
01175 FormulaCursor* cursor = container->activeCursor();
01176 cursor->moveLeft( flag );
01177 formula()->cursorHasMoved( cursor );
01178 break;
01179 }
01180 case Qt::Key_Right: {
01181 FormulaCursor* cursor = container->activeCursor();
01182 cursor->moveRight( flag );
01183 formula()->cursorHasMoved( cursor );
01184 break;
01185 }
01186 case Qt::Key_Up: {
01187 FormulaCursor* cursor = container->activeCursor();
01188 cursor->moveUp( flag );
01189 formula()->cursorHasMoved( cursor );
01190 break;
01191 }
01192 case Qt::Key_Down: {
01193 FormulaCursor* cursor = container->activeCursor();
01194 cursor->moveDown( flag );
01195 formula()->cursorHasMoved( cursor );
01196 break;
01197 }
01198 case Qt::Key_Home: {
01199 FormulaCursor* cursor = container->activeCursor();
01200 cursor->moveHome( flag );
01201 formula()->cursorHasMoved( cursor );
01202 break;
01203 }
01204 case Qt::Key_End: {
01205 FormulaCursor* cursor = container->activeCursor();
01206 cursor->moveEnd( flag );
01207 formula()->cursorHasMoved( cursor );
01208 break;
01209 }
01210 default:
01211 if ( state & Qt::ControlButton ) {
01212 switch ( event->key() ) {
01213 case Qt::Key_AsciiCircum: {
01214 IndexRequest r( upperLeftPos );
01215 return buildCommand( container, &r );
01216 }
01217 case Qt::Key_Underscore: {
01218 IndexRequest r( lowerLeftPos );
01219 return buildCommand( container, &r );
01220 }
01221 default:
01222 break;
01223 }
01224 }
01225 }
01226 }
01227 return 0;
01228 }
01229
01230
01231 KCommand* SequenceElement::input( Container* container, QChar ch )
01232 {
01233 int unicode = ch.unicode();
01234 switch (unicode) {
01235 case '(': {
01236 BracketRequest r( container->document()->leftBracketChar(),
01237 container->document()->rightBracketChar() );
01238 singlePipe = true;
01239 return buildCommand( container, &r );
01240 }
01241 case '[': {
01242 BracketRequest r( LeftSquareBracket, RightSquareBracket );
01243 singlePipe = true;
01244 return buildCommand( container, &r );
01245 }
01246 case '{': {
01247 BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01248 singlePipe = true;
01249 return buildCommand( container, &r );
01250 }
01251 case '|': {
01252 if (!singlePipe) {
01253
01254 DirectedRemove rDelete( req_remove, beforeCursor );
01255 KCommand* command = buildCommand( container, &rDelete );
01256 command->execute();
01257
01258 BracketRequest rBracket( LeftLineBracket , RightLineBracket);
01259 singlePipe = true;
01260 return buildCommand( container, &rBracket );
01261 }
01262 else {
01263 TextCharRequest r(ch);
01264
01265
01266 singlePipe = false;
01267
01268 return buildCommand( container, &r );
01269 }
01270 }
01271 case '^': {
01272 IndexRequest r( upperRightPos );
01273 singlePipe = true;
01274 return buildCommand( container, &r );
01275 }
01276 case '_': {
01277 IndexRequest r( lowerRightPos );
01278 singlePipe = true;
01279 return buildCommand( container, &r );
01280 }
01281 case ' ': {
01282 Request r( req_compactExpression );
01283 singlePipe = true;
01284 return buildCommand( container, &r );
01285 }
01286 case '}': {
01287 Request r( req_addEmptyBox );
01288 singlePipe = true;
01289 return buildCommand( container, &r );
01290 }
01291 case ']':
01292 case ')':
01293 singlePipe = true;
01294 break;
01295 case '\\': {
01296 Request r( req_addNameSequence );
01297 singlePipe = true;
01298 return buildCommand( container, &r );
01299 }
01300 default: {
01301 TextCharRequest r( ch );
01302 singlePipe = true;
01303 return buildCommand( container, &r );
01304 }
01305 }
01306 return 0;
01307 }
01308
01312 void SequenceElement::getChildrenDom( QDomDocument& doc, QDomElement elem,
01313 uint from, uint to)
01314 {
01315 for (uint i = from; i < to; i++) {
01316 QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01317 elem.appendChild(tmpEleDom);
01318 }
01319 }
01320
01321
01327 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01328 {
01329 while (!n.isNull()) {
01330 if (n.isElement()) {
01331 QDomElement e = n.toElement();
01332 BasicElement* child = 0;
01333 QString tag = e.tagName().upper();
01334
01335 child = createElement(tag);
01336 if (child != 0) {
01337 child->setParent(this);
01338 if (child->buildFromDom(e)) {
01339 list.append(child);
01340 }
01341 else {
01342 delete child;
01343 return false;
01344 }
01345 }
01346 else {
01347 return false;
01348 }
01349 }
01350 n = n.nextSibling();
01351 }
01352 parse();
01353 return true;
01354 }
01355
01356
01357 BasicElement* SequenceElement::createElement( QString type )
01358 {
01359 return creationStrategy->createElement( type );
01360 }
01361
01365 void SequenceElement::writeDom(QDomElement element)
01366 {
01367 BasicElement::writeDom(element);
01368
01369 uint count = children.count();
01370 QDomDocument doc = element.ownerDocument();
01371 getChildrenDom(doc, element, 0, count);
01372 }
01373
01378 bool SequenceElement::readAttributesFromDom(QDomElement element)
01379 {
01380 if (!BasicElement::readAttributesFromDom(element)) {
01381 return false;
01382 }
01383 return true;
01384 }
01385
01391 bool SequenceElement::readContentFromDom(QDomNode& node)
01392 {
01393 if (!BasicElement::readContentFromDom(node)) {
01394 return false;
01395 }
01396
01397 return buildChildrenFromDom(children, node);
01398 }
01399
01400
01401 void SequenceElement::parse()
01402 {
01403 delete parseTree;
01404
01405 textSequence = true;
01406 for (BasicElement* element = children.first();
01407 element != 0;
01408 element = children.next()) {
01409
01410
01411
01412 element->setElementType(0);
01413
01414 if (element->getCharacter().isNull()) {
01415 textSequence = false;
01416 }
01417 }
01418
01419 const SymbolTable& symbols = formula()->getSymbolTable();
01420 SequenceParser parser(symbols);
01421 parseTree = parser.parse(children);
01422
01423
01424
01425 BasicElement* p = getParent();
01426 if ( p != 0 ) {
01427 SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01428 if ( seq != 0 ) {
01429 seq->parse();
01430 }
01431 }
01432
01433
01434 }
01435
01436
01437 bool SequenceElement::isFirstOfToken( BasicElement* child )
01438 {
01439 return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01440 }
01441
01442
01443 QString SequenceElement::toLatex()
01444 {
01445 QString content;
01446 uint count = children.count();
01447 for ( uint i = 0; i < count; i++ ) {
01448 BasicElement* child = children.at( i );
01449
01450
01451
01452 content += child->toLatex();
01453 }
01454 return content;
01455 }
01456
01457
01458 QString SequenceElement::formulaString()
01459 {
01460 QString content;
01461 uint count = children.count();
01462 for ( uint i = 0; i < count; i++ ) {
01463 BasicElement* child = children.at( i );
01464
01465
01466
01467 content += child->formulaString();
01468 }
01469 return content;
01470 }
01471
01472
01473 void SequenceElement::writeMathML( QDomDocument& doc, QDomNode parent, bool oasisFormat )
01474 {
01475 QDomElement de = doc.createElement( oasisFormat ? "math:mrow" : "mrow" );
01476
01477 BasicElement* last = children.last();
01478 if ( last != 0 ) {
01479
01480 QPtrList<ElementType> tokenList;
01481 ElementType* token = last->getElementType();
01482 while ( token != 0 ) {
01483
01484 tokenList.prepend( token );
01485 token = token->getPrev();
01486 }
01487
01488 if ( tokenList.count() == 1 ) {
01489 tokenList.first()->saveMathML( this, doc, parent.toElement(), oasisFormat );
01490 return;
01491 }
01492
01493 for ( uint i = 0; i < tokenList.count(); ++i ) {
01494 tokenList.at( i )->saveMathML( this, doc, de, oasisFormat );
01495 }
01496 }
01497 parent.appendChild( de );
01498 }
01499
01500
01501 int SequenceElement::childPos( const BasicElement* child ) const
01502 {
01503 QPtrListIterator<BasicElement> it( children );
01504 uint count = it.count();
01505 for ( uint i=0; i<count; ++i, ++it ) {
01506 if ( it.current() == child ) {
01507 return i;
01508 }
01509 }
01510 return -1;
01511 }
01512
01513
01514 NameSequence::NameSequence( BasicElement* parent )
01515 : SequenceElement( parent )
01516 {
01517 }
01518
01519
01520 bool NameSequence::accept( ElementVisitor* visitor )
01521 {
01522 return visitor->visit( this );
01523 }
01524
01525
01526 void NameSequence::calcCursorSize( const ContextStyle& context,
01527 FormulaCursor* cursor, bool smallCursor )
01528 {
01529 inherited::calcCursorSize( context, cursor, smallCursor );
01530 LuPixelPoint point = widgetPos();
01531 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01532 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01533 cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01534 getWidth()+2*unitX, getHeight()+2*unitY ) );
01535 }
01536
01537 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01538 FormulaCursor* cursor, bool smallCursor,
01539 bool activeCursor )
01540 {
01541 LuPixelPoint point = widgetPos();
01542 painter.setPen( QPen( context.getEmptyColor(),
01543 context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
01544 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01545 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01546 painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01547 context.layoutUnitToPixelY( point.y()-unitY ),
01548 context.layoutUnitToPixelX( getWidth()+2*unitX ),
01549 context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01550
01551 inherited::drawCursor( painter, context, cursor, smallCursor, activeCursor );
01552 }
01553
01554 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01555 {
01556 uint pos = cursor->getPos();
01557 if ( pos > 0 ) {
01558 cursor->setTo( this, 0 );
01559 }
01560 else {
01561 moveLeft( cursor, this );
01562 }
01563 }
01564
01565 void NameSequence::moveWordRight( FormulaCursor* cursor )
01566 {
01567 int pos = cursor->getPos();
01568 if ( pos < countChildren() ) {
01569 cursor->setTo( this, countChildren() );
01570 }
01571 else {
01572 moveRight( cursor, this );
01573 }
01574 }
01575
01576
01577 KCommand* NameSequence::compactExpressionCmd( Container* container )
01578 {
01579 BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01580 if ( element != 0 ) {
01581 getParent()->selectChild( container->activeCursor(), this );
01582
01583 KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01584 command->addElement( element );
01585 return command;
01586 }
01587 return 0;
01588 }
01589
01590 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01591 {
01592 switch ( *request ) {
01593 case req_compactExpression:
01594 return compactExpressionCmd( container );
01595 case req_addSpace:
01596 case req_addIndex:
01597 case req_addMatrix:
01598 case req_addOneByTwoMatrix:
01599 case req_addSymbol:
01600 case req_addRoot:
01601 case req_addFraction:
01602 case req_addBracket:
01603 case req_addNameSequence:
01604 return 0;
01605 default:
01606 break;
01607 }
01608 return inherited::buildCommand( container, request );
01609 }
01610
01611
01612 KCommand* NameSequence::input( Container* container, QChar ch )
01613 {
01614 int unicode = ch.unicode();
01615 switch (unicode) {
01616 case '(':
01617 case '[':
01618 case '|':
01619 case '^':
01620 case '_':
01621 case '}':
01622 case ']':
01623 case ')':
01624 case '\\': {
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636 break;
01637 }
01638 case '{':
01639 case ' ': {
01640 Request r( req_compactExpression );
01641 return buildCommand( container, &r );
01642 }
01643 default: {
01644 TextCharRequest r( ch );
01645 return buildCommand( container, &r );
01646 }
01647 }
01648 return 0;
01649 }
01650
01651 void NameSequence::setElementType( ElementType* t )
01652 {
01653 inherited::setElementType( t );
01654 parse();
01655 }
01656
01657 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01658 {
01659 QString name = buildName();
01660 QChar ch = table.unicode( name );
01661 if ( !ch.isNull() ) {
01662 return new TextElement( ch, true );
01663 }
01664 else {
01665 ch = table.unicode( i18n( name.latin1() ) );
01666 if ( !ch.isNull() ) {
01667 return new TextElement( ch, true );
01668 }
01669 }
01670
01671 if ( name == "!" ) return new SpaceElement( NEGTHIN );
01672 if ( name == "," ) return new SpaceElement( THIN );
01673 if ( name == ">" ) return new SpaceElement( MEDIUM );
01674 if ( name == ";" ) return new SpaceElement( THICK );
01675 if ( name == "quad" ) return new SpaceElement( QUAD );
01676
01677 if ( name == "frac" ) return new FractionElement();
01678 if ( name == "atop" ) {
01679 FractionElement* frac = new FractionElement();
01680 frac->showLine( false );
01681 return frac;
01682 }
01683 if ( name == "sqrt" ) return new RootElement();
01684
01685 return 0;
01686 }
01687
01688 BasicElement* NameSequence::createElement( QString type )
01689 {
01690 if ( type == "TEXT" ) return new TextElement();
01691 return 0;
01692 }
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703 QString NameSequence::buildName()
01704 {
01705 QString name;
01706 for ( int i = 0; i < countChildren(); i++ ) {
01707 name += getChild( i )->getCharacter();
01708 }
01709 return name;
01710 }
01711
01712 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01713 {
01714 SequenceElement* sequence = cursor->normal();
01715 if ( sequence == 0 ) {
01716 return false;
01717 }
01718 return sequence->onlyTextSelected( cursor );
01719 }
01720
01721 void NameSequence::writeMathML( QDomDocument& doc, QDomNode parent,bool oasisFormat )
01722 {
01723 QDomElement de = doc.createElement( oasisFormat ? "math:mi" : "mi" );
01724 QString value;
01725 for ( int i = 0; i < countChildren(); ++i ) {
01726
01727 value += getChild( i )->getCharacter();
01728 }
01729 de.appendChild( doc.createTextNode( value ) );
01730 parent.appendChild( de );
01731 }
01732
01733 KFORMULA_NAMESPACE_END