kformula/flake

BasicElement.cpp

Go to the documentation of this file.
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    Copyright (C) 2006 Martin Pfeiffer <hubipete@gmx.net>
00005    Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
00006                  2009 Jeremias Epperlein <jeeree@web.de>
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Library General Public
00010    License as published by the Free Software Foundation; either
00011    version 2 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Library General Public License for more details.
00017 
00018    You should have received a copy of the GNU Library General Public License
00019    along with this library; see the file COPYING.LIB.  If not, write to
00020    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021    Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include "BasicElement.h"
00025 #include "AttributeManager.h"
00026 #include <KoXmlWriter.h>
00027 #include <KoXmlReader.h>
00028 #include <QPainter>
00029 #include <QVariant>
00030 
00031 #include <kdebug.h>
00032 #include "FormulaCursor.h"
00033 #include "TableEntryElement.h"
00034 
00035 BasicElement::BasicElement( BasicElement* p ) : m_parentElement( p )
00036 {
00037     m_scaleFactor = 1.0;
00038     m_scaleLevel = 1;
00039     m_boundingRect.setTopLeft( QPointF( 0.0, 0.0 ) );
00040     m_boundingRect.setWidth( 7.0 );       // standard values
00041     m_boundingRect.setHeight( 10.0 );
00042     m_displayStyle = true;
00043     setBaseLine( 10.0 );
00044 }
00045 
00046 BasicElement::~BasicElement()
00047 {
00048     m_attributes.clear();
00049 }
00050 
00051 void BasicElement::paint( QPainter& painter, AttributeManager* )
00052 {
00053     painter.save();
00054     painter.setBrush( QBrush( Qt::blue ) );
00055     painter.drawRect( QRectF(0.0, 0.0, width(), height()) );
00056     painter.restore();
00057 }
00058 
00059 void BasicElement::paintEditingHints ( QPainter& painter, AttributeManager* am )
00060 {
00061     Q_UNUSED( painter )
00062     Q_UNUSED( am )
00063 }
00064 
00065 void BasicElement::layout( const AttributeManager* )
00066 { /* do nothing */ }
00067 
00068 void BasicElement::stretch()
00069 {
00070     foreach( BasicElement* tmpElement, childElements() ) {
00071         tmpElement->stretch();
00072     }
00073 }
00074 
00075 
00076 bool BasicElement::acceptCursor( const FormulaCursor& cursor )
00077 {
00078     Q_UNUSED( cursor )
00079     return false;
00080 }
00081 
00082 bool BasicElement::moveCursor(FormulaCursor& newcursor, FormulaCursor& oldcursor)
00083 {
00084     Q_UNUSED( newcursor )
00085     Q_UNUSED( oldcursor )
00086     return false;
00087 }
00088 
00089 QLineF BasicElement::cursorLine(int position) const
00090 {
00091     Q_UNUSED( position )
00092     QPointF top = absoluteBoundingRect().topLeft();
00093     QPointF bottom = top + QPointF( 0.0, height() );
00094     return QLineF(top,bottom);   
00095 }
00096 
00097 QPainterPath BasicElement::selectionRegion(const int pos1, const int pos2) const 
00098 {
00099     QLineF l1=cursorLine(pos1);
00100     QLineF l2=cursorLine(pos2);
00101     //TODO: find out why doesn't work
00102     //QRectF r1(l1.p1(),l1.p2());
00103     //QRectF r2(l2.p1(),l2.p2());
00104     
00105     QRectF r1(l1.p1(),l2.p2());
00106     QRectF r2(l2.p1(),l1.p2());
00107     QPainterPath temp;
00108     temp.addRect(r1.unite(r2));
00109     return temp;
00110 }
00111 
00112 
00113 const QRectF BasicElement::absoluteBoundingRect() const 
00114 {
00115     QPointF neworigin = origin();
00116     BasicElement* tmp=parentElement();
00117     while (tmp) {
00118     neworigin+=tmp->origin();
00119     tmp=tmp->parentElement();
00120     }
00121     return QRectF(neworigin,QSizeF(width(),height()));
00122 }
00123 
00124 bool BasicElement::setCursorTo(FormulaCursor& cursor, QPointF point)
00125 {
00126     Q_UNUSED( point )
00127     cursor.setPosition(0);
00128     cursor.setCurrentElement(this);
00129     return true;
00130 }
00131 
00132 bool BasicElement::replaceChild( BasicElement* oldelement, BasicElement* newelement)
00133 {
00134     Q_UNUSED( oldelement )
00135     Q_UNUSED( newelement )
00136     return false;
00137 }
00138 
00139 const QList<BasicElement*> BasicElement::childElements() const
00140 {
00141     kWarning( 39001) << "Returning no elements from BasicElement";
00142     return QList<BasicElement*>();
00143 }
00144 
00145 BasicElement* BasicElement::childElementAt( const QPointF& p )
00146 {
00147     if( !m_boundingRect.contains( p ) )
00148         return 0;
00149 
00150     if( childElements().isEmpty() )
00151         return this;
00152 
00153     BasicElement* ownerElement = 0;
00154     foreach( BasicElement* tmpElement, childElements() )
00155     {
00156         ownerElement = tmpElement->childElementAt( p );
00157 
00158         if( ownerElement )
00159             return ownerElement;
00160     }
00161 
00162     return this;    // if no child contains the point, it's the FormulaElement itsself
00163 }
00164 
00165 void BasicElement::setAttribute( const QString& name, const QVariant& value )
00166 {
00167     if( name.isEmpty() || !value.canConvert( QVariant::String ) )
00168         return;
00169 
00170     if( value.isNull() )
00171         m_attributes.remove( name );
00172     else
00173         m_attributes.insert( name, value.toString() );
00174 }
00175 
00176 QString BasicElement::attribute( const QString& attribute ) const
00177 {
00178     QString tmp = m_attributes.value( attribute );
00179     if( tmp.isEmpty() )
00180         return QString();
00181 
00182     return tmp;
00183 }
00184 
00185 QString BasicElement::inheritsAttribute( const QString& ) const
00186 {
00187     return QString();   // do nothing
00188 }
00189 
00190 QString BasicElement::attributesDefaultValue( const QString& ) const
00191 {
00192     return QString();  // do nothing
00193 }
00194 
00195 bool BasicElement::readMathML( const KoXmlElement& element )
00196 {
00197     readMathMLAttributes( element );
00198     return readMathMLContent( element );
00199 }
00200 
00201 bool BasicElement::readMathMLAttributes( const KoXmlElement& element )
00202 {
00203     QStringList attributeList = KoXml::attributeNames( element );
00204     foreach( QString attributeName, attributeList ) {
00205         m_attributes.insert( attributeName.toLower(),
00206                              element.attribute( attributeName ).toLower() );
00207     }
00208     return true;
00209 }
00210 
00211 bool BasicElement::readMathMLContent( const KoXmlElement& parent )
00212 {
00213     Q_UNUSED( parent )
00214     return true;
00215 }
00216 
00217 void BasicElement::writeMathML( KoXmlWriter* writer ) const
00218 {
00219     if (elementType() == Basic) {
00220         return;
00221     }
00222     if ((elementType() == Row) && (childElements().count()==1)) {
00223         foreach( BasicElement* tmp, childElements() ) {
00224             tmp->writeMathML( writer );
00225         }
00226     } else {
00227         const QByteArray name = ElementFactory::elementName( elementType() ).toLatin1();
00228         writer->startElement( name );
00229         writeMathMLAttributes( writer );
00230         writeMathMLContent( writer );
00231         writer->endElement();
00232     }
00233 }
00234 
00235 void BasicElement::writeMathMLAttributes( KoXmlWriter* writer ) const
00236 {
00237     foreach( const QString &value, m_attributes )
00238         writer->addAttribute( m_attributes.key( value ).toLatin1(), value );
00239 }
00240 
00241 void BasicElement::writeMathMLContent( KoXmlWriter* writer ) const
00242 {
00243     Q_UNUSED( writer )   // this is just to be reimplemented
00244 }
00245 
00246 ElementType BasicElement::elementType() const
00247 {
00248     return Basic;
00249 }
00250 
00251 const QRectF& BasicElement::boundingRect() const
00252 {
00253     return m_boundingRect;
00254 }
00255 const QRectF& BasicElement::childrenBoundingRect() const
00256 {
00257     return m_childrenBoundingRect;
00258 }
00259 void BasicElement::setChildrenBoundingRect(const QRectF &rect)
00260 {
00261     m_childrenBoundingRect = rect;
00262     Q_ASSERT(m_childrenBoundingRect.bottom() <= m_boundingRect.height());
00263     Q_ASSERT(m_childrenBoundingRect.right() <= m_boundingRect.width());
00264 }
00265 double BasicElement::height() const
00266 {
00267     return m_boundingRect.height();
00268 }
00269 
00270 double BasicElement::width() const
00271 {
00272     return m_boundingRect.width();
00273 }
00274 
00275 double BasicElement::baseLine() const
00276 {
00277     return m_baseLine;
00278 }
00279 
00280 QPointF BasicElement::origin() const
00281 {
00282     return m_boundingRect.topLeft();
00283 }
00284 
00285 BasicElement* BasicElement::parentElement() const
00286 {
00287     return m_parentElement;
00288 }
00289 
00290 double BasicElement::scaleFactor() const
00291 {
00292     return m_scaleFactor;
00293 }
00294 int BasicElement::scaleLevel() const
00295 {
00296     return m_scaleLevel;
00297 }
00298 
00299 void BasicElement::setWidth( double width )
00300 {
00301     m_boundingRect.setWidth( width );
00302 }
00303 
00304 void BasicElement::setHeight( double height )
00305 {
00306     m_boundingRect.setHeight( height );
00307 }
00308 
00309 void BasicElement::setOrigin( QPointF origin )
00310 {
00311     m_boundingRect.moveTopLeft( origin );
00312 }
00313 
00314 void BasicElement::setBaseLine( double baseLine )
00315 {
00316     m_baseLine = baseLine;
00317 }
00318 
00319 int BasicElement::endPosition() const
00320 {
00321     return 0;
00322 }
00323 
00324 int BasicElement::positionOfChild(BasicElement* child) const
00325 {
00326     Q_UNUSED( child )
00327     return -1;
00328 }
00329 
00330 void BasicElement::setParentElement( BasicElement* parent )
00331 {
00332     m_parentElement = parent;
00333 }
00334 
00335 void BasicElement::setScaleLevel( int scaleLevel )
00336 {
00337     if(scaleLevel == m_scaleLevel) {
00338         return;
00339     }
00340     m_scaleLevel =  qMax(scaleLevel, 0);
00341     int level = scaleLevel;
00342     m_scaleFactor = 1.9;
00343     while(level-- > 0)  { //raise multiplier to the power of level
00344         m_scaleFactor *= 0.71;
00345     }
00346 }
00347 BasicElement* BasicElement::elementBefore ( int position ) const
00348 {
00349     Q_UNUSED( position )
00350     return 0;
00351 }
00352 
00353 BasicElement* BasicElement::elementAfter ( int position ) const
00354 {
00355     Q_UNUSED( position )
00356     return 0;
00357 }
00358 
00359 QList< BasicElement* > BasicElement::elementsBetween ( int pos1, int pos2 ) const
00360 {
00361     Q_UNUSED( pos1 )
00362     Q_UNUSED( pos2 )
00363     QList<BasicElement*> tmp;
00364     return tmp;
00365 }
00366 
00367 
00368 bool BasicElement::displayStyle() const
00369 {
00370     return m_displayStyle;
00371 }
00372 void BasicElement::setDisplayStyle(bool displayStyle)
00373 {
00374     m_displayStyle = displayStyle;
00375 }
00376 
00377 
00378 bool BasicElement::hasDescendant ( BasicElement* other ) const
00379 {
00380     if (other==this) {
00381         return true;
00382     }
00383     foreach (BasicElement* tmp, childElements()) {
00384         if (tmp->hasDescendant(other)) {
00385             return true;
00386         }
00387     }
00388     return false;
00389 }
00390 
00391 
00392 BasicElement* BasicElement::emptyDescendant()
00393 {
00394     BasicElement* tmp;
00395     if (isEmpty() && parentElement() && parentElement()->isInferredRow()) {
00396         return this;
00397     }
00398     foreach (BasicElement* child, childElements()) {
00399         if ( (tmp=child->emptyDescendant()) ) {
00400             return tmp;
00401         }
00402     }
00403     return 0;
00404 }
00405 
00406 //TODO: This should be cached
00407 BasicElement* BasicElement::formulaElement() 
00408 {
00409     if (parentElement()==0) {
00410         return this;
00411     } else {
00412         return parentElement()->formulaElement();
00413     }
00414 }
00415 
00416 bool BasicElement::isEmpty() const
00417 {
00418     return false;
00419 }
00420 
00421 
00422 void BasicElement::setScaleFactor ( double scaleFactor )
00423 {
00424     m_scaleFactor=scaleFactor;
00425 }
00426 
00427 void BasicElement::writeElementTree(int indent, bool wrong) const
00428 {
00429     QString s;
00430     for (int i=0; i<indent; ++i) {
00431         s+="   ";
00432     }
00433     s+=ElementFactory::elementName(elementType());
00434     s+=" ";
00435     s+=writeElementContent();
00436 /*    s+="        [scale level ";
00437     s+=QString::number(m_scaleFactor)+","+QString::number(m_scaleLevel)+"] ";*/
00438     s+=QString(" [")+QString::number(baseLine())+" ; " + QString::number(height())+"]";
00439     s+=QString(" [")+ QString::number(origin().y())+"]";
00440     if (wrong) {
00441         s+=" -> wrong parent !!!";
00442     }
00443     kDebug()<<s;
00444     foreach (BasicElement* tmp, childElements()) {
00445         if (tmp->parentElement()!=this) {
00446             tmp->writeElementTree(indent+1,true);
00447         } else {
00448             tmp->writeElementTree(indent+1,false);
00449         }
00450     }
00451 }
00452 
00453 
00454 const QString BasicElement::writeElementContent() const
00455 {
00456     return "";
00457 }
00458 
00459 
00460 bool BasicElement::isInferredRow() const
00461 {
00462     return false;
00463 }
00464 
00465 void BasicElement::cleanElementTree ( BasicElement* element )
00466 {
00467     foreach (BasicElement* tmp,element->childElements()) {
00468         cleanElementTree(tmp);
00469     }
00470     if (element->elementType()==Row && element->parentElement() && element->parentElement()->isInferredRow()) {
00471         if ( element->childElements().count()==1) {
00472             BasicElement* parent=element->parentElement();
00473             parent->replaceChild(element,element->childElements()[0]);
00474         } else if ( element->isEmpty()) {
00475             RowElement* parent=static_cast<RowElement*>(element->parentElement());
00476             parent->removeChild(element);
00477         }
00478     }
00479 }
00480 
00481 TableEntryElement* BasicElement::parentTableEntry()
00482 {
00483     if (elementType()==TableEntry) {
00484         return static_cast<TableEntryElement*>(this);
00485     } else if (parentElement()) {
00486         return parentElement()->parentTableEntry();
00487     } else {
00488         return 0;
00489     }
00490 }