KHolidays Library
holidayparserdriverplan.cpp
00001 /* 00002 Original version from plan by Thomas Driemeyer <thomas@bitrot.de> 00003 00004 Adapted for use in KOrganizer by 00005 Preston Brown <pbrown@kde.org> and 00006 Reinhold Kainhofer <reinhold@kainhofer.com> 00007 00008 Portions contributed by 00009 Peter Littlefield <plittle@sofkin.ca> 00010 Armin Liebl <liebla@informatik.tu-muenchen.de> 00011 Efthimios Mavrogeorgiadis <emav@enl.auth.gr> 00012 Erwin Hugo Achermann <acherman@inf.ethz.ch> 00013 00014 Major rewrite using Bison C++ skeleton: 00015 Copyright 2010 John Layt <john@layt.net> 00016 00017 This library is free software; you can redistribute it and/or 00018 modify it under the terms of the GNU Library General Public 00019 License as published by the Free Software Foundation; either 00020 version 2 of the License, or (at your option) any later version. 00021 00022 This library is distributed in the hope that it will be useful, 00023 but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 GNU Library General Public License for more details. 00026 00027 You should have received a copy of the GNU Library General Public License 00028 along with this library; see the file COPYING.LIB. If not, write to the 00029 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00030 Boston, MA 02110-1301, USA. 00031 */ 00032 00033 #include "holidayparserdriverplan_p.h" 00034 #include "holidayscannerplan_p.h" 00035 #include "holidayparserplan.hpp" 00036 00037 #include <sstream> 00038 00039 #include <QFileInfo> 00040 00041 #include <kdebug.h> 00042 00043 #include "holiday_p.h" 00044 00045 #define LAST 99999 00046 #define ANY -99999 00047 #define BEFORE -1 00048 #define AFTER 1 00049 00050 using namespace KHolidays; 00051 00052 HolidayParserDriverPlan::HolidayParserDriverPlan( const QString &planFilePath ) 00053 :HolidayParserDriver( planFilePath ), 00054 m_traceParsing( false ), 00055 m_traceScanning( false ), 00056 m_parseMetadataOnly( false ) 00057 { 00058 QFile holidayFile( filePath() ); 00059 if ( holidayFile.open( QIODevice::ReadOnly ) ) { 00060 m_scanData = holidayFile.readAll(); 00061 holidayFile.close(); 00062 } 00063 m_scanner = new HolidayScannerPlan(); 00064 m_scanner->set_debug( m_traceScanning ); 00065 m_parser = new HolidayParserPlan( *this ); 00066 m_parser->set_debug_level( m_traceParsing ); 00067 parseMetadata(); 00068 } 00069 00070 HolidayParserDriverPlan::~HolidayParserDriverPlan() 00071 { 00072 delete m_parser; 00073 delete m_scanner; 00074 } 00075 00076 //TODO Figure why it doesn't compile 00077 void HolidayParserDriverPlan::error( const KHolidays::location &errorLocation, const QString &errorMessage ) 00078 { 00079 Q_UNUSED( errorLocation ); 00080 //std::cerr << errorLocation << " : " << errorMessage; //Doesn't work??? 00081 //kDebug() << errorLocation << " : " << errorMessage; //Doesn't work??? 00082 kDebug() << errorMessage; 00083 } 00084 00085 void HolidayParserDriverPlan::error( const QString &errorMessage ) 00086 { 00087 kDebug() << errorMessage; 00088 } 00089 00090 00091 void HolidayParserDriverPlan::parse() 00092 { 00093 // Parse the file using every calendar system in the file 00094 foreach( const QString &calendar, m_fileCalendarTypes ) { 00095 00096 // Cater for events defined in other Calendar Systems where request year could cover 2 or 3 event years 00097 // Perhaps also parse year before and year after to allow events to span years or shift to other year? 00098 setParseCalendar( calendar ); 00099 setParseStartEnd(); 00100 00101 // Generate all events for this calendar in the required year(s) 00102 for ( m_parseYear = m_parseStartYear; m_parseYear <= m_parseEndYear; ++m_parseYear ) { 00103 00104 m_parseCalendar->setDate( m_parseYearStart, m_parseYear, 1, 1 ); 00105 m_parseYearEaster = easter( m_parseYear ); 00106 m_parseYearPascha = pascha( m_parseYear ); 00107 00108 std::istringstream iss2( std::string( m_scanData.data() ) ); 00109 m_scanner->yyrestart( &iss2 ); 00110 00111 m_parser->parse(); 00112 } 00113 00114 } 00115 } 00116 00117 void HolidayParserDriverPlan::parseMetadata() 00118 { 00119 m_parseMetadataOnly = true; 00120 m_fileCountryCode.clear(); 00121 m_fileLanguageCode.clear(); 00122 m_fileName.clear(); 00123 m_fileDescription.clear(); 00124 m_fileCalendarTypes.clear(); 00125 m_fileCalendarTypes.append( "gregorian" ); 00126 00127 // Default to files internal metadata 00128 setParseCalendar( "gregorian" ); 00129 m_parseYear = QDate::currentDate().year(); 00130 std::istringstream iss2( std::string( m_scanData.data() ) ); 00131 m_scanner->yyrestart( &iss2 ); 00132 m_parser->parse(); 00133 m_resultList.clear(); 00134 00135 // If not populated, then use filename metadata, this may change later 00136 // metadata is encoded in filename in form holiday_<region>_<type>_<language>_<name> 00137 // with region, type and language sub groups separated by -, and with name optional 00138 QFileInfo file( m_filePath ); 00139 if ( file.exists() ) { 00140 QStringList metadata = file.fileName().split('_'); 00141 if ( metadata[0] == "holiday" && metadata.count() > 2 ) { 00142 if ( m_fileCountryCode.isEmpty() ) { 00143 setFileCountryCode( metadata[1].toUpper() ); 00144 } 00145 if ( m_fileLanguageCode.isEmpty() ) { 00146 QStringList language = metadata[2].split('-'); 00147 m_fileLanguageCode = language[0]; 00148 if ( language.count() > 1 ) { 00149 setFileLanguageCode( language[0].append( '_' ).append( language[1].toUpper() ) ); 00150 } else { 00151 setFileLanguageCode( language[0] ); 00152 } 00153 } 00154 if ( m_fileLanguageCode.isEmpty() && metadata.count() > 3 ) { 00155 m_fileName = metadata[3]; 00156 } 00157 } 00158 } 00159 00160 m_parseMetadataOnly = false; 00161 } 00162 00163 QString HolidayParserDriverPlan::filePath() 00164 { 00165 return m_filePath; 00166 } 00167 00168 00169 /***************************************** 00170 Calendar and Date convenience routines 00171 ******************************************/ 00172 00173 // Adjust month numbering for Hebrew civil calendar leap month 00174 int HolidayParserDriverPlan::adjustedMonthNumber( int month ) 00175 { 00176 if ( m_eventCalendarType != "hebrew" || // Only adjust Hebrew months 00177 m_parseCalendar->calendarType() != "hebrew" || 00178 !m_parseCalendar->isLeapYear( m_parseYear ) || // Only adjust in leap year 00179 month < 6 ) { // Only adjust from Adar onwards 00180 return month; 00181 } 00182 00183 if ( month == 13 ) { // Adar I 00184 return 6; 00185 } 00186 00187 if ( month == 14 ) { // Adar II 00188 return 7; 00189 } 00190 00191 return month + 1; // Inserting Adar I moves other months up by 1 00192 } 00193 00194 bool HolidayParserDriverPlan::isLeapYear( int year ) 00195 { 00196 return m_parseCalendar->isLeapYear( year ); 00197 } 00198 00199 int HolidayParserDriverPlan::parseYear() 00200 { 00201 return m_parseYear; 00202 } 00203 00204 int HolidayParserDriverPlan::monthsInYear( int year ) 00205 { 00206 QDate tempDate; 00207 m_parseCalendar->setDate( tempDate, year, 1, 1 ); 00208 return m_parseCalendar->monthsInYear( tempDate ); 00209 } 00210 00211 int HolidayParserDriverPlan::daysInMonth( int year, int month ) 00212 { 00213 QDate tempDate; 00214 m_parseCalendar->setDate( tempDate, year, month, 1 ); 00215 return m_parseCalendar->daysInMonth( tempDate ); 00216 } 00217 00218 int HolidayParserDriverPlan::julianDay( int year, int month, int day ) 00219 { 00220 QDate tempDate; 00221 m_parseCalendar->setDate( tempDate, year, month, day ); 00222 return tempDate.toJulianDay(); 00223 } 00224 00225 void HolidayParserDriverPlan::julianDayToDate( int jd, int *year, int *month, int *day ) 00226 { 00227 QDate tempDate = QDate::fromJulianDay( jd ); 00228 00229 if ( year ) { 00230 *year = m_parseCalendar->year( tempDate ); 00231 } 00232 if ( month ) { 00233 *month = m_parseCalendar->month( tempDate ); 00234 } 00235 if ( day ) { 00236 *day = m_parseCalendar->day( tempDate ); 00237 } 00238 } 00239 00240 QDate HolidayParserDriverPlan::easter( int year ) 00241 { 00242 if ( m_parseCalendar->calendarType() != "gregorian" ) { 00243 return QDate(); 00244 } 00245 00246 // Algorithm taken from Tondering 00247 // http://www.tondering.dk/claus/cal/node3.html#SECTION003137000000000000000 00248 int g = year % 19; 00249 int c = year / 100; 00250 int h = ( c - ( c / 4 ) - ( ( ( 8 * c ) + 13 ) / 25 ) + ( 19 * g ) + 15 ) % 30; 00251 int i = h - ( ( h / 28 ) * ( 1 - ( ( 29 / ( h + 1 ) ) * ( ( 21 - g ) / 11 ) ) ) ); 00252 int j = ( year + ( year / 4 ) + i + 2 - c + ( c / 4 ) ) % 7; 00253 int l = i - j; 00254 int month = 3 + ( ( l + 40 ) / 44 ); 00255 int day = l + 28 - ( 31 * ( month / 4 ) ); 00256 00257 return QDate::fromJulianDay( julianDay( year, month, day ) ); 00258 } 00259 00260 00261 QDate HolidayParserDriverPlan::pascha( int year ) 00262 { 00263 if ( m_parseCalendar->calendarType() == "gregorian" || 00264 m_parseCalendar->calendarType() == "julian" ) { 00265 // Algorithm taken from Tondering 00266 // http://www.tondering.dk/claus/cal/node3.html#SECTION003137000000000000000 00267 // Gives Orthodox Easter in the Julian Calendar, need to convert afterwards to Gregorian if needed 00268 int g = year % 19; 00269 int i = ( ( 19 * g ) + 15 ) % 30; 00270 int j = ( year + ( year / 4 ) + i ) % 7; 00271 int l = i - j; 00272 int month = 3 + ( ( l + 40 ) / 44 ); 00273 int day = l + 28 - ( 31 * ( month / 4 ) ); 00274 00275 if ( m_parseCalendar->calendarType() == "julian" ) { 00276 return QDate::fromJulianDay( julianDay( year, month, day ) ); 00277 } 00278 00279 if ( m_parseCalendar->calendarType() == "gregorian" ) { 00280 setParseCalendar( "julian" ); 00281 int paschaJd = julianDay( year, month, day ); 00282 setParseCalendar( "gregorian" ); 00283 return QDate::fromJulianDay( paschaJd ); 00284 } 00285 } 00286 00287 return QDate(); 00288 } 00289 00290 00291 /************************* 00292 * Calculate jd routines * 00293 *************************/ 00294 00295 // Return the jd of an existing event, assumes unique names and correct order in file 00296 int HolidayParserDriverPlan::julianDayFromEventName( const QString &eventName ) 00297 { 00298 foreach ( const KHolidays::Holiday &thisHoliday, m_resultList ) { 00299 if ( thisHoliday.text() == eventName ) { 00300 return thisHoliday.date().toJulianDay(); 00301 } 00302 } 00303 return -1; 00304 } 00305 00306 // Return jd of Easter if Gregorian 00307 int HolidayParserDriverPlan::julianDayFromEaster( void ) 00308 { 00309 if ( m_eventCalendarType == "gregorian" ) { 00310 return m_parseYearEaster.toJulianDay(); 00311 } else { 00312 error( "Can only use Easter in Gregorian event rule" ); 00313 return -1; 00314 } 00315 } 00316 00317 // Return jd of Orthodox Easter if Gregorian or Julian 00318 int HolidayParserDriverPlan::julianDayFromPascha( void ) 00319 { 00320 if ( m_eventCalendarType == "gregorian" || m_eventCalendarType == "julian" ) { 00321 return m_parseYearPascha.toJulianDay(); 00322 } else { 00323 error( "Can only use Easter in Gregorian or Julian event rule" ); 00324 return -1; 00325 } 00326 } 00327 00328 // Return jd of weekday from a month/day in parse year 00329 int HolidayParserDriverPlan::julianDayFromMonthDay( int month, int day ) { 00330 return julianDay( m_parseYear, month, day ); 00331 } 00332 00333 // Return jd of weekday relative to a Julian Day number 00334 int HolidayParserDriverPlan::julianDayFromRelativeWeekday( int occurrence, int weekday, int jd ) 00335 { 00336 if ( occurrence == ANY ) { /* Should never get this, convert to AFTER instead */ 00337 occurrence = AFTER; 00338 } 00339 00340 int thisWeekday = m_parseCalendar->dayOfWeek( QDate::fromJulianDay( jd ) ); 00341 00342 /* AFTER actually means on or after */ 00343 /* BEFORE actually means on or before */ 00344 if ( occurrence > 0 ) { 00345 occurrence = occurrence - 1; 00346 } else if ( occurrence < 0 && weekday == thisWeekday ) { 00347 occurrence = occurrence + 1; 00348 } 00349 00350 if ( weekday < thisWeekday ) { 00351 occurrence = occurrence + 1; 00352 } 00353 00354 return jd + weekday - thisWeekday + ( occurrence * 7 ); 00355 } 00356 00357 // Return jd of weekday occurence in a given month and day in the parse year 00358 int HolidayParserDriverPlan::julianDayFromWeekdayInMonth( int occurrence, int weekday, int month ) 00359 { 00360 if ( occurrence == LAST ) { // Is weekday on or before last day of month 00361 return julianDayFromRelativeWeekday( BEFORE, weekday, julianDay( m_parseYear, month, daysInMonth( m_parseYear, month ) ) ); 00362 } else { // Is nth weekday on or after first day of month 00363 return julianDayFromRelativeWeekday( occurrence, weekday, julianDay( m_parseYear, month, 1 ) ); 00364 } 00365 } 00366 00367 00368 /**************************************************** 00369 * Set parsed event variables convenience functions * 00370 ****************************************************/ 00371 00372 void HolidayParserDriverPlan::setFileCountryCode( const QString &countryCode ) 00373 { 00374 m_fileCountryCode = countryCode; 00375 } 00376 00377 void HolidayParserDriverPlan::setFileLanguageCode( const QString &languageCode ) 00378 { 00379 m_fileLanguageCode = languageCode; 00380 } 00381 00382 void HolidayParserDriverPlan::setFileName( const QString &name ) 00383 { 00384 m_fileName = name; 00385 } 00386 00387 void HolidayParserDriverPlan::setFileDescription( const QString &description ) 00388 { 00389 m_fileDescription = description; 00390 } 00391 00392 void HolidayParserDriverPlan::setEventName( const QString &eventName ) 00393 { 00394 m_eventName = eventName; 00395 } 00396 00397 void HolidayParserDriverPlan::setEventColorName( int nameColor ) 00398 { 00399 m_eventColorName = nameColor; 00400 } 00401 00402 void HolidayParserDriverPlan::setEventColorDay( int dayColor ) 00403 { 00404 m_eventColorDay = dayColor; 00405 } 00406 00407 void HolidayParserDriverPlan::setEventCalendarType( const QString &calendarType ) 00408 { 00409 m_eventCalendarType = calendarType; 00410 if ( m_parseMetadataOnly && !m_fileCalendarTypes.contains( calendarType ) ) { 00411 m_fileCalendarTypes.append( calendarType ); 00412 } 00413 } 00414 00415 void HolidayParserDriverPlan::setEventDate( int eventYear, int eventMonth, int eventDay ) 00416 { 00417 m_eventYear = eventYear; 00418 m_eventMonth = eventMonth; 00419 m_eventDay = eventDay; 00420 } 00421 00422 void HolidayParserDriverPlan::setEventDate( int jd ) 00423 { 00424 julianDayToDate( jd, &m_eventYear, &m_eventMonth, &m_eventDay ); 00425 } 00426 00427 /******************************************** 00428 * Set event date from event rules routines * 00429 ********************************************/ 00430 00431 /* 00432 * Set event by weekday (Monday..Sunday). The rule expression is 00433 * "every <occurrence> <weekday> of <month> plus <offset> days length <duration> days". 00434 * Occurrence and month can be ANY or LAST, offset and duration are optional. 00435 */ 00436 00437 void HolidayParserDriverPlan::setFromWeekdayInMonth( int occurrence, int weekday, int month, int offset, int duration ) 00438 { 00439 // Don't set if only parsing metadata or calendar for event rule is not the current parse calendar 00440 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) { 00441 return; 00442 } 00443 00444 int startMonth, endMonth; 00445 if ( month == LAST ) { 00446 startMonth = monthsInYear( m_parseYear ); 00447 endMonth = startMonth; 00448 } else if ( month == ANY ) { 00449 startMonth = 1; 00450 endMonth = monthsInYear( m_parseYear ); 00451 } else { 00452 startMonth = month; 00453 endMonth = month; 00454 } 00455 00456 // Generate all events in the required event month(s) 00457 for ( int thisMonth = startMonth; thisMonth <= endMonth; ++thisMonth ) { 00458 00459 if ( m_parseCalendar->isValid( m_parseYear, thisMonth, 1 ) ) { 00460 int startOccurrence, endOccurrence; 00461 if ( occurrence == ANY ) { // Generate 1st through 5th weekdays, assumes no month with > 35 days 00462 startOccurrence = 1; 00463 endOccurrence = 5; 00464 } else { // Generate just nth or LAST weekday 00465 startOccurrence = occurrence; 00466 endOccurrence = occurrence; 00467 } 00468 00469 int jdMonthStart = julianDay( m_parseYear, thisMonth, 1 ); 00470 int jdMonthEnd = julianDay( m_parseYear, thisMonth, daysInMonth( m_parseYear, thisMonth ) ); 00471 00472 // Generate each required occurrence of weekday in month, check occurrence actually falls in month 00473 for ( int thisOccurrence = startOccurrence; thisOccurrence <= endOccurrence; ++thisOccurrence ) { 00474 int thisJd = julianDayFromWeekdayInMonth( thisOccurrence, weekday, thisMonth ); 00475 if ( thisJd >= jdMonthStart && thisJd <= jdMonthEnd ) { 00476 setEvent( thisJd + offset, 0, duration ); 00477 } 00478 } 00479 } 00480 00481 } 00482 } 00483 00484 /* 00485 * Set event by weekday (Monday..Sunday) relative to a date. The expression is 00486 * "<weekday> <occurrence> <date> plus <offset> days length <duration> days". 00487 * Occurrence, month and day can be ANY or LAST, year can be ANY, offset and duration are optional. 00488 */ 00489 00490 void HolidayParserDriverPlan::setFromRelativeWeekday( int occurrence, int weekday, int offset, int duration ) 00491 { 00492 // Don't set if only parsing metadata or calendar for event rule is not the current parse calendar 00493 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) { 00494 return; 00495 } 00496 00497 int thisYear; 00498 if ( m_eventYear == ANY ) { // Generate the parse year 00499 thisYear = m_parseYear; 00500 } else { // Generate a specific event year 00501 thisYear = m_eventYear; 00502 } 00503 00504 int startMonth, endMonth; 00505 if ( m_eventMonth == LAST ) { // Generate just the last month 00506 startMonth = monthsInYear( thisYear ); 00507 endMonth = startMonth; 00508 } else if ( m_eventMonth == ANY ) { // Generate every month 00509 startMonth = 1; 00510 endMonth = monthsInYear( thisYear ); 00511 } else { // Generate just the specific event month 00512 startMonth = m_eventMonth; 00513 endMonth = m_eventMonth; 00514 } 00515 00516 // Generate all events in the required month(s) 00517 int thisMonth; 00518 for ( thisMonth = startMonth; thisMonth <= endMonth; ++thisMonth ) { 00519 00520 int startDay, endDay; 00521 if ( m_eventDay == LAST ) { // Generate just the last day in the month 00522 startDay = daysInMonth( thisYear, thisMonth ); 00523 endDay = startDay; 00524 } else if ( m_eventDay == ANY ) { // Generate every day in the month 00525 startDay = 1; 00526 endDay = daysInMonth( thisYear, thisMonth ); 00527 } else { // Generate just the specific event day 00528 startDay = m_eventDay; 00529 endDay = m_eventDay; 00530 } 00531 00532 // Generate all events on the required day(s) 00533 for ( int thisDay = startDay; thisDay <= endDay; ++thisDay ) { 00534 if ( m_parseCalendar->isValid( thisYear, thisMonth, thisDay ) ) { 00535 int relativeJd = julianDayFromRelativeWeekday( occurrence, weekday, julianDay( thisYear, thisMonth, thisDay ) ); 00536 setEvent( relativeJd + offset, 0, duration ); 00537 } 00538 } 00539 00540 } 00541 } 00542 00543 // TODO Figure out how this works :-) 00544 int HolidayParserDriverPlan::conditionalOffset( int year, int month, int day, int condition ) 00545 { 00551 int offset = 0; 00552 00553 QDate tempDate; 00554 m_parseCalendar->setDate( tempDate, year, month, day ); 00555 int weekday = m_parseCalendar->dayOfWeek( tempDate ); 00556 00557 if ( condition & ( 1 << weekday ) ) { 00558 /* condition matches -> higher 8 bits contain the possible days to shift to */ 00559 int to = ( condition >> 8 ); 00560 while ( !( to & ( 1 << ( ( weekday + offset ) % 7 ) ) ) && ( offset < 8 ) ) { 00561 ++offset; 00562 } 00563 } 00564 00565 if ( offset >= 8 ) { 00566 offset = 0; 00567 } 00568 00569 return offset; 00570 } 00571 00572 /* 00573 * Set event by date. The expression is 00574 * "<date> plus <offset> days shift <condition> length <duration> days". 00575 * Occurrence, month and day can be ANY or LAST, year can be ANY, offset and duration are optional. 00576 */ 00577 00578 void HolidayParserDriverPlan::setFromDate( int offset, int condition, int duration ) 00579 { 00580 // Don't set if only parsing metadata or calendar for event rule is not the current parse calendar 00581 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) { 00582 return; 00583 } 00584 00585 int thisYear; 00586 if ( m_eventYear == ANY ) { // Generate the parse year 00587 thisYear = m_parseYear; 00588 } else { // Generate a specific event year 00589 thisYear = m_eventYear; 00590 } 00591 00592 int startMonth, endMonth; 00593 if ( m_eventMonth == LAST ) { // Generate just the last month 00594 startMonth = monthsInYear( thisYear ); 00595 endMonth = startMonth; 00596 } else if ( m_eventMonth == ANY ) { // Generate every month 00597 startMonth = 1; 00598 endMonth = monthsInYear( thisYear ); 00599 } else { // Generate just the specific event month 00600 startMonth = m_eventMonth; 00601 endMonth = m_eventMonth; 00602 } 00603 00604 // Generate all events in the required month(s) 00605 for ( int thisMonth = startMonth; thisMonth <= endMonth; ++thisMonth ) { 00606 00607 int startDay, endDay; 00608 if ( m_eventDay == LAST ) { // Generate just the last day in the month 00609 startDay = daysInMonth( thisYear, thisMonth ); 00610 endDay = startDay; 00611 } else if ( m_eventDay == ANY ) { // Generate every day in the month 00612 startDay = 1; 00613 endDay = daysInMonth( thisYear, thisMonth ); 00614 } else { // Generate just the specific event day 00615 startDay = m_eventDay; 00616 endDay = m_eventDay; 00617 } 00618 00619 // Generate all events on the required day(s) 00620 for ( int thisDay = startDay; thisDay <= endDay; ++thisDay ) { 00621 00622 if ( m_parseCalendar->isValid( thisYear, thisMonth, thisDay ) ) { 00623 setEvent( julianDay( thisYear, thisMonth, thisDay ) + offset, 00624 conditionalOffset( thisYear, thisMonth, thisDay, condition ), duration ); 00625 } 00626 00627 } 00628 00629 } 00630 } 00631 00632 /* 00633 * Set event relative to Easter. The expression is 00634 * "EASTER plus <offset> days length <duration> days". 00635 * Offset and duration are optional. 00636 */ 00637 00638 void HolidayParserDriverPlan::setFromEaster( int offset, int duration ) 00639 { 00640 // Don't set if only parsing metadata or calendar for event rule is not the current parse calendar 00641 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) { 00642 return; 00643 } 00644 00645 if ( m_eventCalendarType == "gregorian" ) { 00646 setEvent( m_parseYearEaster.toJulianDay() + offset, 0, duration ); 00647 } else { 00648 error( "Can only use Easter in Gregorian event rule" ); 00649 } 00650 } 00651 00652 /* 00653 * Set event relative to Pascha. The expression is 00654 * "PASCHA plus <offset> days length <duration> days". 00655 * Offset and duration are optional. 00656 */ 00657 00658 void HolidayParserDriverPlan::setFromPascha( int offset, int duration ) 00659 { 00660 // Don't set if only parsing metadata or calendar for event rule is not the current parse calendar 00661 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) { 00662 return; 00663 } 00664 00665 if ( m_eventCalendarType == "gregorian" || m_eventCalendarType == "julian" ) { 00666 setEvent( m_parseYearPascha.toJulianDay(), offset, duration ); 00667 } else { 00668 error( "Can only use Pascha in Julian and Gregorian event rule" ); 00669 } 00670 } 00671 00672 // Set the event if it falls inside the requested date range 00673 void HolidayParserDriverPlan::setEvent( int jd, int observeOffset, int duration ) 00674 { 00675 // Don't set if only parsing metadata or calendar for event rule is not the current parse calendar 00676 if ( m_parseMetadataOnly || m_eventCalendarType != m_parseCalendar->calendarType() ) { 00677 return; 00678 } 00679 00680 // Date the holiday will be observed on 00681 int observeJd = jd + observeOffset; 00682 00683 if ( m_multidayMode == Holiday::MultidayHolidaysAsSingleEvents ) { 00684 addHoliday( QDate::fromJulianDay( observeJd ), duration ); 00685 } else { // KHolidays::MultidayHolidaysAsMultipleEvents 00686 // Create backwards compatible holidays, one incidence per day 00687 for ( int dd = 0; dd < duration; ++dd ) { 00688 addHoliday( QDate::fromJulianDay( observeJd + dd ), 1 ); 00689 } 00690 } 00691 } 00692 00693 void HolidayParserDriverPlan::addHoliday( const QDate &observedDate, int duration ) 00694 { 00695 // Only set if event falls in requested date range, i.e. either starts or ends during range 00696 if ( m_parseCalendar->isValid( observedDate ) && 00697 observedDate <= m_requestEnd && 00698 observedDate.addDays( duration - 1 ) >= m_requestStart ) { 00699 KHolidays::Holiday holiday; 00700 holiday.d->mObservedDate = observedDate; 00701 holiday.d->mDuration = duration; 00702 holiday.d->mText = m_eventName; 00703 holiday.d->mShortText = m_eventName; 00704 if ( m_eventColorName == 2 || m_eventColorName == 9 || 00705 m_eventColorDay == 2 || m_eventColorDay == 9 ) { 00706 holiday.d->mDayType = KHolidays::Holiday::NonWorkday; 00707 } else { 00708 holiday.d->mDayType = KHolidays::Holiday::Workday; 00709 } 00710 m_resultList.append( holiday ); 00711 } 00712 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Apr 30 2012 21:48:30 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Apr 30 2012 21:48:30 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.