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

KHolidays Library

  • sources
  • kde-4.14
  • kdepimlibs
  • 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 <KLocalizedString>
36 #include <KDebug>
37 
38 #include "holiday_p.h"
39 #include "parsers/plan2/holidayparserdriverplan_p.h"
40 
41 using namespace KHolidays;
42 
43 class HolidayRegion::Private
44 {
45  public:
46  Private( const QString &regionCode ) : mDriver( 0 ),
47  mRegionCode( regionCode )
48  {
49  if ( !mRegionCode.isEmpty() ) {
50 
51  if ( mRegionCode.length() == 2 ) { //Backwards compatible mode for old location code
52  mLocation = mRegionCode;
53  QStringList locationFiles = KGlobal::dirs()->findAllResources( "data",
54  QLatin1String("libkholidays/plan2/holiday_") + mLocation + QLatin1Char('*'),
55  KStandardDirs::NoDuplicates );
56  if ( locationFiles.count() > 0 ) {
57  mRegionCode = locationFiles.at( 0 ).
58  mid( locationFiles.at( 0 ).lastIndexOf( QLatin1String("holiday_") ) + 8 );
59  }
60  }
61 
62  mHolidayFile.setFile(
63  KStandardDirs::locate( "data", QLatin1String("libkholidays/plan2/holiday_") + mRegionCode ) );
64  }
65 
66  init();
67  }
68 
69  Private( const QFileInfo &regionFile ) : mDriver( 0 ),
70  mHolidayFile( regionFile )
71  {
72  init();
73  }
74 
75  ~Private()
76  {
77  delete mDriver;
78  }
79 
80  void init()
81  {
82  if ( mHolidayFile.exists() ) {
83  mDriver = new HolidayParserDriverPlan( mHolidayFile.absoluteFilePath() );
84  if ( mDriver ) {
85 
86  if ( mLocation.isEmpty() ) {
87  mLocation = mDriver->fileCountryCode().left( 2 );
88  }
89 
90  if ( mRegionCode.isEmpty() ) {
91  if ( mHolidayFile.fileName().startsWith( QLatin1String( "holiday_" ) ) ) {
92  mRegionCode = mHolidayFile.fileName().mid( 8 );
93  } else {
94  mRegionCode = mHolidayFile.fileName();
95  }
96  }
97 
98  } else {
99  mRegionCode.clear();
100  mLocation.clear();
101  }
102  } else {
103  mRegionCode.clear();
104  mLocation.clear();
105  }
106  }
107 
108  HolidayParserDriver *mDriver; // The parser driver for the holiday file
109  QString mRegionCode; // region code of holiday region
110  QString mLocation; // old location code, use now deprecated
111  QFileInfo mHolidayFile; // file containing holiday data, or null
112 };
113 
114 HolidayRegion::HolidayRegion( const QString &regionCode )
115  : d( new Private( regionCode ) )
116 {
117 }
118 
119 HolidayRegion::HolidayRegion( const QFileInfo &regionFile )
120  : d( new Private( regionFile ) )
121 {
122 }
123 
124 HolidayRegion::~HolidayRegion()
125 {
126  delete d;
127 }
128 
129 QStringList HolidayRegion::locations()
130 {
131  const QStringList files =
132  KGlobal::dirs()->findAllResources( "data", QLatin1String("libkholidays/plan2/holiday_*"),
133  KStandardDirs::NoDuplicates );
134 
135  QStringList locations;
136  foreach ( const QString &filename, files ) {
137  locations.append( filename.mid( filename.lastIndexOf( QLatin1String("holiday_") ) + 8, 2 ) );
138  }
139 
140  locations.removeDuplicates();
141  qSort( locations );
142  return locations;
143 }
144 
145 QString HolidayRegion::location() const
146 {
147  return d->mLocation;
148 }
149 
150 QStringList HolidayRegion::regionCodes()
151 {
152  const QStringList files =
153  KGlobal::dirs()->findAllResources( "data", QLatin1String("libkholidays/plan2/holiday_*"),
154  KStandardDirs::NoDuplicates );
155 
156  QStringList regionCodesList;
157  foreach ( const QString &filename, files ) {
158  regionCodesList.append( filename.mid( filename.lastIndexOf( QLatin1String("holiday_") ) + 8 ) );
159  }
160 
161  qSort( regionCodesList );
162  return regionCodesList;
163 }
164 
165 QString HolidayRegion::regionCode() const
166 {
167  return d->mRegionCode;
168 }
169 
170 QString HolidayRegion::countryCode() const
171 {
172  return d->mDriver->fileCountryCode();
173 }
174 
175 QString HolidayRegion::countryCode( const QString &regionCode )
176 {
177  HolidayRegion temp = HolidayRegion( regionCode );
178  if ( temp.isValid() ) {
179  return temp.countryCode();
180  } else {
181  return QString();
182  }
183 }
184 
185 QString HolidayRegion::languageCode() const
186 {
187  return d->mDriver->fileLanguageCode();
188 }
189 
190 QString HolidayRegion::languageCode( const QString &regionCode )
191 {
192  HolidayRegion temp = HolidayRegion( regionCode );
193  if ( temp.isValid() ) {
194  return temp.languageCode();
195  } else {
196  return QString();
197  }
198 }
199 
200 QString HolidayRegion::name() const
201 {
202  QString tempName = d->mDriver->fileName();
203 
204  if ( tempName.isEmpty() ) {
205  QStringList countryParts = countryCode().toLower().split( QLatin1Char('-') );
206  QString country = countryParts.at( 0 );
207  QString regionName, typeName;
208 
209  if ( country != QLatin1String("xx") ) {
210  if ( countryParts.count() == 2 ) {
211  // Temporary measure to get regions translated, only those files that already exist
212  // In 4.6 hope to have isocodes project integration for translations via KLocale
213  QString subdivision = countryParts.at( 1 );
214  if ( country == QLatin1String("ca") && subdivision == QLatin1String("qc") ) {
215  regionName = i18nc( "Canadian region", "Quebec" );
216  } else if ( country == QLatin1String("de") && subdivision == QLatin1String("by") ) {
217  regionName = i18nc( "German region", "Bavaria" );
218  } else if ( country == QLatin1String("es") && subdivision == QLatin1String("ct") ) {
219  regionName = i18nc( "Spanish region", "Catalonia" );
220  } else if ( country == QLatin1String("gb") && subdivision == QLatin1String("eaw") ) {
221  regionName = i18nc( "UK Region", "England and Wales" );
222  } else if ( country == QLatin1String("gb") && subdivision == QLatin1String("eng") ) {
223  regionName = i18nc( "UK Region", "England" );
224  } else if ( country == QLatin1String("gb") && subdivision == QLatin1String("wls") ) {
225  regionName = i18nc( "UK Region", "Wales" );
226  } else if ( country == QLatin1String("gb") && subdivision == QLatin1String("sct") ) {
227  regionName = i18nc( "UK Region", "Scotland" );
228  } else if ( country == QLatin1String("gb") && subdivision == QLatin1String("nir") ) {
229  regionName = i18nc( "UK Region", "Northern Ireland" );
230  } else if ( country == QLatin1String("it") && subdivision == QLatin1String("bz") ) {
231  regionName = i18nc( "Italian Region", "South Tyrol" );
232  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("nsw") ) {
233  regionName = i18nc( "Australian Region", "New South Wales" );
234  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("qld") ) {
235  regionName = i18nc( "Australian Region", "Queensland" );
236  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("vic") ) {
237  regionName = i18nc( "Australian Region", "Victoria" );
238  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("sa") ) {
239  regionName = i18nc( "Australian Region", "South Australia" );
240  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("nt") ) {
241  regionName = i18nc( "Australian Region", "Northern Territory" );
242  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("act") ) {
243  regionName = i18nc( "Australian Region", "Australian Capital Territory" );
244  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("wa") ) {
245  regionName = i18nc( "Australian Region", "Western Australia" );
246  } else if ( country == QLatin1String("au") && subdivision == QLatin1String("tas") ) {
247  regionName = i18nc( "Australian Region", "Tasmania" );
248  } else if ( country == QLatin1String("ba") && subdivision == QLatin1String("srp") ) {
249  regionName = i18nc( "Bosnian and Herzegovinian Region", "Republic of Srpska" );
250  } else {
251  regionName = KGlobal::locale()->countryCodeToName( country );
252  }
253  } else {
254  regionName = KGlobal::locale()->countryCodeToName( country );
255  }
256  }
257 
258  //Cheat on type for now,take direct from region code until API is introduced in SC 4.6
259  QStringList regionParts = regionCode().toLower().split( QLatin1Char('_') );
260  if ( regionParts.count() == 3 ) {
261  QString type = regionParts.at( 2 );
262  // Will create lots more in 4.6
263  // Religious types, just simple for now
264  if ( type == QLatin1String("public") ) {
265  typeName = i18nc( "Holiday type", "Public" );
266  } else if ( type == QLatin1String("civil") ) {
267  typeName = i18nc( "Holiday type", "Civil" );
268  } else if ( type == QLatin1String("religious") ) {
269  typeName = i18nc( "Holiday type", "Religious" );
270  } else if ( type == QLatin1String("government") ) {
271  typeName = i18nc( "Holiday type", "Government" );
272  } else if ( type == QLatin1String("financial") ) {
273  typeName = i18nc( "Holiday type", "Financial" );
274  } else if ( type == QLatin1String("cultural") ) {
275  typeName = i18nc( "Holiday type", "Cultural" );
276  } else if ( type == QLatin1String("commemorative") ) {
277  typeName = i18nc( "Holiday type", "Commemorative" );
278  } else if ( type == QLatin1String("historical") ) {
279  typeName = i18nc( "Holiday type", "Historical" );
280  } else if ( type == QLatin1String("school") ) {
281  typeName = i18nc( "Holiday type", "School" );
282  } else if ( type == QLatin1String("seasonal") ) {
283  typeName = i18nc( "Holiday type", "Seasonal" );
284  } else if ( type == QLatin1String("nameday") ) {
285  typeName = i18nc( "Holiday type", "Name Days" );
286  } else if ( type == QLatin1String("personal") ) {
287  typeName = i18nc( "Holiday type", "Personal" );
288  } else if ( type == QLatin1String("christian") ) {
289  typeName = i18nc( "Holiday type", "Christian" );
290  } else if ( type == QLatin1String("anglican") ) {
291  typeName = i18nc( "Holiday type", "Anglican" );
292  } else if ( type == QLatin1String("catholic") ) {
293  typeName = i18nc( "Holiday type", "Catholic" );
294  } else if ( type == QLatin1String("protestant") ) {
295  typeName = i18nc( "Holiday type", "Protestant" );
296  } else if ( type == QLatin1String("orthodox") ) {
297  typeName = i18nc( "Holiday type", "Orthodox" );
298  } else if ( type == QLatin1String("jewish") ) {
299  typeName = i18nc( "Holiday type", "Jewish" );
300  } else if ( type == QLatin1String("jewish-orthodox") ) {
301  typeName = i18nc( "Holiday type", "Jewish Orthodox" );
302  } else if ( type == QLatin1String("jewish-conservative") ) {
303  typeName = i18nc( "Holiday type", "Jewish Conservative" );
304  } else if ( type == QLatin1String("jewish-reform") ) {
305  typeName = i18nc( "Holiday type", "Jewish Reform" );
306  } else if ( type == QLatin1String("islamic") ) {
307  typeName = i18nc( "Holiday type", "Islamic" );
308  } else if ( type == QLatin1String("islamic-sunni") ) {
309  typeName = i18nc( "Holiday type", "Islamic Sunni" );
310  } else if ( type == QLatin1String("islamic-shia") ) {
311  typeName = i18nc( "Holiday type", "Islamic Shia" );
312  } else if ( type == QLatin1String("islamic-sufi") ) {
313  typeName = i18nc( "Holiday type", "Islamic Sufi" );
314  }
315  }
316 
317  if ( !regionName.isEmpty() ) {
318  if ( !typeName.isEmpty() ) {
319  tempName = i18nc( "Holiday file display name, %1 = region name, %2 = holiday type", "%1 - %2" ).arg( regionName ).arg( typeName );
320  } else {
321  tempName = regionName;
322  }
323  } else if ( !typeName.isEmpty() ) {
324  tempName = typeName;
325  } else {
326  tempName = i18nc( "Unknown holiday region", "Unknown" );
327  }
328  }
329  return tempName;
330 }
331 
332 QString HolidayRegion::name( const QString &regionCode )
333 {
334  HolidayRegion temp = HolidayRegion( regionCode );
335  if ( temp.isValid() ) {
336  return temp.name();
337  } else {
338  return QString();
339  }
340 }
341 
342 QString HolidayRegion::description() const
343 {
344  return d->mDriver->fileDescription();
345 }
346 
347 QString HolidayRegion::description( const QString &regionCode )
348 {
349  HolidayRegion temp = HolidayRegion( regionCode );
350  if ( temp.isValid() ) {
351  return temp.description();
352  } else {
353  return QString();
354  }
355 }
356 
357 bool HolidayRegion::isValid() const
358 {
359  return d->mHolidayFile.exists() && d->mDriver;
360 }
361 
362 bool HolidayRegion::isValid( const QString &regionCode )
363 {
364  HolidayRegion temp = HolidayRegion( regionCode );
365  return temp.isValid();
366 }
367 
368 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate ) const
369 {
370  return holidays( startDate, endDate, Holiday::MultidayHolidaysAsMultipleEvents );
371 }
372 
373 Holiday::List HolidayRegion::holidays( const QDate &startDate, const QDate &endDate,
374  Holiday::MultidayMode multidayMode ) const
375 {
376  if ( isValid() ) {
377  return d->mDriver->parseHolidays( startDate, endDate, multidayMode );
378  } else {
379  return Holiday::List();
380  }
381 }
382 
383 Holiday::List HolidayRegion::holidays( const QDate &date ) const
384 {
385  return holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
386 }
387 
388 Holiday::List HolidayRegion::holidays( const QDate &date, Holiday::MultidayMode multidayMode ) const
389 {
390  if ( isValid() ) {
391  return d->mDriver->parseHolidays( date, multidayMode );
392  } else {
393  return Holiday::List();
394  }
395 }
396 
397 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType ) const
398 {
399  return holidays( calendarYear, calendarType, Holiday::MultidayHolidaysAsMultipleEvents );
400 }
401 
402 Holiday::List HolidayRegion::holidays( int calendarYear, const QString &calendarType,
403  Holiday::MultidayMode multidayMode ) const
404 {
405  if ( isValid() ) {
406  return d->mDriver->parseHolidays( calendarYear, calendarType, multidayMode );
407  } else {
408  return Holiday::List();
409  }
410 }
411 
412 bool HolidayRegion::isHoliday( const QDate &date ) const
413 {
414  Holiday::List holidayList = holidays( date, Holiday::MultidayHolidaysAsMultipleEvents );
415  if ( holidayList.count() > 0 ) {
416  foreach ( const KHolidays::Holiday &holiday, holidayList ) {
417  if ( holiday.dayType() == Holiday::NonWorkday ) {
418  return true;
419  }
420  }
421  }
422  return false;
423 }
424 
425 QString HolidayRegion::defaultRegionCode( const QString &country, const QString &language )
426 {
427  // Try to match against the users country and language, or failing that the language country.
428  // Scan through all the regions finding the first match for each possible default
429  // Holiday Region Country Code can be a country subdivision or the country itself,
430  // e.g. US or US-CA for California, so we can try match on both but an exact match has priority
431  // The Holiday Region file is in one language only, so give priority to any file in the
432  // users language, e.g. bilingual countries with a separate file for each language
433  // Locale language can have a country code embedded in it e.g. en_GB, which we can try use if
434  // no country set, but a lot of countries use en_GB so it's a lower priority option
435 
436  QString localeCountry, localeLanguage, localeLanguageCountry;
437 
438  if ( country.isEmpty() ) {
439  localeCountry = KGlobal::locale()->country().toLower();
440  } else {
441  localeCountry = country.toLower();
442  }
443 
444  if ( language.isEmpty() ) {
445  localeLanguage = KGlobal::locale()->language().toLower();
446  } else {
447  localeLanguage = language.toLower();
448  }
449 
450  if ( localeLanguage.split( QLatin1Char('_') ).count() > 1 ) {
451  localeLanguageCountry = localeLanguage.split( QLatin1Char('_') ).at( 1 );
452  }
453 
454  QStringList regionList = KHolidays::HolidayRegion::regionCodes();
455 
456  QString countryAndLanguageMatch, countryOnlyMatch, subdivisionAndLanguageMatch,
457  subdivisionOnlyMatch, languageCountryAndLanguageMatch, languageCountryOnlyMatch,
458  languageSubdivisionAndLanguageMatch, languageSubdivisionOnlyMatch;
459 
460  foreach ( const QString &regionCode, regionList ) {
461  QString regionCountry = KHolidays::HolidayRegion::countryCode( regionCode ).toLower();
462  QString regionSubdivisionCountry;
463  if ( regionCountry.split( QLatin1Char('-') ).count() > 1 ) {
464  regionSubdivisionCountry = regionCountry.split( QLatin1Char('-') ).at( 0 );
465  }
466  QString regionLanguage = KHolidays::HolidayRegion::languageCode( regionCode ).toLower();
467 
468  if ( regionCountry == localeCountry && regionLanguage == localeLanguage ) {
469  countryAndLanguageMatch = regionCode;
470  break; // exact match so don't look further
471  } else if ( regionCountry == localeCountry ) {
472  if ( countryOnlyMatch.isEmpty() ) {
473  countryOnlyMatch = regionCode;
474  }
475  } else if ( !regionSubdivisionCountry.isEmpty() &&
476  regionSubdivisionCountry == localeCountry &&
477  regionLanguage == localeLanguage ) {
478  if ( subdivisionAndLanguageMatch.isEmpty() ) {
479  subdivisionAndLanguageMatch = regionCode;
480  }
481  } else if ( !regionSubdivisionCountry.isEmpty() && regionSubdivisionCountry == localeCountry ) {
482  if ( subdivisionOnlyMatch.isEmpty() ) {
483  subdivisionOnlyMatch = regionCode;
484  }
485  } else if ( !localeLanguageCountry.isEmpty() &&
486  regionCountry == localeLanguageCountry &&
487  regionLanguage == localeLanguage ) {
488  if ( languageCountryAndLanguageMatch.isEmpty() ) {
489  languageCountryAndLanguageMatch = regionCode;
490  }
491  } else if ( !localeLanguageCountry.isEmpty() && regionCountry == localeLanguageCountry ) {
492  if ( languageCountryOnlyMatch.isEmpty() ) {
493  languageCountryOnlyMatch = regionCode;
494  }
495  } else if ( !regionSubdivisionCountry.isEmpty() &&
496  !localeLanguageCountry.isEmpty() &&
497  regionSubdivisionCountry == localeLanguageCountry &&
498  regionLanguage == localeLanguage ) {
499  if ( languageSubdivisionAndLanguageMatch.isEmpty() ) {
500  languageSubdivisionAndLanguageMatch = regionCode;
501  }
502  } else if ( !regionSubdivisionCountry.isEmpty() &&
503  !localeLanguageCountry.isEmpty() &&
504  regionSubdivisionCountry == localeLanguageCountry ) {
505  if ( languageSubdivisionOnlyMatch.isEmpty() ) {
506  languageSubdivisionOnlyMatch = regionCode;
507  }
508  }
509  }
510 
511  QString defaultRegionCode;
512 
513  if ( !countryAndLanguageMatch.isEmpty() ) {
514  defaultRegionCode = countryAndLanguageMatch;
515  } else if ( !countryOnlyMatch.isEmpty() ) {
516  defaultRegionCode = countryOnlyMatch;
517  } else if ( !subdivisionAndLanguageMatch.isEmpty() ) {
518  defaultRegionCode = subdivisionAndLanguageMatch;
519  } else if ( !subdivisionOnlyMatch.isEmpty() ) {
520  defaultRegionCode = subdivisionOnlyMatch;
521  } else if ( !languageCountryAndLanguageMatch.isEmpty() ) {
522  defaultRegionCode = languageCountryAndLanguageMatch;
523  } else if ( !languageCountryOnlyMatch.isEmpty() ) {
524  defaultRegionCode = languageCountryOnlyMatch;
525  } else if ( !languageSubdivisionAndLanguageMatch.isEmpty() ) {
526  defaultRegionCode = languageSubdivisionAndLanguageMatch;
527  } else if ( !languageSubdivisionOnlyMatch.isEmpty() ) {
528  defaultRegionCode = languageSubdivisionOnlyMatch;
529  }
530 
531  return defaultRegionCode;
532 }
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QStringList::removeDuplicates
int removeDuplicates()
QList::at
const T & at(int i) const
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString::clear
void clear()
KHolidays::HolidayParserDriver
HolidayParserDriver abstract base class.
Definition: holidayparserdriver_p.h:44
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
QString::isEmpty
bool isEmpty() const
QDate
QString
QList
QStringList
KHolidays::HolidayParserDriver::fileCountryCode
virtual QString fileCountryCode() const
Return the ISO 3166 country/region code of the file.
Definition: holidayparserdriver.cpp:40
QFileInfo
QString::toLower
QString toLower() const
QLatin1Char
QString::mid
QString mid(int position, int n) const
QLatin1String
QStringList::split
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
QString::left
QString left(int n) const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
KHolidays::HolidayParserDriverPlan
HolidayParserDriverPlan implementation class.
Definition: holidayparserdriverplan_p.h:53
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:00 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs 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

Search



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