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 <config.h>
00031 #include "options.h"
00032 #include "fakes.h"
00033 
00034 #include <stdlib.h>
00035 
00036 #include <qdatetime.h>
00037 #include <qregexp.h>
00038 
00039 #include <kglobal.h>
00040 #include <kdebug.h>
00041 #include "libkcal/event.h"
00042 
00043 #include "pilotDateEntry.h"
00044 
00045 PilotDateEntry::PilotDateEntry(struct AppointmentAppInfo &appInfo):PilotRecordBase(), fAppInfo(appInfo)
00046 {
00047     ::memset(&fAppointmentInfo, 0, sizeof(struct Appointment));
00048 }
00049 
00050 /* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDateEntry()
00051 */
00052 PilotDateEntry::PilotDateEntry(struct AppointmentAppInfo &appInfo, PilotRecord * rec) :
00053     PilotRecordBase(rec),
00054     fAppInfo(appInfo)
00055 {
00056     ::memset(&fAppointmentInfo, 0, sizeof(fAppointmentInfo));
00057     if (rec)
00058     {
00059         pi_buffer_t b;
00060         b.data = (unsigned char *) rec->data();
00061         b.allocated = b.used = rec->size();
00062         unpack_Appointment(&fAppointmentInfo, &b, datebook_v1);
00063     }
00064     return;
00065 
00066 }
00067 
00068 void PilotDateEntry::_copyExceptions(const PilotDateEntry & e)
00069 {
00070     if (e.fAppointmentInfo.exceptions > 0)
00071     {
00072         size_t blocksize = e.fAppointmentInfo.exceptions *
00073             sizeof(struct tm);
00074 
00075         fAppointmentInfo.exception = (struct tm *)::malloc(blocksize);
00076 
00077         if (fAppointmentInfo.exception)
00078         {
00079             fAppointmentInfo.exceptions =
00080                 e.fAppointmentInfo.exceptions;
00081             ::memcpy(fAppointmentInfo.exception,
00082                 e.fAppointmentInfo.exception, blocksize);
00083         }
00084         else
00085         {
00086             kdError() << __FUNCTION__
00087                 << ": malloc() failed, exceptions not copied"
00088                 << endl;
00089             fAppointmentInfo.exceptions = 0;
00090         }
00091     }
00092     else
00093     {
00094         fAppointmentInfo.exceptions = 0;
00095         fAppointmentInfo.exception = 0L;
00096     }
00097 }
00098 
00099 
00100 PilotDateEntry::PilotDateEntry(const PilotDateEntry & e) :
00101     PilotRecordBase(e),
00102     fAppInfo(e.fAppInfo)
00103 {
00104     ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
00105         sizeof(struct Appointment));
00106     // See operator = for explanation
00107     fAppointmentInfo.exception = 0L;
00108     fAppointmentInfo.description = 0L;
00109     fAppointmentInfo.note = 0L;
00110 
00111     _copyExceptions(e);
00112     setDescriptionP(e.fAppointmentInfo.description);
00113     setNoteP(e.fAppointmentInfo.note);
00114 }
00115 
00116 
00117 PilotDateEntry & PilotDateEntry::operator = (const PilotDateEntry & e)
00118 {
00119     if (this != &e)     // Pointer equality!
00120     {
00121         KPILOT_FREE(fAppointmentInfo.exception);
00122         KPILOT_FREE(fAppointmentInfo.description);
00123         KPILOT_FREE(fAppointmentInfo.note);
00124         ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
00125             sizeof(fAppointmentInfo));
00126 
00127         // The original pointers were already freed; since we're now
00128         // got the pointers from the new structure and we're going
00129         // to use the standard set functions make sure that
00130         // we don't free() the copies-of-pointers from e, which
00131         // would be disastrous.
00132         //
00133         //
00134         fAppointmentInfo.exception = 0L;
00135         fAppointmentInfo.description = 0L;
00136         fAppointmentInfo.note = 0L;
00137 
00138         _copyExceptions(e);
00139         setDescriptionP(e.fAppointmentInfo.description);
00140         setNoteP(e.fAppointmentInfo.note);
00141     }
00142 
00143     return *this;
00144 }               // end of assignment operator
00145 
00146 
00147 QString PilotDateEntry::getTextRepresentation(bool richText)
00148 {
00149     QString text, tmp;
00150     QString par = richText?CSL1("<p>"):QString::null;
00151     QString ps = richText?CSL1("</p>"):CSL1("\n");
00152     QString br = richText?CSL1("<br/>"):CSL1("\n");
00153 
00154     // title + name
00155     text += par;
00156     tmp=richText?CSL1("<b><big>%1</big></b>"):CSL1("%1");
00157     text += tmp.arg(rtExpand(getDescription(), richText));
00158     text += ps;
00159 
00160     QDateTime dt(readTm(getEventStart()));
00161     QString startDate(dt.toString(Qt::LocalDate));
00162     text+=par;
00163     text+=i18n("Start date: %1").arg(startDate);
00164     text+=ps;
00165 
00166     if (isEvent())
00167     {
00168         text+=par;
00169         text+=i18n("Whole-day event");
00170         text+=ps;
00171     }
00172     else
00173     {
00174         dt=readTm(getEventEnd());
00175         QString endDate(dt.toString(Qt::LocalDate));
00176         text+=par;
00177         text+=i18n("End date: %1").arg(endDate);
00178         text+=ps;
00179     }
00180 
00181     if ( isAlarmEnabled() )
00182     {
00183         text+=par;
00184         tmp=i18n("%1 is the duration, %2 is the time unit", "Alarm: %1 %2 before event starts").
00185             arg(getAdvance());
00186         switch (getAdvanceUnits())
00187         {
00188             case advMinutes: tmp=tmp.arg(i18n("minutes")); break;
00189             case advHours: tmp=tmp.arg(i18n("hours")); break;
00190             case advDays: tmp=tmp.arg(i18n("days")); break;
00191             default: tmp=tmp.arg(QString::null); break;;
00192         }
00193         text+=tmp;
00194         text+=ps;
00195     }
00196 
00197     if (getRepeatType() != repeatNone)
00198     {
00199         text+=par;
00200         tmp=i18n("Recurrence: every %1 %2");
00201         int freq = getRepeatFrequency();
00202         tmp=tmp.arg(freq);
00203 
00204         switch(getRepeatType())
00205         {
00206             case repeatDaily: tmp=tmp.arg(i18n("day(s)")); break;
00207             case repeatWeekly: tmp=tmp.arg(i18n("week(s)")); break;
00208             case repeatMonthlyByDay:
00209             case repeatMonthlyByDate: tmp=tmp.arg(i18n("month(s)")); break;
00210             case repeatYearly: tmp=tmp.arg(i18n("year(s)")); break;
00211             default: tmp=tmp.arg(QString::null); break;
00212         }
00213         text+=tmp;
00214         text+=br;
00215 
00216         bool repeatsForever = getRepeatForever();
00217         if (repeatsForever)
00218         {
00219             text+=i18n("Repeats indefinitely");
00220         }
00221         else
00222         {
00223             dt = readTm(getRepeatEnd()).date();
00224             text+=i18n("Until %1").arg(dt.toString(Qt::LocalDate));
00225         }
00226         text+=br;
00227 
00228         if (getRepeatType()==repeatMonthlyByDay) text+=i18n("Repeating on the i-th day of week j")+br;
00229         if (getRepeatType()==repeatMonthlyByDate) text+=i18n("Repeating on the n-th day of the month")+br;
00230         // TODO: show the dayArray when repeating weekly
00231         /*QBitArray dayArray(7);
00232         if (getRepeatType()==repeatWeekly) text+=i18n("Repeat day flags: %1").arg(getRepeatDays
00233         const int *days = dateEntry->getRepeatDays();
00234         // Rotate the days of the week, since day numbers on the Pilot and
00235         // in vCal / Events are different.
00236         if (days[0]) dayArray.setBit(6);
00237         for (int i = 1; i < 7; i++)
00238         {
00239             if (days[i]) dayArray.setBit(i-1);
00240         }*/
00241         text+=ps;
00242     }
00243 
00244     if (getExceptionCount()>0 )
00245     {
00246         text+=par;
00247         text+=i18n("Exceptions:")+br;
00248         for (int i = 0; i < getExceptionCount(); i++)
00249         {
00250             QDate exdt=readTm(getExceptions()[i]).date();
00251             text+=exdt.toString(Qt::LocalDate);
00252             text+=br;
00253         }
00254         text+=ps;
00255     }
00256 
00257     if (!getNote().isEmpty())
00258     {
00259         text += richText?CSL1("<hr/>"):CSL1("-------------------------\n");
00260         text+=par;
00261         text+=richText?i18n("<b><em>Note:</em></b><br>"):i18n("Note:\n");
00262         text+=rtExpand(getNote(), richText);
00263         text+=ps;
00264     }
00265 
00266     return text;
00267 }
00268 
00269 QDateTime PilotDateEntry::dtStart() const
00270 {
00271     FUNCTIONSETUP;
00272     return readTm( getEventStart() );
00273 }
00274 
00275 QDateTime PilotDateEntry::dtEnd() const
00276 {
00277     FUNCTIONSETUP;
00278     return readTm( getEventEnd() );
00279 }
00280 
00281 QDateTime PilotDateEntry::dtRepeatEnd() const
00282 {
00283     FUNCTIONSETUP;
00284     return readTm( getRepeatEnd() );
00285 }
00286 
00287 unsigned int PilotDateEntry::alarmLeadTime() const
00288 {
00289     FUNCTIONSETUP;
00290     if (!isAlarmEnabled()) return 0;
00291 
00292     int adv = getAdvance();
00293     if ( adv < 0 ) return 0; // Not possible to enter on the pilot
00294     unsigned int t = adv;
00295     int u = getAdvanceUnits();
00296 
00297 
00298     switch(u)
00299     {
00300     case advMinutes : t *= 60; break;
00301     case advHours : t *= 3600; break;
00302     case advDays : t *= 3600 * 24; break;
00303     default: t = 0;
00304     }
00305 
00306     return t;
00307 }
00308 
00309 QString PilotDateEntry::getCategoryLabel() const
00310 {
00311     return Pilot::fromPilot(fAppInfo.category.name[category()]);
00312 }
00313 
00314 PilotRecord *PilotDateEntry::pack() const
00315 {
00316     int i;
00317 
00318     pi_buffer_t *b = pi_buffer_new( sizeof(fAppointmentInfo) );
00319     i = pack_Appointment(const_cast<Appointment_t *>(&fAppointmentInfo), b, datebook_v1);
00320     if (i<0)
00321     {
00322         // Generic error from the pack_*() functions.
00323         return 0;
00324     }
00325 
00326     // pack_Appointment sets b->used
00327     return new PilotRecord( b, this );
00328 }
00329 
00330 /* setExceptions sets a new set of exceptions. Note that
00331     PilotDateEntry assumes ownership of the array and will
00332     delete the old one. */
00333 void PilotDateEntry::setExceptions(struct tm *e) {
00334     if (fAppointmentInfo.exception != e)
00335     {
00336         KPILOT_FREE(fAppointmentInfo.exception);
00337     }
00338     fAppointmentInfo.exception=e;
00339 }
00340 
00341 
00342 void PilotDateEntry::setDescriptionP(const char *desc, int l)
00343 {
00344     FUNCTIONSETUP;
00345     KPILOT_FREE(fAppointmentInfo.description);
00346 
00347     if (desc && *desc)
00348     {
00349         if (-1 == l) l=::strlen(desc);
00350         fAppointmentInfo.description =
00351             (char *) ::malloc(l + 1);
00352         if (fAppointmentInfo.description)
00353         {
00354             strlcpy(fAppointmentInfo.description, desc, l+1);
00355         }
00356         else
00357         {
00358             kdError() << __FUNCTION__
00359                 << ": malloc() failed, description not set"
00360                 << endl;
00361         }
00362     }
00363     else
00364     {
00365         fAppointmentInfo.description = 0L;
00366     }
00367 }
00368 
00369 void PilotDateEntry::setNoteP(const char *note, int l)
00370 {
00371     FUNCTIONSETUP;
00372     KPILOT_FREE(fAppointmentInfo.note);
00373 
00374     if (note && *note)
00375     {
00376         if (-1 == l) l=::strlen(note);
00377         fAppointmentInfo.note = (char *)::malloc(l + 1);
00378         if (fAppointmentInfo.note)
00379         {
00380             strlcpy(fAppointmentInfo.note, note,l+1);
00381         }
00382         else
00383         {
00384             kdError() << __FUNCTION__
00385                 << ": malloc() failed, note not set" << endl;
00386         }
00387     }
00388     else
00389     {
00390         fAppointmentInfo.note = 0L;
00391     }
00392 }
00393 
00394 void PilotDateEntry::setNote(const QString &s)
00395 {
00396     QCString t = Pilot::toPilot(s);
00397     setNoteP( t.data(),t.length() );
00398 }
00399 
00400 void PilotDateEntry::setLocation(const QString &s)
00401 {
00402     QString note = Pilot::fromPilot(getNoteP());
00403     QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");
00404 
00405     if( s.isNull() )
00406     {
00407         note.replace(rxp,"");
00408     }
00409     else
00410     {
00411         QString location = "Location: " + s + "\n";
00412         int pos = note.find(rxp);
00413 
00414         if(pos >= 0)
00415         {
00416             note.replace( rxp, location );
00417         }
00418         else
00419         {
00420             note = location + note;
00421             setNote( note );
00422         }
00423     }
00424 }
00425 
00426 QString PilotDateEntry::getLocation() const
00427 {
00428     // Read the complete note here and not the filtered
00429     // one from PilotDateEntry::getNote();
00430     QString note = Pilot::fromPilot(getNoteP());
00431     QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");
00432     int pos = note.find(rxp, 0);
00433 
00434     if(pos >= 0)
00435     {
00436         QString location = rxp.capturedTexts().first();
00437         rxp = QRegExp("^[Ll]ocation:[\\s|\t]*");
00438         location.replace(rxp,"");
00439         location.replace("\n", "");
00440         return location;
00441     }
00442     else
00443     {
00444         return "";
00445     }
00446 }
00447 
00448 void PilotDateEntry::setDescription(const QString &s)
00449 {
00450     QCString t = Pilot::toPilot(s);
00451     setDescriptionP( t.data(),t.length() );
00452 }
00453 
00454 QString PilotDateEntry::getNote() const
00455 {
00456     QString note = Pilot::fromPilot(getNoteP());
00457     QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");
00458     note.replace(rxp, "" );
00459     return note;
00460 }
00461 
00462 QString PilotDateEntry::getDescription() const
00463 {
00464     return Pilot::fromPilot(getDescriptionP());
00465 }
00466 
KDE Home | KDE Accessibility Home | Description of Access Keys