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

KHolidays Library

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • 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.6.1
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