00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "valueparser.h"
00022
00023 #include "kspread_cell.h"
00024 #include "kspread_locale.h"
00025
00026 using namespace KSpread;
00027
00028 ValueParser::ValueParser( KLocale* locale ) : parserLocale( locale )
00029 {
00030 }
00031
00032 KLocale* ValueParser::locale()
00033 {
00034 return parserLocale;
00035 }
00036
00037 void ValueParser::parse (const QString& str, KSpreadCell *cell)
00038 {
00039 FormatType format = cell->formatType();
00040
00041
00042
00043
00044
00045 if ( str.isEmpty() || format == Text_format || str.at(0)=='\'' )
00046 {
00047 cell->setValue (str);
00048 return;
00049 }
00050
00051 QString strStripped = str.stripWhiteSpace();
00052
00053
00054 if (tryParseBool (strStripped, cell))
00055 return;
00056
00057
00058 if (tryParseNumber (strStripped, cell))
00059 return;
00060
00061
00062 bool ok;
00063 double money = parserLocale->readMoney (strStripped, &ok);
00064 if (ok)
00065 {
00066 cell->setPrecision(2);
00067 KSpreadValue val (money);
00068 val.setFormat (KSpreadValue::fmt_Money);
00069 cell->setValue (val);
00070 return;
00071 }
00072
00073 if (tryParseDate (strStripped, cell))
00074 return;
00075
00076 if (tryParseTime (strStripped, cell))
00077 return;
00078
00079
00080 cell->setValue (KSpreadValue (str));
00081 }
00082
00083 KSpreadValue ValueParser::parse (const QString &str)
00084 {
00085 KSpreadValue val;
00086
00087
00088
00089
00090
00091 if ( str.isEmpty() || str.at(0)=='\'' )
00092 {
00093 val.setValue (str);
00094 return val;
00095 }
00096
00097 bool ok;
00098
00099 QString strStripped = str.stripWhiteSpace();
00100
00101
00102 val = tryParseBool (strStripped, &ok);
00103 if (ok)
00104 return val;
00105
00106
00107 val = tryParseNumber (strStripped, &ok);
00108 if (ok)
00109 return val;
00110
00111
00112 double money = parserLocale->readMoney (strStripped, &ok);
00113 if (ok)
00114 {
00115 val.setValue (money);
00116 val.setFormat (KSpreadValue::fmt_Money);
00117 return val;
00118 }
00119
00120 val = tryParseDate (strStripped, &ok);
00121 if (ok)
00122 return val;
00123
00124 val = tryParseTime (strStripped, &ok);
00125 if (ok)
00126 return val;
00127
00128
00129 val.setValue (str);
00130 return val;
00131 }
00132
00133 bool ValueParser::tryParseBool (const QString& str, KSpreadCell *cell)
00134 {
00135 bool ok;
00136 KSpreadValue val = tryParseBool (str, &ok);
00137 if (ok)
00138 cell->setValue (val);
00139 return ok;
00140 }
00141
00142 bool ValueParser::tryParseNumber (const QString& str, KSpreadCell *cell)
00143 {
00144 bool ok;
00145 KSpreadValue val = tryParseNumber (str, &ok);
00146 if (ok)
00147 cell->setValue (val);
00148 return ok;
00149 }
00150
00151 bool ValueParser::tryParseDate (const QString& str, KSpreadCell *cell)
00152 {
00153 bool ok;
00154 KSpreadValue value = tryParseDate (str, &ok);
00155 if (ok)
00156 cell->setValue (value);
00157 return ok;
00158 }
00159
00160 bool ValueParser::tryParseTime (const QString& str, KSpreadCell *cell)
00161 {
00162 bool ok;
00163 KSpreadValue value = tryParseTime (str, &ok);
00164 if (ok)
00165 cell->setValue (value);
00166 return ok;
00167 }
00168
00169
00170 KSpreadValue ValueParser::tryParseBool (const QString& str, bool *ok)
00171 {
00172 KSpreadValue val;
00173 if (ok) *ok = false;
00174 if ((str.lower() == "true") ||
00175 (str.lower() == parserLocale->translate("True").lower()))
00176 {
00177 val.setValue (true);
00178 if (ok) *ok = true;
00179 }
00180 else if ((str.lower() == "false") ||
00181 (str.lower() == parserLocale->translate("false").lower()))
00182 {
00183 val.setValue (false);
00184 if (ok) *ok = true;
00185 fmtType = Number_format;
00186 }
00187 return val;
00188 }
00189
00190 KSpreadValue ValueParser::tryParseNumber (const QString& str, bool *ok)
00191 {
00192 KSpreadValue value;
00193
00194 bool percent = false;
00195 QString str2;
00196 if( str.at(str.length()-1)=='%')
00197 {
00198 str2 = str.left (str.length()-1).stripWhiteSpace();
00199 percent = true;
00200 }
00201 else
00202 str2 = str;
00203
00204
00205
00206 double val = parserLocale->readNumber (str2, ok);
00207
00208 if (!(*ok))
00209 val = str2.toDouble(ok);
00210
00211 if (*ok)
00212 {
00213 if (percent)
00214 {
00215 kdDebug(36001) << "ValueParser::tryParseNumber '" << str <<
00216 "' successfully parsed as percentage: " << val << "%" << endl;
00217 value.setValue (val / 100.0);
00218 value.setFormat (KSpreadValue::fmt_Percent);
00219 fmtType = Percentage_format;
00220 }
00221 else
00222 {
00223 kdDebug(36001) << "ValueParser::tryParseNumber '" << str <<
00224 "' successfully parsed as number: " << val << endl;
00225 value.setValue (val);
00226
00227 if ( str2.contains('E') || str2.contains('e') )
00228 fmtType = Scientific_format;
00229 else
00230 {
00231 if (val > 1e+10)
00232 fmtType = Scientific_format;
00233 else
00234 fmtType = Number_format;
00235 }
00236 }
00237 }
00238
00239 return value;
00240 }
00241
00242 KSpreadValue ValueParser::tryParseDate (const QString& str, bool *ok)
00243 {
00244 bool valid = false;
00245 QDate tmpDate = parserLocale->readDate (str, &valid);
00246 if (!valid)
00247 {
00248
00249
00250
00251
00252
00253 QString fmt = parserLocale->dateFormatShort();
00254 int yearPos = fmt.find ("%Y", 0, false);
00255 if ( yearPos > -1 )
00256 {
00257 if ( yearPos == 0 )
00258 {
00259 fmt.remove( 0, 2 );
00260 while ( fmt[0] != '%' )
00261 fmt.remove( 0, 1 );
00262 } else
00263 {
00264 fmt.remove( yearPos, 2 );
00265 for ( ; yearPos > 0 && fmt[yearPos-1] != '%'; --yearPos )
00266 fmt.remove( yearPos, 1 );
00267 }
00268
00269 tmpDate = parserLocale->readDate( str, fmt, &valid );
00270 }
00271 }
00272 if (valid)
00273 {
00274
00275
00276
00277
00278
00279
00280
00281 QString fmt = parserLocale->dateFormatShort();
00282 if( ( fmt.contains( "%y" ) == 1 ) && ( tmpDate.year() > 2999 ) )
00283 tmpDate = tmpDate.addYears( -1900 );
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 if( ( tmpDate.year() >= 2030 ) && ( tmpDate.year() <= 2069 ) )
00294 {
00295 QString yearFourDigits = QString::number( tmpDate.year() );
00296 QString yearTwoDigits = QString::number( tmpDate.year() % 100 );
00297
00298
00299
00300 if( ( str.contains( yearTwoDigits ) >= 1 ) &&
00301 ( str.contains( yearFourDigits ) == 0 ) )
00302 tmpDate = tmpDate.addYears( -100 );
00303 }
00304
00305
00306 if (parserLocale->formatDate (tmpDate, false) == str)
00307 fmtType = TextDate_format;
00308 else
00309 fmtType = ShortDate_format;
00310 }
00311 if (ok)
00312 *ok = valid;
00313
00314 return KSpreadValue (tmpDate);
00315 }
00316
00317 KSpreadValue ValueParser::tryParseTime (const QString& str, bool *ok)
00318 {
00319 if (ok)
00320 *ok = false;
00321
00322 bool valid = false;
00323 bool duration = false;
00324 KSpreadValue val;
00325
00326 QDateTime tmpTime = readTime (str, true, &valid, duration);
00327 if (!tmpTime.isValid())
00328 tmpTime = readTime (str, false, &valid, duration);
00329
00330 if (!valid)
00331 {
00332 QTime tm;
00333 if (parserLocale->use12Clock())
00334 {
00335 QString stringPm = parserLocale->translate("pm");
00336 QString stringAm = parserLocale->translate("am");
00337 int pos=0;
00338 if((pos=str.find(stringPm))!=-1)
00339 {
00340 QString tmp=str.mid(0,str.length()-stringPm.length());
00341 tmp=tmp.simplifyWhiteSpace();
00342 tm = parserLocale->readTime(tmp+" "+stringPm, &valid);
00343 if (!valid)
00344 tm = parserLocale->readTime(tmp+":00 "+stringPm, &valid);
00345 }
00346 else if((pos=str.find(stringAm))!=-1)
00347 {
00348 QString tmp = str.mid(0,str.length()-stringAm.length());
00349 tmp = tmp.simplifyWhiteSpace();
00350 tm = parserLocale->readTime (tmp + " " + stringAm, &valid);
00351 if (!valid)
00352 tm = parserLocale->readTime (tmp + ":00 " + stringAm, &valid);
00353 }
00354 }
00355 }
00356 if (valid)
00357 {
00358 fmtType = Time_format;
00359 if ( duration )
00360 {
00361 val.setValue (tmpTime);
00362 fmtType = Time_format7;
00363 }
00364 else
00365 val.setValue (tmpTime.time());
00366 }
00367
00368 if (ok)
00369 *ok = valid;
00370
00371 return val;
00372 }
00373
00374 QDateTime ValueParser::readTime (const QString & intstr, bool withSeconds,
00375 bool *ok, bool & duration)
00376 {
00377 duration = false;
00378 QString str = intstr.simplifyWhiteSpace().lower();
00379 QString format = parserLocale->timeFormat().simplifyWhiteSpace();
00380 if ( !withSeconds )
00381 {
00382 int n = format.find("%S");
00383 format = format.left( n - 1 );
00384 }
00385
00386 int days = -1;
00387 int hour = -1, minute = -1;
00388 int second = withSeconds ? -1 : 0;
00389 bool g_12h = false;
00390 bool pm = false;
00391 uint strpos = 0;
00392 uint formatpos = 0;
00393
00394 QDate refDate( 1899, 12, 31 );
00395
00396 uint l = format.length();
00397 uint sl = str.length();
00398
00399 while (l > formatpos || sl > strpos)
00400 {
00401 if ( !(l > formatpos && sl > strpos) )
00402 goto error;
00403
00404 QChar c( format.at( formatpos++ ) );
00405
00406 if (c != '%')
00407 {
00408 if (c.isSpace())
00409 ++strpos;
00410 else if (c != str.at(strpos++))
00411 goto error;
00412 continue;
00413 }
00414
00415
00416 if (sl > strpos && str.at( strpos).isSpace() )
00417 ++strpos;
00418
00419 c = format.at( formatpos++ );
00420 switch (c)
00421 {
00422 case 'p':
00423 {
00424 QString s;
00425 s = parserLocale->translate("pm").lower();
00426 int len = s.length();
00427 if (str.mid(strpos, len) == s)
00428 {
00429 pm = true;
00430 strpos += len;
00431 }
00432 else
00433 {
00434 s = parserLocale->translate("am").lower();
00435 len = s.length();
00436 if (str.mid(strpos, len) == s)
00437 {
00438 pm = false;
00439 strpos += len;
00440 }
00441 else
00442 goto error;
00443 }
00444 }
00445 break;
00446
00447 case 'k':
00448 case 'H':
00449 g_12h = false;
00450 hour = readInt(str, strpos);
00451 if (hour < 0)
00452 goto error;
00453 if (hour > 23)
00454 {
00455 days = (int)(hour / 24);
00456 hour %= 24;
00457 }
00458
00459 break;
00460
00461 case 'l':
00462 case 'I':
00463 g_12h = true;
00464 hour = readInt(str, strpos);
00465 if (hour < 1 || hour > 12)
00466 goto error;
00467
00468 break;
00469
00470 case 'M':
00471 minute = readInt(str, strpos);
00472 if (minute < 0 || minute > 59)
00473 goto error;
00474
00475 break;
00476
00477 case 'S':
00478 second = readInt(str, strpos);
00479 if (second < 0 || second > 59)
00480 goto error;
00481
00482 break;
00483 }
00484 }
00485
00486 if (g_12h)
00487 {
00488 hour %= 12;
00489 if (pm) hour += 12;
00490 }
00491
00492 if (days > 0)
00493 {
00494 refDate.addDays( days );
00495 duration = true;
00496 }
00497
00498 if (ok)
00499 *ok = true;
00500 return QDateTime( refDate, QTime( hour, minute, second ) );
00501
00502 error:
00503 if (ok)
00504 *ok = false;
00505
00506 return QDateTime( refDate, QTime( -1, -1, -1 ) );
00507 }
00508
00515 int ValueParser::readInt (const QString &str, uint &pos)
00516 {
00517 if (!str.at(pos).isDigit())
00518 return -1;
00519 int result = 0;
00520 for ( ; str.length() > pos && str.at(pos).isDigit(); pos++ )
00521 {
00522 result *= 10;
00523 result += str.at(pos).digitValue();
00524 }
00525
00526 return result;
00527 }
00528