kpilot/lib

pilotDateEntry.cc

00001 /* KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 ** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 **
00006 ** This is a C++ wrapper for the Pilot's datebook structures.
00007 */
00008 
00009 /*
00010 ** This program is free software; you can redistribute it and/or modify
00011 ** it under the terms of the GNU Lesser General Public License as published by
00012 ** the Free Software Foundation; either version 2.1 of the License, or
00013 ** (at your option) any later version.
00014 **
00015 ** This program is distributed in the hope that it will be useful,
00016 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018 ** GNU Lesser General Public License for more details.
00019 **
00020 ** You should have received a copy of the GNU Lesser General Public License
00021 ** along with this program in a file called COPYING; if not, write to
00022 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00023 ** MA 02110-1301, USA.
00024 */
00025 
00026 /*
00027 ** Bug reports and questions can be sent to kde-pim@kde.org
00028 */
00029 
00030 #include "options.h"
00031 
00032 #include <stdlib.h>
00033 
00034 #include <qtextcodec.h>
00035 #include <qdatetime.h>
00036 
00037 #include <kglobal.h>
00038 #include <kdebug.h>
00039 #include "libkcal/event.h"
00040 
00041 #include "pilotDateEntry.h"
00042 
00043 static const char *pilotDateEntry_id = "$Id: pilotDateEntry.cc 437980 2005-07-23 19:53:57Z kainhofe $";
00044 const int PilotDateEntry::APP_BUFFER_SIZE = 0xffff;
00045 
00046 
00047 PilotDateEntry::PilotDateEntry(struct AppointmentAppInfo &appInfo):PilotAppCategory(), fAppInfo(appInfo)
00048 {
00049     ::memset(&fAppointmentInfo, 0, sizeof(struct Appointment));
00050 }
00051 
00052 /* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDateEntry()
00053 */
00054 PilotDateEntry::PilotDateEntry(struct AppointmentAppInfo &appInfo, PilotRecord * rec) :
00055     PilotAppCategory(rec),
00056     fAppInfo(appInfo)
00057 {
00058     ::memset(&fAppointmentInfo, 0, sizeof(fAppointmentInfo));
00059     if (rec)
00060     {
00061 #if PILOT_LINK_NUMBER >= PILOT_LINK_0_12_0
00062         pi_buffer_t b;
00063         b.data = (unsigned char *) rec->getData();
00064         b.allocated = b.used = rec->size();
00065         unpack_Appointment(&fAppointmentInfo, &b, datebook_v1);
00066 #else
00067         unpack_Appointment(&fAppointmentInfo,
00068             (unsigned char *) rec->data(), rec->size());
00069 #endif
00070     }
00071     return;
00072 
00073     /* NOTREACHED */
00074     /* Included to avoid warning that id isn't used. */
00075     (void) pilotDateEntry_id;
00076 }
00077 
00078 void PilotDateEntry::_copyExceptions(const PilotDateEntry & e)
00079 {
00080     if (e.fAppointmentInfo.exceptions > 0)
00081     {
00082         size_t blocksize = e.fAppointmentInfo.exceptions *
00083             sizeof(struct tm);
00084 
00085         fAppointmentInfo.exception = (struct tm *)::malloc(blocksize);
00086 
00087         if (fAppointmentInfo.exception)
00088         {
00089             fAppointmentInfo.exceptions =
00090                 e.fAppointmentInfo.exceptions;
00091             ::memcpy(fAppointmentInfo.exception,
00092                 e.fAppointmentInfo.exception, blocksize);
00093         }
00094         else
00095         {
00096             kdError() << __FUNCTION__
00097                 << ": malloc() failed, exceptions not copied"
00098                 << endl;
00099             fAppointmentInfo.exceptions = 0;
00100         }
00101     }
00102     else
00103     {
00104         fAppointmentInfo.exceptions = 0;
00105         fAppointmentInfo.exception = 0L;
00106     }
00107 }
00108 
00109 
00110 PilotDateEntry::PilotDateEntry(const PilotDateEntry & e) :
00111     PilotAppCategory(e),
00112     fAppInfo(e.fAppInfo)
00113 {
00114     ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
00115         sizeof(struct Appointment));
00116     // See operator = for explanation
00117     fAppointmentInfo.exception = 0L;
00118     fAppointmentInfo.description = 0L;
00119     fAppointmentInfo.note = 0L;
00120 
00121     _copyExceptions(e);
00122     setDescriptionP(e.fAppointmentInfo.description);
00123     setNoteP(e.fAppointmentInfo.note);
00124 }
00125 
00126 
00127 PilotDateEntry & PilotDateEntry::operator = (const PilotDateEntry & e)
00128 {
00129     if (this != &e)     // Pointer equality!
00130     {
00131         KPILOT_FREE(fAppointmentInfo.exception);
00132         KPILOT_FREE(fAppointmentInfo.description);
00133         KPILOT_FREE(fAppointmentInfo.note);
00134         ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
00135             sizeof(fAppointmentInfo));
00136 
00137         // The original pointers were already freed; since we're now
00138         // got the pointers from the new structure and we're going
00139         // to use the standard set functions make sure that
00140         // we don't free() the copies-of-pointers from e, which
00141         // would be disastrous.
00142         //
00143         //
00144         fAppointmentInfo.exception = 0L;
00145         fAppointmentInfo.description = 0L;
00146         fAppointmentInfo.note = 0L;
00147 
00148         _copyExceptions(e);
00149         setDescriptionP(e.fAppointmentInfo.description);
00150         setNoteP(e.fAppointmentInfo.note);
00151     }
00152 
00153     return *this;
00154 }               // end of assignment operator
00155 
00156 
00157 QString PilotDateEntry::getTextRepresentation(bool richText)
00158 {
00159     QString text, tmp;
00160     QString par = richText?CSL1("<p>"):QString::null;
00161     QString ps = richText?CSL1("</p>"):CSL1("\n");
00162     QString br = richText?CSL1("<br/>"):CSL1("\n");
00163 
00164     // title + name
00165     text += par;
00166     tmp=richText?CSL1("<b><big>%1</big></b>"):CSL1("%1");
00167     text += tmp.arg(rtExpand(getDescription(), richText));
00168     text += ps;
00169 
00170     QDateTime dt(readTm(getEventStart()));
00171     QString startDate(dt.toString(Qt::LocalDate));
00172     text+=par;
00173     text+=i18n("Start date: %1").arg(startDate);
00174     text+=ps;
00175 
00176     if (isEvent())
00177     {
00178         text+=par;
00179         text+=i18n("Whole-day event");
00180         text+=ps;
00181     }
00182     else
00183     {
00184         dt=readTm(getEventEnd());
00185         QString endDate(dt.toString(Qt::LocalDate));
00186         text+=par;
00187         text+=i18n("End date: %1").arg(endDate);
00188         text+=ps;
00189     }
00190 
00191     if ( isAlarmEnabled() )
00192     {
00193         text+=par;
00194         tmp=i18n("%1 is the duration, %2 is the time unit", "Alarm: %1 %2 before event starts").
00195             arg(getAdvance());
00196         switch (getAdvanceUnits())
00197         {
00198             case advMinutes: tmp=tmp.arg(i18n("minutes")); break;
00199             case advHours: tmp=tmp.arg(i18n("hours")); break;
00200             case advDays: tmp=tmp.arg(i18n("days")); break;
00201             default: tmp=tmp.arg(QString::null); break;;
00202         }
00203         text+=tmp;
00204         text+=ps;
00205     }
00206 
00207     if (getRepeatType() != repeatNone)
00208     {
00209         text+=par;
00210         tmp=i18n("Recurrence: every %1 %2");
00211         int freq = getRepeatFrequency();
00212         tmp=tmp.arg(freq);
00213 
00214         switch(getRepeatType())
00215         {
00216             case repeatDaily: tmp=tmp.arg(i18n("day(s)")); break;
00217             case repeatWeekly: tmp=tmp.arg(i18n("week(s)")); break;
00218             case repeatMonthlyByDay:
00219             case repeatMonthlyByDate: tmp=tmp.arg(i18n("month(s)")); break;
00220             case repeatYearly: tmp=tmp.arg(i18n("year(s)")); break;
00221             default: tmp=tmp.arg(QString::null); break;
00222         }
00223         text+=tmp;
00224         text+=br;
00225 
00226         bool repeatsForever = getRepeatForever();
00227         if (repeatsForever)
00228         {
00229             text+=i18n("Repeats indefinitely");
00230         }
00231         else
00232         {
00233             dt = readTm(getRepeatEnd()).date();
00234             text+=i18n("Until %1").arg(dt.toString(Qt::LocalDate));
00235         }
00236         text+=br;
00237 
00238         if (getRepeatType()==repeatMonthlyByDay) text+=i18n("Repeating on the i-th day of week j")+br;
00239         if (getRepeatType()==repeatMonthlyByDate) text+=i18n("Repeating on the n-th day of the month")+br;
00240         // TODO: show the dayArray when repeating weekly
00241         /*QBitArray dayArray(7);
00242         if (getRepeatType()==repeatWeekly) text+=i18n("Repeat day flags: %1").arg(getRepeatDays
00243         const int *days = dateEntry->getRepeatDays();
00244         // Rotate the days of the week, since day numbers on the Pilot and
00245         // in vCal / Events are different.
00246         if (days[0]) dayArray.setBit(6);
00247         for (int i = 1; i < 7; i++)
00248         {
00249             if (days[i]) dayArray.setBit(i-1);
00250         }*/
00251         text+=ps;
00252     }
00253 
00254     if (getExceptionCount()>0 )
00255     {
00256         text+=par;
00257         text+=i18n("Exceptions:")+br;
00258         for (int i = 0; i < getExceptionCount(); i++)
00259         {
00260             QDate exdt=readTm(getExceptions()[i]).date();
00261             text+=exdt.toString(Qt::LocalDate);
00262             text+=br;
00263         }
00264         text+=ps;
00265     }
00266 
00267     if (!getNote().isEmpty())
00268     {
00269         text += richText?CSL1("<hr/>"):CSL1("-------------------------\n");
00270         text+=par;
00271         text+=richText?i18n("<b><em>Note:</em></b><br>"):i18n("Note:\n");
00272         text+=rtExpand(getNote(), richText);
00273         text+=ps;
00274     }
00275 
00276     return text;
00277 }
00278 
00279 QDateTime PilotDateEntry::dtStart() const
00280 {
00281     FUNCTIONSETUP;
00282     return readTm( getEventStart() );
00283 }
00284 
00285 QDateTime PilotDateEntry::dtEnd() const
00286 {
00287     FUNCTIONSETUP;
00288     return readTm( getEventEnd() );
00289 }
00290 
00291 QDateTime PilotDateEntry::dtRepeatEnd() const
00292 {
00293     FUNCTIONSETUP;
00294     return readTm( getRepeatEnd() );
00295 }
00296 
00297 unsigned int PilotDateEntry::alarmLeadTime() const
00298 {
00299     FUNCTIONSETUP;
00300     if (!isAlarmEnabled()) return 0;
00301 
00302     int adv = getAdvance();
00303     if ( adv < 0 ) return 0; // Not possible to enter on the pilot
00304     unsigned int t = adv;
00305     int u = getAdvanceUnits();
00306 
00307 
00308     switch(u)
00309     {
00310     case advMinutes : t *= 60; break;
00311     case advHours : t *= 3600; break;
00312     case advDays : t *= 3600 * 24; break;
00313     default: t = 0;
00314     }
00315 
00316     return t;
00317 }
00318 
00319 QString PilotDateEntry::getCategoryLabel() const
00320 {
00321     return codec()->toUnicode(fAppInfo.category.name[category()]);
00322 }
00323 
00324 void *PilotDateEntry::pack_(void *buf, int *len)
00325 {
00326     int i;
00327 
00328 #if PILOT_LINK_NUMBER >= PILOT_LINK_0_12_0
00329     pi_buffer_t b = { 0,0,0 } ;
00330     i = pack_Appointment(&fAppointmentInfo, &b, datebook_v1);
00331     memcpy(buf,b.data,kMin(i,*len));
00332     *len = kMin(i,*len);
00333 #else
00334     i = pack_Appointment(&fAppointmentInfo, (unsigned char *) buf, *len);
00335     *len = i;
00336 #endif
00337     return buf;
00338 }
00339 
00340 /* setExceptions sets a new set of exceptions. Note that
00341     PilotDateEntry assumes ownership of the array and will
00342     delete the old one. */
00343 void PilotDateEntry::setExceptions(struct tm *e) {
00344     if (fAppointmentInfo.exception != e)
00345     {
00346         KPILOT_FREE(fAppointmentInfo.exception);
00347     }
00348     fAppointmentInfo.exception=e;
00349 }
00350 
00351 
00352 void PilotDateEntry::setDescriptionP(const char *desc, int l)
00353 {
00354     FUNCTIONSETUP;
00355     KPILOT_FREE(fAppointmentInfo.description);
00356 
00357     if (desc && *desc)
00358     {
00359         if (-1 == l) l=::strlen(desc);
00360         fAppointmentInfo.description =
00361             (char *) ::malloc(l + 1);
00362         if (fAppointmentInfo.description)
00363         {
00364             strlcpy(fAppointmentInfo.description, desc, l+1);
00365         }
00366         else
00367         {
00368             kdError() << __FUNCTION__
00369                 << ": malloc() failed, description not set"
00370                 << endl;
00371         }
00372     }
00373     else
00374     {
00375         fAppointmentInfo.description = 0L;
00376     }
00377 }
00378 
00379 void PilotDateEntry::setNoteP(const char *note, int l)
00380 {
00381     FUNCTIONSETUP;
00382     KPILOT_FREE(fAppointmentInfo.note);
00383 
00384     if (note && *note)
00385     {
00386         if (-1 == l) l=::strlen(note);
00387         fAppointmentInfo.note = (char *)::malloc(l + 1);
00388         if (fAppointmentInfo.note)
00389         {
00390             strlcpy(fAppointmentInfo.note, note,l+1);
00391         }
00392         else
00393         {
00394             kdError() << __FUNCTION__
00395                 << ": malloc() failed, note not set" << endl;
00396         }
00397     }
00398     else
00399     {
00400         fAppointmentInfo.note = 0L;
00401     }
00402 }
00403 
00404 void PilotDateEntry::setNote(const QString &s)
00405 {
00406     QCString t = codec()->fromUnicode(s);
00407     setNoteP( t.data(),t.length() );
00408 }
00409 
00410 void PilotDateEntry::setDescription(const QString &s)
00411 {
00412     QCString t = codec()->fromUnicode(s);
00413     setDescriptionP( t.data(),t.length() );
00414 }
00415 
00416 QString PilotDateEntry::getNote() const
00417 {
00418     return codec()->toUnicode(getNoteP());
00419 }
00420 
00421 QString PilotDateEntry::getDescription() const
00422 {
00423     return codec()->toUnicode(getDescriptionP());
00424 }
00425 
KDE Home | KDE Accessibility Home | Description of Access Keys