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