00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <float.h>
00023
00024 #include "kspread_cell.h"
00025 #include "kspread_sheet.h"
00026 #include "kspread_doc.h"
00027 #include "kspread_style.h"
00028 #include "kspread_style_manager.h"
00029 #include "kspread_util.h"
00030
00031 #include <KoGenStyles.h>
00032
00033 #include <KoXmlWriter.h>
00034 #include <KoXmlNS.h>
00035 #include <kdebug.h>
00036 #include <qdom.h>
00037 #include <qbuffer.h>
00038
00039 #include "kspread_condition.h"
00040
00041 using namespace KSpread;
00042
00043 Conditional::Conditional():
00044 val1( 0.0 ), val2( 0.0 ), strVal1( 0 ), strVal2( 0 ),
00045 colorcond( 0 ), fontcond( 0 ), styleName( 0 ),
00046 style( 0 ), cond( None )
00047 {
00048 }
00049
00050 Conditional::~Conditional()
00051 {
00052 delete strVal1;
00053 delete strVal2;
00054 delete colorcond;
00055 delete fontcond;
00056 delete styleName;
00057 }
00058
00059 Conditional::Conditional( const Conditional& c )
00060 {
00061 operator=( c );
00062 }
00063
00064 Conditional& Conditional::operator=( const Conditional& d )
00065 {
00066 strVal1 = d.strVal1 ? new QString( *d.strVal1 ) : 0;
00067 strVal2 = d.strVal2 ? new QString( *d.strVal2 ) : 0;
00068 styleName = d.styleName ? new QString( *d.styleName ) : 0;
00069 fontcond = d.fontcond ? new QFont( *d.fontcond ) : 0;
00070 colorcond = d.colorcond ? new QColor( *d.colorcond ) : 0;
00071 val1 = d.val1;
00072 val2 = d.val2;
00073 style = d.style;
00074 cond = d.cond;
00075
00076 return *this;
00077 }
00078
00079 Conditions::Conditions( const Cell * ownerCell )
00080 : m_cell( ownerCell ), m_matchedStyle( 0 )
00081 {
00082 Q_ASSERT( ownerCell != NULL );
00083 }
00084
00085 Conditions::~Conditions()
00086 {
00087 m_condList.clear();
00088 }
00089
00090 void Conditions::checkMatches()
00091 {
00092 Conditional condition;
00093
00094 if ( currentCondition( condition ) )
00095 m_matchedStyle = condition.style;
00096 else
00097 m_matchedStyle = 0;
00098 }
00099
00100 bool Conditions::currentCondition( Conditional & condition )
00101 {
00102
00103
00104 QValueList<Conditional>::const_iterator it;
00105 double value = m_cell->value().asFloat();
00106 QString strVal = m_cell->text();
00107
00108
00109 for ( it = m_condList.begin(); it != m_condList.end(); ++it )
00110 {
00111 condition = *it;
00112
00113 if ( (*it).styleName )
00114 kdDebug()<<"*it :"<< *( ( *it ).styleName ) <<endl;
00115
00116 kdDebug()<<"*it style :"<<( *it ).style <<endl;
00117
00118
00119 if ( condition.strVal1 && m_cell->value().isNumber() )
00120 continue;
00121
00122 switch ( condition.cond )
00123 {
00124 case Conditional::Equal:
00125 if ( condition.strVal1 )
00126 {
00127 if ( strVal == *condition.strVal1 )
00128 return true;
00129 }
00130 else
00131 if ( value - condition.val1 < DBL_EPSILON &&
00132 value - condition.val1 > (0.0 - DBL_EPSILON) )
00133 {
00134 return true;
00135 }
00136 break;
00137
00138 case Conditional::Superior:
00139 if ( condition.strVal1 )
00140 {
00141 if ( strVal > *condition.strVal1 )
00142 return true;
00143 }
00144 else
00145 if ( value > condition.val1 )
00146 {
00147 return true;
00148 }
00149 break;
00150
00151 case Conditional::Inferior:
00152 if ( condition.strVal1 )
00153 {
00154 if ( strVal < *condition.strVal1 )
00155 return true;
00156 }
00157 else
00158 if ( value < condition.val1 )
00159 {
00160 return true;
00161 }
00162 break;
00163
00164 case Conditional::SuperiorEqual :
00165 if ( condition.strVal1 )
00166 {
00167 if ( strVal >= *condition.strVal1 )
00168 return true;
00169 }
00170 else
00171 if ( value >= condition.val1 )
00172 {
00173 return true;
00174 }
00175 break;
00176
00177 case Conditional::InferiorEqual :
00178 if ( condition.strVal1 )
00179 {
00180 if ( strVal <= *condition.strVal1 )
00181 return true;
00182 }
00183 else
00184 if ( value <= condition.val1 )
00185 {
00186 return true;
00187 }
00188 break;
00189
00190 case Conditional::Between :
00191 if ( condition.strVal1 && condition.strVal2 )
00192 {
00193 if ( strVal > *condition.strVal1 && strVal < *condition.strVal2 )
00194 return true;
00195 }
00196 else
00197 if ( ( value > QMIN(condition.val1, condition.val2 ) )
00198 && ( value < QMAX(condition.val1, condition.val2 ) ) )
00199 {
00200 return true;
00201 }
00202 break;
00203
00204 case Conditional::Different :
00205 if ( condition.strVal1 && condition.strVal2 )
00206 {
00207 if ( strVal < *condition.strVal1 || strVal > *condition.strVal2 )
00208 return true;
00209 }
00210 else
00211 if ( ( value < QMIN(condition.val1, condition.val2 ) )
00212 || ( value > QMAX(condition.val1, condition.val2) ) )
00213 {
00214 return true;
00215 }
00216 break;
00217 case Conditional::DifferentTo :
00218 if ( condition.strVal1 )
00219 {
00220 if ( strVal != *condition.strVal1 )
00221 return true;
00222 }
00223 else
00224 if ( value != condition.val1 )
00225 {
00226 return true;
00227 }
00228 break;
00229
00230 default:
00231 break;
00232 }
00233 }
00234 return false;
00235 }
00236
00237 QValueList<Conditional> Conditions::conditionList() const
00238 {
00239 return m_condList;
00240 }
00241
00242 void Conditions::setConditionList( const QValueList<Conditional> & list )
00243 {
00244 m_condList.clear();
00245
00246 QValueList<Conditional>::const_iterator it;
00247 for ( it = list.begin(); it != list.end(); ++it )
00248 {
00249 Conditional d = *it;
00250 m_condList.append( Conditional( d ) );
00251 }
00252 }
00253
00254 void Conditions::saveOasisConditions( KoGenStyle ¤tCellStyle )
00255 {
00256
00257 if ( m_condList.isEmpty() )
00258 return;
00259 QValueList<Conditional>::const_iterator it;
00260 int i = 0;
00261 for ( it = m_condList.begin(); it != m_condList.end(); ++it, ++i )
00262 {
00263 Conditional condition = *it;
00264
00265 QMap<QString, QString> map;
00266 map.insert( "style:condition", saveOasisConditionValue( condition ) );
00267 map.insert( "style:apply-style-name", *( condition.styleName ) );
00268
00269 currentCellStyle.addStyleMap( map );
00270 }
00271 }
00272
00273 QString Conditions::saveOasisConditionValue( Conditional &condition)
00274 {
00275
00276
00277 QString value;
00278 switch( condition.cond )
00279 {
00280 case Conditional::None:
00281 break;
00282 case Conditional::Equal:
00283 value="cell-content()=";
00284 if ( condition.strVal1 )
00285 value+=*condition.strVal1;
00286 else
00287 value+=QString::number( condition.val1 );
00288 break;
00289 case Conditional::Superior:
00290 value="cell-content()>";
00291 if ( condition.strVal1 )
00292 value+=*condition.strVal1;
00293 else
00294 value+=QString::number( condition.val1 );
00295 break;
00296 case Conditional::Inferior:
00297 value="cell-content()<";
00298 if ( condition.strVal1 )
00299 value+=*condition.strVal1;
00300 else
00301 value+=QString::number( condition.val1 );
00302 break;
00303 case Conditional::SuperiorEqual:
00304 value="cell-content()>=";
00305 if ( condition.strVal1 )
00306 value+=*condition.strVal1;
00307 else
00308 value+=QString::number( condition.val1 );
00309 break;
00310 case Conditional::InferiorEqual:
00311 value="cell-content()<=";
00312 if ( condition.strVal1 )
00313 value+=*condition.strVal1;
00314 else
00315 value+=QString::number( condition.val1 );
00316 break;
00317 case Conditional::Between:
00318 value="cell-content-is-between(";
00319 if ( condition.strVal1 )
00320 {
00321 value+=*condition.strVal1;
00322 value+=",";
00323 if ( condition.strVal2 )
00324 value+=*condition.strVal2;
00325 }
00326 else
00327 {
00328 value+=QString::number( condition.val1 );
00329 value+=",";
00330 value+=QString::number( condition.val2 );
00331 }
00332 value+=")";
00333 break;
00334 case Conditional::DifferentTo:
00335 value="cell-content()!=";
00336 if ( condition.strVal1 )
00337 value+=*condition.strVal1;
00338 else
00339 value+=QString::number( condition.val1 );
00340 break;
00341 case Conditional::Different:
00342 value="cell-content-is-not-between(";
00343 if ( condition.strVal1 )
00344 {
00345 value+=*condition.strVal1;
00346 value+=",";
00347 if ( condition.strVal2 )
00348 value+=*condition.strVal2;
00349 }
00350 else
00351 {
00352 value+=QString::number( condition.val1 );
00353 value+=",";
00354 value+=QString::number( condition.val2 );
00355 }
00356 value+=")";
00357 break;
00358 }
00359 return value;
00360 }
00361
00362
00363 QDomElement Conditions::saveConditions( QDomDocument & doc ) const
00364 {
00365 QDomElement conditions = doc.createElement("condition");
00366 QValueList<Conditional>::const_iterator it;
00367 QDomElement child;
00368 int num = 0;
00369 QString name;
00370
00371 for ( it = m_condList.begin(); it != m_condList.end(); ++it )
00372 {
00373 Conditional condition = *it;
00374
00375
00376
00377
00378
00379 name.setNum( num );
00380 name.prepend( "condition" );
00381
00382 child = doc.createElement( name );
00383 child.setAttribute( "cond", (int) condition.cond );
00384
00385
00386 if ( condition.strVal1 )
00387 {
00388 child.setAttribute( "strval1", *condition.strVal1 );
00389 if ( condition.strVal2 )
00390 child.setAttribute( "strval2", *condition.strVal2 );
00391 }
00392 else
00393 {
00394 child.setAttribute( "val1", condition.val1 );
00395 child.setAttribute( "val2", condition.val2 );
00396 }
00397 if ( condition.styleName )
00398 {
00399 child.setAttribute( "style", *condition.styleName );
00400 }
00401 else
00402 {
00403 child.setAttribute( "color", condition.colorcond->name() );
00404 child.appendChild( util_createElement( "font", *condition.fontcond, doc ) );
00405 }
00406
00407 conditions.appendChild( child );
00408
00409 ++num;
00410 }
00411
00412 if ( num == 0 )
00413 {
00414
00415 return QDomElement();
00416 }
00417 else
00418 {
00419 return conditions;
00420 }
00421 }
00422
00423 void Conditions::loadOasisConditions( const QDomElement & element )
00424 {
00425 kdDebug()<<"void Conditions::loadOasisConditions( const QDomElement & element )\n";
00426 QDomElement elementItem( element );
00427 StyleManager * manager = m_cell->sheet()->doc()->styleManager();
00428
00429 while ( !elementItem.isNull() )
00430 {
00431 kdDebug()<<"elementItem.tagName() :"<<elementItem.tagName()<<endl;
00432 if ( elementItem.tagName()== "map" && elementItem.namespaceURI() == KoXmlNS::style )
00433 {
00434 bool ok = true;
00435 kdDebug()<<"elementItem.attribute(style:condition ) :"<<elementItem.attributeNS( KoXmlNS::style, "condition", QString::null )<<endl;
00436 Conditional newCondition;
00437 loadOasisConditionValue( elementItem.attributeNS( KoXmlNS::style, "condition", QString::null ), newCondition );
00438 if ( elementItem.hasAttributeNS( KoXmlNS::style, "apply-style-name" ) )
00439 {
00440 kdDebug()<<"elementItem.attribute( style:apply-style-name ) :"<<elementItem.attributeNS( KoXmlNS::style, "apply-style-name", QString::null )<<endl;
00441 newCondition.styleName = new QString( elementItem.attributeNS( KoXmlNS::style, "apply-style-name", QString::null ) );
00442 newCondition.style = manager->style( *newCondition.styleName );
00443 if ( !newCondition.style )
00444 ok = false;
00445 else
00446 ok = true;
00447 }
00448
00449 if ( ok )
00450 m_condList.append( newCondition );
00451 else
00452 kdDebug(36001) << "Error loading condition " << elementItem.nodeName()<< endl;
00453 }
00454 elementItem = elementItem.nextSibling().toElement();
00455 }
00456 }
00457
00458 void Conditions::loadOasisConditionValue( const QString &styleCondition, Conditional &newCondition )
00459 {
00460 QString val( styleCondition );
00461 if ( val.contains( "cell-content()" ) )
00462 {
00463 val = val.remove( "cell-content()" );
00464 loadOasisCondition( val,newCondition );
00465 }
00466
00467
00468 if ( val.contains( "cell-content-is-between(" ) )
00469 {
00470 val = val.remove( "cell-content-is-between(" );
00471 val = val.remove( ")" );
00472 QStringList listVal = QStringList::split( "," , val );
00473 loadOasisValidationValue( listVal, newCondition );
00474 newCondition.cond = Conditional::Between;
00475 }
00476 if ( val.contains( "cell-content-is-not-between(" ) )
00477 {
00478 val = val.remove( "cell-content-is-not-between(" );
00479 val = val.remove( ")" );
00480 QStringList listVal = QStringList::split( ",", val );
00481 loadOasisValidationValue( listVal,newCondition );
00482 newCondition.cond = Conditional::Different;
00483 }
00484
00485 }
00486
00487
00488 void Conditions::loadOasisCondition( QString &valExpression, Conditional &newCondition )
00489 {
00490 QString value;
00491 if (valExpression.find( "<=" )==0 )
00492 {
00493 value = valExpression.remove( 0,2 );
00494 newCondition.cond = Conditional::InferiorEqual;
00495 }
00496 else if (valExpression.find( ">=" )==0 )
00497 {
00498 value = valExpression.remove( 0,2 );
00499 newCondition.cond = Conditional::SuperiorEqual;
00500 }
00501 else if (valExpression.find( "!=" )==0 )
00502 {
00503
00504 value = valExpression.remove( 0,2 );
00505 newCondition.cond = Conditional::DifferentTo;
00506 }
00507 else if ( valExpression.find( "<" )==0 )
00508 {
00509 value = valExpression.remove( 0,1 );
00510 newCondition.cond = Conditional::Inferior;
00511 }
00512 else if(valExpression.find( ">" )==0 )
00513 {
00514 value = valExpression.remove( 0,1 );
00515 newCondition.cond = Conditional::Superior;
00516 }
00517 else if (valExpression.find( "=" )==0 )
00518 {
00519 value = valExpression.remove( 0,1 );
00520 newCondition.cond = Conditional::Equal;
00521 }
00522 else
00523 kdDebug()<<" I don't know how to parse it :"<<valExpression<<endl;
00524 kdDebug()<<" value :"<<value<<endl;
00525 bool ok = false;
00526 newCondition.val1 = value.toDouble(&ok);
00527 if ( !ok )
00528 {
00529 newCondition.val1 = value.toInt(&ok);
00530 if ( !ok )
00531 {
00532 newCondition.strVal1 = new QString( value );
00533 kdDebug()<<" Try to parse this value :"<<value<<endl;
00534 }
00535
00536 }
00537 }
00538
00539
00540 void Conditions::loadOasisValidationValue( const QStringList &listVal, Conditional &newCondition )
00541 {
00542 bool ok = false;
00543 kdDebug()<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
00544
00545 newCondition.val1 = listVal[0].toDouble(&ok);
00546 if ( !ok )
00547 {
00548 newCondition.val1 = listVal[0].toInt(&ok);
00549 if ( !ok )
00550 {
00551 newCondition.strVal1 = new QString( listVal[0] );
00552 kdDebug()<<" Try to parse this value :"<<listVal[0]<<endl;
00553 }
00554 }
00555 ok=false;
00556 newCondition.val2 = listVal[1].toDouble(&ok);
00557 if ( !ok )
00558 {
00559 newCondition.val2 = listVal[1].toInt(&ok);
00560 if ( !ok )
00561 {
00562 newCondition.strVal2 = new QString( listVal[1] );
00563 kdDebug()<<" Try to parse this value :"<<listVal[1]<<endl;
00564 }
00565 }
00566 }
00567
00568
00569 void Conditions::loadConditions( const QDomElement & element )
00570 {
00571 QDomNodeList nodeList = element.childNodes();
00572 Conditional newCondition;
00573 bool ok;
00574 StyleManager * manager = m_cell->sheet()->doc()->styleManager();
00575
00576 for ( int i = 0; i < (int)(nodeList.length()); ++i )
00577 {
00578 newCondition.strVal1 = 0;
00579 newCondition.strVal2 = 0;
00580 newCondition.styleName = 0;
00581 newCondition.fontcond = 0;
00582 newCondition.colorcond = 0;
00583
00584 QDomElement conditionElement = nodeList.item( i ).toElement();
00585
00586 ok = conditionElement.hasAttribute( "cond" );
00587
00588 if ( ok )
00589 newCondition.cond = (Conditional::Type) conditionElement.attribute( "cond" ).toInt( &ok );
00590 else continue;
00591
00592 if ( conditionElement.hasAttribute( "val1" ) )
00593 {
00594 newCondition.val1 = conditionElement.attribute( "val1" ).toDouble( &ok );
00595
00596 if ( conditionElement.hasAttribute( "val2" ) )
00597 newCondition.val2 = conditionElement.attribute("val2").toDouble( &ok );
00598 }
00599
00600 if ( conditionElement.hasAttribute( "strval1" ) )
00601 {
00602 newCondition.strVal1 = new QString( conditionElement.attribute( "strval1" ) );
00603
00604 if ( conditionElement.hasAttribute( "strval2" ) )
00605 newCondition.strVal2 = new QString( conditionElement.attribute( "strval2" ) );
00606 }
00607
00608 if ( conditionElement.hasAttribute( "color" ) )
00609 newCondition.colorcond = new QColor( conditionElement.attribute( "color" ) );
00610
00611 QDomElement font = conditionElement.namedItem( "font" ).toElement();
00612 if ( !font.isNull() )
00613 newCondition.fontcond = new QFont( util_toFont( font ) );
00614
00615 if ( conditionElement.hasAttribute( "style" ) )
00616 {
00617 newCondition.styleName = new QString( conditionElement.attribute( "style" ) );
00618 newCondition.style = manager->style( *newCondition.styleName );
00619 if ( !newCondition.style )
00620 ok = false;
00621 }
00622
00623 if ( ok )
00624 {
00625 m_condList.append( newCondition );
00626 }
00627 else
00628 {
00629 kdDebug(36001) << "Error loading condition " << conditionElement.nodeName()<< endl;
00630 }
00631 }
00632 }