summaryrefslogtreecommitdiffstats
path: root/lib/pilotDateEntry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pilotDateEntry.cpp')
-rw-r--r--lib/pilotDateEntry.cpp478
1 files changed, 478 insertions, 0 deletions
diff --git a/lib/pilotDateEntry.cpp b/lib/pilotDateEntry.cpp
new file mode 100644
index 0000000..58da804
--- /dev/null
+++ b/lib/pilotDateEntry.cpp
@@ -0,0 +1,478 @@
+/* KPilot
+**
+** Copyright (C) 1998-2001 by Dan Pilone
+** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
+**
+** This is a C++ wrapper for the Pilot's datebook structures.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <stdlib.h>
+
+#include <tqdatetime.h>
+#include <tqnamespace.h>
+#include <tqregexp.h>
+
+#include <tdeglobal.h>
+
+#include "pilotDateEntry.h"
+
+static const char *default_date_category_names[] = {
+ "Unfiled",
+ "Business",
+ "Personal",
+ 0L
+} ;
+
+void PilotDateInfo::resetToDefault()
+{
+ FUNCTIONSETUP;
+ // Reset to all 0s
+ memset(&fInfo,0,sizeof(fInfo));
+ // Fill up default categories
+ for (unsigned int i=0; (i<4) && default_date_category_names[i]; ++i)
+ {
+ strncpy(fInfo.category.name[i],default_date_category_names[i],sizeof(fInfo.category.name[0]));
+ }
+
+ fInfo.startOfWeek = 0;
+
+}
+
+
+PilotDateEntry::PilotDateEntry():PilotRecordBase()
+{
+ ::memset(&fAppointmentInfo, 0, sizeof(struct Appointment));
+}
+
+/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDateEntry()
+*/
+PilotDateEntry::PilotDateEntry(PilotRecord * rec) :
+ PilotRecordBase(rec)
+{
+ ::memset(&fAppointmentInfo, 0, sizeof(fAppointmentInfo));
+ if (rec)
+ {
+ // Construct a fake pi_buffer for unpack_Appointment.
+ // No ownership changes occur here.
+ pi_buffer_t b = { (unsigned char *) rec->data(), rec->size(), rec->size() } ;
+ unpack_Appointment(&fAppointmentInfo, &b, datebook_v1);
+ }
+ return;
+
+}
+
+void PilotDateEntry::_copyExceptions(const PilotDateEntry & e)
+{
+ if (e.fAppointmentInfo.exceptions > 0)
+ {
+ size_t blocksize = e.fAppointmentInfo.exceptions *
+ sizeof(struct tm);
+
+ fAppointmentInfo.exception = (struct tm *)::malloc(blocksize);
+
+ if (fAppointmentInfo.exception)
+ {
+ fAppointmentInfo.exceptions =
+ e.fAppointmentInfo.exceptions;
+ ::memcpy(fAppointmentInfo.exception,
+ e.fAppointmentInfo.exception, blocksize);
+ }
+ else
+ {
+ WARNINGKPILOT << "malloc() failed, exceptions not copied" << endl;
+ fAppointmentInfo.exceptions = 0;
+ }
+ }
+ else
+ {
+ fAppointmentInfo.exceptions = 0;
+ fAppointmentInfo.exception = 0L;
+ }
+}
+
+
+PilotDateEntry::PilotDateEntry(const PilotDateEntry & e) :
+ PilotRecordBase(e)
+{
+ ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
+ sizeof(struct Appointment));
+ // See operator = for explanation
+ fAppointmentInfo.exception = 0L;
+ fAppointmentInfo.description = 0L;
+ fAppointmentInfo.note = 0L;
+
+ _copyExceptions(e);
+ setDescriptionP(e.fAppointmentInfo.description);
+ setNoteP(e.fAppointmentInfo.note);
+}
+
+
+PilotDateEntry & PilotDateEntry::operator = (const PilotDateEntry & e)
+{
+ if (this != &e) // Pointer equality!
+ {
+ KPILOT_FREE(fAppointmentInfo.exception);
+ KPILOT_FREE(fAppointmentInfo.description);
+ KPILOT_FREE(fAppointmentInfo.note);
+ ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
+ sizeof(fAppointmentInfo));
+
+ // The original pointers were already freed; since we're now
+ // got the pointers from the new structure and we're going
+ // to use the standard set functions make sure that
+ // we don't free() the copies-of-pointers from e, which
+ // would be disastrous.
+ //
+ //
+ fAppointmentInfo.exception = 0L;
+ fAppointmentInfo.description = 0L;
+ fAppointmentInfo.note = 0L;
+
+ _copyExceptions(e);
+ setDescriptionP(e.fAppointmentInfo.description);
+ setNoteP(e.fAppointmentInfo.note);
+ }
+
+ return *this;
+} // end of assignment operator
+
+
+TQString PilotDateEntry::getTextRepresentation(TQt::TextFormat richText)
+{
+ TQString text, tmp;
+ TQString par = (richText==TQt::RichText) ?CSL1("<p>"):TQString();
+ TQString ps = (richText==TQt::RichText) ?CSL1("</p>"):CSL1("\n");
+ TQString br = (richText==TQt::RichText) ?CSL1("<br/>"):CSL1("\n");
+
+ // title + name
+ text += par;
+ tmp=richText?CSL1("<b><big>%1</big></b>"):CSL1("%1");
+ text += tmp.arg(rtExpand(getDescription(), richText));
+ text += ps;
+
+ TQDateTime dt(readTm(getEventStart()));
+ TQString startDate(dt.toString(Qt::LocalDate));
+ text+=par;
+ text+=i18n("Start date: %1").arg(startDate);
+ text+=ps;
+
+ if (isEvent())
+ {
+ text+=par;
+ text+=i18n("Whole-day event");
+ text+=ps;
+ }
+ else
+ {
+ dt=readTm(getEventEnd());
+ TQString endDate(dt.toString(Qt::LocalDate));
+ text+=par;
+ text+=i18n("End date: %1").arg(endDate);
+ text+=ps;
+ }
+
+ if ( isAlarmEnabled() )
+ {
+ text+=par;
+ tmp=i18n("%1 is the duration, %2 is the time unit", "Alarm: %1 %2 before event starts").
+ arg(getAdvance());
+ switch (getAdvanceUnits())
+ {
+ case advMinutes: tmp=tmp.arg(i18n("minutes")); break;
+ case advHours: tmp=tmp.arg(i18n("hours")); break;
+ case advDays: tmp=tmp.arg(i18n("days")); break;
+ default: tmp=tmp.arg(TQString()); break;;
+ }
+ text+=tmp;
+ text+=ps;
+ }
+
+ if (getRepeatType() != repeatNone)
+ {
+ text+=par;
+ tmp=i18n("Recurrence: every %1 %2");
+ int freq = getRepeatFrequency();
+ tmp=tmp.arg(freq);
+
+ switch(getRepeatType())
+ {
+ case repeatDaily: tmp=tmp.arg(i18n("day(s)")); break;
+ case repeatWeekly: tmp=tmp.arg(i18n("week(s)")); break;
+ case repeatMonthlyByDay:
+ case repeatMonthlyByDate: tmp=tmp.arg(i18n("month(s)")); break;
+ case repeatYearly: tmp=tmp.arg(i18n("year(s)")); break;
+ default: tmp=tmp.arg(TQString()); break;
+ }
+ text+=tmp;
+ text+=br;
+
+ bool repeatsForever = getRepeatForever();
+ if (repeatsForever)
+ {
+ text+=i18n("Repeats indefinitely");
+ }
+ else
+ {
+ dt = readTm(getRepeatEnd()).date();
+ text+=i18n("Until %1").arg(dt.toString(Qt::LocalDate));
+ }
+ text+=br;
+
+ if (getRepeatType()==repeatMonthlyByDay) text+=i18n("Repeating on the i-th day of week j")+br;
+ if (getRepeatType()==repeatMonthlyByDate) text+=i18n("Repeating on the n-th day of the month")+br;
+ // TODO: show the dayArray when repeating weekly
+ /*TQBitArray dayArray(7);
+ if (getRepeatType()==repeatWeekly) text+=i18n("Repeat day flags: %1").arg(getRepeatDays
+ const int *days = dateEntry->getRepeatDays();
+ // Rotate the days of the week, since day numbers on the Pilot and
+ // in vCal / Events are different.
+ if (days[0]) dayArray.setBit(6);
+ for (int i = 1; i < 7; i++)
+ {
+ if (days[i]) dayArray.setBit(i-1);
+ }*/
+ text+=ps;
+ }
+
+ if (getExceptionCount()>0 )
+ {
+ text+=par;
+ text+=i18n("Exceptions:")+br;
+ for (int i = 0; i < getExceptionCount(); i++)
+ {
+ TQDate exdt=readTm(getExceptions()[i]).date();
+ text+=exdt.toString(Qt::LocalDate);
+ text+=br;
+ }
+ text+=ps;
+ }
+
+ if (!getNote().isEmpty())
+ {
+ text += richText?CSL1("<hr/>"):CSL1("-------------------------\n");
+ text+=par;
+ text+=richText?i18n("<b><em>Note:</em></b><br>"):i18n("Note:\n");
+ text+=rtExpand(getNote(), richText);
+ text+=ps;
+ }
+
+ return text;
+}
+
+TQDateTime PilotDateEntry::dtStart() const
+{
+ FUNCTIONSETUP;
+ return readTm( getEventStart() );
+}
+
+TQDateTime PilotDateEntry::dtEnd() const
+{
+ FUNCTIONSETUP;
+ return readTm( getEventEnd() );
+}
+
+TQDateTime PilotDateEntry::dtRepeatEnd() const
+{
+ FUNCTIONSETUP;
+ return readTm( getRepeatEnd() );
+}
+
+unsigned int PilotDateEntry::alarmLeadTime() const
+{
+ FUNCTIONSETUP;
+ if (!isAlarmEnabled()) return 0;
+
+ int adv = getAdvance();
+ if ( adv < 0 )
+ {
+ return 0; // Not possible to enter on the pilot
+ }
+ unsigned int t = adv;
+ int u = getAdvanceUnits();
+
+
+ switch(u)
+ {
+ case advMinutes : t *= 60; break;
+ case advHours : t *= 3600; break;
+ case advDays : t *= 3600 * 24; break;
+ default: t = 0;
+ }
+
+ return t;
+}
+
+PilotRecord *PilotDateEntry::pack() const
+{
+ int i;
+
+ pi_buffer_t *b = pi_buffer_new( sizeof(fAppointmentInfo) );
+ i = pack_Appointment(const_cast<Appointment_t *>(&fAppointmentInfo), b, datebook_v1);
+ if (i<0)
+ {
+ // Generic error from the pack_*() functions.
+ return 0;
+ }
+
+ // pack_Appointment sets b->used
+ return new PilotRecord( b, this );
+}
+
+/* setExceptions sets a new set of exceptions. Note that
+ PilotDateEntry assumes ownership of the array and will
+ delete the old one. */
+void PilotDateEntry::setExceptions(struct tm *e) {
+ if (fAppointmentInfo.exception != e)
+ {
+ KPILOT_FREE(fAppointmentInfo.exception);
+ }
+ fAppointmentInfo.exception=e;
+}
+
+
+void PilotDateEntry::setDescriptionP(const char *desc, int l)
+{
+ FUNCTIONSETUP;
+ KPILOT_FREE(fAppointmentInfo.description);
+
+ if (desc && *desc)
+ {
+ if (-1 == l) l=::strlen(desc);
+ fAppointmentInfo.description =
+ (char *) ::malloc(l + 1);
+ if (fAppointmentInfo.description)
+ {
+ strlcpy(fAppointmentInfo.description, desc, l+1);
+ }
+ else
+ {
+ WARNINGKPILOT << "malloc() failed, description not set" << endl;
+ }
+ }
+ else
+ {
+ fAppointmentInfo.description = 0L;
+ }
+}
+
+void PilotDateEntry::setNoteP(const char *note, int l)
+{
+ FUNCTIONSETUP;
+ KPILOT_FREE(fAppointmentInfo.note);
+
+ if (note && *note)
+ {
+ if (-1 == l) l=::strlen(note);
+ fAppointmentInfo.note = (char *)::malloc(l + 1);
+ if (fAppointmentInfo.note)
+ {
+ strlcpy(fAppointmentInfo.note, note,l+1);
+ }
+ else
+ {
+ WARNINGKPILOT << "malloc() failed, note not set" << endl;
+ }
+ }
+ else
+ {
+ fAppointmentInfo.note = 0L;
+ }
+}
+
+void PilotDateEntry::setNote(const TQString &s)
+{
+ TQCString t = Pilot::toPilot(s);
+ setNoteP( t.data(),t.length() );
+}
+
+void PilotDateEntry::setLocation(const TQString &s)
+{
+ TQString note = Pilot::fromPilot(getNoteP());
+ TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n");
+
+ // per TQString docs, this covers null and 0 length
+ if( s.isEmpty() )
+ {
+ note.replace(rxp,"");
+ }
+ else
+ {
+ TQString location = "Location: " + s + "\n";
+ int pos = note.find(rxp);
+
+ if(pos >= 0)
+ {
+ note.replace( rxp, location );
+ }
+ else
+ {
+ note = location + note;
+ setNote( note );
+ }
+ }
+}
+
+TQString PilotDateEntry::getLocation() const
+{
+ // Read the complete note here and not the filtered
+ // one from PilotDateEntry::getNote();
+ TQString note = Pilot::fromPilot(getNoteP());
+ TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n");
+ int pos = note.find(rxp, 0);
+
+ if(pos >= 0)
+ {
+ TQString location = rxp.capturedTexts().first();
+ rxp = TQRegExp("^[Ll]ocation:[\\s|\t]*");
+ location.replace(rxp,"");
+ location.replace("\n", "");
+ return location;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+void PilotDateEntry::setDescription(const TQString &s)
+{
+ TQCString t = Pilot::toPilot(s);
+ setDescriptionP( t.data(),t.length() );
+}
+
+TQString PilotDateEntry::getNote() const
+{
+ TQString note = Pilot::fromPilot(getNoteP());
+ TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n");
+ note.replace(rxp, "" );
+ return note;
+}
+
+TQString PilotDateEntry::getDescription() const
+{
+ return Pilot::fromPilot(getDescriptionP());
+}
+