• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

KDECore

ktimezone.cpp
Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE libraries
00003    Copyright (c) 2005-2008,2011 David Jarvie <djarvie@kde.org>
00004    Copyright (c) 2005 S.R.Haque <srhaque@iee.org>.
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "ktimezone.h"
00023 
00024 #include <config.h>
00025 #include <config-date.h> // SIZEOF_TIME_T
00026 
00027 #ifdef HAVE_SYS_TIME_H
00028 #include <sys/time.h>
00029 #endif
00030 #ifdef HAVE_TIME_H
00031 #include <time.h>
00032 #endif
00033 #include <climits>
00034 #include <cstdlib>
00035 
00036 #include <QtCore/QSet>
00037 #include <QtCore/QSharedData>
00038 #include <QtCore/QCoreApplication>
00039 
00040 #include <kdebug.h>
00041 #include <kglobal.h>
00042 
00043 int gmtoff(time_t t);   // defined in ksystemtimezone.cpp
00044 
00045 
00046 /******************************************************************************/
00047 
00048 class KTimeZonesPrivate
00049 {
00050 public:
00051     KTimeZonesPrivate() {}
00052 
00053     KTimeZones::ZoneMap zones;
00054 };
00055 
00056 
00057 KTimeZones::KTimeZones()
00058   : d(new KTimeZonesPrivate)
00059 {
00060 }
00061 
00062 KTimeZones::~KTimeZones()
00063 {
00064     delete d;
00065 }
00066 
00067 const KTimeZones::ZoneMap KTimeZones::zones() const
00068 {
00069     return d->zones;
00070 }
00071 
00072 bool KTimeZones::add(const KTimeZone &zone)
00073 {
00074     if (!zone.isValid())
00075         return false;
00076     if (d->zones.find(zone.name()) != d->zones.end())
00077         return false;    // name already exists
00078     d->zones.insert(zone.name(), zone);
00079     return true;
00080 }
00081 
00082 KTimeZone KTimeZones::remove(const KTimeZone &zone)
00083 {
00084     if (zone.isValid())
00085     {
00086         for (ZoneMap::Iterator it = d->zones.begin(), end = d->zones.end();  it != end;  ++it)
00087         {
00088             if (it.value() == zone)
00089             {
00090                 d->zones.erase(it);
00091                 return zone;
00092             }
00093         }
00094     }
00095     return KTimeZone();
00096 }
00097 
00098 KTimeZone KTimeZones::remove(const QString &name)
00099 {
00100     if (!name.isEmpty())
00101     {
00102         ZoneMap::Iterator it = d->zones.find(name);
00103         if (it != d->zones.end())
00104         {
00105             KTimeZone zone = it.value();
00106             d->zones.erase(it);
00107             return zone;
00108         }
00109     }
00110     return KTimeZone();
00111 }
00112 
00113 void KTimeZones::clear()
00114 {
00115   d->zones.clear();
00116 }
00117 
00118 KTimeZone KTimeZones::zone(const QString &name) const
00119 {
00120     if (!name.isEmpty())
00121     {
00122         ZoneMap::ConstIterator it = d->zones.constFind(name);
00123         if (it != d->zones.constEnd())
00124             return it.value();
00125         if (name == KTimeZone::utc().name())
00126             return KTimeZone::utc();
00127     }
00128     return KTimeZone();    // error
00129 }
00130 
00131 
00132 /******************************************************************************/
00133 
00134 class KTimeZonePhasePrivate : public QSharedData
00135 {
00136     public:
00137         QByteArray       abbreviations;  // time zone abbreviations (zero-delimited)
00138         QString          comment;        // optional comment
00139         int              utcOffset;      // seconds to add to UTC
00140         bool             dst;            // true if daylight savings time
00141 
00142         explicit KTimeZonePhasePrivate(int offset = 0, bool ds = false)
00143         : QSharedData(),
00144           utcOffset(offset),
00145           dst(ds)
00146         {}
00147         KTimeZonePhasePrivate(const KTimeZonePhasePrivate& rhs)
00148         : QSharedData(rhs),
00149           abbreviations(rhs.abbreviations),
00150           comment(rhs.comment),
00151           utcOffset(rhs.utcOffset),
00152           dst(rhs.dst)
00153         {}
00154         bool operator==(const KTimeZonePhasePrivate &rhs) const
00155         {
00156             return abbreviations == rhs.abbreviations
00157                &&  comment       == rhs.comment
00158                &&  utcOffset     == rhs.utcOffset
00159                &&  dst           == rhs.dst;
00160         }
00161 };
00162 
00163 
00164 KTimeZone::Phase::Phase()
00165   : d(new KTimeZonePhasePrivate)
00166 {
00167 }
00168 
00169 KTimeZone::Phase::Phase(int utcOffset, const QByteArray &abbrevs,
00170                         bool dst, const QString &cmt)
00171   : d(new KTimeZonePhasePrivate(utcOffset, dst))
00172 {
00173     d->abbreviations = abbrevs;
00174     d->comment       = cmt;
00175 }
00176 
00177 KTimeZone::Phase::Phase(int utcOffset, const QList<QByteArray> &abbrevs,
00178                         bool dst, const QString &cmt)
00179   : d(new KTimeZonePhasePrivate(utcOffset, dst))
00180 {
00181     for (int i = 0, end = abbrevs.count();  i < end;  ++i)
00182     {
00183         if (i > 0)
00184             d->abbreviations += '\0';
00185         d->abbreviations += abbrevs[i];
00186     }
00187     d->comment = cmt;
00188 }
00189 
00190 KTimeZone::Phase::Phase(const KTimeZone::Phase &rhs)
00191   : d(rhs.d)
00192 {
00193 }
00194 
00195 KTimeZone::Phase::~Phase()
00196 {
00197 }
00198 
00199 KTimeZone::Phase &KTimeZone::Phase::operator=(const KTimeZone::Phase &rhs)
00200 {
00201     d = rhs.d;
00202     return *this;
00203 }
00204 
00205 bool KTimeZone::Phase::operator==(const KTimeZone::Phase &rhs) const
00206 {
00207     return d == rhs.d  ||  *d == *rhs.d;
00208 }
00209 
00210 int KTimeZone::Phase::utcOffset() const
00211 {
00212     return d->utcOffset;
00213 }
00214 
00215 QList<QByteArray> KTimeZone::Phase::abbreviations() const
00216 {
00217     return d->abbreviations.split('\0');
00218 }
00219 
00220 bool KTimeZone::Phase::isDst() const
00221 {
00222     return d->dst;
00223 }
00224 
00225 QString KTimeZone::Phase::comment() const
00226 {
00227     return d->comment;
00228 }
00229 
00230 
00231 /******************************************************************************/
00232 
00233 class KTimeZoneTransitionPrivate
00234 {
00235 public:
00236     QDateTime time;
00237     KTimeZone::Phase phase;
00238 };
00239 
00240 
00241 KTimeZone::Transition::Transition()
00242     : d(new KTimeZoneTransitionPrivate)
00243 {
00244 }
00245 
00246 KTimeZone::Transition::Transition(const QDateTime &t, const KTimeZone::Phase &p)
00247     : d(new KTimeZoneTransitionPrivate)
00248 {
00249     d->time  = t;
00250     d->phase = p;
00251 }
00252 
00253 KTimeZone::Transition::Transition(const KTimeZone::Transition &t)
00254     : d(new KTimeZoneTransitionPrivate)
00255 {
00256     d->time  = t.d->time;
00257     d->phase = t.d->phase;
00258 }
00259 
00260 KTimeZone::Transition::~Transition()
00261 {
00262     delete d;
00263 }
00264 
00265 KTimeZone::Transition &KTimeZone::Transition::operator=(const KTimeZone::Transition &t)
00266 {
00267     d->time  = t.d->time;
00268     d->phase = t.d->phase;
00269     return *this;
00270 }
00271 
00272 bool KTimeZone::Transition::operator<(const KTimeZone::Transition &rhs) const
00273 {
00274     return d->time < rhs.d->time;
00275 }
00276 
00277 QDateTime        KTimeZone::Transition::time() const   { return d->time; }
00278 KTimeZone::Phase KTimeZone::Transition::phase() const  { return d->phase; }
00279 
00280 
00281 /******************************************************************************/
00282 
00283 class KTimeZoneDataPrivate
00284 {
00285     public:
00286         QList<KTimeZone::Phase>       phases;
00287         QList<KTimeZone::Transition>  transitions;
00288         QList<KTimeZone::LeapSeconds> leapChanges;
00289         QList<int>                    utcOffsets;
00290         QList<QByteArray>             abbreviations;
00291         KTimeZone::Phase              prePhase;    // phase to use before the first transition
00292 
00293         KTimeZoneDataPrivate() {}
00294         // Find the last transition before a specified UTC or local date/time.
00295         int transitionIndex(const QDateTime &dt) const;
00296         bool transitionIndexes(const QDateTime &start, const QDateTime &end, int &ixstart, int &ixend) const;
00297         bool isSecondOccurrence(const QDateTime &utcLocalTime, int transitionIndex) const;
00298 };
00299 
00300 
00301 /******************************************************************************/
00302 
00303 class KTimeZonePrivate : public QSharedData
00304 {
00305 public:
00306     KTimeZonePrivate() : source(0), data(0), refCount(1), cachedTransitionIndex(-1) {}
00307     KTimeZonePrivate(KTimeZoneSource *src, const QString& nam,
00308                      const QString &country, float lat, float lon, const QString &cmnt);
00309     KTimeZonePrivate(const KTimeZonePrivate &);
00310     ~KTimeZonePrivate()  { delete data; }
00311     KTimeZonePrivate &operator=(const KTimeZonePrivate &);
00312     static KTimeZoneSource *utcSource();
00313     static void cleanup();
00314 
00315     KTimeZoneSource *source;
00316     QString name;
00317     QString countryCode;
00318     QString comment;
00319     float   latitude;
00320     float   longitude;
00321     mutable KTimeZoneData *data;
00322     int     refCount; // holds the number of KTimeZoneBackend instances using the KTimeZonePrivate instance as a d-pointer.
00323     int       cachedTransitionIndex;
00324     QDateTime cachedTransitionStartZoneTime;
00325     QDateTime cachedTransitionEndZoneTime;
00326     bool      cachedTransitionTimesValid;
00327 
00328 private:
00329     static KTimeZoneSource *mUtcSource;
00330 };
00331 
00332 KTimeZoneSource *KTimeZonePrivate::mUtcSource = 0;
00333 
00334 
00335 KTimeZonePrivate::KTimeZonePrivate(KTimeZoneSource *src, const QString& nam,
00336                  const QString &country, float lat, float lon, const QString &cmnt)
00337   : source(src),
00338     name(nam),
00339     countryCode(country.toUpper()),
00340     comment(cmnt),
00341     latitude(lat),
00342     longitude(lon),
00343     data(0),
00344     refCount(1),
00345     cachedTransitionIndex(-1)
00346 {
00347     // Detect duff values.
00348     if (latitude > 90 || latitude < -90)
00349         latitude = KTimeZone::UNKNOWN;
00350     if (longitude > 180 || longitude < -180)
00351         longitude = KTimeZone::UNKNOWN;
00352 }
00353 
00354 KTimeZonePrivate::KTimeZonePrivate(const KTimeZonePrivate &rhs)
00355   : QSharedData(rhs),
00356     source(rhs.source),
00357     name(rhs.name),
00358     countryCode(rhs.countryCode),
00359     comment(rhs.comment),
00360     latitude(rhs.latitude),
00361     longitude(rhs.longitude),
00362     refCount(1),
00363     cachedTransitionIndex(rhs.cachedTransitionIndex),
00364     cachedTransitionStartZoneTime(rhs.cachedTransitionStartZoneTime),
00365     cachedTransitionEndZoneTime(rhs.cachedTransitionEndZoneTime),
00366     cachedTransitionTimesValid(rhs.cachedTransitionTimesValid)
00367 {
00368     if (rhs.data)
00369         data = rhs.data->clone();
00370     else
00371         data = 0;
00372 }
00373 
00374 KTimeZonePrivate &KTimeZonePrivate::operator=(const KTimeZonePrivate &rhs)
00375 {
00376     // Changing the contents of a KTimeZonePrivate instance by means of operator=() doesn't affect how
00377     // many references to it are held.
00378     source      = rhs.source;
00379     name        = rhs.name;
00380     countryCode = rhs.countryCode;
00381     comment     = rhs.comment;
00382     latitude    = rhs.latitude;
00383     longitude   = rhs.longitude;
00384     cachedTransitionIndex         = rhs.cachedTransitionIndex;
00385     cachedTransitionStartZoneTime = rhs.cachedTransitionStartZoneTime;
00386     cachedTransitionEndZoneTime   = rhs.cachedTransitionEndZoneTime;
00387     cachedTransitionTimesValid    = rhs.cachedTransitionTimesValid;
00388     delete data;
00389     if (rhs.data)
00390         data = rhs.data->clone();
00391     else
00392         data = 0;
00393     // refCount is unchanged
00394     return *this;
00395 }
00396 
00397 KTimeZoneSource *KTimeZonePrivate::utcSource()
00398 {
00399     if (!mUtcSource)
00400     {
00401         mUtcSource = new KTimeZoneSource;
00402         qAddPostRoutine(KTimeZonePrivate::cleanup);
00403     }
00404     return mUtcSource;
00405 }
00406 
00407 void KTimeZonePrivate::cleanup()
00408 {
00409     delete mUtcSource;
00410 }
00411 
00412 
00413 /******************************************************************************/
00414 
00415 K_GLOBAL_STATIC(KTimeZonePrivate, s_emptyTimeZonePrivate)
00416 
00417 KTimeZoneBackend::KTimeZoneBackend()
00418   : d(&*s_emptyTimeZonePrivate)
00419 {
00420     ++d->refCount;
00421 }
00422 
00423 KTimeZoneBackend::KTimeZoneBackend(const QString &name)
00424   : d(new KTimeZonePrivate(KTimeZonePrivate::utcSource(), name, QString(), KTimeZone::UNKNOWN, KTimeZone::UNKNOWN, QString()))
00425 {}
00426 
00427 KTimeZoneBackend::KTimeZoneBackend(KTimeZoneSource *source, const QString &name,
00428         const QString &countryCode, float latitude, float longitude, const QString &comment)
00429   : d(new KTimeZonePrivate(source, name, countryCode, latitude, longitude, comment))
00430 {}
00431 
00432 KTimeZoneBackend::KTimeZoneBackend(const KTimeZoneBackend &other)
00433   : d(other.d)
00434 {
00435     ++d->refCount;
00436 }
00437 
00438 KTimeZoneBackend::~KTimeZoneBackend()
00439 {
00440     if (d && --d->refCount == 0)
00441         delete d;
00442     d = 0;
00443 }
00444 
00445 KTimeZoneBackend &KTimeZoneBackend::operator=(const KTimeZoneBackend &other)
00446 {
00447     if (d != other.d)
00448     {
00449         if (--d->refCount == 0)
00450             delete d;
00451         d = other.d;
00452         ++d->refCount;
00453     }
00454     return *this;
00455 }
00456 
00457 QByteArray KTimeZoneBackend::type() const
00458 {
00459     return "KTimeZone";
00460 }
00461 
00462 KTimeZoneBackend *KTimeZoneBackend::clone() const
00463 {
00464     return new KTimeZoneBackend(*this);
00465 }
00466 
00467 int KTimeZoneBackend::offsetAtZoneTime(const KTimeZone* caller, const QDateTime &zoneDateTime, int *secondOffset) const
00468 {
00469     if (!zoneDateTime.isValid()  ||  zoneDateTime.timeSpec() != Qt::LocalTime)    // check for invalid time
00470     {
00471         if (secondOffset)
00472             *secondOffset = 0;
00473         return 0;
00474     }
00475     const QList<KTimeZone::Transition> transitions = caller->transitions();
00476     int index = d->cachedTransitionIndex;
00477     if (index >= 0 && index < transitions.count())
00478     {
00479         // There is a cached transition - check whether zoneDateTime uses it.
00480         // Caching is used because this method has been found to consume
00481         // significant CPU in real life applications.
00482         if (!d->cachedTransitionTimesValid)
00483         {
00484             const int offset = transitions[index].phase().utcOffset();
00485         const int preoffset = (index > 0) ? transitions[index - 1].phase().utcOffset() : d->data ? d->data->previousUtcOffset() : 0;
00486             d->cachedTransitionStartZoneTime = transitions[index].time().addSecs(qMax(offset, preoffset));
00487             if (index + 1 < transitions.count())
00488         {
00489                 const int postoffset = transitions[index + 1].phase().utcOffset();
00490                 d->cachedTransitionEndZoneTime = transitions[index + 1].time().addSecs(qMin(offset, postoffset));
00491         }
00492             d->cachedTransitionTimesValid = true;
00493         }
00494         QDateTime dtutc = zoneDateTime;
00495         dtutc.setTimeSpec(Qt::UTC);
00496         if (dtutc >= d->cachedTransitionStartZoneTime
00497         &&  (index + 1 >= transitions.count() || dtutc < d->cachedTransitionEndZoneTime))
00498         {
00499             // The time falls within the cached transition limits, so return its UTC offset
00500             const int offset = transitions[index].phase().utcOffset();
00501             if (secondOffset)
00502                 *secondOffset = offset;
00503 #ifdef COMPILING_TESTS
00504             qDebug("-> Using cache");   // test output requires qDebug instead of kDebug
00505 #endif
00506             return offset;
00507         }
00508     }
00509 
00510     // The time doesn't fall within the cached transition, or there isn't a cached transition
00511 #ifdef COMPILING_TESTS
00512     qDebug("-> No cache");   // test output requires qDebug instead of kDebug
00513 #endif
00514     bool validTime;
00515     int secondIndex = -1;
00516     index = caller->transitionIndex(zoneDateTime, (secondOffset ? &secondIndex : 0), &validTime);
00517     const KTimeZone::Transition* tr = (index >= 0) ? &transitions[index] : 0;
00518     const int offset = tr ? tr->phase().utcOffset()
00519                           : validTime ? (d->data ? d->data->previousUtcOffset() : 0)
00520                                       : KTimeZone::InvalidOffset;
00521     if (secondOffset)
00522         *secondOffset = (secondIndex >= 0) ? transitions.at(secondIndex).phase().utcOffset() : offset;
00523 
00524     // Cache transition data for subsequent date/time values which occur after the same transition.
00525     d->cachedTransitionIndex = index;
00526     d->cachedTransitionTimesValid = false;
00527     return offset;
00528 }
00529 
00530 int KTimeZoneBackend::offsetAtUtc(const KTimeZone* caller, const QDateTime &utcDateTime) const
00531 {
00532     if (!utcDateTime.isValid()  ||  utcDateTime.timeSpec() != Qt::UTC)    // check for invalid time
00533         return 0;
00534     const QList<KTimeZone::Transition> transitions = caller->transitions();
00535     int index = d->cachedTransitionIndex;
00536     if (index >= 0 && index < transitions.count())
00537     {
00538         // There is a cached transition - check whether utcDateTime uses it.
00539         if (utcDateTime >= transitions[index].time()
00540         &&  (index + 1 >= transitions.count()
00541              || utcDateTime < transitions[index + 1].time()))
00542         {
00543             // The time falls within the cached transition, so return its UTC offset
00544 #ifdef COMPILING_TESTS
00545             qDebug("Using cache");   // test output requires qDebug instead of kDebug
00546 #endif
00547             return transitions[index].phase().utcOffset();
00548         }
00549     }
00550 
00551     // The time doesn't fall within the cached transition, or there isn't a cached transition
00552 #ifdef COMPILING_TESTS
00553     qDebug("No cache");   // test output requires qDebug instead of kDebug
00554 #endif
00555     index = caller->transitionIndex(utcDateTime);
00556     d->cachedTransitionIndex = index;   // cache transition data
00557     d->cachedTransitionTimesValid = false;
00558     const KTimeZone::Transition* tr = (index >= 0) ? &transitions.at(index) : 0;
00559     return tr ? tr->phase().utcOffset() : (d->data ? d->data->previousUtcOffset() : 0);
00560 }
00561 
00562 int KTimeZoneBackend::offset(const KTimeZone* caller, time_t t) const
00563 {
00564     return offsetAtUtc(caller, KTimeZone::fromTime_t(t));
00565 }
00566 
00567 bool KTimeZoneBackend::isDstAtUtc(const KTimeZone* caller, const QDateTime &utcDateTime) const
00568 {
00569     if (!utcDateTime.isValid()  ||  utcDateTime.timeSpec() != Qt::UTC)    // check for invalid time
00570         return false;
00571     const KTimeZone::Transition *tr = caller->transition(utcDateTime);
00572     if (!tr)
00573         return false;
00574     return tr->phase().isDst();
00575 }
00576 
00577 bool KTimeZoneBackend::isDst(const KTimeZone* caller, time_t t) const
00578 {
00579     return isDstAtUtc(caller, KTimeZone::fromTime_t(t));
00580 }
00581 
00582 bool KTimeZoneBackend::hasTransitions(const KTimeZone* caller) const
00583 {
00584     Q_UNUSED(caller);
00585     return false;
00586 }
00587 
00588 
00589 /******************************************************************************/
00590 
00591 #if SIZEOF_TIME_T == 8
00592 const time_t KTimeZone::InvalidTime_t = 0x800000000000000LL;
00593 #else
00594 const time_t KTimeZone::InvalidTime_t = 0x80000000;
00595 #endif
00596 const int    KTimeZone::InvalidOffset = 0x80000000;
00597 const float  KTimeZone::UNKNOWN = 1000.0;
00598 
00599 
00600 KTimeZone::KTimeZone()
00601   : d(new KTimeZoneBackend())
00602 {}
00603 
00604 KTimeZone::KTimeZone(const QString &name)
00605   : d(new KTimeZoneBackend(name))
00606 {}
00607 
00608 KTimeZone::KTimeZone(const KTimeZone &tz)
00609   : d(tz.d->clone())
00610 {}
00611 
00612 KTimeZone::~KTimeZone()
00613 {
00614     delete d;
00615 }
00616 
00617 KTimeZone::KTimeZone(KTimeZoneBackend *impl)
00618   : d(impl)
00619 {
00620     // 'impl' should be a newly constructed object, with refCount = 1
00621     Q_ASSERT(d->d->refCount == 1 || d->d == &*s_emptyTimeZonePrivate);
00622 }
00623 
00624 KTimeZone &KTimeZone::operator=(const KTimeZone &tz)
00625 {
00626     if (d != tz.d)
00627     {
00628         delete d;
00629         d = tz.d->clone();
00630     }
00631     return *this;
00632 }
00633 
00634 bool KTimeZone::operator==(const KTimeZone &rhs) const
00635 {
00636     return d->d == rhs.d->d;
00637 }
00638 
00639 QByteArray KTimeZone::type() const
00640 {
00641     return d->type();
00642 }
00643 
00644 bool KTimeZone::isValid() const
00645 {
00646     return !d->d->name.isEmpty();
00647 }
00648 
00649 QString KTimeZone::countryCode() const
00650 {
00651     return d->d->countryCode;
00652 }
00653 
00654 float KTimeZone::latitude() const
00655 {
00656     return d->d->latitude;
00657 }
00658 
00659 float KTimeZone::longitude() const
00660 {
00661     return d->d->longitude;
00662 }
00663 
00664 QString KTimeZone::comment() const
00665 {
00666     return d->d->comment;
00667 }
00668 
00669 QString KTimeZone::name() const
00670 {
00671     return d->d->name;
00672 }
00673 
00674 QList<QByteArray> KTimeZone::abbreviations() const
00675 {
00676     if (!data(true))
00677         return QList<QByteArray>();
00678     return d->d->data->abbreviations();
00679 }
00680 
00681 QByteArray KTimeZone::abbreviation(const QDateTime &utcDateTime) const
00682 {
00683     if (utcDateTime.timeSpec() != Qt::UTC  ||  !data(true))
00684         return QByteArray();
00685     return d->d->data->abbreviation(utcDateTime);
00686 }
00687 
00688 QList<int> KTimeZone::utcOffsets() const
00689 {
00690     if (!data(true))
00691         return QList<int>();
00692     return d->d->data->utcOffsets();
00693 }
00694 
00695 QList<KTimeZone::Phase> KTimeZone::phases() const
00696 {
00697     if (!data(true))
00698         return QList<KTimeZone::Phase>();
00699     return d->d->data->phases();
00700 }
00701 
00702 bool KTimeZone::hasTransitions() const
00703 {
00704     return d->hasTransitions(this);
00705 }
00706 
00707 QList<KTimeZone::Transition> KTimeZone::transitions(const QDateTime &start, const QDateTime &end) const
00708 {
00709     if (!data(true))
00710         return QList<KTimeZone::Transition>();
00711     return d->d->data->transitions(start, end);
00712 }
00713 
00714 const KTimeZone::Transition *KTimeZone::transition(const QDateTime &dt, const Transition **secondTransition,
00715                                                    bool *validTime) const
00716 {
00717     if (!data(true))
00718         return 0;
00719     return d->d->data->transition(dt, secondTransition, validTime);
00720 }
00721 
00722 int KTimeZone::transitionIndex(const QDateTime &dt, int *secondIndex, bool *validTime) const
00723 {
00724     if (!data(true))
00725         return -1;
00726     return d->d->data->transitionIndex(dt, secondIndex, validTime);
00727 }
00728 
00729 QList<QDateTime> KTimeZone::transitionTimes(const Phase &phase, const QDateTime &start, const QDateTime &end) const
00730 {
00731     if (!data(true))
00732         return QList<QDateTime>();
00733     return d->d->data->transitionTimes(phase, start, end);
00734 }
00735 
00736 QList<KTimeZone::LeapSeconds> KTimeZone::leapSecondChanges() const
00737 {
00738     if (!data(true))
00739         return QList<KTimeZone::LeapSeconds>();
00740     return d->d->data->leapSecondChanges();
00741 }
00742 
00743 KTimeZoneSource *KTimeZone::source() const
00744 {
00745     return d->d->source;
00746 }
00747 
00748 const KTimeZoneData *KTimeZone::data(bool create) const
00749 {
00750     if (!isValid())
00751         return 0;
00752     if (create && !d->d->data && d->d->source->useZoneParse())
00753         d->d->data = d->d->source->parse(*this);
00754     return d->d->data;
00755 }
00756 
00757 void KTimeZone::setData(KTimeZoneData *data, KTimeZoneSource *source)
00758 {
00759     if (!isValid())
00760         return;
00761     delete d->d->data;
00762     d->d->data = data;
00763     if (source)
00764         d->d->source = source;
00765 }
00766 
00767 bool KTimeZone::updateBase(const KTimeZone &other)
00768 {
00769     if (d->d->name.isEmpty() || d->d->name != other.d->d->name)
00770         return false;
00771     d->d->countryCode = other.d->d->countryCode;
00772     d->d->comment     = other.d->d->comment;
00773     d->d->latitude    = other.d->d->latitude;
00774     d->d->longitude   = other.d->d->longitude;
00775     return true;
00776 }
00777 
00778 bool KTimeZone::parse() const
00779 {
00780     if (!isValid())
00781         return false;
00782     if (d->d->source->useZoneParse())
00783     {
00784         delete d->d->data;
00785         d->d->data = d->d->source->parse(*this);
00786     }
00787     return d->d->data;
00788 }
00789 
00790 QDateTime KTimeZone::toUtc(const QDateTime &zoneDateTime) const
00791 {
00792     if (!zoneDateTime.isValid()  ||  zoneDateTime.timeSpec() != Qt::LocalTime)
00793         return QDateTime();
00794     const int secs = offsetAtZoneTime(zoneDateTime);
00795     if (secs == InvalidOffset)
00796         return QDateTime();
00797     QDateTime dt = zoneDateTime;
00798     dt.setTimeSpec(Qt::UTC);
00799     return dt.addSecs(-secs);
00800 }
00801 
00802 QDateTime KTimeZone::toZoneTime(const QDateTime &utcDateTime, bool *secondOccurrence) const
00803 {
00804     if (secondOccurrence)
00805         *secondOccurrence = false;
00806     if (!utcDateTime.isValid()  ||  utcDateTime.timeSpec() != Qt::UTC)    // check for invalid time
00807         return QDateTime();
00808 
00809     // Convert UTC to local time
00810     if (hasTransitions())
00811     {
00812         if (!data(true))
00813         {
00814             // No data - default to UTC
00815             QDateTime dt = utcDateTime;
00816             dt.setTimeSpec(Qt::LocalTime);
00817             return dt;
00818         }
00819 
00820         const KTimeZoneData *data = d->d->data;
00821         const int index = data->transitionIndex(utcDateTime);
00822         const int secs = (index >= 0) ? data->transitions()[index].phase().utcOffset() : data->previousUtcOffset();
00823         QDateTime dt = utcDateTime.addSecs(secs);
00824         if (secondOccurrence)
00825         {
00826             // Check whether the local time occurs twice around a daylight savings time
00827             // shift, and if so, whether it's the first or second occurrence.
00828             *secondOccurrence = data->d->isSecondOccurrence(dt, index);
00829         }
00830         dt.setTimeSpec(Qt::LocalTime);
00831         return dt;
00832     }
00833     else
00834     {
00835         const int secs = offsetAtUtc(utcDateTime);
00836         QDateTime dt = utcDateTime.addSecs(secs);
00837         dt.setTimeSpec(Qt::LocalTime);
00838         if (secondOccurrence)
00839         {
00840             // Check whether the local time occurs twice around a daylight savings time
00841             // shift, and if so, whether it's the first or second occurrence.
00842             *secondOccurrence = (secs != offsetAtZoneTime(dt));
00843         }
00844         return dt;
00845     }
00846 }
00847 
00848 QDateTime KTimeZone::convert(const KTimeZone &newZone, const QDateTime &zoneDateTime) const
00849 {
00850     if (newZone == *this)
00851     {
00852         if (zoneDateTime.timeSpec() != Qt::LocalTime)
00853             return QDateTime();
00854         return zoneDateTime;
00855     }
00856     return newZone.toZoneTime(toUtc(zoneDateTime));
00857 }
00858 
00859 int KTimeZone::offsetAtZoneTime(const QDateTime &zoneDateTime, int *secondOffset) const
00860 {
00861     return d->offsetAtZoneTime(this, zoneDateTime, secondOffset);
00862 }
00863 
00864 int KTimeZone::offsetAtUtc(const QDateTime &utcDateTime) const
00865 {
00866     return d->offsetAtUtc(this, utcDateTime);
00867 }
00868 
00869 int KTimeZone::offset(time_t t) const
00870 {
00871     return d->offset(this, t);
00872 }
00873 
00874 int KTimeZone::currentOffset(Qt::TimeSpec basis) const
00875 {
00876     // Get current offset of this time zone to UTC
00877     const time_t now = time(0);
00878     const int secs = offset(now);
00879 
00880     switch (basis)
00881     {
00882         case Qt::LocalTime:
00883             // Return the current offset of this time zone to the local system time
00884             return secs - gmtoff(now);
00885         case Qt::UTC:
00886             // Return the current offset of this time zone to UTC
00887             return secs;
00888 
00889         default:
00890             break;
00891     }
00892     return 0;
00893 }
00894 
00895 bool KTimeZone::isDstAtUtc(const QDateTime &utcDateTime) const
00896 {
00897     return d->isDstAtUtc(this, utcDateTime);
00898 }
00899 
00900 bool KTimeZone::isDst(time_t t) const
00901 {
00902     return d->isDst(this, t);
00903 }
00904 
00905 KTimeZone KTimeZone::utc()
00906 {
00907     static KTimeZone utcZone(QLatin1String("UTC"));
00908     return utcZone;
00909 }
00910 
00911 QDateTime KTimeZone::fromTime_t(time_t t)
00912 {
00913     static const int secondsADay = 86400;
00914     static const QDate epochDate(1970,1,1);
00915     static const QTime epochTime(0,0,0);
00916     int days = t / secondsADay;
00917     int secs;
00918     if (t >= 0)
00919         secs = t % secondsADay;
00920     else
00921     {
00922         secs = secondsADay - (-t % secondsADay);
00923         --days;
00924     }
00925     return QDateTime(epochDate.addDays(days), epochTime.addSecs(secs), Qt::UTC);
00926 }
00927 
00928 time_t KTimeZone::toTime_t(const QDateTime &utcDateTime)
00929 {
00930     static const QDate epochDate(1970,1,1);
00931     static const QTime epochTime(0,0,0);
00932     if (utcDateTime.timeSpec() != Qt::UTC)
00933         return InvalidTime_t;
00934     const qint64 days = epochDate.daysTo(utcDateTime.date());
00935     const qint64 secs = epochTime.secsTo(utcDateTime.time());
00936     const qint64 t64 = days * 86400 + secs;
00937     const time_t t = static_cast<time_t>(t64);
00938     if (static_cast<qint64>(t) != t64)
00939         return InvalidTime_t;
00940     return t;
00941 }
00942 
00943 
00944 /******************************************************************************/
00945 
00946 class KTimeZoneSourcePrivate
00947 {
00948 public:
00949     bool mUseZoneParse;
00950 };
00951 
00952 
00953 KTimeZoneSource::KTimeZoneSource()
00954   : d(new KTimeZoneSourcePrivate)
00955 {
00956     d->mUseZoneParse = true;
00957 }
00958 
00959 KTimeZoneSource::KTimeZoneSource(bool useZoneParse)
00960   : d(new KTimeZoneSourcePrivate)
00961 {
00962     d->mUseZoneParse = useZoneParse;
00963 }
00964 
00965 KTimeZoneSource::~KTimeZoneSource()
00966 {
00967     delete d;
00968 }
00969 
00970 KTimeZoneData *KTimeZoneSource::parse(const KTimeZone &) const
00971 {
00972     Q_ASSERT(d->mUseZoneParse);  // method should never be called if it isn't usable
00973     return new KTimeZoneData;
00974 }
00975 
00976 bool KTimeZoneSource::useZoneParse() const
00977 {
00978     return d->mUseZoneParse;
00979 }
00980 
00981 
00982 /******************************************************************************/
00983 
00984 class KTimeZoneLeapSecondsPrivate
00985 {
00986     public:
00987         QDateTime  dt;         // UTC time when this change occurred
00988         QString    comment;    // optional comment
00989         int        seconds;    // number of leap seconds
00990 };
00991 
00992 
00993 KTimeZone::LeapSeconds::LeapSeconds()
00994   : d(new KTimeZoneLeapSecondsPrivate)
00995 {
00996 }
00997 
00998 KTimeZone::LeapSeconds::LeapSeconds(const QDateTime &utc, int leap, const QString &cmt)
00999   : d(new KTimeZoneLeapSecondsPrivate)
01000 {
01001     if (utc.timeSpec() == Qt::UTC)   // invalid if start time is not UTC
01002     {
01003         d->dt      = utc;
01004         d->comment = cmt;
01005         d->seconds = leap;
01006     }
01007 }
01008 
01009 KTimeZone::LeapSeconds::LeapSeconds(const KTimeZone::LeapSeconds &c)
01010   : d(new KTimeZoneLeapSecondsPrivate)
01011 {
01012     d->dt      = c.d->dt;
01013     d->comment = c.d->comment;
01014     d->seconds = c.d->seconds;
01015 }
01016 
01017 KTimeZone::LeapSeconds::~LeapSeconds()
01018 {
01019     delete d;
01020 }
01021 
01022 KTimeZone::LeapSeconds &KTimeZone::LeapSeconds::operator=(const KTimeZone::LeapSeconds &c)
01023 {
01024     d->dt      = c.d->dt;
01025     d->comment = c.d->comment;
01026     d->seconds = c.d->seconds;
01027     return *this;
01028 }
01029 
01030 bool KTimeZone::LeapSeconds::operator<(const KTimeZone::LeapSeconds& c) const
01031 {
01032     return d->dt < c.d->dt;
01033 }
01034 
01035 QDateTime KTimeZone::LeapSeconds::dateTime() const
01036 {
01037     return d->dt;
01038 }
01039 
01040 bool KTimeZone::LeapSeconds::isValid() const
01041 {
01042     return d->dt.isValid();
01043 }
01044 
01045 int KTimeZone::LeapSeconds::leapSeconds() const
01046 {
01047     return d->seconds;
01048 }
01049 
01050 QString KTimeZone::LeapSeconds::comment() const
01051 {
01052     return d->comment;
01053 }
01054 
01055 
01056 /******************************************************************************/
01057 
01058 
01059 int KTimeZoneDataPrivate::transitionIndex(const QDateTime &dt) const
01060 {
01061     // Do a binary search to find the last transition before this date/time
01062     int start = -1;
01063     int end = transitions.count();
01064     if (dt.timeSpec() == Qt::UTC)
01065     {
01066         while (end - start > 1)
01067         {
01068             int i = (start + end) / 2;
01069             if (dt < transitions[i].time())
01070                 end = i;
01071             else
01072                 start = i;
01073         }
01074     }
01075     else
01076     {
01077         QDateTime dtutc = dt;
01078         dtutc.setTimeSpec(Qt::UTC);
01079         while (end - start > 1)
01080         {
01081             const int i = (start + end) / 2;
01082             if (dtutc.addSecs(-transitions[i].phase().utcOffset()) < transitions[i].time())
01083                 end = i;
01084             else
01085                 start = i;
01086         }
01087     }
01088     return end ? start : -1;
01089 }
01090 
01091 // Find the indexes to the transitions at or after start, and before or at end.
01092 // start and end must be UTC.
01093 // Reply = false if none.
01094 bool KTimeZoneDataPrivate::transitionIndexes(const QDateTime &start, const QDateTime &end, int &ixstart, int &ixend) const
01095 {
01096     ixstart = 0;
01097     if (start.isValid() && start.timeSpec() == Qt::UTC)
01098     {
01099         ixstart = transitionIndex(start);
01100         if (ixstart < 0)
01101             ixstart = 0;
01102         else if (transitions[ixstart].time() < start)
01103         {
01104             if (++ixstart >= transitions.count())
01105                 return false;   // there are no transitions at/after 'start'
01106         }
01107     }
01108     ixend = -1;
01109     if (end.isValid() && end.timeSpec() == Qt::UTC)
01110     {
01111         ixend = transitionIndex(end);
01112         if (ixend < 0)
01113             return false;   // there are no transitions at/before 'end'
01114     }
01115     return true;
01116 }
01117 
01118 /* Check if it's a local time which occurs both before and after the specified
01119  * transition (for which it has to span a daylight saving to standard time change).
01120  * @param utcLocalTime local time set to Qt::UTC
01121  */
01122 bool KTimeZoneDataPrivate::isSecondOccurrence(const QDateTime &utcLocalTime, int transitionIndex) const
01123 {
01124     if (transitionIndex < 0)
01125         return false;
01126     const int offset = transitions[transitionIndex].phase().utcOffset();
01127     const int prevoffset = (transitionIndex > 0) ? transitions[transitionIndex-1].phase().utcOffset() : prePhase.utcOffset();
01128     const int phaseDiff = prevoffset - offset;
01129     if (phaseDiff <= 0)
01130         return false;
01131     // Find how long after the start of the latest phase 'dt' is
01132     const int afterStart = transitions[transitionIndex].time().secsTo(utcLocalTime) - offset;
01133     return (afterStart < phaseDiff);
01134 }
01135 
01136 
01137 
01138 KTimeZoneData::KTimeZoneData()
01139   : d(new KTimeZoneDataPrivate)
01140 { }
01141 
01142 KTimeZoneData::KTimeZoneData(const KTimeZoneData &c)
01143   : d(new KTimeZoneDataPrivate)
01144 {
01145     d->phases        = c.d->phases;
01146     d->transitions   = c.d->transitions;
01147     d->leapChanges   = c.d->leapChanges;
01148     d->utcOffsets    = c.d->utcOffsets;
01149     d->abbreviations = c.d->abbreviations;
01150     d->prePhase      = c.d->prePhase;
01151 }
01152 
01153 KTimeZoneData::~KTimeZoneData()
01154 {
01155     delete d;
01156 }
01157 
01158 KTimeZoneData &KTimeZoneData::operator=(const KTimeZoneData &c)
01159 {
01160     d->phases        = c.d->phases;
01161     d->transitions   = c.d->transitions;
01162     d->leapChanges   = c.d->leapChanges;
01163     d->utcOffsets    = c.d->utcOffsets;
01164     d->abbreviations = c.d->abbreviations;
01165     d->prePhase      = c.d->prePhase;
01166     return *this;
01167 }
01168 
01169 KTimeZoneData *KTimeZoneData::clone() const
01170 {
01171     return new KTimeZoneData(*this);
01172 }
01173 
01174 QList<QByteArray> KTimeZoneData::abbreviations() const
01175 {
01176     if (d->abbreviations.isEmpty())
01177     {
01178         for (int i = 0, end = d->phases.count();  i < end;  ++i)
01179         {
01180             const QList<QByteArray> abbrevs = d->phases[i].abbreviations();
01181             for (int j = 0, jend = abbrevs.count();  j < jend;  ++j)
01182                 if (!d->abbreviations.contains(abbrevs[j]))
01183                     d->abbreviations.append(abbrevs[j]);
01184         }
01185         if (d->abbreviations.isEmpty())
01186             d->abbreviations += "UTC";
01187     }
01188     return d->abbreviations;
01189 }
01190 
01191 QByteArray KTimeZoneData::abbreviation(const QDateTime &utcDateTime) const
01192 {
01193     if (d->phases.isEmpty())
01194         return "UTC";
01195     const KTimeZone::Transition *tr = transition(utcDateTime);
01196     const QList<QByteArray> abbrevs = tr ? tr->phase().abbreviations()
01197                                          : d->prePhase.abbreviations();
01198     if (abbrevs.isEmpty())
01199         return QByteArray();
01200     return abbrevs[0];
01201 }
01202 
01203 QList<int> KTimeZoneData::utcOffsets() const
01204 {
01205     if (d->utcOffsets.isEmpty())
01206     {
01207         for (int i = 0, end = d->phases.count();  i < end;  ++i)
01208         {
01209             const int offset = d->phases[i].utcOffset();
01210             if (!d->utcOffsets.contains(offset))
01211                 d->utcOffsets.append(offset);
01212         }
01213         if (d->utcOffsets.isEmpty())
01214             d->utcOffsets += 0;
01215         else
01216             qSort(d->utcOffsets);
01217     }
01218     return d->utcOffsets;
01219 }
01220 
01221 QList<KTimeZone::Phase> KTimeZoneData::phases() const
01222 {
01223     return d->phases;
01224 }
01225 
01226 void KTimeZoneData::setPhases(const QList<KTimeZone::Phase> &phases, const KTimeZone::Phase& previousPhase)
01227 {
01228     d->phases   = phases;
01229     d->prePhase = previousPhase;
01230 }
01231 
01232 void KTimeZoneData::setPhases(const QList<KTimeZone::Phase> &phases, int previousUtcOffset)
01233 {
01234     d->phases   = phases;
01235     d->prePhase = KTimeZone::Phase(previousUtcOffset, QByteArray(), false);
01236 }
01237 
01238 bool KTimeZoneData::hasTransitions() const
01239 {
01240     return false;
01241 }
01242 
01243 QList<KTimeZone::Transition> KTimeZoneData::transitions(const QDateTime &start, const QDateTime &end) const
01244 {
01245     int ixstart, ixend;
01246     if (!d->transitionIndexes(start, end, ixstart, ixend))
01247         return QList<KTimeZone::Transition>();   // there are no transitions within the time period
01248     if (ixend >= 0)
01249         return d->transitions.mid(ixstart, ixend - ixstart + 1);
01250     if (ixstart > 0)
01251         return d->transitions.mid(ixstart);
01252     return d->transitions;
01253 }
01254 
01255 void KTimeZoneData::setTransitions(const QList<KTimeZone::Transition> &transitions)
01256 {
01257     d->transitions = transitions;
01258 }
01259 
01260 int KTimeZoneData::previousUtcOffset() const
01261 {
01262     return d->prePhase.utcOffset();
01263 }
01264 
01265 const KTimeZone::Transition *KTimeZoneData::transition(const QDateTime &dt, const KTimeZone::Transition **secondTransition,
01266                                                        bool *validTime) const
01267 {
01268     int secondIndex;
01269     const int index = transitionIndex(dt, (secondTransition ? &secondIndex : 0), validTime);
01270     if (secondTransition)
01271         *secondTransition = (secondIndex >= 0) ? &d->transitions[secondIndex] : 0;
01272     return (index >= 0) ? &d->transitions[index] : 0;
01273 }
01274 
01275 int KTimeZoneData::transitionIndex(const QDateTime &dt, int *secondIndex, bool *validTime) const
01276 {
01277     if (validTime)
01278         *validTime = true;
01279 
01280     // Find the last transition before this date/time
01281     int index = d->transitionIndex(dt);
01282     if (dt.timeSpec() == Qt::UTC)
01283     {
01284         if (secondIndex)
01285             *secondIndex = index;
01286         return index;
01287     }
01288     else
01289     {
01290         /* Check whether the specified local time actually occurs.
01291          * Find the start of the next phase, and check if it falls in the gap
01292          * between the two phases.
01293          */
01294         QDateTime dtutc = dt;
01295         dtutc.setTimeSpec(Qt::UTC);
01296         const int count = d->transitions.count();
01297         const int next = (index >= 0) ? index + 1 : 0;
01298         if (next < count)
01299         {
01300             KTimeZone::Phase nextPhase = d->transitions[next].phase();
01301             const int offset = (index >= 0) ? d->transitions[index].phase().utcOffset() : d->prePhase.utcOffset();
01302             const int phaseDiff = nextPhase.utcOffset() - offset;
01303             if (phaseDiff > 0)
01304             {
01305                 // Get UTC equivalent as if 'dt' was in the next phase
01306                 if (dtutc.secsTo(d->transitions[next].time()) + nextPhase.utcOffset() < phaseDiff)
01307                 {
01308                     // The time falls in the gap between the two phases,
01309                     // so return an invalid value.
01310                     if (validTime)
01311                         *validTime = false;
01312                     if (secondIndex)
01313                         *secondIndex = -1;
01314                     return -1;
01315                 }
01316             }
01317         }
01318 
01319         if (index < 0)
01320         {
01321             // The specified time is before the first phase
01322             if (secondIndex)
01323                 *secondIndex = -1;
01324             return -1;
01325         }
01326 
01327         /* Check if it's a local time which occurs both before and after the 'latest'
01328          * phase start time (for which it has to span a daylight saving to standard
01329          * time change).
01330          */
01331         bool duplicate = true;
01332         if (d->isSecondOccurrence(dtutc, index))
01333         {
01334             // 'dt' occurs twice
01335             if (secondIndex)
01336             {
01337                 *secondIndex = index;
01338                 duplicate = false;
01339             }
01340             // Get the transition containing the first occurrence of 'dt'
01341             if (index <= 0)
01342                 return -1;   // first occurrence of 'dt' is just before the first transition
01343             --index;
01344         }
01345 
01346         if (secondIndex  &&  duplicate)
01347             *secondIndex = index;
01348         return index;
01349     }
01350 }
01351 
01352 QList<QDateTime> KTimeZoneData::transitionTimes(const KTimeZone::Phase &phase, const QDateTime &start, const QDateTime &end) const
01353 {
01354     QList<QDateTime> times;
01355     int ixstart, ixend;
01356     if (d->transitionIndexes(start, end, ixstart, ixend))
01357     {
01358         if (ixend < 0)
01359             ixend = d->transitions.count() - 1;
01360         while (ixstart <= ixend)
01361         {
01362             if (d->transitions[ixstart].phase() == phase)
01363                 times += d->transitions[ixstart].time();
01364         }
01365     }
01366     return times;
01367 }
01368 
01369 QList<KTimeZone::LeapSeconds> KTimeZoneData::leapSecondChanges() const
01370 {
01371     return d->leapChanges;
01372 }
01373 
01374 void KTimeZoneData::setLeapSecondChanges(const QList<KTimeZone::LeapSeconds> &adjusts)
01375 {
01376     d->leapChanges = adjusts;
01377 }
01378 
01379 KTimeZone::LeapSeconds KTimeZoneData::leapSecondChange(const QDateTime &utc) const
01380 {
01381     if (utc.timeSpec() != Qt::UTC)
01382         kError() << "KTimeZoneData::leapSecondChange(): non-UTC time specified" << endl;
01383     else
01384     {
01385         for (int i = d->leapChanges.count();  --i >= 0;  )
01386         {
01387             if (d->leapChanges[i].dateTime() < utc)
01388                 return d->leapChanges[i];
01389         }
01390     }
01391     return KTimeZone::LeapSeconds();
01392 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:49:33 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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