• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KHolidays Library

  • kholidays
holidayregion.cpp
1 /*
2  This file is part of the kholidays library.
3 
4  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (c) 2004 Allen Winter <winter@kde.org>
6  Copyright (c) 2008 David Jarvie <djarvie@kde.org>
7  Copyright 2010 John Layt <john@layt.net>
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Library General Public
11  License as published by the Free Software Foundation; either
12  version 2 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Library General Public License for more details.
18 
19  You should have received a copy of the GNU Library General Public License
20  along with this library; see the file COPYING.LIB. If not, write to the
21  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  Boston, MA 02110-1301, USA.
23 */
24 
25 #include "holidayregion.h"
26 
27 #include <QtCore/QDateTime>
28 #include <QtCore/QFile>
29 #include <QtCore/QSharedData>
30 #include <QtCore/QFileInfo>
31 
32 #include <KStandardDirs>
33 #include <KGlobal>
34 #include <KLocale>
35 #include <KDebug>
36 
37 #include "holiday_p.h"
38 #include "parsers/plan2/holidayparserdriverplan_p.h"
39 
40 using namespace KHolidays;
41 
42 class HolidayRegion::Private
43 {
44  public:
45  Private( const QString &regionCode ) : mDriver( 0 ),
46  mRegionCode( regionCode )
47  {
48  if ( !mRegionCode.isEmpty() ) {
49 
50  if ( mRegionCode.length() == 2 ) { //Backwards compatible mode for old location code
51  mLocation = mRegionCode;
52  QStringList locationFiles = KGlobal::dirs()->findAllResources( "data",
53  "libkholidays/plan2/holiday_" + mLocation + '*',
54  KStandardDirs::NoDuplicates );
55  if ( locationFiles.count() > 0 ) {
56  mRegionCode = locationFiles.at( 0 ).
57  mid( locationFiles.at( 0 ).lastIndexOf( "holiday_" ) + 8 );
58  }
59  }
60 
61  mHolidayFile.setFile(
62  KStandardDirs::locate( "data", "libkholidays/plan2/holiday_" + mRegionCode ) );
63  }
64 
65  init();
66  }
67 
68  Private( const QFileInfo &regionFile ) : mDriver( 0 ),
69  mHolidayFile( regionFile )
70  {
71  init();
72  }
73 
74  ~Private()
75  {
76  delete mDriver;
77  }
78 
79  void init()
80  {
81  if ( mHolidayFile.exists() ) {
82  mDriver = new HolidayParserDriverPlan( mHolidayFile.absoluteFilePath() );
83  if ( mDriver ) {
84 
85  if ( mLocation.isEmpty() ) {
86  mLocation = mDriver->fileCountryCode().left( 2 );
87  }
88 
89  if ( mRegionCode.isEmpty() ) {
90  if ( mHolidayFile.fileName().startsWith( QLatin1String( "holiday_" ) ) ) {
91  mRegionCode = mHolidayFile.fileName().mid( 8 );
92  } else {
93  mRegionCode = mHolidayFile.fileName();
94  }
95  }
96 
97  } else {
98  mRegionCode.clear();
99  mLocation.clear();
100  }
101  } else {
102  mRegionCode.clear();
103  mLocation.clear();
104  }
105  }
106 
107  HolidayParserDriver *mDriver; // The parser driver for the holiday file
108  QString mRegionCode; // region code of holiday region
109  QString mLocation; // old location code, use now deprecated
110  QFileInfo mHolidayFile; // file containing holiday data, or null
111 };
112 
113 HolidayRegion::HolidayRegion( const QString &regionCode )
114  : d( new Private( regionCode ) )
115 {
116 }
117 
118 HolidayRegion::HolidayRegion( const QFileInfo &regionFile )
119  : d( new Private( regionFile ) )
120 {
121 }
122 
123 HolidayRegion::~HolidayRegion()
124 {
125  delete d;
126 }
127 
128 QStringList HolidayRegion::locations()
129 {
130  const QStringList files =
131  KGlobal::dirs()->findAllResources( "data", "libkholidays/plan2/holiday_*",
132  KStandardDirs::NoDuplicates );
133 
134  QStringList locations;
135  foreach ( const QString &filename, files ) {
136  locations.append( filename.mid( filename.lastIndexOf( "holiday_" ) + 8, 2 ) );
137  }
138 
139  locations.removeDuplicates();
140  qSort( locations );
141  return locations;
142 }
143 
144 QString HolidayRegion::location() const
145 {
146  return d->mLocation;
147 }
148 
149 QStringList HolidayRegion::regionCodes()
150 {
151  const QStringList files =
152  KGlobal::dirs()->findAllResources( "data", "libkholidays/plan2/holiday_*",
153  KStandardDirs::NoDuplicates );
154 
155  QStringList regionCodesList;
156  foreach ( const QString &filename, files ) {
157  regionCodesList.append( filename.mid( filename.lastIndexOf( "holiday_" ) + 8 ) );
158  }
159 
160  qSort( regionCodesList );
161  return regionCodesList;
162 }
163 
164 QString HolidayRegion::regionCode() const
165 {
166  return d->mRegionCode;
167 }
168 
169 QString HolidayRegion::countryCode() const
170 {
171  return d->mDriver->fileCountryCode();
172 }
173 
174 QString HolidayRegion::countryCode( const QString &regionCode )
175 {
176  HolidayRegion temp = HolidayRegion( regionCode );
177  if ( temp.isValid() ) {
178  return temp.countryCode();
179  } else {
180  return QString();
181  }
182 }
183 
184 QString HolidayRegion::languageCode() const
185 {
186  return d->mDriver->fileLanguageCode();
187 }
188 
189 QString HolidayRegion::languageCode( const QString &regionCode )
190 {
191  HolidayRegion temp = HolidayRegion( regionCode );
192  if ( temp.isValid() ) {
193  return temp.languageCode();
194  } else {
195  return QString();
196  }
197 }
198 
199 QString HolidayRegion::name() const
200 {
201  QString tempName = d->mDriver->fileName();
202 
203  if ( tempName.isEmpty() ) {
204  QStringList countryParts = countryCode().toLower().split( '-' );
205  QString country = countryParts.at( 0 );
206  QString regionName, typeName;
207 
208  if ( country != "xx" ) {
209  if ( countryParts.count() == 2 ) {
210  // Temporary measure to get regions translated, only those files that already exist
211  // In 4.6 hope to have isocodes project integration for translations via KLocale
212  QString subdivision = countryParts.at( 1 );
213  if ( country == "ca" && subdivision == "qc" ) {
214  regionName = i18nc( "Canadian region", "Quebec" );
215  } else if ( country == "de" && subdivision == "by" ) {
216  regionName = i18nc( "German region", "Bavaria" );
217  } else if ( country == "es" && subdivision == "ct" ) {
218  regionName = i18nc( "Spanish region", "Catalonia" );
219  } else if ( country == "gb" && subdivision == "eaw" ) {
220  regionName = i18nc( "UK Region", "England and Wales" );
221  } else if ( country == "gb" && subdivision == "eng" ) {
222  regionName = i18nc( "UK Region", "England" );
223  } else if ( country == "gb" && subdivision == "wls" ) {
224  regionName = i18nc( "UK Region", "Wales" );
225  } else if ( country == "gb" && subdivision == "sct" ) {
226  regionName = i18nc( "UK Region", "Scotland" );
227  } else if ( country == "gb" && subdivision == "nir" ) {
228  regionName = i18nc( "UK Region", "Northern Ireland" );
229  } else if ( country == "it" && subdivision == "bz" ) {
230  regionName = i18nc( "Italian Region", "South Tyrol" );
231  } else if ( country == "au" && subdivision == "nsw" ) {
232  regionName = i18nc( "Australian Region", "New South Wales" );
233  } else if ( country == "au" && subdivision == "qld" ) {
234  regionName = i18nc( "Australian Region", "Queensland" );
235  } else if ( country == "au" && subdivision == "vic" ) {
236  regionName = i18nc( "Australian Region", "Victoria" );
237  } else if ( country == "au" && subdivision == "sa" ) {
238  regionName = i18nc( "Australian Region", "South Australia" );
239  } else if ( country == "au" && subdivision == "nt" ) {
240  regionName = i18nc( "Australian Region", "Northern Territory" );
241  } else if ( country == "au" && subdivision == "act" ) {
242  regionName = i18nc( "Australian Region", "Australian Capital Territory" );
243  } else if ( country == "au" && subdivision == "wa" ) {
244  regionName = i18nc( "Australian Region", "Western Australia" );
245  } else if ( country == "au" && subdivision == "tas" ) {
246  regionName = i18nc( "Australian Region", "Tasmania" );
247  } else if ( country == "ba" && subdivision == "srp" ) {
248  regionName = i18nc( "Bosnian and Herzegovinian Region", "Republic of Srpska" );
249  } else {
250  regionName = KGlobal::locale()->countryCodeToName( country );
251  }
252  } else {
253  regionName = KGlobal::locale()->countryCodeToName( country );
254  }
255  }
256 
257  //Cheat on type for now,take direct from region code until API is introduced in SC 4.6
258  QStringList regionParts = regionCode().toLower().split( '_' );
259  if ( regionParts.count() == 3 ) {
260  QString type = regionParts.at( 2 );
261  // Will create lots more in 4.6
262  // Religious types, just simple for now
263  if ( type == "public" ) {
264  typeName = i18nc( "Holiday type", "Public" );
265  } else if ( type == "religious" ) {
266  typeName = i18nc( "Holiday type", "Religious" );
267  } else if ( type == "financial" ) {
268  typeName = i18nc( "Holiday type", "Financial" );
269  } else if ( type == "cultural" ) {
270  typeName = i18nc( "Holiday type", "Cultural" );
271  } else if ( type == "school" ) {
272  typeName = i18nc( "Holiday type", "School" );
273  } else if ( type == "seasons" ) {
274  typeName = i18nc( "Holiday type", "Seasons" );
275  } else if ( type == "name" ) {
276  typeName = i18nc( "Holiday type", "Name Days" );
277  } else if ( type == "personal" ) {
278  typeName = i18nc( "Holiday type", "Personal" );
279  } else if ( type == "catholic" ) {
280  typeName = i18nc( "Holiday type", "Catholic" );
281  } else if ( type == "protestant" ) {
282  typeName = i18nc( "Holiday type", "Protestant" );
283  } else if ( type == "orthodox" ) {
284  typeName = i18nc( "Holiday type", "Orthodox" );
285  } else if ( type == "jewish" ) {
286  typeName = i18nc( "Holiday type", "Jewish" );
287  } else if ( type == "islamic" ) {
288  typeName = i18nc( "Holiday type", "Islamic" );
289  }
290  }
291 
292  if ( !regionName.isEmpty() ) {
293  if ( !typeName.isEmpty() ) {
294  //TODO translate when not frozen
295  tempName = QString( "%1 - %2" ).arg( regionName ).arg( typeName );
296  } else {
297  tempName = regionName;
298  }
299  } else if ( !typeName.isEmpty() ) {
300  tempName = typeName;
301  } else {
302  tempName = i18nc( "Unknown holiday region", "Unknown" );
303  }
304  }
305  return tempName;
306 }
307 
308 QString HolidayRegion::name( const QString &regionCode )
309 {
310  HolidayRegion temp = HolidayRegion( regionCode );
311  if ( temp.isValid() ) {
312  return temp.name();
313  } else {
314  return QString();
315  }
316 }
317 
318 QString HolidayRegion::description() const
319 {
320  return d->mDriver->fileDescription();
321 }
322 
323 QString HolidayRegion::description( const QString &regionCode )
324 {
325  HolidayRegion temp = HolidayRegion( regionCode );
326  if ( temp.isValid() ) {
327  return temp.description();
328  } else {
329  return QString();
330  }
331 }
332 
333 bool HolidayRegion::isValid() const
334 {
335  return d->mHolidayFile.exists() && d->mDriver;
336 }
337 
338 bool HolidayRegion::isValid( const QString &regionCode )
339 {
340  HolidayRegion temp = HolidayRegion( regionCode );
341  return temp.isValid();
342 }
343 
344 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate ) const
345 {
346  return holidays( startDate, endDate, Holiday::MultidayHolidaysAsMultipleEvents );
347 }
348 
349 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate,
350  Holiday::MultidayMode multidayMode ) const
351 {
352  if ( isValid() ) {
353  return d->mDriver->parseHolidays( startDate, endDate, multidayMode );
354  } else {
355  return Holiday::List();
356  }
357 }
358 
359 Holiday::List HolidayRegion::holidays( const QDate &date ) const
360 {
361  return holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
362 }
363 
364 Holiday::List HolidayRegion::holidays( const QDate &date, Holiday::MultidayMode multidayMode ) const
365 {
366  if ( isValid() ) {
367  return d->mDriver->parseHolidays( date, multidayMode );
368  } else {
369  return Holiday::List();
370  }
371 }
372 
373 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType ) const
374 {
375  return holidays( calendarYear, calendarType, Holiday::MultidayHolidaysAsMultipleEvents );
376 }
377 
378 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType,
379  Holiday::MultidayMode multidayMode ) const
380 {
381  if ( isValid() ) {
382  return d->mDriver->parseHolidays( calendarYear, calendarType, multidayMode );
383  } else {
384  return Holiday::List();
385  }
386 }
387 
388 bool HolidayRegion::isHoliday( const QDate &date ) const
389 {
390  Holiday::List holidayList = holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
391  if ( holidayList.count() > 0 ) {
392  foreach ( const KHolidays::Holiday &holiday, holidayList ) {
393  if ( holiday.dayType() == Holiday::NonWorkday ) {
394  return true;
395  }
396  }
397  }
398  return false;
399 }
400 
401 QString HolidayRegion::defaultRegionCode( const QString &country, const QString &language )
402 {
403  // Try to match against the users country and language, or failing that the language country.
404  // Scan through all the regions finding the first match for each possible default
405  // Holiday Region Country Code can be a country subdivision or the country itself,
406  // e.g. US or US-CA for California, so we can try match on both but an exact match has priority
407  // The Holiday Region file is in one language only, so give priority to any file in the
408  // users language, e.g. bilingual countries with a separate file for each language
409  // Locale language can have a country code embedded in it e.g. en_GB, which we can try use if
410  // no country set, but a lot of countries use en_GB so it's a lower priority option
411 
412  QString localeCountry, localeLanguage, localeLanguageCountry;
413 
414  if ( country.isEmpty() ) {
415  localeCountry = KGlobal::locale()->country().toLower();
416  } else {
417  localeCountry = country.toLower();
418  }
419 
420  if ( language.isEmpty() ) {
421  localeLanguage = KGlobal::locale()->language().toLower();
422  } else {
423  localeLanguage = language.toLower();
424  }
425 
426  if ( localeLanguage.split( '_' ).count() > 1 ) {
427  localeLanguageCountry = localeLanguage.split( '_' ).at( 1 );
428  }
429 
430  QStringList regionList = KHolidays::HolidayRegion::regionCodes();
431 
432  QString countryAndLanguageMatch, countryOnlyMatch, subdivisionAndLanguageMatch,
433  subdivisionOnlyMatch, languageCountryAndLanguageMatch, languageCountryOnlyMatch,
434  languageSubdivisionAndLanguageMatch, languageSubdivisionOnlyMatch;
435 
436  foreach ( const QString &regionCode, regionList ) {
437  QString regionCountry = KHolidays::HolidayRegion::countryCode( regionCode ).toLower();
438  QString regionSubdivisionCountry;
439  if ( regionCountry.split( '-' ).count() > 1 ) {
440  regionSubdivisionCountry = regionCountry.split( '-' ).at( 0 );
441  }
442  QString regionLanguage = KHolidays::HolidayRegion::languageCode( regionCode ).toLower();
443 
444  if ( regionCountry == localeCountry && regionLanguage == localeLanguage ) {
445  countryAndLanguageMatch = regionCode;
446  break; // exact match so don't look further
447  } else if ( regionCountry == localeCountry ) {
448  if ( countryOnlyMatch.isEmpty() ) {
449  countryOnlyMatch = regionCode;
450  }
451  } else if ( !regionSubdivisionCountry.isEmpty() &&
452  regionSubdivisionCountry == localeCountry &&
453  regionLanguage == localeLanguage ) {
454  if ( subdivisionAndLanguageMatch.isEmpty() ) {
455  subdivisionAndLanguageMatch = regionCode;
456  }
457  } else if ( !regionSubdivisionCountry.isEmpty() && regionSubdivisionCountry == localeCountry ) {
458  if ( subdivisionOnlyMatch.isEmpty() ) {
459  subdivisionOnlyMatch = regionCode;
460  }
461  } else if ( !localeLanguageCountry.isEmpty() &&
462  regionCountry == localeLanguageCountry &&
463  regionLanguage == localeLanguage ) {
464  if ( languageCountryAndLanguageMatch.isEmpty() ) {
465  languageCountryAndLanguageMatch = regionCode;
466  }
467  } else if ( !localeLanguageCountry.isEmpty() && regionCountry == localeLanguageCountry ) {
468  if ( languageCountryOnlyMatch.isEmpty() ) {
469  languageCountryOnlyMatch = regionCode;
470  }
471  } else if ( !regionSubdivisionCountry.isEmpty() &&
472  !localeLanguageCountry.isEmpty() &&
473  regionSubdivisionCountry == localeLanguageCountry &&
474  regionLanguage == localeLanguage ) {
475  if ( languageSubdivisionAndLanguageMatch.isEmpty() ) {
476  languageSubdivisionAndLanguageMatch = regionCode;
477  }
478  } else if ( !regionSubdivisionCountry.isEmpty() &&
479  !localeLanguageCountry.isEmpty() &&
480  regionSubdivisionCountry == localeLanguageCountry ) {
481  if ( languageSubdivisionOnlyMatch.isEmpty() ) {
482  languageSubdivisionOnlyMatch = regionCode;
483  }
484  }
485  }
486 
487  QString defaultRegionCode;
488 
489  if ( !countryAndLanguageMatch.isEmpty() ) {
490  defaultRegionCode = countryAndLanguageMatch;
491  } else if ( !countryOnlyMatch.isEmpty() ) {
492  defaultRegionCode = countryOnlyMatch;
493  } else if ( !subdivisionAndLanguageMatch.isEmpty() ) {
494  defaultRegionCode = subdivisionAndLanguageMatch;
495  } else if ( !subdivisionOnlyMatch.isEmpty() ) {
496  defaultRegionCode = subdivisionOnlyMatch;
497  } else if ( !languageCountryAndLanguageMatch.isEmpty() ) {
498  defaultRegionCode = languageCountryAndLanguageMatch;
499  } else if ( !languageCountryOnlyMatch.isEmpty() ) {
500  defaultRegionCode = languageCountryOnlyMatch;
501  } else if ( !languageSubdivisionAndLanguageMatch.isEmpty() ) {
502  defaultRegionCode = languageSubdivisionAndLanguageMatch;
503  } else if ( !languageSubdivisionOnlyMatch.isEmpty() ) {
504  defaultRegionCode = languageSubdivisionOnlyMatch;
505  }
506 
507  return defaultRegionCode;
508 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:25:09 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KHolidays Library

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

kdepimlibs-4.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • 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