• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.3 API Reference
  • 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 if ( country == "ba" && subdivision == "srp" ) {
00248           regionName = i18nc( "Bosnian and Herzegovinian Region", "Republic of Srpska" );
00249         } else {
00250           regionName = KGlobal::locale()->countryCodeToName( country );
00251         }
00252       } else {
00253           regionName = KGlobal::locale()->countryCodeToName( country );
00254       }
00255     }
00256 
00257     //Cheat on type for now,take direct from region code until API is introduced in SC 4.6
00258     QStringList regionParts = regionCode().toLower().split( '_' );
00259     if ( regionParts.count() == 3 ) {
00260       QString type = regionParts.at( 2 );
00261       // Will create lots more in 4.6
00262       // Religious types, just simple for now
00263       if ( type == "public" ) {
00264         typeName = i18nc( "Holiday type", "Public" );
00265       } else if ( type == "religious" ) {
00266         typeName = i18nc( "Holiday type", "Religious" );
00267       } else if ( type == "financial" ) {
00268         typeName = i18nc( "Holiday type", "Financial" );
00269       } else if ( type == "cultural" ) {
00270         typeName = i18nc( "Holiday type", "Cultural" );
00271       } else if ( type == "school" ) {
00272         typeName = i18nc( "Holiday type", "School" );
00273       } else if ( type == "seasons" ) {
00274         typeName = i18nc( "Holiday type", "Seasons" );
00275       } else if ( type == "name" ) {
00276         typeName = i18nc( "Holiday type", "Name Days" );
00277       } else if ( type == "personal" ) {
00278         typeName = i18nc( "Holiday type", "Personal" );
00279       } else if ( type == "catholic" ) {
00280         typeName = i18nc( "Holiday type", "Catholic" );
00281       } else if ( type == "protestant" ) {
00282         typeName = i18nc( "Holiday type", "Protestant" );
00283       } else if ( type == "orthodox" ) {
00284         typeName = i18nc( "Holiday type", "Orthodox" );
00285       } else if ( type == "jewish" ) {
00286         typeName = i18nc( "Holiday type", "Jewish" );
00287       } else if ( type == "islamic" ) {
00288         typeName = i18nc( "Holiday type", "Islamic" );
00289       }
00290     }
00291 
00292     if ( !regionName.isEmpty() ) {
00293       if ( !typeName.isEmpty() ) {
00294         //TODO translate when not frozen
00295         tempName = QString( "%1 - %2" ).arg( regionName ).arg( typeName );
00296       } else {
00297         tempName = regionName;
00298       }
00299     } else if ( !typeName.isEmpty() ) {
00300       tempName = typeName;
00301     } else {
00302       tempName = i18nc( "Unknown holiday region", "Unknown" );
00303     }
00304   }
00305   return tempName;
00306 }
00307 
00308 QString HolidayRegion::name( const QString &regionCode )
00309 {
00310   HolidayRegion temp = HolidayRegion( regionCode );
00311   if ( temp.isValid() ) {
00312     return temp.name();
00313   } else {
00314     return QString();
00315   }
00316 }
00317 
00318 QString HolidayRegion::description() const
00319 {
00320   return d->mDriver->fileDescription();
00321 }
00322 
00323 QString HolidayRegion::description( const QString &regionCode )
00324 {
00325   HolidayRegion temp = HolidayRegion( regionCode );
00326   if ( temp.isValid() ) {
00327     return temp.description();
00328   } else {
00329     return QString();
00330   }
00331 }
00332 
00333 bool HolidayRegion::isValid() const
00334 {
00335   return d->mHolidayFile.exists() && d->mDriver;
00336 }
00337 
00338 bool HolidayRegion::isValid( const QString &regionCode )
00339 {
00340   HolidayRegion temp = HolidayRegion( regionCode );
00341   return temp.isValid();
00342 }
00343 
00344 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate ) const
00345 {
00346   return holidays( startDate, endDate, Holiday::MultidayHolidaysAsMultipleEvents );
00347 }
00348 
00349 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate,
00350                                        Holiday::MultidayMode multidayMode ) const
00351 {
00352   if ( isValid() ) {
00353     return d->mDriver->parseHolidays( startDate, endDate, multidayMode );
00354   } else {
00355     return Holiday::List();
00356   }
00357 }
00358 
00359 Holiday::List HolidayRegion::holidays( const QDate &date ) const
00360 {
00361   return holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
00362 }
00363 
00364 Holiday::List HolidayRegion::holidays( const QDate &date, Holiday::MultidayMode multidayMode ) const
00365 {
00366   if ( isValid() ) {
00367     return d->mDriver->parseHolidays( date, multidayMode );
00368   } else {
00369     return Holiday::List();
00370   }
00371 }
00372 
00373 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType ) const
00374 {
00375   return holidays( calendarYear, calendarType, Holiday::MultidayHolidaysAsMultipleEvents );
00376 }
00377 
00378 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType,
00379                                        Holiday::MultidayMode multidayMode ) const
00380 {
00381   if ( isValid() ) {
00382     return d->mDriver->parseHolidays( calendarYear, calendarType, multidayMode );
00383   } else {
00384     return Holiday::List();
00385   }
00386 }
00387 
00388 bool HolidayRegion::isHoliday( const QDate &date ) const
00389 {
00390   Holiday::List holidayList = holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
00391   if ( holidayList.count() > 0 ) {
00392     foreach ( const KHolidays::Holiday &holiday, holidayList ) {
00393       if ( holiday.dayType() == Holiday::NonWorkday ) {
00394         return true;
00395       }
00396     }
00397   }
00398   return false;
00399 }
00400 
00401 QString HolidayRegion::defaultRegionCode( const QString &country, const QString &language )
00402 {
00403   // Try to match against the users country and language, or failing that the language country.
00404   // Scan through all the regions finding the first match for each possible default
00405   // Holiday Region Country Code can be a country subdivision or the country itself,
00406   // e.g. US or US-CA for California, so we can try match on both but an exact match has priority
00407   // The Holiday Region file is in one language only, so give priority to any file in the
00408   // users language, e.g. bilingual countries with a separate file for each language
00409   // Locale language can have a country code embedded in it e.g. en_GB, which we can try use if
00410   // no country set, but a lot of countries use en_GB so it's a lower priority option
00411 
00412   QString localeCountry, localeLanguage, localeLanguageCountry;
00413 
00414   if ( country.isEmpty() ) {
00415     localeCountry = KGlobal::locale()->country().toLower();
00416   } else {
00417     localeCountry = country.toLower();
00418   }
00419 
00420   if ( language.isEmpty() ) {
00421     localeLanguage = KGlobal::locale()->language().toLower();
00422   } else {
00423     localeLanguage = language.toLower();
00424   }
00425 
00426   if ( localeLanguage.split( '_' ).count() > 1 ) {
00427     localeLanguageCountry = localeLanguage.split( '_' ).at( 1 );
00428   }
00429 
00430   QStringList regionList = KHolidays::HolidayRegion::regionCodes();
00431 
00432   QString countryAndLanguageMatch, countryOnlyMatch, subdivisionAndLanguageMatch,
00433           subdivisionOnlyMatch, languageCountryAndLanguageMatch, languageCountryOnlyMatch,
00434           languageSubdivisionAndLanguageMatch, languageSubdivisionOnlyMatch;
00435 
00436   foreach ( const QString &regionCode, regionList ) {
00437     QString regionCountry = KHolidays::HolidayRegion::countryCode( regionCode ).toLower();
00438     QString regionSubdivisionCountry;
00439     if ( regionCountry.split( '-' ).count() > 1 ) {
00440       regionSubdivisionCountry = regionCountry.split( '-' ).at( 0 );
00441     }
00442     QString regionLanguage = KHolidays::HolidayRegion::languageCode( regionCode ).toLower();
00443 
00444     if ( regionCountry == localeCountry && regionLanguage == localeLanguage ) {
00445       countryAndLanguageMatch = regionCode;
00446       break; // exact match so don't look further
00447     } else if ( regionCountry == localeCountry ) {
00448       if ( countryOnlyMatch.isEmpty() ) {
00449         countryOnlyMatch = regionCode;
00450       }
00451     } else if ( !regionSubdivisionCountry.isEmpty() &&
00452                 regionSubdivisionCountry == localeCountry &&
00453                 regionLanguage == localeLanguage ) {
00454       if ( subdivisionAndLanguageMatch.isEmpty() ) {
00455         subdivisionAndLanguageMatch = regionCode;
00456       }
00457     } else if ( !regionSubdivisionCountry.isEmpty() && regionSubdivisionCountry == localeCountry ) {
00458       if ( subdivisionOnlyMatch.isEmpty() ) {
00459         subdivisionOnlyMatch = regionCode;
00460       }
00461     } else if ( !localeLanguageCountry.isEmpty() &&
00462                 regionCountry == localeLanguageCountry &&
00463                 regionLanguage == localeLanguage ) {
00464       if ( languageCountryAndLanguageMatch.isEmpty() ) {
00465         languageCountryAndLanguageMatch = regionCode;
00466       }
00467     } else if ( !localeLanguageCountry.isEmpty() && regionCountry == localeLanguageCountry ) {
00468       if ( languageCountryOnlyMatch.isEmpty() ) {
00469         languageCountryOnlyMatch = regionCode;
00470       }
00471     } else if ( !regionSubdivisionCountry.isEmpty() &&
00472                 !localeLanguageCountry.isEmpty() &&
00473                 regionSubdivisionCountry == localeLanguageCountry &&
00474                 regionLanguage == localeLanguage ) {
00475       if ( languageSubdivisionAndLanguageMatch.isEmpty() ) {
00476         languageSubdivisionAndLanguageMatch = regionCode;
00477       }
00478     } else if ( !regionSubdivisionCountry.isEmpty() &&
00479                 !localeLanguageCountry.isEmpty() &&
00480                 regionSubdivisionCountry == localeLanguageCountry ) {
00481       if ( languageSubdivisionOnlyMatch.isEmpty() ) {
00482         languageSubdivisionOnlyMatch = regionCode;
00483       }
00484     }
00485   }
00486 
00487   QString defaultRegionCode;
00488 
00489   if ( !countryAndLanguageMatch.isEmpty() ) {
00490     defaultRegionCode = countryAndLanguageMatch;
00491   } else if ( !countryOnlyMatch.isEmpty() ) {
00492     defaultRegionCode = countryOnlyMatch;
00493   } else if ( !subdivisionAndLanguageMatch.isEmpty() ) {
00494     defaultRegionCode = subdivisionAndLanguageMatch;
00495   } else if ( !subdivisionOnlyMatch.isEmpty() ) {
00496     defaultRegionCode = subdivisionOnlyMatch;
00497   } else if ( !languageCountryAndLanguageMatch.isEmpty() ) {
00498     defaultRegionCode = languageCountryAndLanguageMatch;
00499   } else if ( !languageCountryOnlyMatch.isEmpty() ) {
00500     defaultRegionCode = languageCountryOnlyMatch;
00501   } else if ( !languageSubdivisionAndLanguageMatch.isEmpty() ) {
00502     defaultRegionCode = languageSubdivisionAndLanguageMatch;
00503   } else if ( !languageSubdivisionOnlyMatch.isEmpty() ) {
00504     defaultRegionCode = languageSubdivisionOnlyMatch;
00505   }
00506 
00507   return defaultRegionCode;
00508 }
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

KDE's Doxygen guidelines are available online.

KHolidays Library

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

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal