summaryrefslogtreecommitdiffabout
authorzautrix <zautrix>2005-02-13 11:55:52 (UTC)
committer zautrix <zautrix>2005-02-13 11:55:52 (UTC)
commit0a33f91e166747406ca2ccb5819881feeecfdb40 (patch) (side-by-side diff)
treee9130a16aaa6365e106d6733c3e1adeca01f72ac
parent00ec9899a4727a4c9100d320935dde7da4803801 (diff)
downloadkdepimpi-0a33f91e166747406ca2ccb5819881feeecfdb40.zip
kdepimpi-0a33f91e166747406ca2ccb5819881feeecfdb40.tar.gz
kdepimpi-0a33f91e166747406ca2ccb5819881feeecfdb40.tar.bz2
todo recurchanges
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--korganizer/koeditorgeneraltodo.cpp2
-rw-r--r--korganizer/koeditorgeneraltodo.h1
-rw-r--r--korganizer/koeditorrecurrence.cpp20
-rw-r--r--korganizer/koeditorrecurrence.h4
-rw-r--r--korganizer/kotodoeditor.cpp43
-rw-r--r--korganizer/kotodoeditor.h4
-rw-r--r--libkcal/icalformatimpl.cpp10
-rw-r--r--libkcal/incidence.cpp35
-rw-r--r--libkcal/incidence.h9
-rw-r--r--microkde/kdialogbase.h2
10 files changed, 119 insertions, 11 deletions
diff --git a/korganizer/koeditorgeneraltodo.cpp b/korganizer/koeditorgeneraltodo.cpp
index 6370b54..a9d1ed3 100644
--- a/korganizer/koeditorgeneraltodo.cpp
+++ b/korganizer/koeditorgeneraltodo.cpp
@@ -1,497 +1,499 @@
/*
This file is part of KOrganizer.
Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, permission is given to link this program
with any edition of Qt, and distribute the resulting executable,
without including the source code for Qt in the source distribution.
*/
#include <qtooltip.h>
#include <qfiledialog.h>
#include <qlayout.h>
#include <qvbox.h>
#include <qbuttongroup.h>
#include <qvgroupbox.h>
#include <qwidgetstack.h>
#include <qdatetime.h>
#include <qapplication.h>
#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <krestrictedline.h>
#include <kstandarddirs.h>
#include <kfiledialog.h>
#include <libkcal/todo.h>
#include <libkdepim/kdateedit.h>
#include "koprefs.h"
#include "ktimeedit.h"
#include "koeditorgeneraltodo.h"
#include "kolocationbox.h"
KOEditorGeneralTodo::KOEditorGeneralTodo(QObject* parent,
const char* name)
: KOEditorGeneral( parent, name)
{
}
KOEditorGeneralTodo::~KOEditorGeneralTodo()
{
}
void KOEditorGeneralTodo::finishSetup()
{
// QWidget::setTabOrder(mSummaryEdit, mLocationEdit);
// QWidget::setTabOrder(mLocationEdit, mDueCheck);
// QWidget::setTabOrder(mDueCheck, mDueDateEdit);
// QWidget::setTabOrder(mDueDateEdit, mDueTimeEdit);
// QWidget::setTabOrder(mDueTimeEdit, mStartCheck);
// QWidget::setTabOrder(mStartCheck, mStartDateEdit);
// QWidget::setTabOrder(mStartDateEdit, mStartTimeEdit);
// QWidget::setTabOrder(mStartTimeEdit, mTimeButton);
// QWidget::setTabOrder(mTimeButton, mCompletedCombo);
// QWidget::setTabOrder(mCompletedCombo, mPriorityCombo);
// QWidget::setTabOrder(mPriorityCombo, mAlarmButton);
// QWidget::setTabOrder(mAlarmButton, mCategoriesButton);
// QWidget::setTabOrder(mCategoriesButton, mSecrecyCombo);
// QWidget::setTabOrder(mSecrecyCombo, mDescriptionEdit);
mSummaryEdit->load(KOLocationBox::SUMMARYTODO);
mSummaryEdit->setFocus();
}
void KOEditorGeneralTodo::initTime(QWidget *parent,QBoxLayout *topLayout)
{
QBoxLayout *timeLayout = new QVBoxLayout(topLayout);
QGroupBox *timeGroupBox = new QGroupBox(1,QGroupBox::Horizontal,
i18n("Date && Time"),parent);
timeLayout->addWidget(timeGroupBox);
timeGroupBox->layout()->setSpacing( 0 );
timeGroupBox->layout()->setMargin( 5 );
QFrame *timeBoxFrame = new QFrame(timeGroupBox);
QGridLayout *layoutTimeBox = new QGridLayout(timeBoxFrame,3,3);
layoutTimeBox->setSpacing(topLayout->spacing());
layoutTimeBox->setColStretch( 1, 1 );
mDueCheck = new QCheckBox(i18n("Due:"),timeBoxFrame);
layoutTimeBox->addWidget(mDueCheck,0,0);
connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(enableDueEdit(bool)));
connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(showAlarm()));
mDueDateEdit = new KDateEdit(timeBoxFrame);
layoutTimeBox->addWidget(mDueDateEdit,0,1);
mDueTimeEdit = new KOTimeEdit(timeBoxFrame);
layoutTimeBox->addWidget(mDueTimeEdit,0,2);
mStartCheck = new QCheckBox(i18n("Start:"),timeBoxFrame);
layoutTimeBox->addWidget(mStartCheck,1,0);
connect(mStartCheck,SIGNAL(toggled(bool)),SLOT(enableStartEdit(bool)));
mStartDateEdit = new KDateEdit(timeBoxFrame);
layoutTimeBox->addWidget(mStartDateEdit,1,1);
mStartTimeEdit = new KOTimeEdit(timeBoxFrame);
layoutTimeBox->addWidget(mStartTimeEdit,1,2);
mTimeButton = new QCheckBox(i18n("Time associated"),timeBoxFrame);
layoutTimeBox->addMultiCellWidget(mTimeButton,2,2,0,1);
connect(mTimeButton,SIGNAL(toggled(bool)),SLOT(enableTimeEdits(bool)));
// some more layouting
//layoutTimeBox->setColStretch(3,1);
}
void KOEditorGeneralTodo::initCompletion(QWidget *parent, QBoxLayout *topLayout)
{
mCompletedCombo = new QComboBox(parent);
// xgettext:no-c-format
mCompletedCombo->insertItem(i18n(" 0 %"));
// xgettext:no-c-format
mCompletedCombo->insertItem(i18n(" 20 %"));
// xgettext:no-c-format
mCompletedCombo->insertItem(i18n(" 40 %"));
// xgettext:no-c-format
mCompletedCombo->insertItem(i18n(" 60 %"));
// xgettext:no-c-format
mCompletedCombo->insertItem(i18n(" 80 %"));
// xgettext:no-c-format
mCompletedCombo->insertItem(i18n("100 %"));
connect(mCompletedCombo,SIGNAL(activated(int)),SLOT(completedChanged(int)));
topLayout->addWidget(mCompletedCombo);
mCompletedLabel = new QLabel(i18n("completed"),parent);
topLayout->addWidget(mCompletedLabel);
mCompleteDateEdit = new KDateEdit(parent);
topLayout->addWidget(mCompleteDateEdit );
mCompleteTimeEdit = new KOTimeEdit(parent);
topLayout->addWidget( mCompleteTimeEdit);
mCompletedCombo->setSizePolicy( QSizePolicy( QSizePolicy::Preferred,QSizePolicy::Preferred) );
mCompletedLabel->setSizePolicy( QSizePolicy( QSizePolicy::Expanding,QSizePolicy::Preferred) );
if ( QApplication::desktop()->width() <= 480 ) {
if ( QApplication::desktop()->width() < 320 )
mCompleteDateEdit->setMaximumWidth( 85 );
else
mCompleteDateEdit->setMaximumWidth( 140 );
topLayout->setSpacing( 0 );
}
}
void KOEditorGeneralTodo::initPriority(QWidget *parent, QBoxLayout *topLayout)
{
QHBox* h = new QHBox ( parent );
topLayout->addWidget( h );
QLabel *priorityLabel = new QLabel(i18n("Priority:"), h);
// topLayout->addWidget(priorityLabel);
mPriorityCombo = new QComboBox( h );
mPriorityCombo->insertItem(i18n("1 (high)"));
mPriorityCombo->insertItem(i18n("2"));
mPriorityCombo->insertItem(i18n("3"));
mPriorityCombo->insertItem(i18n("4"));
mPriorityCombo->insertItem(i18n("5 (low)"));
//topLayout->addWidget(mPriorityCombo);
}
void KOEditorGeneralTodo::initStatus(QWidget *parent,QBoxLayout *topLayout)
{
QBoxLayout *statusLayout = new QHBoxLayout(topLayout);
initCompletion( parent, statusLayout );
statusLayout->addStretch( 1 );
initPriority( parent, statusLayout );
}
void KOEditorGeneralTodo::setDefaults(QDateTime due,bool allDay)
{
mSummaryEdit->load(KOLocationBox::SUMMARYTODO);
mLocationEdit->load(KOLocationBox::LOCATION);
KOEditorGeneral::setDefaults(allDay);
mTimeButton->setChecked( !allDay );
if(mTimeButton->isChecked()) {
mTimeButton->setEnabled(true);
}
else {
mTimeButton->setEnabled(false);
}
enableTimeEdits( !allDay );
if ( due.isValid() ) {
mDueCheck->setChecked(true);
enableDueEdit(true);
} else {
mDueCheck->setChecked(false);
enableDueEdit(false);
due = QDateTime::currentDateTime().addDays(7);
}
alarmDisable(true);
mStartCheck->setChecked(false);
enableStartEdit(false);
mDueDateEdit->setDate(due.date());
mDueTimeEdit->setTime(due.time());
due = due.addDays(-7);
mStartDateEdit->setDate(due.date());
mStartTimeEdit->setTime(due.time());
mPriorityCombo->setCurrentItem(2);
mCompletedLabel->setText(i18n(" completed"));;
mCompletedCombo->setCurrentItem(0);
mCompleteDateEdit->hide();
mCompleteTimeEdit->hide();
}
void KOEditorGeneralTodo::readTodo(Todo *todo)
{
mSummaryEdit->load(KOLocationBox::SUMMARYTODO);
mLocationEdit->load(KOLocationBox::LOCATION);
KOEditorGeneral::readIncidence(todo);
QDateTime dueDT;
if (todo->hasDueDate()) {
enableAlarmEdit(true);
dueDT = todo->dtDue();
mDueDateEdit->setDate(todo->dtDue().date());
mDueTimeEdit->setTime(todo->dtDue().time());
mDueCheck->setChecked(true);
} else {
alarmDisable(true);
mDueDateEdit->setEnabled(false);
mDueTimeEdit->setEnabled(false);
mDueDateEdit->setDate(QDate::currentDate());
mDueTimeEdit->setTime(QTime::currentTime());
mDueCheck->setChecked(false);
}
if (todo->hasStartDate()) {
mStartDateEdit->setDate(todo->dtStart().date());
mStartTimeEdit->setTime(todo->dtStart().time());
mStartCheck->setChecked(true);
} else {
mStartDateEdit->setEnabled(false);
mStartTimeEdit->setEnabled(false);
mStartDateEdit->setDate(QDate::currentDate());
mStartTimeEdit->setTime(QTime::currentTime());
mStartCheck->setChecked(false);
}
mTimeButton->setChecked( !todo->doesFloat() );
mCompletedCombo->setCurrentItem(todo->percentComplete() / 20);
if (todo->isCompleted() && todo->hasCompletedDate()) {
mCompleted = todo->completed();
}
setCompletedDate();
mPriorityCombo->setCurrentItem(todo->priority()-1);
}
void KOEditorGeneralTodo::writeTodo(Todo *todo)
{
KOEditorGeneral::writeIncidence(todo);
// temp. until something better happens.
QString tmpStr;
todo->setHasDueDate(mDueCheck->isChecked());
todo->setHasStartDate(mStartCheck->isChecked());
QDate tmpDate;
QTime tmpTime;
QDateTime tmpDT;
if ( mTimeButton->isChecked() ) {
todo->setFloats(false);
// set due date/time
tmpDate = mDueDateEdit->date();
tmpTime = mDueTimeEdit->getTime();
tmpDT.setDate(tmpDate);
tmpDT.setTime(tmpTime);
todo->setDtDue(tmpDT);
// set start date/time
tmpDate = mStartDateEdit->date();
tmpTime = mStartTimeEdit->getTime();
tmpDT.setDate(tmpDate);
tmpDT.setTime(tmpTime);
todo->setDtStart(tmpDT);
} else {
todo->setFloats(true);
// need to change this.
tmpDate = mDueDateEdit->date();
tmpTime.setHMS(0,0,0);
tmpDT.setDate(tmpDate);
tmpDT.setTime(tmpTime);
todo->setDtDue(tmpDT);
tmpDate = mStartDateEdit->date();
tmpTime.setHMS(0,0,0);
tmpDT.setDate(tmpDate);
tmpDT.setTime(tmpTime);
todo->setDtStart(tmpDT);
}
todo->setPriority(mPriorityCombo->currentItem()+1);
// set completion state
if ( mCompletedCombo->currentItem() == 5 ) {
QDateTime comp ( mCompleteDateEdit->date(), mCompleteTimeEdit->getTime() );
if ( comp.isValid () ) {
todo->setPercentComplete(0);
todo->setPercentComplete(100);
todo->setCompleted(comp);
} else {
todo->setPercentComplete( 100 );
if ( mCompleted.isValid() )
todo->setCompleted(mCompleted);
}
} else {
todo->setPercentComplete(mCompletedCombo->currentItem() * 20);
}
mSummaryEdit->save(KOLocationBox::SUMMARYTODO);
}
void KOEditorGeneralTodo::enableDueEdit(bool enable)
{
mDueDateEdit->setEnabled( enable );
if(mDueCheck->isChecked() || mStartCheck->isChecked()) {
mTimeButton->setEnabled(true);
}
else {
mTimeButton->setEnabled(false);
mTimeButton->setChecked(false);
}
if (enable) {
mDueTimeEdit->setEnabled( mTimeButton->isChecked() );
} else {
mDueTimeEdit->setEnabled( false );
}
+ emit datesChecked();
}
void KOEditorGeneralTodo::enableStartEdit( bool enable )
{
mStartDateEdit->setEnabled( enable );
if(mDueCheck->isChecked() || mStartCheck->isChecked()) {
mTimeButton->setEnabled(true);
}
else {
mTimeButton->setEnabled(false);
mTimeButton->setChecked(false);
}
if (enable) {
mStartTimeEdit->setEnabled( mTimeButton->isChecked() );
} else {
mStartTimeEdit->setEnabled( false );
}
+ emit datesChecked();
}
void KOEditorGeneralTodo::enableTimeEdits(bool enable)
{
if(mStartCheck->isChecked()) {
mStartTimeEdit->setEnabled( enable );
}
if(mDueCheck->isChecked()) {
mDueTimeEdit->setEnabled( enable );
}
}
void KOEditorGeneralTodo::showAlarm()
{
if ( mDueCheck->isChecked() ) {
alarmDisable(false);
}
else {
alarmDisable(true);
}
}
bool KOEditorGeneralTodo::validateInput()
{
if (mDueCheck->isChecked()) {
if (!mDueDateEdit->inputIsValid()) {
KMessageBox::sorry(0,i18n("Please specify a valid due date."));
return false;
}
}
if (mStartCheck->isChecked()) {
if (!mStartDateEdit->inputIsValid()) {
KMessageBox::sorry(0,i18n("Please specify a valid start date."));
return false;
}
}
if (mStartCheck->isChecked() && mDueCheck->isChecked()) {
QDateTime startDate;
QDateTime dueDate;
startDate.setDate(mStartDateEdit->date());
dueDate.setDate(mDueDateEdit->date());
if (mTimeButton->isChecked()) {
startDate.setTime(mStartTimeEdit->getTime());
dueDate.setTime(mDueTimeEdit->getTime());
}
if (startDate > dueDate) {
KMessageBox::sorry(0,
i18n("The start date cannot be after the due date."));
return false;
}
}
return KOEditorGeneral::validateInput();
}
void KOEditorGeneralTodo::completedChanged(int index)
{
if (index == 5) {
//get rid of milli sec
mCompleted = QDateTime::currentDateTime();
}
setCompletedDate();
}
void KOEditorGeneralTodo::setCompletedDate()
{
if (mCompletedCombo->currentItem() == 5 && mCompleted.isValid()) {
if ( QApplication::desktop()->width() < 480 ) {
mCompletedLabel->setText(i18n(" on"));
}
else
mCompletedLabel->setText(i18n(" completed on "));
mCompleteDateEdit->show();
mCompleteTimeEdit->show();
mCompleteTimeEdit->setTime( mCompleted.time() );
mCompleteDateEdit->setDate( mCompleted.date() );
} else {
mCompletedLabel->setText(i18n(" completed"));
mCompleteDateEdit->hide();
mCompleteTimeEdit->hide();
}
}
void KOEditorGeneralTodo::modified (Todo* todo, int modification)
{
switch (modification) {
case KOGlobals::PRIORITY_MODIFIED:
mPriorityCombo->setCurrentItem(todo->priority()-1);
break;
case KOGlobals::COMPLETION_MODIFIED:
mCompletedCombo->setCurrentItem(todo->percentComplete() / 20);
if (todo->isCompleted() && todo->hasCompletedDate()) {
mCompleted = todo->completed();
}
setCompletedDate();
break;
case KOGlobals::CATEGORY_MODIFIED:
setCategories (todo->categoriesStr ());
break;
case KOGlobals::UNKNOWN_MODIFIED: // fall through
default:
readTodo( todo );
break;
}
}
diff --git a/korganizer/koeditorgeneraltodo.h b/korganizer/koeditorgeneraltodo.h
index 98f43dd..b198539 100644
--- a/korganizer/koeditorgeneraltodo.h
+++ b/korganizer/koeditorgeneraltodo.h
@@ -1,108 +1,109 @@
/*
This file is part of KOrganizer.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, permission is given to link this program
with any edition of Qt, and distribute the resulting executable,
without including the source code for Qt in the source distribution.
*/
#ifndef _KOEDITORGENERALTODO_H
#define _KOEDITORGENERALTODO_H
#include <qframe.h>
#include <qlabel.h>
#include <qcheckbox.h>
#include <qpushbutton.h>
#include <qgroupbox.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qmultilineedit.h>
#include <qlistview.h>
#include <qradiobutton.h>
#include "koeditorgeneral.h"
#include "koglobals.h"
class KRestrictedLine;
class KDateEdit;
using namespace KCal;
class KOEditorGeneralTodo : public KOEditorGeneral
{
Q_OBJECT
public:
KOEditorGeneralTodo (QObject* parent=0,const char* name=0);
virtual ~KOEditorGeneralTodo();
void initTime(QWidget *, QBoxLayout *);
void initStatus(QWidget *, QBoxLayout *);
void initCompletion(QWidget *, QBoxLayout *);
void initPriority(QWidget *, QBoxLayout *);
void finishSetup();
/** Set widgets to default values */
void setDefaults(QDateTime due,bool allDay);
/** Read todo object and setup widgets accordingly */
void readTodo(Todo *);
/** Write todo settings to event object */
void writeTodo(Todo *);
/** Check if the input is valid. */
bool validateInput();
/** The todo has been modified externally */
void modified (Todo*, int);
signals:
void openCategoryDialog();
+ void datesChecked();
protected slots:
void completedChanged(int);
void enableDueEdit( bool enable );
void enableStartEdit( bool enable );
void enableTimeEdits( bool enable );
void showAlarm();
protected:
void setCompletedDate();
private:
friend class KOTodoEditor;
KDateEdit *mStartDateEdit;
KOTimeEdit *mStartTimeEdit;
KDateEdit *mCompleteDateEdit;
KOTimeEdit *mCompleteTimeEdit;
QCheckBox *mTimeButton;
QCheckBox *mDueCheck;
KDateEdit *mDueDateEdit;
KOTimeEdit *mDueTimeEdit;
QComboBox *mCompletedCombo;
QLabel *mCompletedLabel;
QLabel *mPriorityLabel;
QComboBox *mPriorityCombo;
QCheckBox *mStartCheck;
QDateTime mCompleted;
};
#endif
diff --git a/korganizer/koeditorrecurrence.cpp b/korganizer/koeditorrecurrence.cpp
index 4209e10..bedc75a 100644
--- a/korganizer/koeditorrecurrence.cpp
+++ b/korganizer/koeditorrecurrence.cpp
@@ -1,1139 +1,1147 @@
/*
This file is part of KOrganizer.
Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, permission is given to link this program
with any edition of Qt, and distribute the resulting executable,
without including the source code for Qt in the source distribution.
*/
#include <qtooltip.h>
#include <qfiledialog.h>
#include <qlayout.h>
#include <qvbox.h>
#include <qbuttongroup.h>
#include <qvgroupbox.h>
#include <qwidgetstack.h>
#include <qdatetime.h>
#include <qlistbox.h>
#include <qspinbox.h>
#include <qcheckbox.h>
#include <qapplication.h>
#include <kdialog.h>
#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kdebug.h>
#include <knumvalidator.h>
#include <libkcal/event.h>
+#include <libkcal/todo.h>
#include <libkdepim/kdateedit.h>
#include "koprefs.h"
#include "koeditorrecurrence.h"
/////////////////////////// RecurBase ///////////////////////////////
RecurBase::RecurBase( QWidget *parent, const char *name ) :
QWidget( parent, name )
{
mFrequencyEdit = new QSpinBox( 1, 9999, 1, this );
mFrequencyEdit->setValue( 1 );
}
QWidget *RecurBase::frequencyEdit()
{
return mFrequencyEdit;
}
void RecurBase::setFrequency( int f )
{
if ( f < 1 ) f = 1;
mFrequencyEdit->setValue( f );
}
int RecurBase::frequency()
{
return mFrequencyEdit->value();
}
/////////////////////////// RecurDaily ///////////////////////////////
RecurDaily::RecurDaily( QWidget *parent, const char *name ) :
RecurBase( parent, name )
{
QBoxLayout *topLayout = new QHBoxLayout( this );
topLayout->setSpacing( KDialog::spacingHint() );
QLabel *preLabel = new QLabel( i18n("Recur every"), this );
topLayout->addWidget( preLabel );
topLayout->addWidget( frequencyEdit() );
QLabel *postLabel = new QLabel( i18n("day(s)"), this );
topLayout->addWidget( postLabel );
}
/////////////////////////// RecurWeekly ///////////////////////////////
RecurWeekly::RecurWeekly( QWidget *parent, const char *name ) :
RecurBase( parent, name )
{
QBoxLayout *topLayout = new QVBoxLayout( this );
topLayout->setSpacing( KDialog::spacingHint() );
topLayout->addStretch( 1 );
QBoxLayout *weeksLayout = new QHBoxLayout( topLayout );
QLabel *preLabel = new QLabel( i18n("Recur every"), this );
weeksLayout->addWidget( preLabel );
weeksLayout->addWidget( frequencyEdit() );
QLabel *postLabel = new QLabel( i18n("week(s) on:"), this );
weeksLayout->addWidget( postLabel );
QHBox *dayBox = new QHBox( this );
topLayout->addWidget( dayBox, 1, AlignVCenter );
// TODO: Respect start of week setting
for ( int i = 0; i < 7; ++i ) {
QString weekDayName = KGlobal::locale()->weekDayName( i + 1, true );
if ( KOPrefs::instance()->mCompactDialogs ) {
weekDayName = weekDayName.left( 1 );
}
mDayBoxes[ i ] = new QCheckBox( weekDayName, dayBox );
}
topLayout->addStretch( 1 );
}
void RecurWeekly::setDays( const QBitArray &days )
{
for ( int i = 0; i < 7; ++i ) {
mDayBoxes[ i ]->setChecked( days.testBit( i ) );
}
}
QBitArray RecurWeekly::days()
{
QBitArray days( 7 );
for ( int i = 0; i < 7; ++i ) {
days.setBit( i, mDayBoxes[ i ]->isChecked() );
}
return days;
}
/////////////////////////// RecurMonthly ///////////////////////////////
RecurMonthly::RecurMonthly( QWidget *parent, const char *name ) :
RecurBase( parent, name )
{
QBoxLayout *topLayout = new QVBoxLayout( this );
topLayout->setSpacing( KDialog::spacingHint() );
QBoxLayout *freqLayout = new QHBoxLayout( topLayout );
QLabel *preLabel = new QLabel( i18n("every"), this );
freqLayout->addWidget( preLabel );
freqLayout->addWidget( frequencyEdit() );
QLabel *postLabel = new QLabel( i18n("month(s)"), this );
freqLayout->addWidget( postLabel );
QButtonGroup *buttonGroup = new QButtonGroup( this );
buttonGroup->setFrameStyle( QFrame::NoFrame );
topLayout->addWidget( buttonGroup, 1, AlignVCenter );
QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 );
buttonLayout->setSpacing( KDialog::spacingHint() );
QString recurOnText;
if ( !KOPrefs::instance()->mCompactDialogs ) {
recurOnText = i18n("Recur on the");
}
mByDayRadio = new QRadioButton( recurOnText, buttonGroup );
buttonLayout->addWidget( mByDayRadio, 0, 0 );
mByDayCombo = new QComboBox( buttonGroup );
mByDayCombo->setSizeLimit( 7 );
mByDayCombo->insertItem( i18n("1st") );
mByDayCombo->insertItem( i18n("2nd") );
mByDayCombo->insertItem( i18n("3rd") );
mByDayCombo->insertItem( i18n("4th") );
mByDayCombo->insertItem( i18n("5th") );
mByDayCombo->insertItem( i18n("6th") );
mByDayCombo->insertItem( i18n("7th") );
mByDayCombo->insertItem( i18n("8th") );
mByDayCombo->insertItem( i18n("9th") );
mByDayCombo->insertItem( i18n("10th") );
mByDayCombo->insertItem( i18n("11th") );
mByDayCombo->insertItem( i18n("12th") );
mByDayCombo->insertItem( i18n("13th") );
mByDayCombo->insertItem( i18n("14th") );
mByDayCombo->insertItem( i18n("15th") );
mByDayCombo->insertItem( i18n("16th") );
mByDayCombo->insertItem( i18n("17th") );
mByDayCombo->insertItem( i18n("18th") );
mByDayCombo->insertItem( i18n("19th") );
mByDayCombo->insertItem( i18n("20th") );
mByDayCombo->insertItem( i18n("21st") );
mByDayCombo->insertItem( i18n("22nd") );
mByDayCombo->insertItem( i18n("23rd") );
mByDayCombo->insertItem( i18n("24th") );
mByDayCombo->insertItem( i18n("25th") );
mByDayCombo->insertItem( i18n("26th") );
mByDayCombo->insertItem( i18n("27th") );
mByDayCombo->insertItem( i18n("28th") );
mByDayCombo->insertItem( i18n("29th") );
mByDayCombo->insertItem( i18n("30th") );
mByDayCombo->insertItem( i18n("31st") );
buttonLayout->addWidget( mByDayCombo, 0, 1 );
QLabel *byDayLabel = new QLabel( i18n("day"), buttonGroup );
buttonLayout->addWidget( byDayLabel, 0, 2 );
mByPosRadio = new QRadioButton( recurOnText, buttonGroup);
buttonLayout->addWidget( mByPosRadio, 1, 0 );
mByPosCountCombo = new QComboBox( buttonGroup );
mByPosCountCombo->insertItem( i18n("1st") );
mByPosCountCombo->insertItem( i18n("2nd") );
mByPosCountCombo->insertItem( i18n("3rd") );
mByPosCountCombo->insertItem( i18n("4th") );
mByPosCountCombo->insertItem( i18n("5th") );
buttonLayout->addWidget( mByPosCountCombo, 1, 1 );
mByPosWeekdayCombo = new QComboBox( buttonGroup );
mByPosWeekdayCombo->insertItem( i18n("Monday") );
mByPosWeekdayCombo->insertItem( i18n("Tuesday") );
mByPosWeekdayCombo->insertItem( i18n("Wednesday") );
mByPosWeekdayCombo->insertItem( i18n("Thursday") );
mByPosWeekdayCombo->insertItem( i18n("Friday") );
mByPosWeekdayCombo->insertItem( i18n("Saturday") );
mByPosWeekdayCombo->insertItem( i18n("Sunday") );
buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 );
}
void RecurMonthly::setByDay( int day )
{
mByDayRadio->setChecked( true );
mByDayCombo->setCurrentItem( day );
}
void RecurMonthly::setByPos( int count, int weekday )
{
mByPosRadio->setChecked( true );
mByPosCountCombo->setCurrentItem( count );
mByPosWeekdayCombo->setCurrentItem( weekday );
}
bool RecurMonthly::byDay()
{
return mByDayRadio->isChecked();
}
bool RecurMonthly::byPos()
{
return mByPosRadio->isChecked();
}
int RecurMonthly::day()
{
return mByDayCombo->currentItem() + 1;
}
int RecurMonthly::count()
{
return mByPosCountCombo->currentItem() + 1;
}
int RecurMonthly::weekday()
{
return mByPosWeekdayCombo->currentItem();
}
/////////////////////////// RecurYearly ///////////////////////////////
RecurYearly::RecurYearly( QWidget *parent, const char *name ) :
RecurBase( parent, name )
{
QBoxLayout *topLayout = new QVBoxLayout( this );
topLayout->setSpacing( KDialog::spacingHint() );
QBoxLayout *freqLayout = new QHBoxLayout( topLayout );
QLabel *preLabel = new QLabel( i18n("every"), this );
freqLayout->addWidget( preLabel );
freqLayout->addWidget( frequencyEdit() );
QLabel *postLabel = new QLabel( i18n("year(s)"), this );
freqLayout->addWidget( postLabel );
QButtonGroup *buttonGroup = new QButtonGroup( this );
buttonGroup->setFrameStyle( QFrame::NoFrame );
topLayout->addWidget( buttonGroup, 1, AlignVCenter );
QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 2, 3 );
mByMonthRadio = new QRadioButton( i18n("On day "), buttonGroup);
buttonLayout->addWidget( mByMonthRadio, 0, 0 , Qt::AlignRight);
mByDayLabel = new QLabel( i18n("%1 of ").arg(1), buttonGroup );
buttonLayout->addWidget( mByDayLabel, 0, 1 );
mByMonthCombo = new QComboBox( buttonGroup );
mByMonthCombo->insertItem( i18n("January") );
mByMonthCombo->insertItem( i18n("February") );
mByMonthCombo->insertItem( i18n("March") );
mByMonthCombo->insertItem( i18n("April") );
mByMonthCombo->insertItem( i18n("May") );
mByMonthCombo->insertItem( i18n("June") );
mByMonthCombo->insertItem( i18n("July") );
mByMonthCombo->insertItem( i18n("August") );
mByMonthCombo->insertItem( i18n("September") );
mByMonthCombo->insertItem( i18n("October") );
mByMonthCombo->insertItem( i18n("November") );
mByMonthCombo->insertItem( i18n("December") );
buttonLayout->addWidget( mByMonthCombo, 0, 2,Qt::AlignLeft );
if ( QApplication::desktop()->width() <= 640 ) {
mByMonthCombo->setSizeLimit( 6 );
}
mByDayRadio = new QRadioButton( i18n("On day "), buttonGroup);
buttonLayout->addWidget( mByDayRadio, 1, 0 , Qt::AlignRight);
mDayOfLabel = new QLabel( i18n("%1 of the year").arg(1), buttonGroup );
buttonLayout->addMultiCellWidget( mDayOfLabel, 1, 1, 1,3 );
}
void RecurYearly::setByDay( int doy )
{
mByDayRadio->setChecked( true );
mDayOfLabel->setText(i18n("%1 of the year").arg( doy ) );
}
void RecurYearly::setByMonth( int month, int day )
{
mByMonthRadio->setChecked( true );
mByMonthCombo->setCurrentItem( month - 1 );
mByDayLabel->setText(i18n("%1 of ").arg( day ) );
mDay = day;
}
bool RecurYearly::byMonth()
{
return mByMonthRadio->isChecked();
}
bool RecurYearly::byDay()
{
return mByDayRadio->isChecked();
}
int RecurYearly::month()
{
return mByMonthCombo->currentItem() + 1;
}
int RecurYearly::day()
{
return mDay;//mByDayCombo->currentItem() + 1;
}
//////////////////////////// ExceptionsWidget //////////////////////////
ExceptionsWidget::ExceptionsWidget( QWidget *parent, const char *name ) :
QWidget( parent, name )
{
QBoxLayout *topLayout = new QVBoxLayout( this );
QGroupBox *groupBox = new QGroupBox( 1, Horizontal, i18n("Exceptions"),
this );
topLayout->addWidget( groupBox );
QWidget *box = new QWidget( groupBox );
QGridLayout *boxLayout = new QGridLayout( box );
mExceptionDateEdit = new KDateEdit( box );
boxLayout->addWidget( mExceptionDateEdit, 0, 0 );
QPushButton *addExceptionButton = new QPushButton( i18n("Add"), box );
boxLayout->addWidget( addExceptionButton, 1, 0 );
QPushButton *changeExceptionButton = new QPushButton( i18n("Change"), box );
boxLayout->addWidget( changeExceptionButton, 2, 0 );
QPushButton *deleteExceptionButton = new QPushButton( i18n("Delete"), box );
boxLayout->addWidget( deleteExceptionButton, 3, 0 );
mExceptionList = new QListBox( box );
boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 );
boxLayout->setRowStretch( 4, 1 );
boxLayout->setColStretch( 1, 3 );
connect( addExceptionButton, SIGNAL( clicked() ),
SLOT( addException() ) );
connect( changeExceptionButton, SIGNAL( clicked() ),
SLOT( changeException() ) );
connect( deleteExceptionButton, SIGNAL( clicked() ),
SLOT( deleteException() ) );
if ( QApplication::desktop()->width() < 480 ) {
setMinimumWidth( 220 );
} else {
setMinimumWidth( 440 );
mExceptionDateEdit->setMinimumWidth( 200 );
}
}
void ExceptionsWidget::setDefaults( const QDateTime &from )
{
mExceptionDateEdit->setDate( from.date() );
}
void ExceptionsWidget::addException()
{
QDate date = mExceptionDateEdit->date();
QString dateStr = KGlobal::locale()->formatDate( date );
if( !mExceptionList->findItem( dateStr ) ) {
mExceptionDates.append( date );
mExceptionList->insertItem( dateStr );
}
}
void ExceptionsWidget::changeException()
{
int pos = mExceptionList->currentItem();
if ( pos < 0 ) return;
QDate date = mExceptionDateEdit->date();
mExceptionDates[ pos ] = date;
mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos );
}
void ExceptionsWidget::deleteException()
{
int pos = mExceptionList->currentItem();
if ( pos < 0 ) return;
mExceptionDates.remove( mExceptionDates.at( pos ) );
mExceptionList->removeItem( pos );
}
void ExceptionsWidget::setDates( const DateList &dates )
{
mExceptionList->clear();
mExceptionDates.clear();
DateList::ConstIterator dit;
for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) );
mExceptionDates.append( *dit );
}
}
DateList ExceptionsWidget::dates()
{
return mExceptionDates;
}
///////////////////////// ExceptionsDialog ///////////////////////////
ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) :
KDialogBase( parent, name, true, i18n("Edit exceptions"), Ok|Cancel )
{
mExceptions = new ExceptionsWidget( this );
setMainWidget( mExceptions );
resize(220,10);
}
void ExceptionsDialog::setDefaults( const QDateTime &from )
{
mExceptions->setDefaults( from );
}
void ExceptionsDialog::setDates( const DateList &dates )
{
mExceptions->setDates( dates );
}
DateList ExceptionsDialog::dates()
{
return mExceptions->dates();
}
///////////////////////// RecurrenceRangeWidget ///////////////////////////
RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent,
const char *name )
: QWidget( parent, name )
{
QBoxLayout *topLayout = new QVBoxLayout( this );
mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"),
this );
topLayout->addWidget( mRangeGroupBox );
QWidget *rangeBox = new QWidget( mRangeGroupBox );
QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox );
rangeLayout->setSpacing( KDialog::spacingHint() );
mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox );
rangeLayout->addWidget( mStartDateLabel );
QButtonGroup *rangeButtonGroup = new QButtonGroup;
mNoEndDateButton = new QRadioButton( i18n("No ending date"), rangeBox );
rangeButtonGroup->insert( mNoEndDateButton );
rangeLayout->addWidget( mNoEndDateButton );
QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout );
durationLayout->setSpacing( KDialog::spacingHint() );
mEndDurationButton = new QRadioButton( i18n("End after"), rangeBox );
rangeButtonGroup->insert( mEndDurationButton );
durationLayout->addWidget( mEndDurationButton );
mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox );
durationLayout->addWidget( mEndDurationEdit );
QLabel *endDurationLabel = new QLabel( i18n("occurrence(s)"), rangeBox );
durationLayout ->addWidget( endDurationLabel );
QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout );
endDateLayout->setSpacing( KDialog::spacingHint() );
mEndDateButton = new QRadioButton( i18n("End by:"), rangeBox );
rangeButtonGroup->insert( mEndDateButton );
endDateLayout->addWidget( mEndDateButton );
mEndDateEdit = new KDateEdit( rangeBox );
endDateLayout->addWidget( mEndDateEdit );
endDateLayout->addStretch( 1 );
connect( mNoEndDateButton, SIGNAL( toggled( bool ) ),
SLOT( showCurrentRange() ) );
connect( mEndDurationButton, SIGNAL( toggled( bool ) ),
SLOT( showCurrentRange() ) );
connect( mEndDateButton, SIGNAL( toggled( bool ) ),
SLOT( showCurrentRange() ) );
}
void RecurrenceRangeWidget::setDefaults( const QDateTime &from )
{
mNoEndDateButton->setChecked( true );
setDateTimes( from );
mEndDateEdit->setDate( from.date() );
}
void RecurrenceRangeWidget::setDuration( int duration )
{
if ( duration == -1 ) {
mNoEndDateButton->setChecked( true );
} else if ( duration == 0 ) {
mEndDateButton->setChecked( true );
} else {
mEndDurationButton->setChecked( true );
mEndDurationEdit->setValue( duration );
}
}
int RecurrenceRangeWidget::duration()
{
if ( mNoEndDateButton->isChecked() ) {
return -1;
} else if ( mEndDurationButton->isChecked() ) {
return mEndDurationEdit->value();
} else {
return 0;
}
}
void RecurrenceRangeWidget::setEndDate( const QDate &date )
{
mEndDateEdit->setDate( date );
}
QDate RecurrenceRangeWidget::endDate()
{
return mEndDateEdit->date();
}
void RecurrenceRangeWidget::showCurrentRange()
{
mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
}
void RecurrenceRangeWidget::setDateTimes( const QDateTime &start,
const QDateTime & )
{
mStartDateLabel->setText( i18n("Start date: %1")
.arg( KGlobal::locale()->formatDate( start.date() ) ) );
if(!mEndDateButton->isChecked())
mEndDateEdit->setDate( start.date() );
}
///////////////////////// RecurrenceRangeDialog ///////////////////////////
RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent,
const char *name ) :
KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel )
{
mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
setMainWidget( mRecurrenceRangeWidget );
}
void RecurrenceRangeDialog::setDefaults( const QDateTime &from )
{
mRecurrenceRangeWidget->setDefaults( from );
}
void RecurrenceRangeDialog::setDuration( int duration )
{
mRecurrenceRangeWidget->setDuration( duration );
}
int RecurrenceRangeDialog::duration()
{
return mRecurrenceRangeWidget->duration();
}
void RecurrenceRangeDialog::setEndDate( const QDate &date )
{
mRecurrenceRangeWidget->setEndDate( date );
}
QDate RecurrenceRangeDialog::endDate()
{
return mRecurrenceRangeWidget->endDate();
}
void RecurrenceRangeDialog::setDateTimes( const QDateTime &start,
const QDateTime &end )
{
mRecurrenceRangeWidget->setDateTimes( start, end );
}
//////////////////////////// RecurrenceChooser ////////////////////////
RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) :
QWidget( parent, name )
{
QBoxLayout *topLayout = new QVBoxLayout( this );
if ( KOPrefs::instance()->mCompactDialogs ) {
mTypeCombo = new QComboBox( this );
mTypeCombo->insertItem( i18n("Daily") );
mTypeCombo->insertItem( i18n("Weekly") );
mTypeCombo->insertItem( i18n("Monthly") );
mTypeCombo->insertItem( i18n("Yearly") );
topLayout->addWidget( mTypeCombo );
connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) );
} else {
mTypeCombo = 0;
QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this );
ruleButtonGroup->setFrameStyle( QFrame::NoFrame );
topLayout->addWidget( ruleButtonGroup );
mDailyButton = new QRadioButton( i18n("Daily"), ruleButtonGroup );
mWeeklyButton = new QRadioButton( i18n("Weekly"), ruleButtonGroup );
mMonthlyButton = new QRadioButton( i18n("Monthly"), ruleButtonGroup );
mYearlyButton = new QRadioButton( i18n("Yearly"), ruleButtonGroup );
connect( mDailyButton, SIGNAL( toggled( bool ) ),
SLOT( emitChoice() ) );
connect( mWeeklyButton, SIGNAL( toggled( bool ) ),
SLOT( emitChoice() ) );
connect( mMonthlyButton, SIGNAL( toggled( bool ) ),
SLOT( emitChoice() ) );
connect( mYearlyButton, SIGNAL( toggled( bool ) ),
SLOT( emitChoice() ) );
}
}
int RecurrenceChooser::type()
{
if ( mTypeCombo ) {
return mTypeCombo->currentItem();
} else {
if ( mDailyButton->isChecked() ) return Daily;
else if ( mWeeklyButton->isChecked() ) return Weekly;
else if ( mMonthlyButton->isChecked() ) return Monthly;
else return Yearly;
}
}
void RecurrenceChooser::setType( int type )
{
if ( mTypeCombo ) {
mTypeCombo->setCurrentItem( type );
} else {
switch ( type ) {
case Daily:
mDailyButton->setChecked( true );
break;
case Weekly:
mWeeklyButton->setChecked( true );
break;
case Monthly:
mMonthlyButton->setChecked( true );
break;
case Yearly:
default:
mYearlyButton->setChecked( true );
break;
}
}
}
void RecurrenceChooser::emitChoice()
{
emit chosen ( type() );
}
/////////////////////////////// Main Widget /////////////////////////////
KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) :
QWidget( parent, name )
{
QGridLayout *topLayout = new QGridLayout( this, 2,2 );
topLayout->setSpacing( KDialog::spacingHint() );
mEnabledCheck = new QCheckBox( i18n("Enable Recurrence"), this );
connect( mEnabledCheck, SIGNAL( toggled( bool ) ),
SLOT( setEnabled( bool ) ) );
topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 );
mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "),
this );
topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
if ( KOPrefs::instance()->mCompactDialogs ) {
mTimeGroupBox->hide();
}
// QFrame *timeFrame = new QFrame( mTimeGroupBox );
// QBoxLayout *layoutTimeFrame = new QHBoxLayout( timeFrame );
// layoutTimeFrame->setSpacing( KDialog::spacingHint() );
mDateTimeLabel = new QLabel( mTimeGroupBox );
// mDateTimeLabel = new QLabel( timeFrame );
// layoutTimeFrame->addWidget( mDateTimeLabel );
Qt::Orientation orientation;
if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal;
else orientation = Vertical;
mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this );
if ( KOPrefs::instance()->mCompactDialogs ) {
topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
} else {
topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
}
mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
connect( mRecurrenceChooser, SIGNAL( chosen( int ) ),
SLOT( showCurrentRule( int ) ) );
if ( !KOPrefs::instance()->mCompactDialogs ) {
QFrame *ruleSepFrame = new QFrame( mRuleBox );
ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
}
mRuleStack = new QWidgetStack( mRuleBox );
mDaily = new RecurDaily( mRuleStack );
mRuleStack->addWidget( mDaily, 0 );
mWeekly = new RecurWeekly( mRuleStack );
mRuleStack->addWidget( mWeekly, 0 );
mMonthly = new RecurMonthly( mRuleStack );
mRuleStack->addWidget( mMonthly, 0 );
mYearly = new RecurYearly( mRuleStack );
mRuleStack->addWidget( mYearly, 0 );
showCurrentRule( mRecurrenceChooser->type() );
if ( KOPrefs::instance()->mCompactDialogs ) {
mRecurrenceRangeWidget = 0;
mRecurrenceRangeDialog = new RecurrenceRangeDialog( this );
mRecurrenceRange = mRecurrenceRangeDialog;
mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."),
this );
connect( mRecurrenceRangeButton, SIGNAL( clicked() ),
SLOT( showRecurrenceRangeDialog() ) );
mExceptionsWidget = 0;
mExceptionsDialog = new ExceptionsDialog( this );
mExceptions = mExceptionsDialog;
mExceptionsButton = new QPushButton( i18n("Exceptions..."), this );
if ( QApplication::desktop()->width() < 320 ) {
topLayout->addMultiCellWidget( mRecurrenceRangeButton, 3, 3, 0, 1 );
topLayout->addMultiCellWidget( mExceptionsButton, 4, 4, 0, 1 );
} else {
topLayout->addWidget( mRecurrenceRangeButton, 3, 0 );
topLayout->addWidget( mExceptionsButton, 3, 1 );
}
connect( mExceptionsButton, SIGNAL( clicked() ),
SLOT( showExceptionsDialog() ) );
} else {
mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
mRecurrenceRangeDialog = 0;
mRecurrenceRange = mRecurrenceRangeWidget;
mRecurrenceRangeButton = 0;
topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 );
mExceptionsWidget = new ExceptionsWidget( this );
mExceptionsDialog = 0;
mExceptions = mExceptionsWidget;
mExceptionsButton = 0;
topLayout->addWidget( mExceptionsWidget, 3, 1 );
}
}
KOEditorRecurrence::~KOEditorRecurrence()
{
}
void KOEditorRecurrence::setEnabled( bool enabled )
{
// kdDebug() << "KOEditorRecurrence::setEnabled(): " << (enabled ? "on" : "off") << endl;
mTimeGroupBox->setEnabled( enabled );
if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled );
if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled );
if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled );
if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled );
mRuleBox->setEnabled( enabled );
}
void KOEditorRecurrence::showCurrentRule( int current )
{
switch ( current ) {
case Daily:
mRuleStack->raiseWidget( mDaily );
break;
case Weekly:
mRuleStack->raiseWidget( mWeekly );
break;
case Monthly:
mRuleStack->raiseWidget( mMonthly );
break;
default:
case Yearly:
mRuleStack->raiseWidget( mYearly );
break;
}
}
void KOEditorRecurrence::setDateTimes( QDateTime start, QDateTime end )
{
// kdDebug() << "KOEditorRecurrence::setDateTimes" << endl;
mRecurrenceRange->setDateTimes( start, end );
mExceptions->setDefaults( end );
}
void KOEditorRecurrence::setDefaults( QDateTime from, QDateTime to, bool )
{
// qDebug("KOEditorRecurrence::setDefaults %s %s ",from.toString().latin1(),to.toString().latin1() );
setDateTimes( from, to );
bool enabled = false;
mEnabledCheck->setChecked( enabled );
setEnabled( enabled );
mExceptions->setDefaults( to );
mRecurrenceRange->setDefaults( to );
mRecurrenceChooser->setType( RecurrenceChooser::Weekly );
showCurrentRule( mRecurrenceChooser->type() );
mDaily->setFrequency( 1 );
mWeekly->setFrequency( 1 );
QBitArray days( 7 );
days.fill( 0 );
days.setBit( from.date().dayOfWeek()- 1);
mWeekly->setDays( days );
mMonthly->setFrequency( 1 );
mMonthly->setByPos((from.date().day()/7), from.date().dayOfWeek()-1 );
mMonthly->setByDay( from.date().day()-1 );
mYearly->setFrequency( 1 );
mYearly->setByDay( from.date().dayOfYear() );
mYearly->setByMonth( from.date().month(), from.date().day() );
}
-void KOEditorRecurrence::readEvent(Event *event)
+void KOEditorRecurrence::readEvent(Incidence *event)
{
- setDefaults( event->dtStart(), event->dtEnd(), true );
+
+ QDateTime dtEnd;
+ if ( event->type() == "Event" )
+ dtEnd = ((Event*)event)->dtEnd();
+ else
+ dtEnd = ((Todo*)event)->dtDue();
+
+ setDefaults( event->dtStart(), dtEnd, true );
QBitArray rDays( 7 );
QPtrList<Recurrence::rMonthPos> rmp;
QPtrList<int> rmd;
int day = 0;
int count = 0;
int month = 0;
- setDateTimes( event->dtStart(), event->dtEnd() );
+ setDateTimes( event->dtStart(), dtEnd );
Recurrence *r = event->recurrence();
int f = r->frequency();
int recurs = r->doesRecur();
mEnabledCheck->setChecked( recurs );
setEnabled( recurs );
int recurrenceType = RecurrenceChooser::Weekly;
switch ( recurs ) {
case Recurrence::rNone:
- setDefaults( event->dtStart(), event->dtEnd(), true );
+ setDefaults( event->dtStart(), dtEnd, true );
break;
case Recurrence::rDaily:
recurrenceType = RecurrenceChooser::Daily;
mDaily->setFrequency( f );
break;
case Recurrence::rWeekly:
recurrenceType = RecurrenceChooser::Weekly;
mWeekly->setFrequency( f );
mWeekly->setDays( r->days() );
break;
case Recurrence::rMonthlyPos:
// we only handle one possibility in the list right now,
// so I have hardcoded calls with first(). If we make the GUI
// more extended, this can be changed.
recurrenceType = RecurrenceChooser::Monthly;
rmp = r->monthPositions();
if ( rmp.first()->negative )
count = 5 - rmp.first()->rPos - 1;
else
count = rmp.first()->rPos - 1;
day = 0;
while ( !rmp.first()->rDays.testBit( day ) ) ++day;
mMonthly->setByPos( count, day );
mMonthly->setFrequency( f );
break;
case Recurrence::rMonthlyDay:
recurrenceType = RecurrenceChooser::Monthly;
rmd = r->monthDays();
day = *rmd.first() - 1;
mMonthly->setByDay( day );
mMonthly->setFrequency( f );
break;
case Recurrence::rYearlyMonth:
{
recurrenceType = RecurrenceChooser::Yearly;
qDebug("Recurrence::rYearlyMonth: ");
day = event->dtStart().date().day();
rmd = r->yearNums();
if ( rmd.count() > 0 )
month = *rmd.first();
else
month = event->dtStart().date().month() ;
mYearly->setByMonth( month, day );
#if 0
qDebug("2day = %d ",day );
QPtrList<Recurrence::rMonthPos> monthlist = r->yearMonthPositions();
int month;
if ( !monthlist.isEmpty() ) {
month = monthlist.first()->rPos ;
} else {
month = event->dtStart().date().month() ;
}
mYearly->setByMonth( day, month );
#endif
mYearly->setFrequency( f );
}
break;
case Recurrence::rYearlyDay:
qDebug("Recurrence::rYearlyDay: ");
recurrenceType = RecurrenceChooser::Yearly;
mYearly->setByDay( event->dtStart().date().dayOfYear() );
mYearly->setFrequency( f );
break;
default:
- setDefaults( event->dtStart(), event->dtEnd(), true );
+ setDefaults( event->dtStart(), dtEnd, true );
break;
}
mRecurrenceChooser->setType( recurrenceType );
showCurrentRule( recurrenceType );
mRecurrenceRange->setDateTimes( event->dtStart() );
if ( r->doesRecur() ) {
mRecurrenceRange->setDuration( r->duration() );
if ( r->duration() == 0 )
{
if ( r->endDate() < event->dtStart().date() )
mRecurrenceRange->setEndDate( event->dtStart().date() );
else
mRecurrenceRange->setEndDate( r->endDate() );
} else
mRecurrenceRange->setEndDate( event->dtStart().date() );
}
mExceptions->setDates( event->exDates() );
}
-void KOEditorRecurrence::writeEvent( Event *event )
+void KOEditorRecurrence::writeEvent( Incidence *event )
{
Recurrence *r = event->recurrence();
// clear out any old settings;
r->unsetRecurs();
if ( mEnabledCheck->isChecked() ) {
int duration = mRecurrenceRange->duration();
QDate endDate;
if ( duration == 0 ) endDate = mRecurrenceRange->endDate();
int recurrenceType = mRecurrenceChooser->type();
if ( recurrenceType == RecurrenceChooser::Daily ) {
int freq = mDaily->frequency();
if ( duration != 0 ) r->setDaily( freq, duration );
else r->setDaily( freq, endDate );
} else if ( recurrenceType == RecurrenceChooser::Weekly ) {
int freq = mWeekly->frequency();
QBitArray days = mWeekly->days();
int j;
bool found = false;
for (j = 0; j < 7 ; ++j ) {
found |=days.at(j);
}
if ( !found ) {
days.setBit( event->dtStart().date().dayOfWeek()-1);
qDebug("bit set %d ", event->dtStart().date().dayOfWeek()-1);
}
if ( duration != 0 ) r->setWeekly( freq, days, duration );
else r->setWeekly( freq, days, endDate );
} else if ( recurrenceType == RecurrenceChooser::Monthly ) {
int freq = mMonthly->frequency();
if ( mMonthly->byPos() ) {
int pos = mMonthly->count();
QBitArray days( 7 );
days.fill( false );
days.setBit( mMonthly->weekday() );
if ( duration != 0 )
r->setMonthly( Recurrence::rMonthlyPos, freq, duration );
else
r->setMonthly( Recurrence::rMonthlyPos, freq, endDate );
r->addMonthlyPos( pos, days );
} else {
// it's by day
int day = mMonthly->day();
if ( duration != 0 ) {
r->setMonthly( Recurrence::rMonthlyDay, freq, duration );
} else {
r->setMonthly( Recurrence::rMonthlyDay, freq, endDate );
}
r->addMonthlyDay( day );
}
} else if ( recurrenceType == RecurrenceChooser::Yearly ) {
qDebug("RecurrenceChooser::Yearly ");
int freq = mYearly->frequency();
if ( mYearly->byDay() ) {
if ( duration != 0 ) {
r->setYearly( Recurrence::rYearlyDay, freq, duration );
} else {
r->setYearly( Recurrence::rYearlyDay, freq, endDate );
}
r->addYearlyNum( event->dtStart().date().dayOfYear() );
} else {
if ( duration != 0 ) {
r->setYearly( Recurrence::rYearlyMonth, freq, duration );
} else {
r->setYearly( Recurrence::rYearlyMonth, freq, endDate );
}
r->addYearlyNum( mYearly->month() );
}
}
event->setExDates( mExceptions->dates() );
}
}
void KOEditorRecurrence::setDateTimeStr( const QString &str )
{
mDateTimeLabel->setText( str );
}
bool KOEditorRecurrence::validateInput()
{
// Check input here
return true;
}
void KOEditorRecurrence::showExceptionsDialog()
{
DateList dates = mExceptions->dates();
int result = mExceptionsDialog->exec();
if ( result == QDialog::Rejected ) mExceptions->setDates( dates );
}
void KOEditorRecurrence::showRecurrenceRangeDialog()
{
int duration = mRecurrenceRange->duration();
QDate endDate = mRecurrenceRange->endDate();
int result = mRecurrenceRangeDialog->exec();
if ( result == QDialog::Rejected ) {
mRecurrenceRange->setDuration( duration );
mRecurrenceRange->setEndDate( endDate );
}
}
diff --git a/korganizer/koeditorrecurrence.h b/korganizer/koeditorrecurrence.h
index 2b59085..a15afcb 100644
--- a/korganizer/koeditorrecurrence.h
+++ b/korganizer/koeditorrecurrence.h
@@ -1,324 +1,324 @@
/*
This file is part of KOrganizer.
Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, permission is given to link this program
with any edition of Qt, and distribute the resulting executable,
without including the source code for Qt in the source distribution.
*/
#ifndef _KOEDITORRECURRENCE_H
#define _KOEDITORRECURRENCE_H
#include <qframe.h>
#include <qlabel.h>
#include <qcheckbox.h>
#include <qpushbutton.h>
#include <qgroupbox.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qmultilineedit.h>
#include <qlistview.h>
#include <qradiobutton.h>
#include <kdialogbase.h>
#include <libkcal/event.h>
#include "ktimeedit.h"
class QWidgetStack;
class QSpinBox;
class KDateEdit;
using namespace KCal;
class RecurBase : public QWidget
{
public:
RecurBase( QWidget *parent = 0, const char *name = 0 );
void setFrequency( int );
int frequency();
QWidget *frequencyEdit();
private:
QSpinBox *mFrequencyEdit;
};
class RecurDaily : public RecurBase
{
public:
RecurDaily( QWidget *parent = 0, const char *name = 0 );
};
class RecurWeekly : public RecurBase
{
public:
RecurWeekly( QWidget *parent = 0, const char *name = 0 );
void setDays( const QBitArray & );
QBitArray days();
private:
QCheckBox *mDayBoxes[7];
};
class RecurMonthly : public RecurBase
{
public:
RecurMonthly( QWidget *parent = 0, const char *name = 0 );
void setByDay( int day );
void setByPos( int count, int weekday );
bool byDay();
bool byPos();
int day();
int count();
int weekday();
private:
QRadioButton *mByDayRadio;
QComboBox *mByDayCombo;
QRadioButton *mByPosRadio;
QComboBox *mByPosCountCombo;
QComboBox *mByPosWeekdayCombo;
};
class RecurYearly : public RecurBase
{
public:
RecurYearly( QWidget *parent = 0, const char *name = 0 );
void setByDay( int doy );
void setByMonth( int month, int day );
bool byMonth();
bool byDay();
int month();
int day();
private:
int mDay;
QRadioButton *mByMonthRadio;
QComboBox *mByMonthCombo;
QLabel* mByDayLabel;
QLabel* mDayOfLabel;
QRadioButton *mByDayRadio;
};
class RecurrenceChooser : public QWidget
{
Q_OBJECT
public:
RecurrenceChooser( QWidget *parent = 0, const char *name = 0 );
enum { Daily, Weekly, Monthly, Yearly };
void setType( int );
int type();
signals:
void chosen( int );
protected slots:
void emitChoice();
private:
QComboBox *mTypeCombo;
QRadioButton *mDailyButton;
QRadioButton *mWeeklyButton;
QRadioButton *mMonthlyButton;
QRadioButton *mYearlyButton;
};
class ExceptionsBase
{
public:
virtual void setDefaults( const QDateTime &from ) = 0;
virtual void setDates( const DateList & ) = 0;
virtual DateList dates() = 0;
};
class ExceptionsWidget : public QWidget, public ExceptionsBase
{
Q_OBJECT
public:
ExceptionsWidget( QWidget *parent = 0, const char *name = 0 );
void setDefaults( const QDateTime &from );
void setDates( const DateList & );
DateList dates();
protected slots:
void addException();
void changeException();
void deleteException();
private:
KDateEdit *mExceptionDateEdit;
QListBox *mExceptionList;
DateList mExceptionDates;
};
class ExceptionsDialog : public KDialogBase, public ExceptionsBase
{
public:
ExceptionsDialog( QWidget *parent, const char *name = 0 );
void setDefaults( const QDateTime &from );
void setDates( const DateList & );
DateList dates();
private:
ExceptionsWidget *mExceptions;
};
class RecurrenceRangeBase
{
public:
virtual void setDefaults( const QDateTime &from ) = 0;
virtual void setDuration( int ) = 0;
virtual int duration() = 0;
virtual void setEndDate( const QDate & ) = 0;
virtual QDate endDate() = 0;
virtual void setDateTimes( const QDateTime &start,
const QDateTime &end = QDateTime() ) = 0;
};
class RecurrenceRangeWidget : public QWidget, public RecurrenceRangeBase
{
Q_OBJECT
public:
RecurrenceRangeWidget( QWidget *parent = 0, const char *name = 0 );
void setDefaults( const QDateTime &from );
void setDuration( int );
int duration();
void setEndDate( const QDate & );
QDate endDate();
void setDateTimes( const QDateTime &start,
const QDateTime &end = QDateTime() );
protected slots:
void showCurrentRange();
private:
QGroupBox *mRangeGroupBox;
QLabel *mStartDateLabel;
QRadioButton *mNoEndDateButton;
QRadioButton *mEndDurationButton;
QSpinBox *mEndDurationEdit;
QRadioButton *mEndDateButton;
KDateEdit *mEndDateEdit;
};
class RecurrenceRangeDialog : public KDialogBase, public RecurrenceRangeBase
{
public:
RecurrenceRangeDialog( QWidget *parent = 0, const char *name = 0 );
void setDefaults( const QDateTime &from );
void setDuration( int );
int duration();
void setEndDate( const QDate & );
QDate endDate();
void setDateTimes( const QDateTime &start,
const QDateTime &end = QDateTime() );
private:
RecurrenceRangeWidget *mRecurrenceRangeWidget;
};
class KOEditorRecurrence : public QWidget
{
Q_OBJECT
public:
KOEditorRecurrence ( QWidget *parent = 0, const char *name = 0 );
virtual ~KOEditorRecurrence();
enum { Daily, Weekly, Monthly, Yearly };
/** Set widgets to default values */
void setDefaults( QDateTime from, QDateTime to, bool allday );
/** Read event object and setup widgets accordingly */
- void readEvent( Event * );
+ void readEvent( Incidence * );
/** Write event settings to event object */
- void writeEvent( Event * );
+ void writeEvent( Incidence * );
/** Check if the input is valid. */
bool validateInput();
public slots:
void setEnabled( bool );
void setDateTimes( QDateTime start, QDateTime end );
void setDateTimeStr( const QString & );
signals:
void dateTimesChanged( QDateTime start, QDateTime end );
protected slots:
void showCurrentRule( int );
void showExceptionsDialog();
void showRecurrenceRangeDialog();
private:
QCheckBox *mEnabledCheck;
QGroupBox *mTimeGroupBox;
QLabel *mDateTimeLabel;
QGroupBox *mRuleBox;
QWidgetStack *mRuleStack;
RecurrenceChooser *mRecurrenceChooser;
RecurDaily *mDaily;
RecurWeekly *mWeekly;
RecurMonthly *mMonthly;
RecurYearly *mYearly;
RecurrenceRangeBase *mRecurrenceRange;
RecurrenceRangeWidget *mRecurrenceRangeWidget;
RecurrenceRangeDialog *mRecurrenceRangeDialog;
QPushButton *mRecurrenceRangeButton;
ExceptionsBase *mExceptions;
ExceptionsDialog *mExceptionsDialog;
ExceptionsWidget *mExceptionsWidget;
QPushButton *mExceptionsButton;
};
#endif
diff --git a/korganizer/kotodoeditor.cpp b/korganizer/kotodoeditor.cpp
index 70dfbd1..069dda8 100644
--- a/korganizer/kotodoeditor.cpp
+++ b/korganizer/kotodoeditor.cpp
@@ -1,383 +1,426 @@
/*
This file is part of KOrganizer.
Copyright (c) 1997, 1998 Preston Brown
Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, permission is given to link this program
with any edition of Qt, and distribute the resulting executable,
without including the source code for Qt in the source distribution.
*/
#include <qtooltip.h>
#include <qframe.h>
#include <qpixmap.h>
#include <qlayout.h>
#include <qhbox.h>
#include <qdir.h>
#include <qdatetime.h>
#include <qapplication.h>
+#include <qtabwidget.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kfiledialog.h>
#include <kstandarddirs.h>
#include <kmessagebox.h>
#include <libkdepim/categoryselectdialog.h>
#include <libkcal/calendarlocal.h>
#include <libkcal/calendarresources.h>
#include <libkcal/resourcecalendar.h>
#include <libkcal/icalformat.h>
#include <kresources/resourceselectdialog.h>
+#include <libkdepim/kdateedit.h>
#include "koprefs.h"
#include "kolocationbox.h"
#include "kotodoeditor.h"
extern int globalFlagBlockAgenda;
KOTodoEditor::KOTodoEditor( Calendar *calendar, QWidget *parent ) :
KOIncidenceEditor( i18n("Edit To-Do"), calendar, parent )
{
mTodo = 0;
mRelatedTodo = 0;
findButton(User1)->hide();
init();
}
KOTodoEditor::~KOTodoEditor()
{
emit dialogClose( mTodo );
}
void KOTodoEditor::init()
{
setupGeneral();
setupAttendeesTab();
+ setupRecurrence();
+ connect(mGeneral,SIGNAL(datesChecked()),this ,SLOT(checkRecurrence()));
}
+void KOTodoEditor::setupRecurrence()
+{
+ QFrame *topFrame = addPage( i18n("Recurrence") );
+ QBoxLayout *topLayout = new QVBoxLayout( topFrame );
+
+ mRecurrence = new KOEditorRecurrence( topFrame );
+ topLayout->addWidget( mRecurrence );
+}
+
void KOTodoEditor::setCategories( QString s )
{
mGeneral->setCategories(s);
}
void KOTodoEditor::setSecrecy( int sec )
{
mGeneral->setSecrecy( sec );
}
void KOTodoEditor::reload()
{
if ( mTodo ) readTodo( mTodo );
}
void KOTodoEditor::setupGeneral()
{
mGeneral = new KOEditorGeneralTodo(this);
connect ( mGeneral, SIGNAL ( allAccepted() ), this, SLOT ( slotOk () ) );
// connect(mGeneral,SIGNAL(openCategoryDialog()),mCategoryDialog,SLOT(show()));
//connect(mCategoryDialog, SIGNAL(categoriesSelected(const QString &)),
// mGeneral,SLOT(setCategories(const QString &)));
if (KOPrefs::instance()->mCompactDialogs) {
QFrame *topFrame = addPage(i18n("General"));
QBoxLayout *topLayout = new QVBoxLayout(topFrame);
if ( QApplication::desktop()->width() < 480 ) {
topLayout->setMargin(1);
topLayout->setSpacing(1);
} else {
topLayout->setMargin(marginHint()-1);
topLayout->setSpacing(spacingHint()-1);
}
mGeneral->initHeader(topFrame,topLayout);
mGeneral->initTime(topFrame,topLayout);
mGeneral->initAlarm(topFrame,topLayout);
mGeneral->enableAlarm( false );
QBoxLayout *priorityLayout;
if ( QApplication::desktop()->width() < 500 )
priorityLayout = new QVBoxLayout( topLayout );
else
priorityLayout = new QHBoxLayout( topLayout );
QWidget* prioWidget = new QWidget (topFrame);
priorityLayout->addWidget( prioWidget );
QHBoxLayout* priorityLayout2 = new QHBoxLayout( prioWidget);
QIconSet icon;
if ( QApplication::desktop()->width() < 321 )
icon = SmallIcon("fileexport16");
else
icon = SmallIcon("fileexport");
QPushButton * saveTemplate = new QPushButton( prioWidget);
saveTemplate->setIconSet (icon ) ;
int size = saveTemplate->sizeHint().height();
saveTemplate->setFixedSize( size, size );
if ( QApplication::desktop()->width() < 321 )
icon = SmallIcon("fileimport16");
else
icon = SmallIcon("fileimport");
QPushButton * loadTemplate = new QPushButton( prioWidget);
loadTemplate->setIconSet (icon ) ;
loadTemplate->setFixedSize( size, size );
priorityLayout2->addWidget(loadTemplate);
priorityLayout2->addWidget(saveTemplate);
mGeneral->initPriority(prioWidget,priorityLayout2);
mGeneral->initCategories( topFrame, priorityLayout );
topLayout->addStretch(1);
QFrame *topFrame2 = addPage(i18n("Details"));
QBoxLayout *topLayout2 = new QVBoxLayout(topFrame2);
topLayout2->setMargin(marginHint());
topLayout2->setSpacing(spacingHint());
QHBoxLayout *completionLayout = new QHBoxLayout( topLayout2 );
mGeneral->initCompletion(topFrame2,completionLayout);
mGeneral->initSecrecy( topFrame2, topLayout2 );
mGeneral->initDescription(topFrame2,topLayout2);
// QHBox * hb = new QHBox ( topFrame2 );
// topLayout2->addWidget(hb);
// hb->setSpacing( 3 );
connect( saveTemplate, SIGNAL( clicked() ), this , SLOT( slotSaveTemplate() ) );
connect( loadTemplate, SIGNAL( clicked() ), this , SLOT( slotLoadTemplate() ) );
} else {
QFrame *topFrame = addPage(i18n("General"));
QBoxLayout *topLayout = new QVBoxLayout(topFrame);
topLayout->setSpacing(spacingHint());
mGeneral->initHeader(topFrame,topLayout);
mGeneral->initTime(topFrame,topLayout);
mGeneral->initStatus(topFrame,topLayout);
QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout);
mGeneral->initAlarm(topFrame,alarmLineLayout);
mGeneral->initDescription(topFrame,topLayout);
QBoxLayout *detailsLayout = new QHBoxLayout(topLayout);
mGeneral->initCategories( topFrame, detailsLayout );
mGeneral->initSecrecy( topFrame, detailsLayout );
}
mGeneral->finishSetup();
}
void KOTodoEditor::editTodo(Todo *todo, bool editDescription)
{
//init();
mTodo = todo;
readTodo(mTodo);
if ( editDescription ) {
showPage( 1 );
mGeneral->setFocusOn( 1 );
} else {
showPage( 0 );
mGeneral->setFocusOn( 2 );
}
+ checkRecurrence();
}
void KOTodoEditor::newTodo(QDateTime due,Todo *relatedTodo,bool allDay)
{
//init();
mTodo = 0;
setDefaults(due,relatedTodo,allDay);
}
void KOTodoEditor::loadDefaults()
{
setDefaults(QDateTime::currentDateTime().addDays(7),0,false);
}
bool KOTodoEditor::processInput( bool emitTime )
{
if (!validateInput()) return false;
Todo *todo = 0;
if (mTodo) todo = mTodo;
else {
todo = new Todo;
todo->setOrganizer(KOPrefs::instance()->email());
}
writeTodo(todo);
if ( emitTime ) {
globalFlagBlockAgenda = 1;
emit showAgendaView( false );
if ( todo->hasDueDate() )
emit jumpToTime( todo->dtDue().date() );
globalFlagBlockAgenda = 2;
}
if (mTodo) {
todo->setRevision(todo->revision()+1);
emit todoChanged(todo);
} else {
mCalendar->addTodo(todo);
mTodo = todo;
emit todoAdded(todo);
}
return true;
}
void KOTodoEditor::deleteTodo()
{
if (mTodo) {
if (KOPrefs::instance()->mConfirm) {
switch (msgItemDelete()) {
case KMessageBox::Continue: // OK
emit todoToBeDeleted(mTodo);
emit dialogClose(mTodo);
mCalendar->deleteTodo(mTodo);
emit todoDeleted();
reject();
break;
}
}
else {
emit todoToBeDeleted(mTodo);
emit dialogClose(mTodo);
mCalendar->deleteTodo(mTodo);
emit todoDeleted();
reject();
}
} else {
reject();
}
}
void KOTodoEditor::setDefaults(QDateTime due,Todo *relatedEvent,bool allDay)
{
mRelatedTodo = relatedEvent;
mGeneral->setDefaults(due,allDay);
mDetails->setDefaults();
showPage( 0 );
if ( mRelatedTodo ) {
mGeneral->setCategories (mRelatedTodo->categoriesStr ());
mGeneral->setSecrecy (mRelatedTodo->secrecy ());
if ( mRelatedTodo->priority() < 3 )
mGeneral->mPriorityCombo->setCurrentItem(mRelatedTodo->priority()-1);
mGeneral->mSummaryEdit->lineEdit()->setText(mRelatedTodo->summary()+": ");
int len = mRelatedTodo->summary().length();
mGeneral->mSummaryEdit->lineEdit()->setFocus();
mGeneral->mSummaryEdit->lineEdit()->setCursorPosition ( len+2 );
mGeneral->mSummaryEdit->lineEdit()->setSelection ( 0, len+2 );
} else
mGeneral->setFocusOn( 2 );
+ tabWidget()->setTabEnabled ( mRecurrence->parentWidget(), false );
+ mRecurrence->setDefaults(QDateTime::currentDateTime(),QDateTime::currentDateTime().addSecs( 3600 ),true);
}
+void KOTodoEditor::checkRecurrence()
+{
+ if ( mGeneral->mDueCheck->isChecked() && mGeneral->mStartCheck->isChecked()) {
+ tabWidget()->setTabEnabled ( mRecurrence->parentWidget(), true );
+ if ( mTodo )
+ mRecurrence->readEvent( mTodo );
+ else {
+ bool time = mGeneral->mTimeButton->isChecked();
+ QDateTime from,to;
+ if ( time ) {
+ to = QDateTime( mGeneral->mDueDateEdit->date(), mGeneral->mDueTimeEdit->getTime() ) ;
+ from = QDateTime( mGeneral->mStartDateEdit->date(),mGeneral->mStartTimeEdit->getTime( )) ;
+ } else {
+ to = QDateTime( mGeneral->mDueDateEdit->date(), QTime( 0,0,0) ) ;
+ from = QDateTime( mGeneral->mStartDateEdit->date(),QTime( 0,0,0) ) ;
+ }
+ mRecurrence->setDefaults(from,to,!time);
+ }
+ } else {
+ tabWidget()->setTabEnabled ( mRecurrence->parentWidget(), false );
+ mRecurrence->setDefaults(QDateTime::currentDateTime(),QDateTime::currentDateTime().addSecs( 3600 ),true);
+ }
+}
void KOTodoEditor::readTodo(Todo *todo)
{
mGeneral->readTodo(todo);
mDetails->readEvent(todo);
mRelatedTodo = 0;//todo->relatedTo();
// categories
// mCategoryDialog->setSelected(todo->categories());
// We should handle read-only events here.
}
void KOTodoEditor::writeTodo(Todo *event)
{
mGeneral->writeTodo(event);
mDetails->writeEvent(event);
// set related event, i.e. parent to-do in this case.
if (mRelatedTodo) {
event->setRelatedTo(mRelatedTodo);
}
+ if ( mGeneral->mDueCheck->isChecked() && mGeneral->mStartCheck->isChecked()) {
+ mRecurrence->writeEvent(event);
+ } else
+ event->recurrence()->unsetRecurs();
}
bool KOTodoEditor::validateInput()
{
if (!mGeneral->validateInput()) return false;
if (!mDetails->validateInput()) return false;
return true;
}
int KOTodoEditor::msgItemDelete()
{
return KMessageBox::warningContinueCancel(this,
i18n("This item will be permanently deleted."),
i18n("KOrganizer Confirmation"),i18n("Delete"));
}
void KOTodoEditor::modified (int modification)
{
if (modification == KOGlobals::CATEGORY_MODIFIED ||
KOGlobals::UNKNOWN_MODIFIED == modification )
// mCategoryDialog->setSelected (mTodo->categories ());
mGeneral->modified (mTodo, modification);
}
void KOTodoEditor::slotLoadTemplate()
{
QString fileName =locateLocal( "templates", "todos" );
QDir t_dir;
if ( !t_dir.exists(fileName) )
t_dir.mkdir ( fileName );
fileName += "/todo";
fileName = KFileDialog::getSaveFileName( fileName , "Load Todo template", this );
if ( fileName.length() == 0 )
return;
CalendarLocal cal;
ICalFormat format;
if ( !format.load( &cal, fileName ) ) {
KMessageBox::error( this, i18n("Error loading template file\n '%1'.")
.arg( fileName ) );
return ;
}
QPtrList<Todo> todos = cal.todos();
Todo * todo = todos.first();
if ( !todo ) {
KMessageBox::error( this,
i18n("Template does not\ncontain a valid Todo."));
} else {
readTodo( todo );
}
}
void KOTodoEditor::slotSaveTemplate()
{
QString fileName =locateLocal( "templates", "todos" );
QDir t_dir;
if ( !t_dir.exists(fileName) )
t_dir.mkdir ( fileName );
fileName += "/todo";
fileName = KFileDialog::getSaveFileName( fileName , "Save as Todo template", this );
if ( fileName.length() > 0 )
saveTemplate( fileName );
}
void KOTodoEditor::saveTemplate( const QString &templateName )
{
Todo *todo = new Todo;
writeTodo( todo );
saveAsTemplate( todo, templateName );
}
diff --git a/korganizer/kotodoeditor.h b/korganizer/kotodoeditor.h
index 2657bd8..1b5e3b4 100644
--- a/korganizer/kotodoeditor.h
+++ b/korganizer/kotodoeditor.h
@@ -1,102 +1,106 @@
/*
This file is part of KOrganizer.
Copyright (c) 1997, 1998 Preston Brown
Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, permission is given to link this program
with any edition of Qt, and distribute the resulting executable,
without including the source code for Qt in the source distribution.
*/
#ifndef _KOTODOEDITOR_H
#define _KOTODOEDITOR_H
#include <libkcal/calendar.h>
#include "koeditorgeneraltodo.h"
#include "koeditordetails.h"
#include "koincidenceeditor.h"
+#include "koeditorrecurrence.h"
class QDateTime;
/**
This class provides a dialog for editing a Todo.
*/
class KOTodoEditor : public KOIncidenceEditor
{
Q_OBJECT
public:
/**
Constructs a new todo editor.
*/
KOTodoEditor( Calendar *calendar, QWidget *parent );
virtual ~KOTodoEditor();
void init();
void reload();
void setSecrecy( int sec );
/**
Clear editor for new todo, and preset the dates and times with hint.
*/
void newTodo(QDateTime due,Todo *relatedTodo=0,bool allDay=false);
/** Edit an existing todo. */
void editTodo(Todo * ,bool editDescription = false );
/** Set widgets to default values */
void setDefaults(QDateTime due,Todo *relatedTodo,bool allDay);
/** Read event object and setup widgets accordingly */
void readTodo(Todo *);
/** Write event settings to event object */
void writeTodo(Todo *);
/** Check if the input is valid. */
bool validateInput();
/** Process user input and create or update event. Returns false if input
* is not valid */
bool processInput( bool );
/** This todo has been modified externally */
void modified (int);
void setCategories( QString s );
signals:
void todoChanged(Todo *);
void todoAdded(Todo *);
void todoToBeDeleted(Todo *);
void todoDeleted();
protected slots:
void loadDefaults();
void deleteTodo();
+ void checkRecurrence();
void slotLoadTemplate();
void slotSaveTemplate();
void saveTemplate( const QString & );
protected:
void setupGeneral();
int msgItemDelete();
+ void setupRecurrence();
private:
Todo *mTodo;
Incidence *mRelatedTodo;
KOEditorGeneralTodo *mGeneral;
+ KOEditorRecurrence *mRecurrence;
};
#endif
diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp
index bd13132..bb9cb29 100644
--- a/libkcal/icalformatimpl.cpp
+++ b/libkcal/icalformatimpl.cpp
@@ -1,1718 +1,1726 @@
/*
This file is part of libkcal.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <qdatetime.h>
#include <qstring.h>
#include <qptrlist.h>
#include <qfile.h>
#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
extern "C" {
#include <ical.h>
#include <icalss.h>
#include <icalparser.h>
#include <icalrestriction.h>
}
#include "calendar.h"
#include "journal.h"
#include "icalformat.h"
#include "icalformatimpl.h"
#include "compat.h"
#define _ICAL_VERSION "2.0"
using namespace KCal;
const int gSecondsPerMinute = 60;
const int gSecondsPerHour = gSecondsPerMinute * 60;
const int gSecondsPerDay = gSecondsPerHour * 24;
const int gSecondsPerWeek = gSecondsPerDay * 7;
ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) :
mParent( parent ), mCalendarVersion( 0 )
{
mCompat = new Compat;
}
ICalFormatImpl::~ICalFormatImpl()
{
delete mCompat;
}
class ToStringVisitor : public Incidence::Visitor
{
public:
ToStringVisitor( ICalFormatImpl *impl ) : mImpl( impl ), mComponent( 0 ) {}
bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; }
bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; }
bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; }
icalcomponent *component() { return mComponent; }
private:
ICalFormatImpl *mImpl;
icalcomponent *mComponent;
};
icalcomponent *ICalFormatImpl::writeIncidence(Incidence *incidence)
{
ToStringVisitor v( this );
incidence->accept(v);
return v.component();
}
icalcomponent *ICalFormatImpl::writeTodo(Todo *todo)
{
QString tmpStr;
QStringList tmpStrList;
icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
writeIncidence(vtodo,todo);
// due date
if (todo->hasDueDate()) {
icaltimetype due;
if (todo->doesFloat()) {
due = writeICalDate(todo->dtDue().date());
} else {
due = writeICalDateTime(todo->dtDue());
}
icalcomponent_add_property(vtodo,icalproperty_new_due(due));
}
// start time
if (todo->hasStartDate()) {
icaltimetype start;
if (todo->doesFloat()) {
// kdDebug(5800) << "§§ Incidence " << todo->summary() << " floats." << endl;
start = writeICalDate(todo->dtStart().date());
} else {
// kdDebug(5800) << "§§ incidence " << todo->summary() << " has time." << endl;
start = writeICalDateTime(todo->dtStart());
}
icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start));
}
// completion date
if (todo->isCompleted()) {
if (!todo->hasCompletedDate()) {
// If todo was created by KOrganizer <2.2 it has no correct completion
// date. Set it to now.
todo->setCompleted(QDateTime::currentDateTime());
}
icaltimetype completed = writeICalDateTime(todo->completed());
icalcomponent_add_property(vtodo,icalproperty_new_completed(completed));
}
icalcomponent_add_property(vtodo,
icalproperty_new_percentcomplete(todo->percentComplete()));
return vtodo;
}
icalcomponent *ICalFormatImpl::writeEvent(Event *event)
{
kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid()
<< ")" << endl;
QString tmpStr;
QStringList tmpStrList;
icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
writeIncidence(vevent,event);
// start time
icaltimetype start;
if (event->doesFloat()) {
// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl;
start = writeICalDate(event->dtStart().date());
} else {
// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl;
start = writeICalDateTime(event->dtStart());
}
icalcomponent_add_property(vevent,icalproperty_new_dtstart(start));
if (event->hasEndDate()) {
// end time
icaltimetype end;
if (event->doesFloat()) {
// kdDebug(5800) << "§§ Event " << event->summary() << " floats." << endl;
// +1 day because end date is non-inclusive.
end = writeICalDate( event->dtEnd().date().addDays( 1 ) );
} else {
// kdDebug(5800) << "§§ Event " << event->summary() << " has time." << endl;
end = writeICalDateTime(event->dtEnd());
}
icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
}
// TODO: attachments, resources
#if 0
// attachments
tmpStrList = anEvent->attachments();
for ( QStringList::Iterator it = tmpStrList.begin();
it != tmpStrList.end();
++it )
addPropValue(vevent, VCAttachProp, (*it).utf8());
// resources
tmpStrList = anEvent->resources();
tmpStr = tmpStrList.join(";");
if (!tmpStr.isEmpty())
addPropValue(vevent, VCResourcesProp, tmpStr.utf8());
#endif
// Transparency
switch( event->transparency() ) {
case Event::Transparent:
icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT));
break;
case Event::Opaque:
icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_OPAQUE));
break;
}
return vevent;
}
icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy,
Scheduler::Method method)
{
icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
writeIncidenceBase(vfreebusy,freebusy);
icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart(
writeICalDateTime(freebusy->dtStart())));
icalcomponent_add_property(vfreebusy, icalproperty_new_dtend(
writeICalDateTime(freebusy->dtEnd())));
if (method == Scheduler::Request) {
icalcomponent_add_property(vfreebusy,icalproperty_new_uid(
freebusy->uid().utf8()));
}
//Loops through all the periods in the freebusy object
QValueList<Period> list = freebusy->busyPeriods();
QValueList<Period>::Iterator it;
icalperiodtype period;
for (it = list.begin(); it!= list.end(); ++it) {
period.start = writeICalDateTime((*it).start());
period.end = writeICalDateTime((*it).end());
icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) );
}
return vfreebusy;
}
icalcomponent *ICalFormatImpl::writeJournal(Journal *journal)
{
icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
writeIncidence(vjournal,journal);
// start time
if (journal->dtStart().isValid()) {
icaltimetype start;
if (journal->doesFloat()) {
// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl;
start = writeICalDate(journal->dtStart().date());
} else {
// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl;
start = writeICalDateTime(journal->dtStart());
}
icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start));
}
return vjournal;
}
void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence)
{
// pilot sync stuff
// TODO: move this application-specific code to kpilot
if (incidence->pilotId()) {
incidence->setNonKDECustomProperty("X-PILOTID", QString::number(incidence->pilotId()));
incidence->setNonKDECustomProperty("X-PILOTSTAT", QString::number(incidence->syncStatus()));
}
if ( !incidence->IDStr().isEmpty()) {
incidence->setNonKDECustomProperty("X-KOPIEXTID",incidence->IDStr() );
}
writeIncidenceBase(parent,incidence);
if (incidence->cancelled()) {
icalcomponent_add_property(parent,icalproperty_new_status(ICAL_STATUS_CANCELLED));
}
// creation date
icalcomponent_add_property(parent,icalproperty_new_created(
writeICalDateTime(incidence->created())));
// unique id
icalcomponent_add_property(parent,icalproperty_new_uid(
incidence->uid().utf8()));
// revision
icalcomponent_add_property(parent,icalproperty_new_sequence(
incidence->revision()));
// last modification date
icalcomponent_add_property(parent,icalproperty_new_lastmodified(
writeICalDateTime(incidence->lastModified())));
// description
if (!incidence->description().isEmpty()) {
icalcomponent_add_property(parent,icalproperty_new_description(
incidence->description().utf8()));
}
// summary
if (!incidence->summary().isEmpty()) {
icalcomponent_add_property(parent,icalproperty_new_summary(
incidence->summary().utf8()));
}
// location
if (!incidence->location().isEmpty()) {
icalcomponent_add_property(parent,icalproperty_new_location(
incidence->location().utf8()));
}
// TODO:
// status
// addPropValue(parent, VCStatusProp, incidence->getStatusStr().utf8());
// secrecy
enum icalproperty_class classInt;
switch (incidence->secrecy()) {
case Incidence::SecrecyPublic:
classInt = ICAL_CLASS_PUBLIC;
break;
case Incidence::SecrecyConfidential:
classInt = ICAL_CLASS_CONFIDENTIAL;
break;
case Incidence::SecrecyPrivate:
classInt =ICAL_CLASS_PRIVATE ;
default:
classInt =ICAL_CLASS_PRIVATE ;
break;
}
icalcomponent_add_property(parent,icalproperty_new_class(classInt));
// priority
icalcomponent_add_property(parent,icalproperty_new_priority(
incidence->priority()));
// categories
QStringList categories = incidence->categories();
QStringList::Iterator it;
for(it = categories.begin(); it != categories.end(); ++it ) {
icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8()));
}
// TODO: Ensure correct concatenation of categories properties.
/*
// categories
tmpStrList = incidence->getCategories();
tmpStr = "";
QString catStr;
for ( QStringList::Iterator it = tmpStrList.begin();
it != tmpStrList.end();
++it ) {
catStr = *it;
if (catStr[0] == ' ')
tmpStr += catStr.mid(1);
else
tmpStr += catStr;
// this must be a ';' character as the vCalendar specification requires!
// vcc.y has been hacked to translate the ';' to a ',' when the vcal is
// read in.
tmpStr += ";";
}
if (!tmpStr.isEmpty()) {
tmpStr.truncate(tmpStr.length()-1);
icalcomponent_add_property(parent,icalproperty_new_categories(
writeText(incidence->getCategories().join(";"))));
}
*/
// related event
if (incidence->relatedTo()) {
icalcomponent_add_property(parent,icalproperty_new_relatedto(
incidence->relatedTo()->uid().utf8()));
}
// recurrence rule stuff
Recurrence *recur = incidence->recurrence();
if (recur->doesRecur()) {
icalcomponent_add_property(parent,writeRecurrenceRule(recur));
}
// recurrence excpetion dates
DateList dateList = incidence->exDates();
DateList::ConstIterator exIt;
for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) {
icalcomponent_add_property(parent,icalproperty_new_exdate(
writeICalDate(*exIt)));
}
// attachments
QPtrList<Attachment> attachments = incidence->attachments();
for (Attachment *at = attachments.first(); at; at = attachments.next())
icalcomponent_add_property(parent,writeAttachment(at));
// alarms
QPtrList<Alarm> alarms = incidence->alarms();
Alarm* alarm;
for (alarm = alarms.first(); alarm; alarm = alarms.next()) {
if (alarm->enabled()) {
kdDebug(5800) << "Write alarm for " << incidence->summary() << endl;
icalcomponent_add_component(parent,writeAlarm(alarm));
}
}
-
+ if( incidence->hasRecurrenceID() ) {
+ icalcomponent_add_property(parent,
+ icalproperty_new_recurrenceid( writeICalDateTime( incidence->recurrenceID())));
+ }
// duration
// turned off as it always is set to PTS0 (and must not occur together with DTEND
// if (incidence->hasDuration()) {
// icaldurationtype duration;
// duration = writeICalDuration(incidence->duration());
// icalcomponent_add_property(parent,icalproperty_new_duration(duration));
// }
}
void ICalFormatImpl::writeIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
{
icalcomponent_add_property(parent,icalproperty_new_dtstamp(
writeICalDateTime(QDateTime::currentDateTime())));
// organizer stuff
icalcomponent_add_property(parent,icalproperty_new_organizer(
("MAILTO:" + incidenceBase->organizer()).utf8()));
// attendees
if (incidenceBase->attendeeCount() != 0) {
QPtrList<Attendee> al = incidenceBase->attendees();
QPtrListIterator<Attendee> ai(al);
for (; ai.current(); ++ai) {
icalcomponent_add_property(parent,writeAttendee(ai.current()));
}
}
// custom properties
writeCustomProperties(parent, incidenceBase);
}
void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties)
{
QMap<QCString, QString> custom = properties->customProperties();
for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
icalproperty *p = icalproperty_new_x(c.data().utf8());
icalproperty_set_x_name(p,c.key());
icalcomponent_add_property(parent,p);
}
}
icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee)
{
icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8());
if (!attendee->name().isEmpty()) {
icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8()));
}
icalproperty_add_parameter(p,icalparameter_new_rsvp(
attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE ));
icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
switch (attendee->status()) {
default:
case Attendee::NeedsAction:
status = ICAL_PARTSTAT_NEEDSACTION;
break;
case Attendee::Accepted:
status = ICAL_PARTSTAT_ACCEPTED;
break;
case Attendee::Declined:
status = ICAL_PARTSTAT_DECLINED;
break;
case Attendee::Tentative:
status = ICAL_PARTSTAT_TENTATIVE;
break;
case Attendee::Delegated:
status = ICAL_PARTSTAT_DELEGATED;
break;
case Attendee::Completed:
status = ICAL_PARTSTAT_COMPLETED;
break;
case Attendee::InProcess:
status = ICAL_PARTSTAT_INPROCESS;
break;
}
icalproperty_add_parameter(p,icalparameter_new_partstat(status));
icalparameter_role role = ICAL_ROLE_REQPARTICIPANT;
switch (attendee->role()) {
case Attendee::Chair:
role = ICAL_ROLE_CHAIR;
break;
default:
case Attendee::ReqParticipant:
role = ICAL_ROLE_REQPARTICIPANT;
break;
case Attendee::OptParticipant:
role = ICAL_ROLE_OPTPARTICIPANT;
break;
case Attendee::NonParticipant:
role = ICAL_ROLE_NONPARTICIPANT;
break;
}
icalproperty_add_parameter(p,icalparameter_new_role(role));
if (!attendee->uid().isEmpty()) {
icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8());
icalparameter_set_xname(icalparameter_uid,"X-UID");
icalproperty_add_parameter(p,icalparameter_uid);
}
return p;
}
icalproperty *ICalFormatImpl::writeAttachment(Attachment *att)
{
#if 0
icalattachtype* attach = icalattachtype_new();
if (att->isURI())
icalattachtype_set_url(attach, att->uri().utf8().data());
else
icalattachtype_set_base64(attach, att->data(), 0);
#endif
icalattach *attach;
if (att->isURI())
attach = icalattach_new_from_url( att->uri().utf8().data());
else
attach = icalattach_new_from_data ( (unsigned char *)att->data(), 0, 0);
icalproperty *p = icalproperty_new_attach(attach);
if (!att->mimeType().isEmpty())
icalproperty_add_parameter(p,icalparameter_new_fmttype(att->mimeType().utf8().data()));
if (att->isBinary()) {
icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY));
icalproperty_add_parameter(p,icalparameter_new_encoding(ICAL_ENCODING_BASE64));
}
return p;
}
icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur)
{
// kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl;
icalrecurrencetype r;
icalrecurrencetype_clear(&r);
int index = 0;
int index2 = 0;
QPtrList<Recurrence::rMonthPos> tmpPositions;
QPtrList<int> tmpDays;
int *tmpDay;
Recurrence::rMonthPos *tmpPos;
bool datetime = false;
int day;
int i;
switch(recur->doesRecur()) {
case Recurrence::rMinutely:
r.freq = ICAL_MINUTELY_RECURRENCE;
datetime = true;
break;
case Recurrence::rHourly:
r.freq = ICAL_HOURLY_RECURRENCE;
datetime = true;
break;
case Recurrence::rDaily:
r.freq = ICAL_DAILY_RECURRENCE;
break;
case Recurrence::rWeekly:
r.freq = ICAL_WEEKLY_RECURRENCE;
r.week_start = static_cast<icalrecurrencetype_weekday>(recur->weekStart()%7 + 1);
for (i = 0; i < 7; i++) {
if (recur->days().testBit(i)) {
day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
r.by_day[index++] = icalrecurrencetype_day_day_of_week(day);
}
}
// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
break;
case Recurrence::rMonthlyPos:
r.freq = ICAL_MONTHLY_RECURRENCE;
tmpPositions = recur->monthPositions();
for (tmpPos = tmpPositions.first();
tmpPos;
tmpPos = tmpPositions.next()) {
for (i = 0; i < 7; i++) {
if (tmpPos->rDays.testBit(i)) {
day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
day += tmpPos->rPos*8;
if (tmpPos->negative) day = -day;
r.by_day[index++] = day;
}
}
}
// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
break;
case Recurrence::rMonthlyDay:
r.freq = ICAL_MONTHLY_RECURRENCE;
tmpDays = recur->monthDays();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8);//*tmpDay);
}
// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
break;
case Recurrence::rYearlyMonth:
case Recurrence::rYearlyPos:
r.freq = ICAL_YEARLY_RECURRENCE;
tmpDays = recur->yearNums();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
r.by_month[index++] = *tmpDay;
}
// r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX;
if (recur->doesRecur() == Recurrence::rYearlyPos) {
tmpPositions = recur->monthPositions();
for (tmpPos = tmpPositions.first();
tmpPos;
tmpPos = tmpPositions.next()) {
for (i = 0; i < 7; i++) {
if (tmpPos->rDays.testBit(i)) {
day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
day += tmpPos->rPos*8;
if (tmpPos->negative) day = -day;
r.by_day[index2++] = day;
}
}
}
// r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX;
}
break;
case Recurrence::rYearlyDay:
r.freq = ICAL_YEARLY_RECURRENCE;
tmpDays = recur->yearNums();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
r.by_year_day[index++] = *tmpDay;
}
// r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
break;
default:
r.freq = ICAL_NO_RECURRENCE;
kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl;
break;
}
r.interval = recur->frequency();
if (recur->duration() > 0) {
r.count = recur->duration();
} else if (recur->duration() == -1) {
r.count = 0;
} else {
if (datetime)
r.until = writeICalDateTime(recur->endDateTime());
else
r.until = writeICalDate(recur->endDate());
}
// Debug output
#if 0
const char *str = icalrecurrencetype_as_string(&r);
if (str) {
kdDebug(5800) << " String: " << str << endl;
} else {
kdDebug(5800) << " No String" << endl;
}
#endif
return icalproperty_new_rrule(r);
}
icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm)
{
icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT);
icalproperty_action action;
icalattach *attach = 0;
switch (alarm->type()) {
case Alarm::Procedure:
action = ICAL_ACTION_PROCEDURE;
attach = icalattach_new_from_url( QFile::encodeName(alarm->programFile()).data() );
icalcomponent_add_property(a,icalproperty_new_attach(attach));
if (!alarm->programArguments().isEmpty()) {
icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8()));
}
break;
case Alarm::Audio:
action = ICAL_ACTION_AUDIO;
if (!alarm->audioFile().isEmpty()) {
attach = icalattach_new_from_url(QFile::encodeName( alarm->audioFile() ).data());
icalcomponent_add_property(a,icalproperty_new_attach(attach));
}
break;
case Alarm::Email: {
action = ICAL_ACTION_EMAIL;
QValueList<Person> addresses = alarm->mailAddresses();
for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) {
icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8());
if (!(*ad).name().isEmpty()) {
icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8()));
}
icalcomponent_add_property(a,p);
}
icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8()));
icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
QStringList attachments = alarm->mailAttachments();
if (attachments.count() > 0) {
for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) {
attach = icalattach_new_from_url(QFile::encodeName( *at ).data());
icalcomponent_add_property(a,icalproperty_new_attach(attach));
}
}
break;
}
case Alarm::Display:
action = ICAL_ACTION_DISPLAY;
icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
break;
case Alarm::Invalid:
default:
kdDebug(5800) << "Unknown type of alarm" << endl;
action = ICAL_ACTION_NONE;
break;
}
icalcomponent_add_property(a,icalproperty_new_action(action));
// Trigger time
icaltriggertype trigger;
if ( alarm->hasTime() ) {
trigger.time = writeICalDateTime(alarm->time());
trigger.duration = icaldurationtype_null_duration();
} else {
trigger.time = icaltime_null_time();
Duration offset;
if ( alarm->hasStartOffset() )
offset = alarm->startOffset();
else
offset = alarm->endOffset();
trigger.duration = icaldurationtype_from_int( offset.asSeconds() );
}
icalproperty *p = icalproperty_new_trigger(trigger);
if ( alarm->hasEndOffset() )
icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END));
icalcomponent_add_property(a,p);
// Repeat count and duration
if (alarm->repeatCount()) {
icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount()));
icalcomponent_add_property(a,icalproperty_new_duration(
icaldurationtype_from_int(alarm->snoozeTime()*60)));
}
// Custom properties
QMap<QCString, QString> custom = alarm->customProperties();
for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
icalproperty *p = icalproperty_new_x(c.data().utf8());
icalproperty_set_x_name(p,c.key());
icalcomponent_add_property(a,p);
}
return a;
}
Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo)
{
Todo *todo = new Todo;
readIncidence(vtodo,todo);
icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY);
// int intvalue;
icaltimetype icaltime;
QStringList categories;
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_DUE_PROPERTY: // due date
icaltime = icalproperty_get_due(p);
if (icaltime.is_date) {
todo->setDtDue(QDateTime(readICalDate(icaltime),QTime(0,0,0)));
todo->setFloats(true);
} else {
todo->setDtDue(readICalDateTime(icaltime));
todo->setFloats(false);
}
todo->setHasDueDate(true);
break;
case ICAL_COMPLETED_PROPERTY: // completion date
icaltime = icalproperty_get_completed(p);
todo->setCompleted(readICalDateTime(icaltime));
break;
case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed
todo->setPercentComplete(icalproperty_get_percentcomplete(p));
break;
case ICAL_RELATEDTO_PROPERTY: // related todo (parent)
todo->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p)));
mTodosRelate.append(todo);
break;
case ICAL_DTSTART_PROPERTY:
// Flag that todo has start date. Value is read in by readIncidence().
todo->setHasStartDate(true);
break;
default:
// kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind
// << endl;
break;
}
p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY);
}
return todo;
}
Event *ICalFormatImpl::readEvent(icalcomponent *vevent)
{
Event *event = new Event;
event->setFloats(false);
readIncidence(vevent,event);
icalproperty *p = icalcomponent_get_first_property(vevent,ICAL_ANY_PROPERTY);
// int intvalue;
icaltimetype icaltime;
QStringList categories;
QString transparency;
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_DTEND_PROPERTY: // start date and time
icaltime = icalproperty_get_dtend(p);
if (icaltime.is_date) {
event->setFloats( true );
// End date is non-inclusive
QDate endDate = readICalDate( icaltime ).addDays( -1 );
mCompat->fixFloatingEnd( endDate );
if ( endDate < event->dtStart().date() ) {
endDate = event->dtStart().date();
}
event->setDtEnd( QDateTime( endDate, QTime( 0, 0, 0 ) ) );
} else {
event->setDtEnd(readICalDateTime(icaltime));
}
break;
// TODO:
// at this point, there should be at least a start or end time.
// fix up for events that take up no time but have a time associated
#if 0
if (!(vo = isAPropertyOf(vevent, VCDTstartProp)))
anEvent->setDtStart(anEvent->dtEnd());
if (!(vo = isAPropertyOf(vevent, VCDTendProp)))
anEvent->setDtEnd(anEvent->dtStart());
#endif
// TODO: exdates
#if 0
// recurrence exceptions
if ((vo = isAPropertyOf(vevent, VCExDateProp)) != 0) {
anEvent->setExDates(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
#endif
#if 0
// secrecy
if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) {
anEvent->setSecrecy(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
else
anEvent->setSecrecy("PUBLIC");
// attachments
tmpStrList.clear();
initPropIterator(&voi, vevent);
while (moreIteration(&voi)) {
vo = nextVObject(&voi);
if (strcmp(vObjectName(vo), VCAttachProp) == 0) {
tmpStrList.append(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
}
anEvent->setAttachments(tmpStrList);
// resources
if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) {
QString resources = (s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
tmpStrList.clear();
index1 = 0;
index2 = 0;
QString resource;
while ((index2 = resources.find(';', index1)) != -1) {
resource = resources.mid(index1, (index2 - index1));
tmpStrList.append(resource);
index1 = index2;
}
anEvent->setResources(tmpStrList);
}
#endif
case ICAL_RELATEDTO_PROPERTY: // releated event (parent)
event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p)));
mEventsRelate.append(event);
break;
case ICAL_TRANSP_PROPERTY: // Transparency
if(icalproperty_get_transp(p) == ICAL_TRANSP_TRANSPARENT )
event->setTransparency( Event::Transparent );
else
event->setTransparency( Event::Opaque );
break;
default:
// kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind
// << endl;
break;
}
p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY);
}
QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT");
if (!msade.isNull()) {
bool floats = (msade == QString::fromLatin1("TRUE"));
kdDebug(5800) << "ICALFormat::readEvent(): all day event: " << floats << endl;
event->setFloats(floats);
if (floats) {
QDateTime endDate = event->dtEnd();
event->setDtEnd(endDate.addDays(-1));
}
}
// some stupid vCal exporters ignore the standard and use Description
// instead of Summary for the default field. Correct for this.
if (event->summary().isEmpty() &&
!(event->description().isEmpty())) {
QString tmpStr = event->description().simplifyWhiteSpace();
event->setDescription("");
event->setSummary(tmpStr);
}
return event;
}
FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy)
{
FreeBusy *freebusy = new FreeBusy;
readIncidenceBase(vfreebusy,freebusy);
icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY);
icaltimetype icaltime;
icalperiodtype icalperiod;
QDateTime period_start, period_end;
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_DTSTART_PROPERTY: // start date and time
icaltime = icalproperty_get_dtstart(p);
freebusy->setDtStart(readICalDateTime(icaltime));
break;
case ICAL_DTEND_PROPERTY: // start End Date and Time
icaltime = icalproperty_get_dtend(p);
freebusy->setDtEnd(readICalDateTime(icaltime));
break;
case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times
icalperiod = icalproperty_get_freebusy(p);
period_start = readICalDateTime(icalperiod.start);
period_end = readICalDateTime(icalperiod.end);
freebusy->addPeriod(period_start, period_end);
break;
default:
kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
<< endl;
break;
}
p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY);
}
return freebusy;
}
Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal)
{
Journal *journal = new Journal;
readIncidence(vjournal,journal);
return journal;
}
Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee)
{
icalparameter *p = 0;
QString email = QString::fromUtf8(icalproperty_get_attendee(attendee));
QString name;
QString uid = QString::null;
p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER);
if (p) {
name = QString::fromUtf8(icalparameter_get_cn(p));
} else {
}
bool rsvp=false;
p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER);
if (p) {
icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p);
if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true;
}
Attendee::PartStat status = Attendee::NeedsAction;
p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER);
if (p) {
icalparameter_partstat partStatParameter = icalparameter_get_partstat(p);
switch(partStatParameter) {
default:
case ICAL_PARTSTAT_NEEDSACTION:
status = Attendee::NeedsAction;
break;
case ICAL_PARTSTAT_ACCEPTED:
status = Attendee::Accepted;
break;
case ICAL_PARTSTAT_DECLINED:
status = Attendee::Declined;
break;
case ICAL_PARTSTAT_TENTATIVE:
status = Attendee::Tentative;
break;
case ICAL_PARTSTAT_DELEGATED:
status = Attendee::Delegated;
break;
case ICAL_PARTSTAT_COMPLETED:
status = Attendee::Completed;
break;
case ICAL_PARTSTAT_INPROCESS:
status = Attendee::InProcess;
break;
}
}
Attendee::Role role = Attendee::ReqParticipant;
p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER);
if (p) {
icalparameter_role roleParameter = icalparameter_get_role(p);
switch(roleParameter) {
case ICAL_ROLE_CHAIR:
role = Attendee::Chair;
break;
default:
case ICAL_ROLE_REQPARTICIPANT:
role = Attendee::ReqParticipant;
break;
case ICAL_ROLE_OPTPARTICIPANT:
role = Attendee::OptParticipant;
break;
case ICAL_ROLE_NONPARTICIPANT:
role = Attendee::NonParticipant;
break;
}
}
p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER);
uid = icalparameter_get_xvalue(p);
// This should be added, but there seems to be a libical bug here.
/*while (p) {
// if (icalparameter_get_xname(p) == "X-UID") {
uid = icalparameter_get_xvalue(p);
p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER);
} */
return new Attendee( name, email, rsvp, status, role, uid );
}
Attachment *ICalFormatImpl::readAttachment(icalproperty *attach)
{
icalattach *a = icalproperty_get_attach(attach);
icalparameter_value v = ICAL_VALUE_NONE;
icalparameter_encoding e = ICAL_ENCODING_NONE;
Attachment *attachment = 0;
/*
icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER);
if (vp)
v = icalparameter_get_value(vp);
icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER);
if (ep)
e = icalparameter_get_encoding(ep);
*/
int isurl = icalattach_get_is_url (a);
if (isurl == 0)
attachment = new Attachment((const char*)icalattach_get_data(a));
else {
attachment = new Attachment(QString(icalattach_get_url(a)));
}
icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER);
if (p)
attachment->setMimeType(QString(icalparameter_get_fmttype(p)));
return attachment;
}
#include <qtextcodec.h>
void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence)
{
readIncidenceBase(parent,incidence);
icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
bool readrec = false;
const char *text;
int intvalue;
icaltimetype icaltime;
icaldurationtype icalduration;
struct icalrecurrencetype rectype;
QStringList categories;
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_CREATED_PROPERTY:
icaltime = icalproperty_get_created(p);
incidence->setCreated(readICalDateTime(icaltime));
break;
case ICAL_SEQUENCE_PROPERTY: // sequence
intvalue = icalproperty_get_sequence(p);
incidence->setRevision(intvalue);
break;
case ICAL_LASTMODIFIED_PROPERTY: // last modification date
icaltime = icalproperty_get_lastmodified(p);
incidence->setLastModified(readICalDateTime(icaltime));
break;
case ICAL_DTSTART_PROPERTY: // start date and time
icaltime = icalproperty_get_dtstart(p);
if (icaltime.is_date) {
incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0)));
incidence->setFloats(true);
} else {
incidence->setDtStart(readICalDateTime(icaltime));
}
break;
case ICAL_DURATION_PROPERTY: // start date and time
icalduration = icalproperty_get_duration(p);
incidence->setDuration(readICalDuration(icalduration));
break;
case ICAL_DESCRIPTION_PROPERTY: // description
text = icalproperty_get_description(p);
incidence->setDescription(QString::fromUtf8(text));
break;
case ICAL_SUMMARY_PROPERTY: // summary
{
text = icalproperty_get_summary(p);
incidence->setSummary(QString::fromUtf8(text));
}
break;
case ICAL_STATUS_PROPERTY: // summary
{
if ( ICAL_STATUS_CANCELLED == icalproperty_get_status(p) )
incidence->setCancelled( true );
}
break;
case ICAL_LOCATION_PROPERTY: // location
text = icalproperty_get_location(p);
incidence->setLocation(QString::fromUtf8(text));
break;
+ case ICAL_RECURRENCEID_PROPERTY:
+ icaltime = icalproperty_get_recurrenceid(p);
+ incidence->setRecurrenceID( readICalDateTime(icaltime) );
+ qDebug(" RecurrenceID %s",incidence->recurrenceID().toString().latin1() );
+ break;
#if 0
// status
if ((vo = isAPropertyOf(vincidence, VCStatusProp)) != 0) {
incidence->setStatus(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
else
incidence->setStatus("NEEDS ACTION");
#endif
case ICAL_PRIORITY_PROPERTY: // priority
intvalue = icalproperty_get_priority(p);
incidence->setPriority(intvalue);
break;
case ICAL_CATEGORIES_PROPERTY: // categories
text = icalproperty_get_categories(p);
categories.append(QString::fromUtf8(text));
break;
//*******************************************
case ICAL_RRULE_PROPERTY:
// we do need (maybe )start datetime of incidence for recurrence
// such that we can read recurrence only after we read incidence completely
readrec = true;
rectype = icalproperty_get_rrule(p);
break;
case ICAL_EXDATE_PROPERTY:
icaltime = icalproperty_get_exdate(p);
incidence->addExDate(readICalDate(icaltime));
break;
case ICAL_CLASS_PROPERTY: {
int inttext = icalproperty_get_class(p);
if (inttext == ICAL_CLASS_PUBLIC ) {
incidence->setSecrecy(Incidence::SecrecyPublic);
} else if (inttext == ICAL_CLASS_CONFIDENTIAL ) {
incidence->setSecrecy(Incidence::SecrecyConfidential);
} else {
incidence->setSecrecy(Incidence::SecrecyPrivate);
}
}
break;
case ICAL_ATTACH_PROPERTY: // attachments
incidence->addAttachment(readAttachment(p));
break;
default:
// kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
// << endl;
break;
}
p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
}
if ( readrec ) {
readRecurrenceRule(rectype,incidence);
}
// kpilot stuff
// TODO: move this application-specific code to kpilot
QString kp = incidence->nonKDECustomProperty("X-PILOTID");
if (!kp.isNull()) {
incidence->setPilotId(kp.toInt());
}
kp = incidence->nonKDECustomProperty("X-PILOTSTAT");
if (!kp.isNull()) {
incidence->setSyncStatus(kp.toInt());
}
kp = incidence->nonKDECustomProperty("X-KOPIEXTID");
if (!kp.isNull()) {
incidence->setIDStr(kp);
}
// Cancel backwards compatibility mode for subsequent changes by the application
incidence->recurrence()->setCompatVersion();
// add categories
incidence->setCategories(categories);
// iterate through all alarms
for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT);
alarm;
alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) {
readAlarm(alarm,incidence);
}
}
void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
{
icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_UID_PROPERTY: // unique id
incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p)));
break;
case ICAL_ORGANIZER_PROPERTY: // organizer
incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p)));
break;
case ICAL_ATTENDEE_PROPERTY: // attendee
incidenceBase->addAttendee(readAttendee(p));
break;
default:
break;
}
p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
}
// custom properties
readCustomProperties(parent, incidenceBase);
}
void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties)
{
QMap<QCString, QString> customProperties;
icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
while (p) {
QString value = QString::fromUtf8(icalproperty_get_x(p));
customProperties[icalproperty_get_x_name(p)] = value;
//qDebug("ICalFormatImpl::readCustomProperties %s %s",value.latin1(), icalproperty_get_x_name(p) );
p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
}
properties->setCustomProperties(customProperties);
}
void ICalFormatImpl::readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *incidence)
{
// kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
Recurrence *recur = incidence->recurrence();
recur->setCompatVersion(mCalendarVersion);
recur->unsetRecurs();
struct icalrecurrencetype r = rrule;
dumpIcalRecurrence(r);
readRecurrence( r, recur, incidence);
}
void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur, Incidence *incidence)
{
int wkst;
int index = 0;
short day = 0;
QBitArray qba(7);
int frequ = r.freq;
int interv = r.interval;
// preprocessing for odd recurrence definitions
if ( r.freq == ICAL_MONTHLY_RECURRENCE ) {
if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
interv = 12;
}
}
if ( r.freq == ICAL_YEARLY_RECURRENCE ) {
if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX && r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
frequ = ICAL_MONTHLY_RECURRENCE;
interv = 12* r.interval;
}
}
switch (frequ) {
case ICAL_MINUTELY_RECURRENCE:
if (!icaltime_is_null_time(r.until)) {
recur->setMinutely(interv,readICalDateTime(r.until));
} else {
if (r.count == 0)
recur->setMinutely(interv,-1);
else
recur->setMinutely(interv,r.count);
}
break;
case ICAL_HOURLY_RECURRENCE:
if (!icaltime_is_null_time(r.until)) {
recur->setHourly(interv,readICalDateTime(r.until));
} else {
if (r.count == 0)
recur->setHourly(interv,-1);
else
recur->setHourly(interv,r.count);
}
break;
case ICAL_DAILY_RECURRENCE:
if (!icaltime_is_null_time(r.until)) {
recur->setDaily(interv,readICalDate(r.until));
} else {
if (r.count == 0)
recur->setDaily(interv,-1);
else
recur->setDaily(interv,r.count);
}
break;
case ICAL_WEEKLY_RECURRENCE:
// kdDebug(5800) << "WEEKLY_RECURRENCE" << endl;
wkst = (r.week_start + 5)%7 + 1;
if (!icaltime_is_null_time(r.until)) {
recur->setWeekly(interv,qba,readICalDate(r.until),wkst);
} else {
if (r.count == 0)
recur->setWeekly(interv,qba,-1,wkst);
else
recur->setWeekly(interv,qba,r.count,wkst);
}
if ( r.by_day[0] == ICAL_RECURRENCE_ARRAY_MAX) {
int wday = incidence->dtStart().date().dayOfWeek ()-1;
//qDebug("weekly error found ");
qba.setBit(wday);
} else {
while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << " " << day << endl;
qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
}
}
break;
case ICAL_MONTHLY_RECURRENCE:
if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
if (!icaltime_is_null_time(r.until)) {
recur->setMonthly(Recurrence::rMonthlyPos,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setMonthly(Recurrence::rMonthlyPos,interv,-1);
else
recur->setMonthly(Recurrence::rMonthlyPos,interv,r.count);
}
bool useSetPos = false;
short pos = 0;
while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << "----a " << index << ": " << day << endl;
pos = icalrecurrencetype_day_position(day);
if (pos) {
day = icalrecurrencetype_day_day_of_week(day);
QBitArray ba(7); // don't wipe qba
ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
recur->addMonthlyPos(pos,ba);
} else {
qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
useSetPos = true;
}
}
if (useSetPos) {
if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
recur->addMonthlyPos(r.by_set_pos[0],qba);
}
}
} else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
if (!icaltime_is_null_time(r.until)) {
recur->setMonthly(Recurrence::rMonthlyDay,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setMonthly(Recurrence::rMonthlyDay,interv,-1);
else
recur->setMonthly(Recurrence::rMonthlyDay,interv,r.count);
}
while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << "----b " << day << endl;
recur->addMonthlyDay(day);
}
}
break;
case ICAL_YEARLY_RECURRENCE:
if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
//qDebug(" YEARLY DAY OF YEAR");
if (!icaltime_is_null_time(r.until)) {
recur->setYearly(Recurrence::rYearlyDay,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setYearly(Recurrence::rYearlyDay,interv,-1);
else
recur->setYearly(Recurrence::rYearlyDay,interv,r.count);
}
while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
recur->addYearlyNum(day);
}
} else if ( true /*r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX*/) {
if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
qDebug("YEARLY POS NOT SUPPORTED BY GUI");
if (!icaltime_is_null_time(r.until)) {
recur->setYearly(Recurrence::rYearlyPos,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setYearly(Recurrence::rYearlyPos,interv,-1);
else
recur->setYearly(Recurrence::rYearlyPos,interv,r.count);
}
bool useSetPos = false;
short pos = 0;
while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << "----a " << index << ": " << day << endl;
pos = icalrecurrencetype_day_position(day);
if (pos) {
day = icalrecurrencetype_day_day_of_week(day);
QBitArray ba(7); // don't wipe qba
ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
recur->addYearlyMonthPos(pos,ba);
} else {
qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
useSetPos = true;
}
}
if (useSetPos) {
if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
recur->addYearlyMonthPos(r.by_set_pos[0],qba);
}
}
} else {
//qDebug("YEARLY MONTH ");
if (!icaltime_is_null_time(r.until)) {
recur->setYearly(Recurrence::rYearlyMonth,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setYearly(Recurrence::rYearlyMonth,interv,-1);
else
recur->setYearly(Recurrence::rYearlyMonth,interv,r.count);
}
if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
index = 0;
while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
recur->addYearlyNum(day);
}
} else {
recur->addYearlyNum(incidence->dtStart().date().month());
}
}
}
break;
default:
;
break;
}
}
void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence)
{
//kdDebug(5800) << "Read alarm for " << incidence->summary() << endl;
Alarm* ialarm = incidence->newAlarm();
ialarm->setRepeatCount(0);
ialarm->setEnabled(true);
// Determine the alarm's action type
icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY);
if ( !p ) {
return;
}
icalproperty_action action = icalproperty_get_action(p);
Alarm::Type type = Alarm::Display;
switch ( action ) {
case ICAL_ACTION_DISPLAY: type = Alarm::Display; break;
case ICAL_ACTION_AUDIO: type = Alarm::Audio; break;
case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break;
case ICAL_ACTION_EMAIL: type = Alarm::Email; break;
default:
;
return;
}
ialarm->setType(type);
p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY);
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_TRIGGER_PROPERTY: {
icaltriggertype trigger = icalproperty_get_trigger(p);
if (icaltime_is_null_time(trigger.time)) {
if (icaldurationtype_is_null_duration(trigger.duration)) {
kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl;
} else {
Duration duration = icaldurationtype_as_int( trigger.duration );
icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER);
if (param && icalparameter_get_related(param) == ICAL_RELATED_END)
ialarm->setEndOffset(duration);
else
ialarm->setStartOffset(duration);
}
} else {
ialarm->setTime(readICalDateTime(trigger.time));
}
break;
}
case ICAL_DURATION_PROPERTY: {
icaldurationtype duration = icalproperty_get_duration(p);
ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60);
break;
}
case ICAL_REPEAT_PROPERTY:
ialarm->setRepeatCount(icalproperty_get_repeat(p));
break;
// Only in DISPLAY and EMAIL and PROCEDURE alarms
case ICAL_DESCRIPTION_PROPERTY: {
QString description = QString::fromUtf8(icalproperty_get_description(p));
switch ( action ) {
case ICAL_ACTION_DISPLAY:
ialarm->setText( description );
break;
case ICAL_ACTION_PROCEDURE:
ialarm->setProgramArguments( description );
break;
case ICAL_ACTION_EMAIL:
ialarm->setMailText( description );
break;
default:
break;
}
break;
}
// Only in EMAIL alarm
case ICAL_SUMMARY_PROPERTY:
ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p)));
break;
// Only in EMAIL alarm
case ICAL_ATTENDEE_PROPERTY: {
QString email = QString::fromUtf8(icalproperty_get_attendee(p));
QString name;
icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER);
if (param) {
name = QString::fromUtf8(icalparameter_get_cn(param));
}
ialarm->addMailAddress(Person(name, email));
break;
}
// Only in AUDIO and EMAIL and PROCEDURE alarms
case ICAL_ATTACH_PROPERTY: {
icalattach *attach = icalproperty_get_attach(p);
QString url = QFile::decodeName(icalattach_get_url(attach));
switch ( action ) {
case ICAL_ACTION_AUDIO:
ialarm->setAudioFile( url );
break;
case ICAL_ACTION_PROCEDURE:
ialarm->setProgramFile( url );
break;
case ICAL_ACTION_EMAIL:
ialarm->addMailAttachment( url );
break;
default:
break;
}
break;
}
default:
break;
}
p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY);
}
// custom properties
readCustomProperties(alarm, ialarm);
// TODO: check for consistency of alarm properties
}
icaltimetype ICalFormatImpl::writeICalDate(const QDate &date)
{
icaltimetype t;
t.year = date.year();
t.month = date.month();
t.day = date.day();
t.hour = 0;
t.minute = 0;
t.second = 0;
t.is_date = 1;
t.is_utc = 0;
t.zone = 0;
return t;
}
icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &dt )
{
icaltimetype t;
t.is_date = 0;
t.zone = 0;
QDateTime datetime;
if ( mParent->utc() ) {
int offset = KGlobal::locale()->localTimeOffset( dt );
datetime = dt.addSecs ( -offset*60);
t.is_utc = 1;
}
else {
datetime = dt;
t.is_utc = 0;
diff --git a/libkcal/incidence.cpp b/libkcal/incidence.cpp
index f9e1e9e..dbc159c 100644
--- a/libkcal/incidence.cpp
+++ b/libkcal/incidence.cpp
@@ -1,616 +1,649 @@
/*
This file is part of libkcal.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include "calformat.h"
#include "incidence.h"
#include "todo.h"
using namespace KCal;
Incidence::Incidence() :
IncidenceBase(),
mRelatedTo(0), mSecrecy(SecrecyPublic), mPriority(3)
{
mRecurrence = new Recurrence(this);
mCancelled = false;
recreate();
mHasStartDate = true;
mAlarms.setAutoDelete(true);
mAttachments.setAutoDelete(true);
+ mHasRecurrenceID = false;
}
Incidence::Incidence( const Incidence &i ) : IncidenceBase( i )
{
// TODO: reenable attributes currently commented out.
mRevision = i.mRevision;
mCreated = i.mCreated;
mDescription = i.mDescription;
mSummary = i.mSummary;
mCategories = i.mCategories;
// Incidence *mRelatedTo; Incidence *mRelatedTo;
mRelatedTo = 0;
mRelatedToUid = i.mRelatedToUid;
// QPtrList<Incidence> mRelations; QPtrList<Incidence> mRelations;
mExDates = i.mExDates;
mAttachments = i.mAttachments;
mResources = i.mResources;
mSecrecy = i.mSecrecy;
mPriority = i.mPriority;
mLocation = i.mLocation;
mCancelled = i.mCancelled;
mHasStartDate = i.mHasStartDate;
QPtrListIterator<Alarm> it( i.mAlarms );
const Alarm *a;
while( (a = it.current()) ) {
Alarm *b = new Alarm( *a );
b->setParent( this );
mAlarms.append( b );
++it;
}
mAlarms.setAutoDelete(true);
-
+ mHasRecurrenceID = i.mHasRecurrenceID;
+ mRecurrenceID = i.mRecurrenceID;
mRecurrence = new Recurrence( *(i.mRecurrence), this );
}
Incidence::~Incidence()
{
Incidence *ev;
QPtrList<Incidence> Relations = relations();
for (ev=Relations.first();ev;ev=Relations.next()) {
if (ev->relatedTo() == this) ev->setRelatedTo(0);
}
if (relatedTo()) relatedTo()->removeRelation(this);
delete mRecurrence;
}
+bool Incidence::hasRecurrenceID() const
+{
+ return mHasRecurrenceID;
+}
+
+void Incidence::setHasRecurrenceID( bool b )
+{
+ mHasRecurrenceID = b;
+}
+
+void Incidence::setRecurrenceID(QDateTime d)
+{
+ mRecurrenceID = d;
+ mHasRecurrenceID = true;
+ updated();
+}
+QDateTime Incidence::recurrenceID () const
+{
+ return mRecurrenceID;
+}
bool Incidence::cancelled() const
{
return mCancelled;
}
void Incidence::setCancelled( bool b )
{
mCancelled = b;
updated();
}
bool Incidence::hasStartDate() const
{
return mHasStartDate;
}
void Incidence::setHasStartDate(bool f)
{
if (mReadOnly) return;
mHasStartDate = f;
updated();
}
// A string comparison that considers that null and empty are the same
static bool stringCompare( const QString& s1, const QString& s2 )
{
if ( s1.isEmpty() && s2.isEmpty() )
return true;
return s1 == s2;
}
bool KCal::operator==( const Incidence& i1, const Incidence& i2 )
{
if( i1.alarms().count() != i2.alarms().count() ) {
return false; // no need to check further
}
if ( i1.alarms().count() > 0 ) {
if ( !( *(i1.alarms().first()) == *(i2.alarms().first())) )
{
qDebug("alarm not equal ");
return false;
}
}
#if 0
QPtrListIterator<Alarm> a1( i1.alarms() );
QPtrListIterator<Alarm> a2( i2.alarms() );
for( ; a1.current() && a2.current(); ++a1, ++a2 ) {
if( *a1.current() == *a2.current() ) {
continue;
}
else {
return false;
}
}
#endif
+ if ( i1.hasRecurrenceID() == i2.hasRecurrenceID() ) {
+ if ( i1.hasRecurrenceID() ) {
+ if ( i1.recurrenceID() != i2.recurrenceID() )
+ return false;
+ }
+
+ } else {
+ return false;
+ }
+
if ( ! operator==( (const IncidenceBase&)i1, (const IncidenceBase&)i2 ) )
return false;
if ( i1.hasStartDate() == i2.hasStartDate() ) {
if ( i1.hasStartDate() ) {
if ( i1.dtStart() != i2.dtStart() )
return false;
}
} else {
return false;
}
if (!( *i1.recurrence() == *i2.recurrence()) ) {
qDebug("recurrence is NOT equal ");
return false;
}
return
// i1.created() == i2.created() &&
stringCompare( i1.description(), i2.description() ) &&
stringCompare( i1.summary(), i2.summary() ) &&
i1.categories() == i2.categories() &&
// no need to compare mRelatedTo
stringCompare( i1.relatedToUid(), i2.relatedToUid() ) &&
// i1.relations() == i2.relations() &&
i1.exDates() == i2.exDates() &&
i1.attachments() == i2.attachments() &&
i1.resources() == i2.resources() &&
i1.secrecy() == i2.secrecy() &&
i1.priority() == i2.priority() &&
+ i1.cancelled() == i2.cancelled() &&
stringCompare( i1.location(), i2.location() );
}
Incidence* Incidence::recreateCloneException( QDate d )
{
Incidence* newInc = clone();
newInc->recreate();
if ( doesRecur() ) {
addExDate( d );
newInc->recurrence()->unsetRecurs();
int len = dtStart().secsTo( ((Event*)this)->dtEnd());
QTime tim = dtStart().time();
newInc->setDtStart( QDateTime(d, tim) );
((Event*)newInc)->setDtEnd( newInc->dtStart().addSecs( len ) );
}
return newInc;
}
void Incidence::recreate()
{
setCreated(QDateTime::currentDateTime());
setUid(CalFormat::createUniqueId());
setRevision(0);
setIDStr( ":" );
setLastModified(QDateTime::currentDateTime());
}
void Incidence::setReadOnly( bool readOnly )
{
IncidenceBase::setReadOnly( readOnly );
recurrence()->setRecurReadOnly( readOnly);
}
void Incidence::setCreated(QDateTime created)
{
if (mReadOnly) return;
mCreated = getEvenTime(created);
}
QDateTime Incidence::created() const
{
return mCreated;
}
void Incidence::setRevision(int rev)
{
if (mReadOnly) return;
mRevision = rev;
updated();
}
int Incidence::revision() const
{
return mRevision;
}
void Incidence::setDtStart(const QDateTime &dtStart)
{
QDateTime dt = getEvenTime(dtStart);
recurrence()->setRecurStart( dt);
IncidenceBase::setDtStart( dt );
}
void Incidence::setDescription(const QString &description)
{
if (mReadOnly) return;
mDescription = description;
updated();
}
QString Incidence::description() const
{
return mDescription;
}
void Incidence::setSummary(const QString &summary)
{
if (mReadOnly) return;
mSummary = summary;
updated();
}
QString Incidence::summary() const
{
return mSummary;
}
void Incidence::setCategories(const QStringList &categories)
{
if (mReadOnly) return;
mCategories = categories;
updated();
}
// TODO: remove setCategories(QString) function
void Incidence::setCategories(const QString &catStr)
{
if (mReadOnly) return;
mCategories.clear();
if (catStr.isEmpty()) return;
mCategories = QStringList::split(",",catStr);
QStringList::Iterator it;
for(it = mCategories.begin();it != mCategories.end(); ++it) {
*it = (*it).stripWhiteSpace();
}
updated();
}
QStringList Incidence::categories() const
{
return mCategories;
}
QString Incidence::categoriesStr()
{
return mCategories.join(",");
}
void Incidence::setRelatedToUid(const QString &relatedToUid)
{
if (mReadOnly) return;
mRelatedToUid = relatedToUid;
}
QString Incidence::relatedToUid() const
{
return mRelatedToUid;
}
void Incidence::setRelatedTo(Incidence *relatedTo)
{
//qDebug("Incidence::setRelatedTo %d ", relatedTo);
//qDebug("setRelatedTo(Incidence *relatedTo) %s %s", summary().latin1(), relatedTo->summary().latin1() );
if (mReadOnly || mRelatedTo == relatedTo) return;
if(mRelatedTo) {
// updated();
mRelatedTo->removeRelation(this);
}
mRelatedTo = relatedTo;
if (mRelatedTo) mRelatedTo->addRelation(this);
}
Incidence *Incidence::relatedTo() const
{
return mRelatedTo;
}
QPtrList<Incidence> Incidence::relations() const
{
return mRelations;
}
void Incidence::addRelation(Incidence *event)
{
if( mRelations.findRef( event ) == -1 ) {
mRelations.append(event);
//updated();
}
}
void Incidence::removeRelation(Incidence *event)
{
mRelations.removeRef(event);
// if (event->getRelatedTo() == this) event->setRelatedTo(0);
}
bool Incidence::recursOn(const QDate &qd) const
{
if (recurrence()->recursOnPure(qd) && !isException(qd)) return true;
else return false;
}
void Incidence::setExDates(const DateList &exDates)
{
if (mReadOnly) return;
mExDates = exDates;
recurrence()->setRecurExDatesCount(mExDates.count());
updated();
}
void Incidence::addExDate(const QDate &date)
{
if (mReadOnly) return;
mExDates.append(date);
recurrence()->setRecurExDatesCount(mExDates.count());
updated();
}
DateList Incidence::exDates() const
{
return mExDates;
}
bool Incidence::isException(const QDate &date) const
{
DateList::ConstIterator it;
for( it = mExDates.begin(); it != mExDates.end(); ++it ) {
if ( (*it) == date ) {
return true;
}
}
return false;
}
void Incidence::addAttachment(Attachment *attachment)
{
if (mReadOnly || !attachment) return;
mAttachments.append(attachment);
updated();
}
void Incidence::deleteAttachment(Attachment *attachment)
{
mAttachments.removeRef(attachment);
}
void Incidence::deleteAttachments(const QString& mime)
{
Attachment *at = mAttachments.first();
while (at) {
if (at->mimeType() == mime)
mAttachments.remove();
else
at = mAttachments.next();
}
}
QPtrList<Attachment> Incidence::attachments() const
{
return mAttachments;
}
QPtrList<Attachment> Incidence::attachments(const QString& mime) const
{
QPtrList<Attachment> attachments;
QPtrListIterator<Attachment> it( mAttachments );
Attachment *at;
while ( (at = it.current()) ) {
if (at->mimeType() == mime)
attachments.append(at);
++it;
}
return attachments;
}
void Incidence::setResources(const QStringList &resources)
{
if (mReadOnly) return;
mResources = resources;
updated();
}
QStringList Incidence::resources() const
{
return mResources;
}
void Incidence::setPriority(int priority)
{
if (mReadOnly) return;
mPriority = priority;
updated();
}
int Incidence::priority() const
{
return mPriority;
}
void Incidence::setSecrecy(int sec)
{
if (mReadOnly) return;
mSecrecy = sec;
updated();
}
int Incidence::secrecy() const
{
return mSecrecy;
}
QString Incidence::secrecyStr() const
{
return secrecyName(mSecrecy);
}
QString Incidence::secrecyName(int secrecy)
{
switch (secrecy) {
case SecrecyPublic:
return i18n("Public");
break;
case SecrecyPrivate:
return i18n("Private");
break;
case SecrecyConfidential:
return i18n("Confidential");
break;
default:
return i18n("Undefined");
break;
}
}
QStringList Incidence::secrecyList()
{
QStringList list;
list << secrecyName(SecrecyPublic);
list << secrecyName(SecrecyPrivate);
list << secrecyName(SecrecyConfidential);
return list;
}
QPtrList<Alarm> Incidence::alarms() const
{
return mAlarms;
}
Alarm* Incidence::newAlarm()
{
Alarm* alarm = new Alarm(this);
mAlarms.append(alarm);
// updated();
return alarm;
}
void Incidence::addAlarm(Alarm *alarm)
{
mAlarms.append(alarm);
updated();
}
void Incidence::removeAlarm(Alarm *alarm)
{
mAlarms.removeRef(alarm);
updated();
}
void Incidence::clearAlarms()
{
mAlarms.clear();
updated();
}
bool Incidence::isAlarmEnabled() const
{
Alarm* alarm;
for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) {
if (alarm->enabled())
return true;
}
return false;
}
Recurrence *Incidence::recurrence() const
{
return mRecurrence;
}
void Incidence::setRecurrence( Recurrence * r)
{
delete mRecurrence;
mRecurrence = r;
}
void Incidence::setLocation(const QString &location)
{
if (mReadOnly) return;
mLocation = location;
updated();
}
QString Incidence::location() const
{
return mLocation;
}
ushort Incidence::doesRecur() const
{
if ( mRecurrence ) return mRecurrence->doesRecur();
else return Recurrence::rNone;
}
QDateTime Incidence::getNextOccurence( const QDateTime& dt, bool* ok ) const
{
QDateTime incidenceStart = dt;
*ok = false;
if ( doesRecur() ) {
bool last;
recurrence()->getPreviousDateTime( incidenceStart , &last );
int count = 0;
if ( !last ) {
while ( !last ) {
++count;
incidenceStart = recurrence()->getNextDateTime( incidenceStart, &last );
if ( recursOn( incidenceStart.date() ) ) {
last = true; // exit while llop
} else {
if ( last ) { // no alarm on last recurrence
return QDateTime ();
}
int year = incidenceStart.date().year();
// workaround for bug in recurrence
if ( count == 100 || year < 1000 || year > 5000 ) {
return QDateTime ();
}
incidenceStart = incidenceStart.addSecs( 1 );
}
}
} else {
return QDateTime ();
}
} else {
if ( hasStartDate () ) {
incidenceStart = dtStart();
}
if ( type() =="Todo" ) {
if ( ((Todo*)this)->hasDueDate() )
incidenceStart = ((Todo*)this)->dtDue();
}
}
if ( incidenceStart > dt )
*ok = true;
return incidenceStart;
}
diff --git a/libkcal/incidence.h b/libkcal/incidence.h
index de2a381..38d2aaa 100644
--- a/libkcal/incidence.h
+++ b/libkcal/incidence.h
@@ -1,299 +1,308 @@
/*
This file is part of libkcal.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef INCIDENCE_H
#define INCIDENCE_H
//
// Incidence - base class of calendaring components
//
#include <qdatetime.h>
#include <qstringlist.h>
#include <qvaluelist.h>
#include "recurrence.h"
#include "alarm.h"
#include "attachment.h"
#include "listbase.h"
#include "incidencebase.h"
namespace KCal {
class Event;
class Todo;
class Journal;
/**
This class provides the base class common to all calendar components.
*/
class Incidence : public IncidenceBase
{
public:
/**
This class provides the interface for a visitor of calendar components. It
serves as base class for concrete visitors, which implement certain actions on
calendar components. It allows to add functions, which operate on the concrete
types of calendar components, without changing the calendar component classes.
*/
class Visitor
{
public:
/** Destruct Incidence::Visitor */
virtual ~Visitor() {}
/**
Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions
on an Event object.
*/
virtual bool visit(Event *) { return false; }
/**
Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions
on an Todo object.
*/
virtual bool visit(Todo *) { return false; }
/**
Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions
on an Journal object.
*/
virtual bool visit(Journal *) { return false; }
protected:
/** Constructor is protected to prevent direct creation of visitor base class. */
Visitor() {}
};
/**
This class implements a visitor for adding an Incidence to a resource
supporting addEvent(), addTodo() and addJournal() calls.
*/
template<class T>
class AddVisitor : public Visitor
{
public:
AddVisitor( T *r ) : mResource( r ) {}
bool visit( Event *e ) { return mResource->addEvent( e ); }
bool visit( Todo *t ) { return mResource->addTodo( t ); }
bool visit( Journal *j ) { return mResource->addJournal( j ); }
private:
T *mResource;
};
/** enumeration for describing an event's secrecy. */
enum { SecrecyPublic = 0, SecrecyPrivate = 1, SecrecyConfidential = 2 };
typedef ListBase<Incidence> List;
Incidence();
Incidence(const Incidence &);
~Incidence();
/**
Accept IncidenceVisitor. A class taking part in the visitor mechanism has to
provide this implementation:
<pre>
bool accept(Visitor &v) { return v.visit(this); }
</pre>
*/
virtual bool accept(Visitor &) { return false; }
virtual Incidence *clone() = 0;
virtual QDateTime getNextAlarmDateTime( bool * ok, int * offset ) const = 0;
void setReadOnly( bool );
/**
Recreate event. The event is made a new unique event, but already stored
event information is preserved. Sets uniquie id, creation date, last
modification date and revision number.
*/
void recreate();
Incidence* recreateCloneException(QDate);
/** set creation date */
void setCreated(QDateTime);
/** return time and date of creation. */
QDateTime created() const;
/** set the number of revisions this event has seen */
void setRevision(int rev);
/** return the number of revisions this event has seen */
int revision() const;
/** Set starting date/time. */
virtual void setDtStart(const QDateTime &dtStart);
/** Return the incidence's ending date/time as a QDateTime. */
virtual QDateTime dtEnd() const { return QDateTime(); }
/** sets the event's lengthy description. */
void setDescription(const QString &description);
/** returns a reference to the event's description. */
QString description() const;
/** sets the event's short summary. */
void setSummary(const QString &summary);
/** returns a reference to the event's summary. */
QString summary() const;
/** set event's applicable categories */
void setCategories(const QStringList &categories);
/** set event's categories based on a comma delimited string */
void setCategories(const QString &catStr);
/** return categories in a list */
QStringList categories() const;
/** return categories as a comma separated string */
QString categoriesStr();
/** point at some other event to which the event relates. This function should
* only be used when constructing a calendar before the related Event
* exists. */
void setRelatedToUid(const QString &);
/** what event does this one relate to? This function should
* only be used when constructing a calendar before the related Event
* exists. */
QString relatedToUid() const;
/** point at some other event to which the event relates */
void setRelatedTo(Incidence *relatedTo);
/** what event does this one relate to? */
Incidence *relatedTo() const;
/** All events that are related to this event */
QPtrList<Incidence> relations() const;
/** Add an event which is related to this event */
void addRelation(Incidence *);
/** Remove event that is related to this event */
void removeRelation(Incidence *);
/** returns the list of dates which are exceptions to the recurrence rule */
DateList exDates() const;
/** sets the list of dates which are exceptions to the recurrence rule */
void setExDates(const DateList &_exDates);
void setExDates(const char *dates);
/** Add a date to the list of exceptions of the recurrence rule. */
void addExDate(const QDate &date);
/** returns true if there is an exception for this date in the recurrence
rule set, or false otherwise. */
bool isException(const QDate &qd) const;
/** add attachment to this event */
void addAttachment(Attachment *attachment);
/** remove and delete a specific attachment */
void deleteAttachment(Attachment *attachment);
/** remove and delete all attachments with this mime type */
void deleteAttachments(const QString& mime);
/** return list of all associated attachments */
QPtrList<Attachment> attachments() const;
/** find a list of attachments with this mime type */
QPtrList<Attachment> attachments(const QString& mime) const;
/** sets the event's status the value specified. See the enumeration
* above for possible values. */
void setSecrecy(int);
/** return the event's secrecy. */
int secrecy() const;
/** return the event's secrecy in string format. */
QString secrecyStr() const;
/** return list of all availbale secrecy classes */
static QStringList secrecyList();
/** return human-readable name of secrecy class */
static QString secrecyName(int);
/** returns TRUE if the date specified is one on which the event will
* recur. */
bool recursOn(const QDate &qd) const;
// VEVENT and VTODO, but not VJOURNAL (move to EventBase class?):
/** set resources used, such as Office, Car, etc. */
void setResources(const QStringList &resources);
/** return list of current resources */
QStringList resources() const;
/** set the event's priority, 0 is undefined, 1 highest (decreasing order) */
void setPriority(int priority);
/** get the event's priority */
int priority() const;
/** All alarms that are associated with this incidence */
QPtrList<Alarm> alarms() const;
/** Create a new alarm which is associated with this incidence */
Alarm* newAlarm();
/** Add an alarm which is associated with this incidence */
void addAlarm(Alarm*);
/** Remove an alarm that is associated with this incidence */
void removeAlarm(Alarm*);
/** Remove all alarms that are associated with this incidence */
void clearAlarms();
/** return whether any alarm associated with this incidence is enabled */
bool isAlarmEnabled() const;
/**
Return the recurrence rule associated with this incidence. If there is
none, returns an appropriate (non-0) object.
*/
Recurrence *recurrence() const;
void setRecurrence(Recurrence * r);
/**
Forward to Recurrence::doesRecur().
*/
ushort doesRecur() const;
/** set the event's/todo's location. Do _not_ use it with journal */
void setLocation(const QString &location);
/** return the event's/todo's location. Do _not_ use it with journal */
QString location() const;
/** returns TRUE or FALSE depending on whether the todo has a start date */
bool hasStartDate() const;
/** sets the event's hasStartDate value. */
void setHasStartDate(bool f);
QDateTime getNextOccurence( const QDateTime& dt, bool* yes ) const;
bool cancelled() const;
void setCancelled( bool b );
+ bool hasRecurrenceID() const;
+ void setHasRecurrenceID( bool b );
+
+ void setRecurrenceID(QDateTime);
+ QDateTime recurrenceID () const;
+
+
protected:
QPtrList<Alarm> mAlarms;
QPtrList<Incidence> mRelations;
private:
int mRevision;
bool mCancelled;
// base components of jounal, event and todo
+ QDateTime mRecurrenceID;
+ bool mHasRecurrenceID;
QDateTime mCreated;
QString mDescription;
QString mSummary;
QStringList mCategories;
Incidence *mRelatedTo;
QString mRelatedToUid;
DateList mExDates;
QPtrList<Attachment> mAttachments;
QStringList mResources;
bool mHasStartDate; // if todo has associated start date
int mSecrecy;
int mPriority; // 1 = highest, 2 = less, etc.
//QPtrList<Alarm> mAlarms;
Recurrence *mRecurrence;
QString mLocation;
};
bool operator==( const Incidence&, const Incidence& );
}
#endif
diff --git a/microkde/kdialogbase.h b/microkde/kdialogbase.h
index 7b44bfb..a2fc2dc 100644
--- a/microkde/kdialogbase.h
+++ b/microkde/kdialogbase.h
@@ -1,141 +1,141 @@
#ifndef MINIKDE_KDIALOGBASE_H
#define MINIKDE_KDIALOGBASE_H
#include <qframe.h>
#include "kdialog.h"
class QPushButton;
class QLayout;
class QTabWidget;
class QBoxLayout;
class KDialogBase : public KDialog
{
Q_OBJECT
public:
enum ButtonCode
{
Help = 0x00000001,
Default = 0x00000002,
Ok = 0x00000004,
Apply = 0x00000008,
Try = 0x00000010,
Cancel = 0x00000020,
Close = 0x00000040,
User1 = 0x00000080,
User2 = 0x00000100,
User3 = 0x00000200,
No = 0x00000080,
Yes = 0x00000100,
Details = 0x00000400,
Filler = 0x40000000,
Stretch = 0x80000000
};
enum DialogType
{
TreeList,
Tabbed,
Plain,
Swallow,
IconList
};
KDialogBase();
KDialogBase( QWidget *parent=0, const char *name=0, bool modal=true,
const QString &caption=QString::null,
int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok,
bool separator=false,
const QString &user1=QString::null,
const QString &user2=QString::null,
const QString &user3=QString::null);
KDialogBase( int dialogFace, const QString &caption,
int buttonMask, ButtonCode defaultButton,
QWidget *parent=0, const char *name=0, bool modal=true,
bool separator=false,
const QString &user1=QString::null,
const QString &user2=QString::null,
const QString &user3=QString::null);
virtual ~KDialogBase();
QFrame *addPage( const QString & );
QFrame *addPage( const QString &, int, const QPixmap & );
void setMainWidget( QWidget *widget );
void setButtonText( ButtonCode id, const QString &text );
void enableButton( ButtonCode id, bool state );
void enableButtonOK( bool state );
void enableButtonApply( bool state );
void showButton( ButtonCode, bool show );
int pageIndex( QWidget *widget ) const;
bool showPage( int index );
void hideButtons();
QFrame *plainPage();
signals:
void user1Clicked();
void user2Clicked();
/**
* The Apply button was pressed. This signal is only emitted if
* @ref slotApply() is not replaced.
*/
void applyClicked();
/**
* The OK button was pressed. This signal is only emitted if
* @ref slotOk() is not replaced.
*/
void okClicked();
/**
* The Cancel button was pressed. This signal is only emitted if
* @ref slotCancel() is not replaced.
*/
void cancelClicked();
/**
* The Close button was pressed. This signal is only emitted if
* @ref slotClose() is not replaced.
*/
void closeClicked();
void defaultClicked();
protected slots:
virtual void slotOk();
virtual void slotApply();
virtual void slotCancel();
virtual void slotClose();
virtual void slotUser1();
virtual void slotUser2();
protected:
QPushButton *findButton( ButtonCode );
+ QTabWidget *tabWidget();
private:
- QTabWidget *tabWidget();
void init( const QString &caption, int buttonMask,
const QString &user1=QString::null, const QString &user2=QString::null );
void initLayout();
QWidget *mMainWidget;
QTabWidget *mTabWidget;
QFrame *mPlainPage;
QBoxLayout *mTopLayout;
QPushButton *mUser1Button;
QPushButton *mUser2Button;
QPushButton *mCloseButton;
QPushButton *mOkButton;
QPushButton *mApplyButton;
QPushButton *mCancelButton;
QPushButton *mDefaultButton;
};
#endif