• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • KDE Home
  • Contact Us
 

KHolidays Library

holidayregion.cpp

00001 /*
00002   This file is part of the kholidays library.
00003 
00004   Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00005   Copyright (c) 2004 Allen Winter <winter@kde.org>
00006   Copyright (c) 2008 David Jarvie <djarvie@kde.org>
00007   Copyright 2010 John Layt <john@layt.net>
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Library General Public
00011   License as published by the Free Software Foundation; either
00012   version 2 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017   GNU Library General Public License for more details.
00018 
00019   You should have received a copy of the GNU Library General Public License
00020   along with this library; see the file COPYING.LIB.  If not, write to the
00021   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00022   Boston, MA 02110-1301, USA.
00023 */
00024 
00025 #include "holidayregion.h"
00026 
00027 #include <QtCore/QDateTime>
00028 #include <QtCore/QFile>
00029 #include <QtCore/QSharedData>
00030 #include <QtCore/QFileInfo>
00031 
00032 #include <KStandardDirs>
00033 #include <KGlobal>
00034 #include <KLocale>
00035 #include <KDebug>
00036 
00037 #include "holiday_p.h"
00038 #include "parsers/plan2/holidayparserdriverplan_p.h"
00039 
00040 using namespace KHolidays;
00041 
00042 class HolidayRegion::Private
00043 {
00044   public:
00045     Private( const QString &regionCode ) : mDriver( 0 ),
00046                                            mRegionCode( regionCode )
00047     {
00048       if ( !mRegionCode.isEmpty() ) {
00049 
00050         if ( mRegionCode.length() == 2 ) { //Backwards compatible mode for old location code
00051           mLocation = mRegionCode;
00052           QStringList locationFiles = KGlobal::dirs()->findAllResources( "data",
00053                                       "libkholidays/plan2/holiday_" + mLocation + '*',
00054                                       KStandardDirs::NoDuplicates );
00055           if ( locationFiles.count() > 0 ) {
00056             mRegionCode = locationFiles.at( 0 )
00057                                        .mid( locationFiles.at( 0 ).lastIndexOf( "holiday_" ) + 8 );
00058           }
00059         }
00060 
00061         mHolidayFile.setFile( KStandardDirs::locate( "data", "libkholidays/plan2/holiday_" + mRegionCode ) );
00062       }
00063 
00064       init();
00065     }
00066 
00067     Private( const QFileInfo &regionFile ) : mDriver( 0 ),
00068                                              mHolidayFile( regionFile )
00069     {
00070       init();
00071     }
00072 
00073     ~Private()
00074     {
00075       delete mDriver;
00076     }
00077 
00078     void init()
00079     {
00080       if ( mHolidayFile.exists() ) {
00081         mDriver = new HolidayParserDriverPlan( mHolidayFile.absoluteFilePath() );
00082         if ( mDriver ) {
00083 
00084           if ( mLocation.isEmpty() ) {
00085             mLocation = mDriver->fileCountryCode().left( 2 );
00086           }
00087 
00088           if ( mRegionCode.isEmpty() ) {
00089             if ( mHolidayFile.fileName().startsWith( QLatin1String( "holiday_" ) ) ) {
00090               mRegionCode = mHolidayFile.fileName().mid( 8 );
00091             } else {
00092               mRegionCode = mHolidayFile.fileName();
00093             }
00094           }
00095 
00096         } else {
00097           mRegionCode.clear();
00098           mLocation.clear();
00099         }
00100       } else {
00101         mRegionCode.clear();
00102         mLocation.clear();
00103       }
00104     }
00105 
00106     HolidayParserDriver  *mDriver;  // The parser driver for the holiday file
00107     QString mRegionCode;            // region code of holiday region
00108     QString mLocation;              // old location code, use now deprecated
00109     QFileInfo mHolidayFile;         // file containing holiday data, or null
00110 };
00111 
00112 HolidayRegion::HolidayRegion( const QString &regionCode )
00113   : d( new Private( regionCode ) )
00114 {
00115 }
00116 
00117 HolidayRegion::HolidayRegion( const QFileInfo &regionFile )
00118              : d( new Private( regionFile ) )
00119 {
00120 }
00121 
00122 HolidayRegion::~HolidayRegion()
00123 {
00124   delete d;
00125 }
00126 
00127 QStringList HolidayRegion::locations()
00128 {
00129   const QStringList files =
00130     KGlobal::dirs()->findAllResources( "data", "libkholidays/plan2/holiday_*",
00131                                        KStandardDirs::NoDuplicates );
00132 
00133   QStringList locations;
00134   foreach ( const QString &filename, files ) {
00135     locations.append( filename.mid( filename.lastIndexOf( "holiday_" ) + 8, 2 ) );
00136   }
00137 
00138   locations.removeDuplicates();
00139   qSort( locations );
00140   return locations;
00141 }
00142 
00143 QString HolidayRegion::location() const
00144 {
00145   return d->mLocation;
00146 }
00147 
00148 QStringList HolidayRegion::regionCodes()
00149 {
00150   const QStringList files =
00151     KGlobal::dirs()->findAllResources( "data", "libkholidays/plan2/holiday_*",
00152                                        KStandardDirs::NoDuplicates );
00153 
00154   QStringList regionCodesList;
00155   foreach ( const QString &filename, files ) {
00156     regionCodesList.append( filename.mid( filename.lastIndexOf( "holiday_" ) + 8 ) );
00157   }
00158 
00159   qSort( regionCodesList );
00160   return regionCodesList;
00161 }
00162 
00163 QString HolidayRegion::regionCode() const
00164 {
00165   return d->mRegionCode;
00166 }
00167 
00168 QString HolidayRegion::countryCode() const
00169 {
00170   return d->mDriver->fileCountryCode();
00171 }
00172 
00173 QString HolidayRegion::countryCode( const QString &regionCode )
00174 {
00175   HolidayRegion temp = HolidayRegion( regionCode );
00176   if ( temp.isValid() ) {
00177     return temp.countryCode();
00178   } else {
00179     return QString();
00180   }
00181 }
00182 
00183 QString HolidayRegion::languageCode() const
00184 {
00185   return d->mDriver->fileLanguageCode();
00186 }
00187 
00188 QString HolidayRegion::languageCode( const QString &regionCode )
00189 {
00190   HolidayRegion temp = HolidayRegion( regionCode );
00191   if ( temp.isValid() ) {
00192     return temp.languageCode();
00193   } else {
00194     return QString();
00195   }
00196 }
00197 
00198 QString HolidayRegion::name() const
00199 {
00200   QString tempName = d->mDriver->fileName();
00201 
00202   if ( tempName.isEmpty() ) {
00203     QStringList countryParts = countryCode().toLower().split( '-' );
00204     QString country = countryParts.at( 0 );
00205     QString regionName, typeName;
00206 
00207     if ( country != "xx" ) {
00208       if ( countryParts.count() == 2 ) {
00209         // Temporary measure to get regions translated, only those files that already exist
00210         // In 4.6 hope to have isocodes project integration for translations via KLocale
00211         QString subdivision = countryParts.at( 1 );
00212         if ( country == "ca" && subdivision == "qc" ) {
00213           regionName = i18nc( "Canadian region", "Quebec" );
00214         } else if ( country == "de" && subdivision == "by" ) {
00215           regionName = i18nc( "German region", "Bavaria" );
00216         } else if ( country == "es" && subdivision == "ct" ) {
00217           regionName = i18nc( "Spanish region", "Catalonia" );
00218         } else if ( country == "gb" && subdivision == "eaw" ) {
00219           regionName = i18nc( "UK Region", "England and Wales" );
00220         } else if ( country == "gb" && subdivision == "eng" ) {
00221           regionName = i18nc( "UK Region", "England" );
00222         } else if ( country == "gb" && subdivision == "wls" ) {
00223           regionName = i18nc( "UK Region", "Wales" );
00224         } else if ( country == "gb" && subdivision == "sct" ) {
00225           regionName = i18nc( "UK Region", "Scotland" );
00226         } else if ( country == "gb" && subdivision == "nir" ) {
00227           regionName = i18nc( "UK Region", "Northern Ireland" );
00228         } else if ( country == "it" && subdivision == "bz" ) {
00229           regionName = i18nc( "Italian Region", "South Tyrol" );
00230         } else if ( country == "au" && subdivision == "nsw" ) {
00231           regionName = i18nc( "Australian Region", "New South Wales" );
00232         } else if ( country == "au" && subdivision == "qld" ) {
00233           regionName = i18nc( "Australian Region", "Queensland" );
00234         } else if ( country == "au" && subdivision == "vic" ) {
00235           regionName = i18nc( "Australian Region", "Victoria" );
00236         } else if ( country == "au" && subdivision == "sa" ) {
00237           regionName = i18nc( "Australian Region", "South Australia" );
00238         } else if ( country == "au" && subdivision == "nt" ) {
00239           regionName = i18nc( "Australian Region", "Northern Territory" );
00240         } else if ( country == "au" && subdivision == "act" ) {
00241           regionName = i18nc( "Australian Region", "Australian Capital Territory" );
00242         } else if ( country == "au" && subdivision == "wa" ) {
00243           regionName = i18nc( "Australian Region", "Western Australia" );
00244         } else if ( country == "au" && subdivision == "tas" ) {
00245           regionName = i18nc( "Australian Region", "Tasmania" );
00246         } else {
00247           regionName = KGlobal::locale()->countryCodeToName( country );
00248         }
00249       } else {
00250           regionName = KGlobal::locale()->countryCodeToName( country );
00251       }
00252     }
00253 
00254     //Cheat on type for now,take direct from region code until API is introduced in SC 4.6
00255     QStringList regionParts = regionCode().toLower().split( '_' );
00256     if ( regionParts.count() == 3 ) {
00257       QString type = regionParts.at( 2 );
00258       // Will create lots more in 4.6
00259       // Religious types, just simple for now
00260       if ( type == "public" ) {
00261         typeName = i18nc( "Holiday type", "Public" );
00262       } else if ( type == "religious" ) {
00263         typeName = i18nc( "Holiday type", "Religious" );
00264       } else if ( type == "financial" ) {
00265         typeName = i18nc( "Holiday type", "Financial" );
00266       } else if ( type == "cultural" ) {
00267         typeName = i18nc( "Holiday type", "Cultural" );
00268       } else if ( type == "school" ) {
00269         typeName = i18nc( "Holiday type", "School" );
00270       } else if ( type == "seasons" ) {
00271         typeName = i18nc( "Holiday type", "Seasons" );
00272       } else if ( type == "name" ) {
00273         typeName = i18nc( "Holiday type", "Name Days" );
00274       } else if ( type == "personal" ) {
00275         typeName = i18nc( "Holiday type", "Personal" );
00276       } else if ( type == "catholic" ) {
00277         typeName = i18nc( "Holiday type", "Catholic" );
00278       } else if ( type == "protestant" ) {
00279         typeName = i18nc( "Holiday type", "Protestant" );
00280       } else if ( type == "orthodox" ) {
00281         typeName = i18nc( "Holiday type", "Orthodox" );
00282       } else if ( type == "jewish" ) {
00283         typeName = i18nc( "Holiday type", "Jewish" );
00284       } else if ( type == "islamic" ) {
00285         typeName = i18nc( "Holiday type", "Islamic" );
00286       }
00287     }
00288 
00289     if ( !regionName.isEmpty() ) {
00290       if ( !typeName.isEmpty() ) {
00291         //TODO translate when not frozen
00292         tempName = QString( "%1 - %2" ).arg( regionName ).arg( typeName );
00293       } else {
00294         tempName = regionName;
00295       }
00296     } else if ( !typeName.isEmpty() ) {
00297       tempName = typeName;
00298     } else {
00299       tempName = i18nc( "Unknown holiday region", "Unknown" );
00300     }
00301   }
00302   return tempName;
00303 }
00304 
00305 QString HolidayRegion::name( const QString &regionCode )
00306 {
00307   HolidayRegion temp = HolidayRegion( regionCode );
00308   if ( temp.isValid() ) {
00309     return temp.name();
00310   } else {
00311     return QString();
00312   }
00313 }
00314 
00315 QString HolidayRegion::description() const
00316 {
00317   return d->mDriver->fileDescription();
00318 }
00319 
00320 QString HolidayRegion::description( const QString &regionCode )
00321 {
00322   HolidayRegion temp = HolidayRegion( regionCode );
00323   if ( temp.isValid() ) {
00324     return temp.description();
00325   } else {
00326     return QString();
00327   }
00328 }
00329 
00330 bool HolidayRegion::isValid() const
00331 {
00332   return d->mHolidayFile.exists() && d->mDriver;
00333 }
00334 
00335 bool HolidayRegion::isValid( const QString &regionCode )
00336 {
00337   HolidayRegion temp = HolidayRegion( regionCode );
00338   return temp.isValid();
00339 }
00340 
00341 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate ) const
00342 {
00343   return holidays( startDate, endDate, Holiday::MultidayHolidaysAsMultipleEvents );
00344 }
00345 
00346 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate,
00347                                        Holiday::MultidayMode multidayMode ) const
00348 {
00349   if ( isValid() ) {
00350     return d->mDriver->parseHolidays( startDate, endDate, multidayMode );
00351   } else {
00352     return Holiday::List();
00353   }
00354 }
00355 
00356 Holiday::List HolidayRegion::holidays( const QDate &date ) const
00357 {
00358   return holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
00359 }
00360 
00361 Holiday::List HolidayRegion::holidays( const QDate &date, Holiday::MultidayMode multidayMode ) const
00362 {
00363   if ( isValid() ) {
00364     return d->mDriver->parseHolidays( date, multidayMode );
00365   } else {
00366     return Holiday::List();
00367   }
00368 }
00369 
00370 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType ) const
00371 {
00372   return holidays( calendarYear, calendarType, Holiday::MultidayHolidaysAsMultipleEvents );
00373 }
00374 
00375 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType,
00376                                        Holiday::MultidayMode multidayMode ) const
00377 {
00378   if ( isValid() ) {
00379     return d->mDriver->parseHolidays( calendarYear, calendarType, multidayMode );
00380   } else {
00381     return Holiday::List();
00382   }
00383 }
00384 
00385 bool HolidayRegion::isHoliday( const QDate &date ) const
00386 {
00387   Holiday::List holidayList = holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
00388   if ( holidayList.count() > 0 ) {
00389     foreach ( const KHolidays::Holiday &holiday, holidayList ) {
00390       if ( holiday.dayType() == Holiday::NonWorkday ) {
00391         return true;
00392       }
00393     }
00394   }
00395   return false;
00396 }
00397 
00398 QString HolidayRegion::defaultRegionCode( const QString &country, const QString &language )
00399 {
00400   // Try to match against the users country and language, or failing that the language country.
00401   // Scan through all the regions finding the first match for each possible default
00402   // Holiday Region Country Code can be a country subdivision or the country itself,
00403   // e.g. US or US-CA for California, so we can try match on both but an exact match has priority
00404   // The Holiday Region file is in one language only, so give priority to any file in the
00405   // users language, e.g. bilingual countries with a separate file for each language
00406   // Locale language can have a country code embedded in it e.g. en_GB, which we can try use if
00407   // no country set, but a lot of countries use en_GB so it's a lower priority option
00408 
00409   QString localeCountry, localeLanguage, localeLanguageCountry;
00410 
00411   if ( country.isEmpty() ) {
00412     localeCountry = KGlobal::locale()->country().toLower();
00413   } else {
00414     localeCountry = country.toLower();
00415   }
00416 
00417   if ( language.isEmpty() ) {
00418     localeLanguage = KGlobal::locale()->language().toLower();
00419   } else {
00420     localeLanguage = language.toLower();
00421   }
00422 
00423   if ( localeLanguage.split('_').count() > 1 ) {
00424     localeLanguageCountry = localeLanguage.split( '_' ).at( 1 );
00425   }
00426 
00427   QStringList regionList = KHolidays::HolidayRegion::regionCodes();
00428 
00429   QString countryAndLanguageMatch, countryOnlyMatch, subdivisionAndLanguageMatch,
00430           subdivisionOnlyMatch, languageCountryAndLanguageMatch, languageCountryOnlyMatch,
00431           languageSubdivisionAndLanguageMatch, languageSubdivisionOnlyMatch;
00432 
00433   foreach ( const QString &regionCode, regionList ) {
00434     QString regionCountry = KHolidays::HolidayRegion::countryCode( regionCode ).toLower();
00435     QString regionSubdivisionCountry;
00436     if ( regionCountry.split( '-' ).count() > 1 ) {
00437       regionSubdivisionCountry = regionCountry.split( '-' ).at( 0 );
00438     }
00439     QString regionLanguage = KHolidays::HolidayRegion::languageCode( regionCode ).toLower();
00440 
00441     if ( regionCountry == localeCountry && regionLanguage == localeLanguage ) {
00442       countryAndLanguageMatch = regionCode;
00443       break; // exact match so don't look further
00444     } else if ( regionCountry == localeCountry ) {
00445       if ( countryOnlyMatch.isEmpty() ) {
00446         countryOnlyMatch = regionCode;
00447       }
00448     } else if ( !regionSubdivisionCountry.isEmpty() &&
00449                 regionSubdivisionCountry == localeCountry &&
00450                 regionLanguage == localeLanguage ) {
00451       if ( subdivisionAndLanguageMatch.isEmpty() ) {
00452         subdivisionAndLanguageMatch = regionCode;
00453       }
00454     } else if ( !regionSubdivisionCountry.isEmpty() && regionSubdivisionCountry == localeCountry ) {
00455       if ( subdivisionOnlyMatch.isEmpty() ) {
00456         subdivisionOnlyMatch = regionCode;
00457       }
00458     } else if ( !localeLanguageCountry.isEmpty() &&
00459                 regionCountry == localeLanguageCountry &&
00460                 regionLanguage == localeLanguage ) {
00461       if ( languageCountryAndLanguageMatch.isEmpty() ) {
00462         languageCountryAndLanguageMatch = regionCode;
00463       }
00464     } else if ( !localeLanguageCountry.isEmpty() && regionCountry == localeLanguageCountry ) {
00465       if ( languageCountryOnlyMatch.isEmpty() ) {
00466         languageCountryOnlyMatch = regionCode;
00467       }
00468     } else if ( !regionSubdivisionCountry.isEmpty() &&
00469                 !localeLanguageCountry.isEmpty() &&
00470                 regionSubdivisionCountry == localeLanguageCountry &&
00471                 regionLanguage == localeLanguage ) {
00472       if ( languageSubdivisionAndLanguageMatch.isEmpty() ) {
00473         languageSubdivisionAndLanguageMatch = regionCode;
00474       }
00475     } else if ( !regionSubdivisionCountry.isEmpty() &&
00476                 !localeLanguageCountry.isEmpty() &&
00477                 regionSubdivisionCountry == localeLanguageCountry ) {
00478       if ( languageSubdivisionOnlyMatch.isEmpty() ) {
00479         languageSubdivisionOnlyMatch = regionCode;
00480       }
00481     }
00482   }
00483 
00484   QString defaultRegionCode;
00485 
00486   if ( !countryAndLanguageMatch.isEmpty() ) {
00487     defaultRegionCode = countryAndLanguageMatch;
00488   } else if ( !countryOnlyMatch.isEmpty() ) {
00489     defaultRegionCode = countryOnlyMatch;
00490   } else if ( !subdivisionAndLanguageMatch.isEmpty() ) {
00491     defaultRegionCode = subdivisionAndLanguageMatch;
00492   } else if ( !subdivisionOnlyMatch.isEmpty() ) {
00493     defaultRegionCode = subdivisionOnlyMatch;
00494   } else if ( !languageCountryAndLanguageMatch.isEmpty() ) {
00495     defaultRegionCode = languageCountryAndLanguageMatch;
00496   } else if ( !languageCountryOnlyMatch.isEmpty() ) {
00497     defaultRegionCode = languageCountryOnlyMatch;
00498   } else if ( !languageSubdivisionAndLanguageMatch.isEmpty() ) {
00499     defaultRegionCode = languageSubdivisionAndLanguageMatch;
00500   } else if ( !languageSubdivisionOnlyMatch.isEmpty() ) {
00501     defaultRegionCode = languageSubdivisionOnlyMatch;
00502   }
00503 
00504   return defaultRegionCode;
00505 }

KHolidays Library

Skip menu "KHolidays Library"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal