00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qpainter.h>
00022
00023 #include <kdebug.h>
00024 #include <klocale.h>
00025
00026 #include "elementvisitor.h"
00027 #include "indexelement.h"
00028 #include "formulacursor.h"
00029 #include "formulaelement.h"
00030 #include "kformulacommand.h"
00031 #include "sequenceelement.h"
00032
00033
00034 KFORMULA_NAMESPACE_BEGIN
00035
00036
00037 class IndexSequenceElement : public SequenceElement {
00038 typedef SequenceElement inherited;
00039 public:
00040
00041 IndexSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
00042 virtual IndexSequenceElement* clone() {
00043 return new IndexSequenceElement( *this );
00044 }
00045
00054 virtual KCommand* buildCommand( Container*, Request* );
00055 };
00056
00057
00058 KCommand* IndexSequenceElement::buildCommand( Container* container, Request* request )
00059 {
00060 FormulaCursor* cursor = container->activeCursor();
00061 if ( cursor->isReadOnly() ) {
00062 return 0;
00063 }
00064
00065 switch ( *request ) {
00066 case req_addIndex: {
00067 FormulaCursor* cursor = container->activeCursor();
00068 if ( cursor->isSelection() ||
00069 ( cursor->getPos() > 0 && cursor->getPos() < countChildren() ) ) {
00070 break;
00071 }
00072 IndexElement* element = static_cast<IndexElement*>( getParent() );
00073 IndexRequest* ir = static_cast<IndexRequest*>( request );
00074 ElementIndexPtr index = element->getIndex( ir->index() );
00075 if ( !index->hasIndex() ) {
00076 KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index );
00077 return command;
00078 }
00079 else {
00080 index->moveToIndex( cursor, afterCursor );
00081 cursor->setSelection( false );
00082 formula()->cursorHasMoved( cursor );
00083 return 0;
00084 }
00085 }
00086 default:
00087 break;
00088 }
00089 return inherited::buildCommand( container, request );
00090 }
00091
00092
00093 IndexElement::IndexElement(BasicElement* parent)
00094 : BasicElement(parent),
00095 m_subScriptShiftType( NoSize ),
00096 m_superScriptShiftType( NoSize ),
00097 m_customAccentUnder( false ),
00098 m_customAccent ( false )
00099 {
00100 content = new IndexSequenceElement( this );
00101
00102 upperLeft = 0;
00103 upperMiddle = 0;
00104 upperRight = 0;
00105 lowerLeft = 0;
00106 lowerMiddle = 0;
00107 lowerRight = 0;
00108 }
00109
00110 IndexElement::~IndexElement()
00111 {
00112 delete content;
00113 delete upperLeft;
00114 delete upperMiddle;
00115 delete upperRight;
00116 delete lowerLeft;
00117 delete lowerMiddle;
00118 delete lowerRight;
00119 }
00120
00121
00122 IndexElement::IndexElement( const IndexElement& other )
00123 : BasicElement( other ),
00124 m_subScriptShiftType( other.m_subScriptShiftType ),
00125 m_subScriptShift( other.m_subScriptShift ),
00126 m_superScriptShiftType( other.m_superScriptShiftType ),
00127 m_superScriptShift( other.m_superScriptShift ),
00128 m_customAccentUnder( other.m_customAccentUnder ),
00129 m_accentUnder( other.m_accentUnder ),
00130 m_customAccent ( other.m_customAccent ),
00131 m_accent( other.m_accent )
00132 {
00133 content = new IndexSequenceElement( *dynamic_cast<IndexSequenceElement*>( other.content ) );
00134
00135 if ( other.upperLeft ) {
00136 upperLeft = new SequenceElement( *( other.upperLeft ) );
00137 upperLeft->setParent( this );
00138 }
00139 else {
00140 upperLeft = 0;
00141 }
00142 if ( other.upperMiddle ) {
00143 upperMiddle = new SequenceElement( *( other.upperMiddle ) );
00144 upperMiddle->setParent( this );
00145 }
00146 else {
00147 upperMiddle = 0;
00148 }
00149 if ( other.upperRight ) {
00150 upperRight = new SequenceElement( *( other.upperRight ) );
00151 upperRight->setParent( this );
00152 }
00153 else {
00154 upperRight = 0;
00155 }
00156
00157 if ( other.lowerLeft ) {
00158 lowerLeft = new SequenceElement( *( other.lowerLeft ) );
00159 lowerLeft->setParent( this );
00160 }
00161 else {
00162 lowerLeft = 0;
00163 }
00164 if ( other.lowerMiddle ) {
00165 lowerMiddle = new SequenceElement( *( other.lowerMiddle ) );
00166 lowerMiddle->setParent( this );
00167 }
00168 else {
00169 lowerMiddle = 0;
00170 }
00171 if ( other.lowerRight ) {
00172 lowerRight = new SequenceElement( *( other.lowerRight ) );
00173 lowerRight->setParent( this );
00174 }
00175 else {
00176 lowerRight = 0;
00177 }
00178 }
00179
00180
00181 bool IndexElement::accept( ElementVisitor* visitor )
00182 {
00183 return visitor->visit( this );
00184 }
00185
00186
00187 QChar IndexElement::getCharacter() const
00188 {
00189 if ( !content->isTextOnly() ) {
00190 return QChar::null;
00191 }
00192
00193 if ( hasUpperRight() && !upperRight->isTextOnly() ) {
00194 return QChar::null;
00195 }
00196 if ( hasUpperMiddle() && !upperMiddle->isTextOnly() ) {
00197 return QChar::null;
00198 }
00199 if ( hasUpperLeft() && !upperLeft->isTextOnly() ) {
00200 return QChar::null;
00201 }
00202 if ( hasLowerRight() && !lowerRight->isTextOnly() ) {
00203 return QChar::null;
00204 }
00205 if ( hasLowerMiddle() && !lowerMiddle->isTextOnly() ) {
00206 return QChar::null;
00207 }
00208 if ( hasLowerLeft() && !lowerLeft->isTextOnly() ) {
00209 return QChar::null;
00210 }
00211
00212 return ' ';
00213 }
00214
00215 void IndexElement::entered( SequenceElement* child )
00216 {
00217 if ( child == content ) {
00218 formula()->tell( i18n( "Indexed list" ) );
00219 }
00220 else {
00221 formula()->tell( i18n( "Index" ) );
00222 }
00223 }
00224
00225
00229 BasicElement* IndexElement::goToPos( FormulaCursor* cursor, bool& handled,
00230 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00231 {
00232 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00233 if (e != 0) {
00234 LuPixelPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY());
00235 e = content->goToPos(cursor, handled, point, myPos);
00236 if (e != 0) return e;
00237
00238 if (hasUpperRight()) {
00239 e = upperRight->goToPos(cursor, handled, point, myPos);
00240 if (e != 0) return e;
00241 }
00242 if (hasUpperMiddle()) {
00243 e = upperMiddle->goToPos(cursor, handled, point, myPos);
00244 if (e != 0) return e;
00245 }
00246 if (hasUpperLeft()) {
00247 e = upperLeft->goToPos(cursor, handled, point, myPos);
00248 if (e != 0) return e;
00249 }
00250 if (hasLowerRight()) {
00251 e = lowerRight->goToPos(cursor, handled, point, myPos);
00252 if (e != 0) return e;
00253 }
00254 if (hasLowerMiddle()) {
00255 e = lowerMiddle->goToPos(cursor, handled, point, myPos);
00256 if (e != 0) return e;
00257 }
00258 if (hasLowerLeft()) {
00259 e = lowerLeft->goToPos(cursor, handled, point, myPos);
00260 if (e != 0) return e;
00261 }
00262
00263 luPixel dx = point.x() - myPos.x();
00264 luPixel dy = point.y() - myPos.y();
00265
00266
00267 if (dx < content->getX()+content->getWidth()) {
00268 if (dy < content->getY()) {
00269 if (hasUpperMiddle() && (dx > upperMiddle->getX())) {
00270 upperMiddle->moveLeft(cursor, this);
00271 handled = true;
00272 return upperMiddle;
00273 }
00274 if (hasUpperLeft() && (dx > upperLeft->getX())) {
00275 upperLeft->moveLeft(cursor, this);
00276 handled = true;
00277 return upperLeft;
00278 }
00279 }
00280 else if (dy > content->getY()+content->getHeight()) {
00281 if (hasLowerMiddle() && (dx > lowerMiddle->getX())) {
00282 lowerMiddle->moveLeft(cursor, this);
00283 handled = true;
00284 return lowerMiddle;
00285 }
00286 if (hasLowerLeft() && (dx > lowerLeft->getX())) {
00287 lowerLeft->moveLeft(cursor, this);
00288 handled = true;
00289 return lowerLeft;
00290 }
00291 }
00292 }
00293
00294 else {
00295 if (dy < content->getY()) {
00296 if (hasUpperRight()) {
00297 upperRight->moveLeft(cursor, this);
00298 handled = true;
00299 return upperRight;
00300 }
00301 }
00302 else if (dy > content->getY()+content->getHeight()) {
00303 if (hasLowerRight()) {
00304 lowerRight->moveLeft(cursor, this);
00305 handled = true;
00306 return lowerRight;
00307 }
00308 }
00309 else {
00310 content->moveLeft(cursor, this);
00311 handled = true;
00312 return content;
00313 }
00314 }
00315
00316 return this;
00317 }
00318 return 0;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 void IndexElement::setMiddleX(int xOffset, int middleWidth)
00331 {
00332 content->setX(xOffset + (middleWidth - content->getWidth()) / 2);
00333 if (hasUpperMiddle()) {
00334 upperMiddle->setX(xOffset + (middleWidth - upperMiddle->getWidth()) / 2);
00335 }
00336 if (hasLowerMiddle()) {
00337 lowerMiddle->setX(xOffset + (middleWidth - lowerMiddle->getWidth()) / 2);
00338 }
00339 }
00340
00341
00346 void IndexElement::calcSizes(const ContextStyle& context,
00347 ContextStyle::TextStyle tstyle,
00348 ContextStyle::IndexStyle istyle,
00349 StyleAttributes& style )
00350 {
00351 double factor = style.sizeFactor();
00352 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
00353
00354 ContextStyle::TextStyle i_tstyle = context.convertTextStyleIndex(tstyle);
00355 ContextStyle::IndexStyle u_istyle = context.convertIndexStyleUpper( istyle );
00356 ContextStyle::IndexStyle l_istyle = context.convertIndexStyleLower( istyle );
00357
00358
00359 luPixel ulWidth = 0, ulHeight = 0, ulMidline = 0;
00360 if (hasUpperLeft()) {
00361 upperLeft->calcSizes( context, i_tstyle, u_istyle, style );
00362 ulWidth = upperLeft->getWidth();
00363 ulHeight = upperLeft->getHeight();
00364 ulMidline = upperLeft->axis( context, i_tstyle, factor );
00365 }
00366
00367 luPixel umWidth = 0, umHeight = 0, umMidline = 0;
00368 if (hasUpperMiddle()) {
00369 upperMiddle->calcSizes( context, i_tstyle, u_istyle, style );
00370 umWidth = upperMiddle->getWidth();
00371 umHeight = upperMiddle->getHeight() + distY;
00372 umMidline = upperMiddle->axis( context, i_tstyle, factor );
00373 }
00374
00375 luPixel urWidth = 0, urHeight = 0, urMidline = 0;
00376 if (hasUpperRight()) {
00377 upperRight->calcSizes( context, i_tstyle, u_istyle, style );
00378 urWidth = upperRight->getWidth();
00379 urHeight = upperRight->getHeight();
00380 urMidline = upperRight->axis( context, i_tstyle, factor );
00381 }
00382
00383 luPixel llWidth = 0, llHeight = 0, llMidline = 0;
00384 if (hasLowerLeft()) {
00385 lowerLeft->calcSizes( context, i_tstyle, l_istyle, style );
00386 llWidth = lowerLeft->getWidth();
00387 llHeight = lowerLeft->getHeight();
00388 llMidline = lowerLeft->axis( context, i_tstyle, factor );
00389 }
00390
00391 luPixel lmWidth = 0, lmHeight = 0, lmMidline = 0;
00392 if (hasLowerMiddle()) {
00393 lowerMiddle->calcSizes( context, i_tstyle, l_istyle, style );
00394 lmWidth = lowerMiddle->getWidth();
00395 lmHeight = lowerMiddle->getHeight() + distY;
00396 lmMidline = lowerMiddle->axis( context, i_tstyle, factor );
00397 }
00398
00399 luPixel lrWidth = 0, lrHeight = 0, lrMidline = 0;
00400 if (hasLowerRight()) {
00401 lowerRight->calcSizes( context, i_tstyle, l_istyle, style );
00402 lrWidth = lowerRight->getWidth();
00403 lrHeight = lowerRight->getHeight();
00404 lrMidline = lowerRight->axis( context, i_tstyle, factor );
00405 }
00406
00407
00408 content->calcSizes( context, tstyle, istyle, style );
00409 luPixel width = QMAX(content->getWidth(), QMAX(umWidth, lmWidth));
00410 luPixel toMidline = content->axis( context, tstyle, factor );
00411 luPixel fromMidline = content->getHeight() - toMidline;
00412
00413
00414 if (ulWidth > llWidth) {
00415 upperLeft->setX(0);
00416 if (hasLowerLeft()) {
00417 lowerLeft->setX(ulWidth - llWidth);
00418 }
00419 setMiddleX(ulWidth, width);
00420 width += ulWidth;
00421 }
00422 else {
00423 if (hasUpperLeft()) {
00424 upperLeft->setX(llWidth - ulWidth);
00425 }
00426 if (hasLowerLeft()) {
00427 lowerLeft->setX(0);
00428 }
00429 setMiddleX(llWidth, width);
00430 width += llWidth;
00431 }
00432
00433 if (hasUpperRight()) {
00434 upperRight->setX(width);
00435 }
00436 if (hasLowerRight()) {
00437 lowerRight->setX(width);
00438 }
00439 width += QMAX(urWidth, lrWidth);
00440
00441
00442 luPixel ulOffset = 0;
00443 luPixel urOffset = 0;
00444 luPixel llOffset = 0;
00445 luPixel lrOffset = 0;
00446 if (content->isTextOnly()) {
00447 luPt mySize = context.getAdjustedSize( tstyle, factor );
00448 QFont font = context.getDefaultFont();
00449 font.setPointSizeFloat( context.layoutUnitPtToPt( mySize ) );
00450
00451 QFontMetrics fm(font);
00452 LuPixelRect bound = fm.boundingRect('x');
00453
00454 luPixel exBaseline = context.ptToLayoutUnitPt( -bound.top() );
00455
00456
00457 ulOffset = ulHeight + exBaseline - content->getBaseline();
00458 urOffset = urHeight + exBaseline - content->getBaseline();
00459
00460
00461 llOffset = lrOffset = content->getBaseline();
00462 }
00463 else {
00464
00465
00466 ulOffset = QMAX(ulMidline, ulHeight-toMidline);
00467 urOffset = QMAX(urMidline, urHeight-toMidline);
00468
00469
00470 llOffset = QMAX(content->getHeight()-llMidline, toMidline);
00471 lrOffset = QMAX(content->getHeight()-lrMidline, toMidline);
00472 }
00473
00474
00475 switch ( m_superScriptShiftType ) {
00476 case AbsoluteSize:
00477 urOffset += context.ptToLayoutUnitPt( m_superScriptShift );
00478 break;
00479 case RelativeSize:
00480 urOffset += urOffset * m_superScriptShift;
00481 break;
00482 case PixelSize:
00483 urOffset += context.pixelToLayoutUnitY( m_superScriptShift );
00484 break;
00485 default:
00486 break;
00487 }
00488
00489 switch ( m_subScriptShiftType ) {
00490 case AbsoluteSize:
00491 lrOffset += context.ptToLayoutUnitPt( m_subScriptShift );
00492 break;
00493 case RelativeSize:
00494 lrOffset += lrOffset * m_subScriptShift;
00495 break;
00496 case PixelSize:
00497 lrOffset += context.pixelToLayoutUnitY( m_subScriptShift );
00498 break;
00499 default:
00500 break;
00501 }
00502
00503 luPixel height = QMAX(umHeight, QMAX(ulOffset, urOffset));
00504
00505
00506 content->setY(height);
00507 toMidline += height;
00508 if (hasUpperLeft()) {
00509 upperLeft->setY(height-ulOffset);
00510 }
00511 if (hasUpperMiddle()) {
00512 upperMiddle->setY(height-umHeight);
00513 }
00514 if (hasUpperRight()) {
00515 upperRight->setY( height - urOffset );
00516 }
00517
00518
00519 if (hasLowerLeft()) {
00520 lowerLeft->setY(height+llOffset);
00521 }
00522 if (hasLowerMiddle()) {
00523 lowerMiddle->setY(height+content->getHeight()+distY);
00524 }
00525 if (hasLowerRight()) {
00526 lowerRight->setY( height + lrOffset );
00527 }
00528
00529 fromMidline += QMAX(QMAX(llHeight+llOffset, lrHeight+lrOffset) - content->getHeight(), lmHeight);
00530
00531
00532 setWidth(width);
00533 setHeight(toMidline+fromMidline);
00534 if (content->isTextOnly()) {
00535 setBaseline(content->getY() + content->getBaseline());
00536
00537 }
00538 else {
00539
00540 setBaseline(content->getBaseline() + content->getY());
00541 }
00542 }
00543
00549 void IndexElement::draw( QPainter& painter, const LuPixelRect& r,
00550 const ContextStyle& context,
00551 ContextStyle::TextStyle tstyle,
00552 ContextStyle::IndexStyle istyle,
00553 StyleAttributes& style,
00554 const LuPixelPoint& parentOrigin )
00555 {
00556 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00557
00558
00559
00560 ContextStyle::TextStyle i_tstyle = context.convertTextStyleIndex(tstyle);
00561 ContextStyle::IndexStyle u_istyle = context.convertIndexStyleUpper( istyle );
00562 ContextStyle::IndexStyle l_istyle = context.convertIndexStyleLower( istyle );
00563
00564 content->draw(painter, r, context, tstyle, istyle, style, myPos);
00565 if (hasUpperLeft()) {
00566 upperLeft->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
00567 }
00568 if (hasUpperMiddle()) {
00569 upperMiddle->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
00570 }
00571 if (hasUpperRight()) {
00572 upperRight->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
00573 }
00574 if (hasLowerLeft()) {
00575 lowerLeft->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
00576 }
00577 if (hasLowerMiddle()) {
00578 lowerMiddle->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
00579 }
00580 if (hasLowerRight()) {
00581 lowerRight->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
00582 }
00583
00584
00585
00586
00587
00588
00589
00590 }
00591
00592
00593 void IndexElement::dispatchFontCommand( FontCommand* cmd )
00594 {
00595 content->dispatchFontCommand( cmd );
00596 if (hasUpperLeft()) {
00597 upperLeft->dispatchFontCommand( cmd );
00598 }
00599 if (hasUpperMiddle()) {
00600 upperMiddle->dispatchFontCommand( cmd );
00601 }
00602 if (hasUpperRight()) {
00603 upperRight->dispatchFontCommand( cmd );
00604 }
00605 if (hasLowerLeft()) {
00606 lowerLeft->dispatchFontCommand( cmd );
00607 }
00608 if (hasLowerMiddle()) {
00609 lowerMiddle->dispatchFontCommand( cmd );
00610 }
00611 if (hasLowerRight()) {
00612 lowerRight->dispatchFontCommand( cmd );
00613 }
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 int IndexElement::getFromPos(BasicElement* from)
00626 {
00627 if (from == lowerRight) {
00628 return lowerRightPos;
00629 }
00630 else if (from == upperRight) {
00631 return upperRightPos;
00632 }
00633 else if (from == lowerMiddle) {
00634 return lowerMiddlePos;
00635 }
00636 else if (from == content) {
00637 return contentPos;
00638 }
00639 else if (from == upperMiddle) {
00640 return upperMiddlePos;
00641 }
00642 else if (from == lowerLeft) {
00643 return lowerLeftPos;
00644 }
00645 else if (from == upperLeft) {
00646 return upperLeftPos;
00647 }
00648 return parentPos;
00649 }
00650
00656 void IndexElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00657 {
00658 if (cursor->isSelectionMode()) {
00659 getParent()->moveLeft(cursor, this);
00660 }
00661 else {
00662 bool linear = cursor->getLinearMovement();
00663 int fromPos = getFromPos(from);
00664 if (!linear) {
00665 if ((fromPos == lowerRightPos) && hasLowerMiddle()) {
00666 lowerMiddle->moveLeft(cursor, this);
00667 return;
00668 }
00669 else if ((fromPos == upperRightPos) && hasUpperMiddle()) {
00670 upperMiddle->moveLeft(cursor, this);
00671 return;
00672 }
00673 else if ((fromPos == lowerMiddlePos) && hasLowerLeft()) {
00674 lowerLeft->moveLeft(cursor, this);
00675 return;
00676 }
00677 else if ((fromPos == upperMiddlePos) && hasUpperLeft()) {
00678 upperLeft->moveLeft(cursor, this);
00679 return;
00680 }
00681 }
00682 switch (fromPos) {
00683 case parentPos:
00684 if (hasLowerRight() && linear) {
00685 lowerRight->moveLeft(cursor, this);
00686 break;
00687 }
00688 case lowerRightPos:
00689 if (hasUpperRight() && linear) {
00690 upperRight->moveLeft(cursor, this);
00691 break;
00692 }
00693 case upperRightPos:
00694 if (hasLowerMiddle() && linear) {
00695 lowerMiddle->moveLeft(cursor, this);
00696 break;
00697 }
00698 case lowerMiddlePos:
00699 content->moveLeft(cursor, this);
00700 break;
00701 case contentPos:
00702 if (hasUpperMiddle() && linear) {
00703 upperMiddle->moveLeft(cursor, this);
00704 break;
00705 }
00706 case upperMiddlePos:
00707 if (hasLowerLeft() && linear) {
00708 lowerLeft->moveLeft(cursor, this);
00709 break;
00710 }
00711 case lowerLeftPos:
00712 if (hasUpperLeft() && linear) {
00713 upperLeft->moveLeft(cursor, this);
00714 break;
00715 }
00716 case upperLeftPos:
00717 getParent()->moveLeft(cursor, this);
00718 }
00719 }
00720 }
00721
00727 void IndexElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00728 {
00729 if (cursor->isSelectionMode()) {
00730 getParent()->moveRight(cursor, this);
00731 }
00732 else {
00733 bool linear = cursor->getLinearMovement();
00734 int fromPos = getFromPos(from);
00735 if (!linear) {
00736 if ((fromPos == lowerLeftPos) && hasLowerMiddle()) {
00737 lowerMiddle->moveRight(cursor, this);
00738 return;
00739 }
00740 else if ((fromPos == upperLeftPos) && hasUpperMiddle()) {
00741 upperMiddle->moveRight(cursor, this);
00742 return;
00743 }
00744 else if ((fromPos == lowerMiddlePos) && hasLowerRight()) {
00745 lowerRight->moveRight(cursor, this);
00746 return;
00747 }
00748 else if ((fromPos == upperMiddlePos) && hasUpperRight()) {
00749 upperRight->moveRight(cursor, this);
00750 return;
00751 }
00752 }
00753 switch (fromPos) {
00754 case parentPos:
00755 if (hasUpperLeft() && linear) {
00756 upperLeft->moveRight(cursor, this);
00757 break;
00758 }
00759 case upperLeftPos:
00760 if (hasLowerLeft() && linear) {
00761 lowerLeft->moveRight(cursor, this);
00762 break;
00763 }
00764 case lowerLeftPos:
00765 if (hasUpperMiddle() && linear) {
00766 upperMiddle->moveRight(cursor, this);
00767 break;
00768 }
00769 case upperMiddlePos:
00770 content->moveRight(cursor, this);
00771 break;
00772 case contentPos:
00773 if (hasLowerMiddle() && linear) {
00774 lowerMiddle->moveRight(cursor, this);
00775 break;
00776 }
00777 case lowerMiddlePos:
00778 if (hasUpperRight() && linear) {
00779 upperRight->moveRight(cursor, this);
00780 break;
00781 }
00782 case upperRightPos:
00783 if (hasLowerRight() && linear) {
00784 lowerRight->moveRight(cursor, this);
00785 break;
00786 }
00787 case lowerRightPos:
00788 getParent()->moveRight(cursor, this);
00789 }
00790 }
00791 }
00792
00798 void IndexElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00799 {
00800 if (cursor->isSelectionMode()) {
00801 getParent()->moveUp(cursor, this);
00802 }
00803 else {
00804 if (from == content) {
00805 if ((cursor->getPos() == 0) && (cursor->getElement() == from)) {
00806 if (hasUpperLeft()) {
00807 upperLeft->moveLeft(cursor, this);
00808 return;
00809 }
00810 else if (hasUpperMiddle()) {
00811 upperMiddle->moveRight(cursor, this);
00812 return;
00813 }
00814 }
00815 if (hasUpperRight()) {
00816 upperRight->moveRight(cursor, this);
00817 }
00818 else if (hasUpperMiddle()) {
00819 upperMiddle->moveLeft(cursor, this);
00820 }
00821 else if (hasUpperLeft()) {
00822 upperLeft->moveLeft(cursor, this);
00823 }
00824 else {
00825 getParent()->moveUp(cursor, this);
00826 }
00827 }
00828 else if ((from == upperLeft) || (from == upperMiddle) || (from == upperRight)) {
00829 getParent()->moveUp(cursor, this);
00830 }
00831 else if ((from == getParent()) || (from == lowerLeft) || (from == lowerMiddle)) {
00832 content->moveRight(cursor, this);
00833 }
00834 else if (from == lowerRight) {
00835 content->moveLeft(cursor, this);
00836 }
00837 }
00838 }
00839
00845 void IndexElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00846 {
00847 if (cursor->isSelectionMode()) {
00848 getParent()->moveDown(cursor, this);
00849 }
00850 else {
00851 if (from == content) {
00852 if ((cursor->getPos() == 0) && (cursor->getElement() == from)) {
00853 if (hasLowerLeft()) {
00854 lowerLeft->moveLeft(cursor, this);
00855 return;
00856 }
00857 else if (hasLowerMiddle()) {
00858 lowerMiddle->moveRight(cursor, this);
00859 return;
00860 }
00861 }
00862 if (hasLowerRight()) {
00863 lowerRight->moveRight(cursor, this);
00864 }
00865 else if (hasLowerMiddle()) {
00866 lowerMiddle->moveLeft(cursor, this);
00867 }
00868 else if (hasLowerLeft()) {
00869 lowerLeft->moveLeft(cursor, this);
00870 }
00871 else {
00872 getParent()->moveDown(cursor, this);
00873 }
00874 }
00875 else if ((from == lowerLeft) || (from == lowerMiddle) || (from == lowerRight)) {
00876 getParent()->moveDown(cursor, this);
00877 }
00878 else if ((from == getParent()) || (from == upperLeft) || (from == upperMiddle)) {
00879 content->moveRight(cursor, this);
00880 }
00881 if (from == upperRight) {
00882 content->moveLeft(cursor, this);
00883 }
00884 }
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00914 void IndexElement::insert(FormulaCursor* cursor,
00915 QPtrList<BasicElement>& newChildren,
00916 Direction direction)
00917 {
00918 SequenceElement* index = static_cast<SequenceElement*>(newChildren.take(0));
00919 index->setParent(this);
00920
00921 switch (cursor->getPos()) {
00922 case upperLeftPos:
00923 upperLeft = index;
00924 break;
00925 case lowerLeftPos:
00926 lowerLeft = index;
00927 break;
00928 case upperMiddlePos:
00929 upperMiddle = index;
00930 break;
00931 case lowerMiddlePos:
00932 lowerMiddle = index;
00933 break;
00934 case upperRightPos:
00935 upperRight = index;
00936 break;
00937 case lowerRightPos:
00938 lowerRight = index;
00939 break;
00940 default:
00941
00942 return;
00943 }
00944
00945 if (direction == beforeCursor) {
00946 index->moveLeft(cursor, this);
00947 }
00948 else {
00949 index->moveRight(cursor, this);
00950 }
00951 cursor->setSelection(false);
00952 formula()->changed();
00953 }
00954
00955
00967 void IndexElement::remove(FormulaCursor* cursor,
00968 QPtrList<BasicElement>& removedChildren,
00969 Direction direction)
00970 {
00971 int pos = cursor->getPos();
00972 switch (pos) {
00973 case upperLeftPos:
00974 removedChildren.append(upperLeft);
00975 formula()->elementRemoval(upperLeft);
00976 upperLeft = 0;
00977 setToUpperLeft(cursor);
00978 break;
00979 case lowerLeftPos:
00980 removedChildren.append(lowerLeft);
00981 formula()->elementRemoval(lowerLeft);
00982 lowerLeft = 0;
00983 setToLowerLeft(cursor);
00984 break;
00985 case contentPos: {
00986 BasicElement* parent = getParent();
00987 parent->selectChild(cursor, this);
00988 parent->remove(cursor, removedChildren, direction);
00989 break;
00990 }
00991 case upperMiddlePos:
00992 removedChildren.append(upperMiddle);
00993 formula()->elementRemoval(upperMiddle);
00994 upperMiddle = 0;
00995 setToUpperMiddle(cursor);
00996 break;
00997 case lowerMiddlePos:
00998 removedChildren.append(lowerMiddle);
00999 formula()->elementRemoval(lowerMiddle);
01000 lowerMiddle = 0;
01001 setToLowerMiddle(cursor);
01002 break;
01003 case upperRightPos:
01004 removedChildren.append(upperRight);
01005 formula()->elementRemoval(upperRight);
01006 upperRight = 0;
01007 setToUpperRight(cursor);
01008 break;
01009 case lowerRightPos:
01010 removedChildren.append(lowerRight);
01011 formula()->elementRemoval(lowerRight);
01012 lowerRight = 0;
01013 setToLowerRight(cursor);
01014 break;
01015 }
01016 formula()->changed();
01017 }
01018
01023 void IndexElement::normalize(FormulaCursor* cursor, Direction direction)
01024 {
01025 if (direction == beforeCursor) {
01026 content->moveLeft(cursor, this);
01027 }
01028 else {
01029 content->moveRight(cursor, this);
01030 }
01031 }
01032
01038 bool IndexElement::isSenseless()
01039 {
01040 return !hasUpperLeft() && !hasUpperRight() && !hasUpperMiddle() &&
01041 !hasLowerLeft() && !hasLowerRight() && !hasLowerMiddle();
01042 }
01043
01044
01048 BasicElement* IndexElement::getChild(FormulaCursor* cursor, Direction)
01049 {
01050 int pos = cursor->getPos();
01051
01052
01053
01054
01055
01056
01057 switch (pos) {
01058 case contentPos:
01059 return content;
01060 case upperLeftPos:
01061 return upperLeft;
01062 case lowerLeftPos:
01063 return lowerLeft;
01064 case upperMiddlePos:
01065 return upperMiddle;
01066 case lowerMiddlePos:
01067 return lowerMiddle;
01068 case upperRightPos:
01069 return upperRight;
01070 case lowerRightPos:
01071 return lowerRight;
01072 }
01073 return 0;
01074 }
01075
01076
01081 void IndexElement::selectChild(FormulaCursor* cursor, BasicElement* child)
01082 {
01083 if (child == content) {
01084 setToContent(cursor);
01085 }
01086 else if (child == upperLeft) {
01087 setToUpperLeft(cursor);
01088 }
01089 else if (child == lowerLeft) {
01090 setToLowerLeft(cursor);
01091 }
01092 else if (child == upperMiddle) {
01093 setToUpperMiddle(cursor);
01094 }
01095 else if (child == lowerMiddle) {
01096 setToLowerMiddle(cursor);
01097 }
01098 else if (child == upperRight) {
01099 setToUpperRight(cursor);
01100 }
01101 else if (child == lowerRight) {
01102 setToLowerRight(cursor);
01103 }
01104 }
01105
01106
01113 void IndexElement::setToContent(FormulaCursor* cursor)
01114 {
01115 cursor->setTo(this, contentPos);
01116 }
01117
01118
01119
01120
01121 void IndexElement::setToUpperLeft(FormulaCursor* cursor)
01122 {
01123 cursor->setTo(this, upperLeftPos);
01124 }
01125
01126 void IndexElement::setToUpperMiddle(FormulaCursor* cursor)
01127 {
01128 cursor->setTo(this, upperMiddlePos);
01129 }
01130
01131 void IndexElement::setToUpperRight(FormulaCursor* cursor)
01132 {
01133 cursor->setTo(this, upperRightPos);
01134 }
01135
01136 void IndexElement::setToLowerLeft(FormulaCursor* cursor)
01137 {
01138 cursor->setTo(this, lowerLeftPos);
01139 }
01140
01141 void IndexElement::setToLowerMiddle(FormulaCursor* cursor)
01142 {
01143 cursor->setTo(this, lowerMiddlePos);
01144 }
01145
01146 void IndexElement::setToLowerRight(FormulaCursor* cursor)
01147 {
01148 cursor->setTo(this, lowerRightPos);
01149 }
01150
01151
01152
01153
01154 void IndexElement::moveToUpperLeft(FormulaCursor* cursor, Direction direction)
01155 {
01156 if (hasUpperLeft()) {
01157 if (direction == beforeCursor) {
01158 upperLeft->moveLeft(cursor, this);
01159 }
01160 else {
01161 upperLeft->moveRight(cursor, this);
01162 }
01163 }
01164 }
01165
01166 void IndexElement::moveToUpperMiddle(FormulaCursor* cursor, Direction direction)
01167 {
01168 if (hasUpperMiddle()) {
01169 if (direction == beforeCursor) {
01170 upperMiddle->moveLeft(cursor, this);
01171 }
01172 else {
01173 upperMiddle->moveRight(cursor, this);
01174 }
01175 }
01176 }
01177
01178 void IndexElement::moveToUpperRight(FormulaCursor* cursor, Direction direction)
01179 {
01180 if (hasUpperRight()) {
01181 if (direction == beforeCursor) {
01182 upperRight->moveLeft(cursor, this);
01183 }
01184 else {
01185 upperRight->moveRight(cursor, this);
01186 }
01187 }
01188 }
01189
01190 void IndexElement::moveToLowerLeft(FormulaCursor* cursor, Direction direction)
01191 {
01192 if (hasLowerLeft()) {
01193 if (direction == beforeCursor) {
01194 lowerLeft->moveLeft(cursor, this);
01195 }
01196 else {
01197 lowerLeft->moveRight(cursor, this);
01198 }
01199 }
01200 }
01201
01202 void IndexElement::moveToLowerMiddle(FormulaCursor* cursor, Direction direction)
01203 {
01204 if (hasLowerMiddle()) {
01205 if (direction == beforeCursor) {
01206 lowerMiddle->moveLeft(cursor, this);
01207 }
01208 else {
01209 lowerMiddle->moveRight(cursor, this);
01210 }
01211 }
01212 }
01213
01214 void IndexElement::moveToLowerRight(FormulaCursor* cursor, Direction direction)
01215 {
01216 if (hasLowerRight()) {
01217 if (direction == beforeCursor) {
01218 lowerRight->moveLeft(cursor, this);
01219 }
01220 else {
01221 lowerRight->moveRight(cursor, this);
01222 }
01223 }
01224 }
01225
01226
01230 void IndexElement::writeDom(QDomElement element)
01231 {
01232 BasicElement::writeDom(element);
01233
01234 QDomDocument doc = element.ownerDocument();
01235
01236 QDomElement cont = doc.createElement("CONTENT");
01237 cont.appendChild(content->getElementDom(doc));
01238 element.appendChild(cont);
01239
01240 if (hasUpperLeft()) {
01241 QDomElement ind = doc.createElement("UPPERLEFT");
01242 ind.appendChild(upperLeft->getElementDom(doc));
01243 element.appendChild(ind);
01244 }
01245 if (hasUpperMiddle()) {
01246 QDomElement ind = doc.createElement("UPPERMIDDLE");
01247 ind.appendChild(upperMiddle->getElementDom(doc));
01248 element.appendChild(ind);
01249 }
01250 if (hasUpperRight()) {
01251 QDomElement ind = doc.createElement("UPPERRIGHT");
01252 ind.appendChild(upperRight->getElementDom(doc));
01253 element.appendChild(ind);
01254 }
01255 if (hasLowerLeft()) {
01256 QDomElement ind = doc.createElement("LOWERLEFT");
01257 ind.appendChild(lowerLeft->getElementDom(doc));
01258 element.appendChild(ind);
01259 }
01260 if (hasLowerMiddle()) {
01261 QDomElement ind = doc.createElement("LOWERMIDDLE");
01262 ind.appendChild(lowerMiddle->getElementDom(doc));
01263 element.appendChild(ind);
01264 }
01265 if (hasLowerRight()) {
01266 QDomElement ind = doc.createElement("LOWERRIGHT");
01267 ind.appendChild(lowerRight->getElementDom(doc));
01268 element.appendChild(ind);
01269 }
01270 }
01271
01276 bool IndexElement::readAttributesFromDom(QDomElement element)
01277 {
01278 if (!BasicElement::readAttributesFromDom(element)) {
01279 return false;
01280 }
01281 return true;
01282 }
01283
01289 bool IndexElement::readContentFromDom(QDomNode& node)
01290 {
01291 if (!BasicElement::readContentFromDom(node)) {
01292 return false;
01293 }
01294
01295 if ( !buildChild( content, node, "CONTENT" ) ) {
01296 kdWarning( DEBUGID ) << "Empty content in IndexElement." << endl;
01297 return false;
01298 }
01299 node = node.nextSibling();
01300
01301 bool upperLeftRead = false;
01302 bool upperMiddleRead = false;
01303 bool upperRightRead = false;
01304 bool lowerLeftRead = false;
01305 bool lowerMiddleRead = false;
01306 bool lowerRightRead = false;
01307
01308 while (!node.isNull() &&
01309 !(upperLeftRead && upperMiddleRead && upperRightRead &&
01310 lowerLeftRead && lowerMiddleRead && lowerRightRead)) {
01311
01312 if (!upperLeftRead && (node.nodeName().upper() == "UPPERLEFT")) {
01313 upperLeftRead = buildChild( upperLeft=new SequenceElement( this ), node, "UPPERLEFT" );
01314 if ( !upperLeftRead ) return false;
01315 }
01316
01317 if (!upperMiddleRead && (node.nodeName().upper() == "UPPERMIDDLE")) {
01318 upperMiddleRead = buildChild( upperMiddle=new SequenceElement( this ), node, "UPPERMIDDLE" );
01319 if ( !upperMiddleRead ) return false;
01320 }
01321
01322 if (!upperRightRead && (node.nodeName().upper() == "UPPERRIGHT")) {
01323 upperRightRead = buildChild( upperRight=new SequenceElement( this ), node, "UPPERRIGHT" );
01324 if ( !upperRightRead ) return false;
01325 }
01326
01327 if (!lowerLeftRead && (node.nodeName().upper() == "LOWERLEFT")) {
01328 lowerLeftRead = buildChild( lowerLeft=new SequenceElement( this ), node, "LOWERLEFT" );
01329 if ( !lowerLeftRead ) return false;
01330 }
01331
01332 if (!lowerMiddleRead && (node.nodeName().upper() == "LOWERMIDDLE")) {
01333 lowerMiddleRead = buildChild( lowerMiddle=new SequenceElement( this ), node, "LOWERMIDDLE" );
01334 if ( !lowerMiddleRead ) return false;
01335 }
01336
01337 if (!lowerRightRead && (node.nodeName().upper() == "LOWERRIGHT")) {
01338 lowerRightRead = buildChild( lowerRight=new SequenceElement( this ), node, "LOWERRIGHT" );
01339 if ( !lowerRightRead ) return false;
01340 }
01341
01342 node = node.nextSibling();
01343 }
01344 return upperLeftRead || upperMiddleRead || upperRightRead ||
01345 lowerLeftRead || lowerMiddleRead || lowerRightRead;
01346 }
01347
01348 bool IndexElement::readAttributesFromMathMLDom( const QDomElement& element )
01349 {
01350 if ( !BasicElement::readAttributesFromMathMLDom( element ) ) {
01351 return false;
01352 }
01353
01354 QString tag = element.tagName().stripWhiteSpace().lower();
01355 if ( tag == "msub" || tag == "msubsup" ) {
01356 QString subscriptshiftStr = element.attribute( "subscriptshift" ).stripWhiteSpace().lower();
01357 if ( ! subscriptshiftStr.isNull() ) {
01358 m_subScriptShift = getSize( subscriptshiftStr, &m_subScriptShiftType );
01359 }
01360 }
01361 if ( tag == "msup" || tag == "msubsup" ) {
01362 QString superscriptshiftStr = element.attribute( "superscriptshift" ).stripWhiteSpace().lower();
01363 if ( ! superscriptshiftStr.isNull() ) {
01364 m_superScriptShift = getSize( superscriptshiftStr, &m_superScriptShiftType );
01365 }
01366 }
01367
01368 if ( tag == "munder" || tag == "munderover" ) {
01369 QString accentunderStr = element.attribute( "accentunder" ).stripWhiteSpace().lower();
01370 if ( ! accentunderStr.isNull() ) {
01371 if ( accentunderStr == "true" ) {
01372 m_customAccentUnder = true;
01373 m_accentUnder = true;
01374 }
01375 else if ( accentunderStr == "false" ) {
01376 m_customAccentUnder = true;
01377 m_accentUnder = false;
01378 }
01379 else {
01380 kdWarning( DEBUGID ) << "Invalid value for attribute `accentunder': "
01381 << accentunderStr << endl;
01382 }
01383 }
01384 }
01385 if ( tag == "mover" || tag == "munderover" ) {
01386 QString accentStr = element.attribute( "accent" ).stripWhiteSpace().lower();
01387 if ( ! accentStr.isNull() ) {
01388 if ( accentStr == "true" ) {
01389 m_customAccent = true;
01390 m_accent = true;
01391 }
01392 else if ( accentStr == "false" ) {
01393 m_customAccent = true;
01394 m_accent = false;
01395 }
01396 else {
01397 kdWarning( DEBUGID ) << "Invalid value for attribute `accent': "
01398 << accentStr << endl;
01399 }
01400 }
01401 }
01402 return true;
01403 }
01404
01411 int IndexElement::readContentFromMathMLDom( QDomNode& node )
01412 {
01413 if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
01414 return -1;
01415 }
01416
01417 int contentNumber = content->buildMathMLChild( node );
01418 if ( contentNumber == -1 ) {
01419 kdWarning( DEBUGID ) << "Empty base in Script" << endl;
01420 return -1;
01421 }
01422 for (int i = 0; i < contentNumber; i++ ) {
01423 if ( node.isNull() ) {
01424 return -1;
01425 }
01426 node = node.nextSibling();
01427 }
01428
01429 QString indexType = node.parentNode().toElement().tagName().lower();
01430 if ( indexType == "msub" ) {
01431 lowerRight = new SequenceElement( this );
01432 int lowerRightNumber = lowerRight->buildMathMLChild( node );
01433 if ( lowerRightNumber == -1 ) {
01434 kdWarning( DEBUGID ) << "Empty subscript in Script" << endl;
01435 return -1;
01436 }
01437 for (int i = 0; i < lowerRightNumber; i++ ) {
01438 if ( node.isNull() ) {
01439 return -1;
01440 }
01441 node = node.nextSibling();
01442 }
01443
01444 return 1;
01445 }
01446
01447 if ( indexType == "msup" ) {
01448 upperRight = new SequenceElement( this );
01449 int upperRightNumber = upperRight->buildMathMLChild( node );
01450 if ( upperRightNumber == -1 ) {
01451 kdWarning( DEBUGID ) << "Empty superscript in Script" << endl;
01452 return -1;
01453 }
01454 for (int i = 0; i < upperRightNumber; i++ ) {
01455 if ( node.isNull() ) {
01456 return -1;
01457 }
01458 node = node.nextSibling();
01459 }
01460
01461 return 1;
01462 }
01463
01464 if ( indexType == "msubsup" ) {
01465 lowerRight = new SequenceElement( this );
01466 int lowerRightNumber = lowerRight->buildMathMLChild( node );
01467 if ( lowerRightNumber == -1 ) {
01468 kdWarning( DEBUGID ) << "Empty subscript in Script" << endl;
01469 return -1;
01470 }
01471 for (int i = 0; i < lowerRightNumber; i++ ) {
01472 if ( node.isNull() ) {
01473 return -1;
01474 }
01475 node = node.nextSibling();
01476 }
01477
01478 upperRight = new SequenceElement( this );
01479 int upperRightNumber = upperRight->buildMathMLChild( node );
01480 if ( upperRightNumber == -1 ) {
01481 kdWarning( DEBUGID ) << "Empty superscript in Script" << endl;
01482 return -1;
01483 }
01484 for (int i = 0; i < upperRightNumber; i++ ) {
01485 if ( node.isNull() ) {
01486 return -1;
01487 }
01488 node = node.nextSibling();
01489 }
01490
01491 return 1;
01492 }
01493 if ( indexType == "munder" ) {
01494 lowerMiddle = new SequenceElement( this );
01495 int lowerMiddleNumber = lowerMiddle->buildMathMLChild( node );
01496 if ( lowerMiddleNumber == -1 ) {
01497 kdWarning( DEBUGID ) << "Empty underscript in Script" << endl;
01498 return -1;
01499 }
01500 for (int i = 0; i < lowerMiddleNumber; i++ ) {
01501 if ( node.isNull() ) {
01502 return -1;
01503 }
01504 node = node.nextSibling();
01505 }
01506
01507 return 1;
01508 }
01509
01510 if ( indexType == "mover" ) {
01511 upperMiddle = new SequenceElement( this );
01512 int upperMiddleNumber = upperMiddle->buildMathMLChild( node );
01513 if ( upperMiddleNumber == -1 ) {
01514 kdWarning( DEBUGID ) << "Empty overscript in Script" << endl;
01515 return -1;
01516 }
01517 for (int i = 0; i < upperMiddleNumber; i++ ) {
01518 if ( node.isNull() ) {
01519 return -1;
01520 }
01521 node = node.nextSibling();
01522 }
01523
01524 return 1;
01525 }
01526
01527 if ( indexType == "munderover" ) {
01528 lowerMiddle = new SequenceElement( this );
01529 int lowerMiddleNumber = lowerMiddle->buildMathMLChild( node );
01530 if ( lowerMiddleNumber == -1 ) {
01531 kdWarning( DEBUGID ) << "Empty underscript in Script" << endl;
01532 return -1;
01533 }
01534 for (int i = 0; i < lowerMiddleNumber; i++ ) {
01535 if ( node.isNull() ) {
01536 return -1;
01537 }
01538 node = node.nextSibling();
01539 }
01540
01541
01542 upperMiddle = new SequenceElement( this );
01543 int upperMiddleNumber = upperMiddle->buildMathMLChild( node );
01544 if ( upperMiddleNumber == -1 ) {
01545 kdWarning( DEBUGID ) << "Empty overscript in Script" << endl;
01546 return -1;
01547 }
01548 for (int i = 0; i < upperMiddleNumber; i++ ) {
01549 if ( node.isNull() ) {
01550 return -1;
01551 }
01552 node = node.nextSibling();
01553 }
01554
01555 return 1;
01556 }
01557
01558 return 1;
01559 }
01560
01561
01562 ElementIndexPtr IndexElement::getIndex( int position )
01563 {
01564 switch (position) {
01565 case upperRightPos:
01566 return getUpperRight();
01567 case lowerRightPos:
01568 return getLowerRight();
01569 case lowerMiddlePos:
01570 return getLowerMiddle();
01571 case upperMiddlePos:
01572 return getUpperMiddle();
01573 case lowerLeftPos:
01574 return getLowerLeft();
01575 case upperLeftPos:
01576 return getUpperLeft();
01577 }
01578 return getUpperRight();
01579 }
01580
01581
01582
01583 QString IndexElement::toLatex()
01584 {
01585 QString index;
01586
01587 if ( hasUpperMiddle() ) {
01588 index += "\\overset{" + upperMiddle->toLatex() + "}{";
01589 }
01590
01591 if ( hasLowerMiddle() ) {
01592 index += "\\underset{" + lowerMiddle->toLatex() + "}{";
01593 }
01594
01595 if ( hasUpperLeft() || hasUpperRight() ) {
01596
01597
01598
01599
01600
01601
01602 }
01603
01604 index += content->toLatex();
01605
01606 if ( hasUpperRight() || hasLowerRight() ) {
01607 if ( hasUpperRight() )
01608 index += "^{" + upperRight->toLatex() + "}";
01609 if ( hasLowerRight() )
01610 index += "_{" + lowerRight->toLatex() + "}";
01611 index += " ";
01612 }
01613
01614 if ( hasLowerMiddle() ) {
01615 index += "}";
01616 }
01617
01618 if ( hasUpperMiddle() ) {
01619 index += "}";
01620 }
01621
01622 return index;
01623 }
01624
01625 QString IndexElement::formulaString()
01626 {
01627 QString index = "(" + content->formulaString() + ")";
01628 if ( hasLowerRight() ) {
01629 index += "_(" + lowerRight->formulaString() + ")";
01630 }
01631 if ( hasUpperRight() ) {
01632 index += "**(" + upperRight->formulaString() + ")";
01633 }
01634 return index;
01635 }
01636
01637 QString IndexElement::getElementName() const
01638 {
01639 if ( hasUpperMiddle() && hasLowerMiddle() )
01640 return "munderover";
01641 if ( hasUpperMiddle() )
01642 return "mover";
01643 if ( hasLowerMiddle() )
01644 return "munder";
01645 if ( hasLowerLeft() || hasUpperLeft() )
01646 return "mmultiscripts";
01647 if ( hasLowerRight() || hasUpperRight() ) {
01648 if ( ! hasUpperRight() )
01649 return "msub";
01650 if ( ! hasLowerRight() )
01651 return "msup";
01652 }
01653 return "msubsup";
01654 }
01655
01656 void IndexElement::writeMathMLAttributes( QDomElement& element ) const
01657 {
01658 QString tag = getElementName();
01659 if ( tag == "msub" || tag == "msubsup" ) {
01660 switch ( m_subScriptShiftType ) {
01661 case AbsoluteSize:
01662 element.setAttribute( "subscriptshift", QString( "%1pt" ).arg( m_subScriptShift ) );
01663 break;
01664 case RelativeSize:
01665 element.setAttribute( "subscriptshift", QString( "%1%" ).arg( m_subScriptShift * 100.0 ) );
01666 break;
01667 case PixelSize:
01668 element.setAttribute( "subscriptshift", QString( "%1px" ).arg( m_subScriptShift ) );
01669 break;
01670 default:
01671 break;
01672 }
01673 }
01674 if ( tag == "msup" || tag == "msubsup" ) {
01675 switch ( m_superScriptShiftType ) {
01676 case AbsoluteSize:
01677 element.setAttribute( "superscriptshift", QString( "%1pt" ).arg( m_superScriptShift ) );
01678 break;
01679 case RelativeSize:
01680 element.setAttribute( "superscriptshift", QString( "%1%" ).arg( m_superScriptShift * 100.0 ) );
01681 break;
01682 case PixelSize:
01683 element.setAttribute( "superscriptshift", QString( "%1px" ).arg( m_superScriptShift ) );
01684 break;
01685 default:
01686 break;
01687 }
01688 }
01689 if ( tag == "munder" || tag == "munderover" ) {
01690 if ( m_customAccentUnder ) {
01691 element.setAttribute( "accentunder", m_accentUnder ? "true" : "false" );
01692 }
01693 }
01694 if ( tag == "mover" || tag == "munderover" ) {
01695 if ( m_customAccent ) {
01696 element.setAttribute( "accent", m_accent ? "true" : "false" );
01697 }
01698 }
01699 }
01700
01701
01702 void IndexElement::writeMathMLContent( QDomDocument& doc,
01703 QDomElement& element,
01704 bool oasisFormat ) const
01705 {
01706 QDomElement de;
01707
01708 content->writeMathML( doc, element, oasisFormat );
01709 if ( hasUpperMiddle() && hasLowerMiddle() )
01710 {
01711 lowerMiddle->writeMathML( doc, element, oasisFormat );
01712 upperMiddle->writeMathML( doc, element,oasisFormat );
01713 }
01714 else if ( hasUpperMiddle() )
01715 {
01716 upperMiddle->writeMathML( doc, element,oasisFormat );
01717 }
01718 else if ( hasLowerMiddle() )
01719 {
01720 lowerMiddle->writeMathML( doc, element,oasisFormat );
01721 }
01722
01723 if ( hasLowerLeft() || hasUpperLeft() )
01724 {
01725 if ( hasLowerRight() )
01726 lowerRight->writeMathML( doc, element, oasisFormat );
01727 else
01728 element.appendChild( doc.createElement( "none" ) );
01729
01730 if ( hasUpperRight() )
01731 upperRight->writeMathML( doc, element, oasisFormat );
01732 else
01733 element.appendChild( doc.createElement( "none" ) );
01734
01735 element.appendChild( doc.createElement( "mprescripts" ) );
01736
01737 if ( hasLowerLeft() )
01738 lowerLeft->writeMathML( doc, element, oasisFormat );
01739 else
01740 element.appendChild( doc.createElement( "none" ) );
01741
01742 if ( hasUpperLeft() )
01743 upperLeft->writeMathML( doc, element, oasisFormat );
01744 else
01745 element.appendChild( doc.createElement( "none" ) );
01746 }
01747 else if ( hasLowerRight() || hasUpperRight() )
01748 {
01749 if ( !hasUpperRight() ) {
01750 lowerRight->writeMathML( doc, element, oasisFormat );
01751 }
01752 else if ( !hasLowerRight() ) {
01753 upperRight->writeMathML( doc, element, oasisFormat );
01754 }
01755 else
01756 {
01757 lowerRight->writeMathML( doc, element, oasisFormat );
01758 upperRight->writeMathML( doc, element,oasisFormat );
01759 }
01760 }
01761 }
01762
01763 KFORMULA_NAMESPACE_END