summaryrefslogtreecommitdiffabout
authorzautrix <zautrix>2005-07-27 22:26:08 (UTC)
committer zautrix <zautrix>2005-07-27 22:26:08 (UTC)
commit0e38cffd7ba745f237c659e1c48080fcb25b126c (patch) (side-by-side diff)
tree6069600e18bae5300c6ce427735457dbfed93141
parent136f9082862e7a56abb3a201e96f5e7386c4f1b9 (diff)
downloadkdepimpi-0e38cffd7ba745f237c659e1c48080fcb25b126c.zip
kdepimpi-0e38cffd7ba745f237c659e1c48080fcb25b126c.tar.gz
kdepimpi-0e38cffd7ba745f237c659e1c48080fcb25b126c.tar.bz2
rec changes
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--korganizer/calendarview.cpp2
-rw-r--r--korganizer/koagenda.cpp4
-rw-r--r--korganizer/koagendaitem.cpp2
-rw-r--r--korganizer/koagendaview.cpp2
-rw-r--r--korganizer/kodaymatrix.cpp2
-rw-r--r--korganizer/koeditorrecurrence.cpp172
-rw-r--r--korganizer/koeventviewer.cpp6
-rw-r--r--korganizer/kolistview.cpp4
-rw-r--r--korganizer/komonthview.cpp6
-rw-r--r--korganizer/kotodoeditor.cpp3
-rw-r--r--korganizer/kowhatsnextview.cpp4
-rw-r--r--libkcal/event.cpp1
-rw-r--r--libkcal/icalformatimpl.cpp24
-rw-r--r--libkcal/incidence.cpp63
-rw-r--r--libkcal/incidence.h5
-rw-r--r--libkcal/kincidenceformatter.cpp4
-rw-r--r--libkcal/vcalformat.cpp4
-rw-r--r--libkcal/vcalformat.h2
18 files changed, 175 insertions, 135 deletions
diff --git a/korganizer/calendarview.cpp b/korganizer/calendarview.cpp
index a76f2ed..a9d42f0 100644
--- a/korganizer/calendarview.cpp
+++ b/korganizer/calendarview.cpp
@@ -690,4166 +690,4166 @@ void CalendarView::nextConflict( bool all, bool allday )
if ( !all ) skip = ( allday != test->doesFloat() );
if ( !skip ) {
if ( found )
skip = !test->matchTime( &startDT, &conflict );
else
skip = !test->matchTime( &startDT, 0 );
}
if ( !skip ) {
Event * test2 = testlist2.first();
while ( test2 ) {
skip = test2->isTagged();
if ( !skip && !all ) skip = ( allday != test2->doesFloat() );
if ( !skip ) {
if ( found )
skip = !test2->matchTime( &startDT, &conflict );
else
skip = !test2->matchTime( &startDT, 0 );
}
if ( !skip ) {
if ( test->isOverlapping ( test2, &retVal, &startDT ) ) {
//qDebug("overlap ");
if ( ! found ) {
if ( retVal >= startDT ) {
conflict = retVal;
cE = test;
cE2 = test2;
found = true;
}
} else {
if ( retVal >= startDT && retVal < conflict ) {
conflict = retVal;
cE = test;
cE2 = test2;
}
}
}
}
test2 = testlist2.next();
}
}
test->setTagged( true );
test = testlist.next();
}
//qDebug("Search time : %d", tm.elapsed());
if ( found ) {
if ( mViewManager->currentView() != mViewManager->agendaView() || mNavigator->selectedDates().count() > 1 )
mViewManager->showDayView();
mNavigator->slotDaySelect( conflict.date() );
int hour = conflict.time().hour();
mViewManager->agendaView()->setStartHour( hour );
topLevelWidget()->setCaption( i18n("Conflict %1 <-> %2"). arg( cE->summary().left( 20 ) ).arg( cE2->summary().left( 20 ) ) );
block = false;
return;
}
topLevelWidget()->setCaption( i18n("No conflict found") );
//qDebug("No conflict found ");
block = false;
return;
}
void CalendarView::conflictAll()
{
nextConflict ( true, true );
}
void CalendarView::conflictAllday()
{
nextConflict ( false, true );
}
void CalendarView::conflictNotAll()
{
nextConflict ( false, false );
}
void CalendarView::setCalReadOnly( int id, bool readO )
{
if ( readO ) {
emit save();
}
mCalendar->setReadOnly( id, readO );
}
void CalendarView::setScrollBarStep(int val )
{
#ifdef DESKTOP_VERSION
mDateScrollBar->setLineStep ( val );
#endif
}
void CalendarView::scrollBarValue(int val )
{
#ifdef DESKTOP_VERSION
if ( QApplication::desktop()->width() < 800 ) return;
static bool block = false;
if ( block ) return;
block = true;
int count = mNavigator->selectedDates().count();
int day = mNavigator->selectedDates().first().dayOfYear();
int stepdays = val;
if ( mDateScrollBar->lineStep () <= count ) {
//val = val/mDateScrollBar->lineStep ()*mDateScrollBar->lineStep();
//qDebug("VAL %d ",val );
stepdays = (val-day)/mDateScrollBar->lineStep ()*mDateScrollBar->lineStep();
stepdays = day+stepdays;
if ( stepdays < 0 ) stepdays = 0;
}
if ( stepdays == day ) {
block = false;
return;
}
int year = mNavigator->selectedDates().first().year();
QDate d ( year,1,1 );
mNavigator->selectDates( d.addDays( stepdays-1) , count );
block = false;
#endif
}
void CalendarView::updateView(const QDate &start, const QDate &end)
{
#ifdef DESKTOP_VERSION
if ( ! mDateScrollBar->draggingSlider () ) {
int dof = start.dayOfYear();
//qDebug("dof %d day %d val %d ", dof, start.dayOfYear(),mDateScrollBar->value() );
if ( dof != mDateScrollBar->value() ) {
mDateScrollBar->blockSignals( true );
mDateScrollBar->setValue( start.dayOfYear());
mDateScrollBar->blockSignals( false );
}
}
#endif
mTodoList->updateView();
mViewManager->updateView(start, end);
//mDateNavigator->updateView();
}
void CalendarView::checkFiles()
{
QString message;
QPtrList<KopiCalendarFile> calendars = KOPrefs::instance()->mCalendars;
KopiCalendarFile * cal = calendars.first();
while ( cal ) {
if ( cal->mErrorOnLoad ) {
message += cal->mName +"\n"+KGlobal::formatMessage ( "(" +i18n( "Filepath: ")+ cal->mFileName+")" ,0 )+"\n";
}
cal = calendars.next();
}
if ( !message.isEmpty() ) {
message = KGlobal::formatMessage( i18n("Calendar(s) not loaded:"),0 )+"\n" + message +KGlobal::formatMessage(i18n("You can try to reload the calendar in the Resource View!"),0);
KMessageBox::error(this,message, i18n("Loding of calendar(s) failed"));
}
QTimer::singleShot( 2000, this, SLOT ( checkAlarms() ));
}
void CalendarView::checkAlarms()
{
KConfig *config = KOGlobals::config();
config->setGroup( "AppRun" );
QDateTime dt ( QDate (2005,1,1), QTime( 0,0,0 ) );
int daysto = dt.daysTo( QDate::currentDate() );
int days = config->readNumEntry( "LatestProgramStopDays" , daysto);
dt = dt.addDays( days );
int secto = dt.secsTo( QDateTime::currentDateTime() );
int secs = config->readNumEntry( "LatestProgramStopSecs" , secto) - 30;
//qDebug("KO: Reading program stop %d ", secs);
//secs -= ( 3600 * 24*3 ); // debug only
QDateTime latest = dt.addSecs ( secs );
qDebug("KO: Last termination on %s ", latest.toString().latin1());
//qDebug("KO: Current Time %s ",QDateTime::currentDateTime().toString().latin1() );
QPtrList<Incidence> el = mCalendar->rawIncidences();
QPtrList<Incidence> al;
Incidence* inL = el.first();
QDateTime cur = QDateTime::currentDateTime().addSecs(-59);
qDebug("KO: Checking alarm until %s ", cur.toString().latin1());
while ( inL ) {
bool ok = false;
int offset = 0;
QDateTime next = inL->getNextAlarmDateTime(& ok, &offset, latest ) ;
if ( ok ) {
//qDebug("OK %s",next.toString().latin1());
if ( next < cur ) {
al.append( inL );
//qDebug("found missed alarm: %s ", inL->summary().latin1() );
}
}
inL = el.next();
}
if ( al.count() ) {
QDialog* dia = new QDialog( this, "huhu", false, WDestructiveClose | WStyle_StaysOnTop );
dia->setCaption( i18n("KO/Pi: Missing alarms!") );
QVBoxLayout* lay = new QVBoxLayout( dia );
lay->setSpacing( 0 );
lay->setMargin( 0 );
MissedAlarmTextBrowser* matb = new MissedAlarmTextBrowser ( dia, al, latest );
connect( matb, SIGNAL( showIncidence( QString ) ),SLOT( showIncidence( QString ) ));
lay->addWidget( matb );
if ( QApplication::desktop()->width() == 480 || QApplication::desktop()->width() == 640 ) {
int wid = 210;
int x = QApplication::desktop()->width() - wid - 7;
int y = QApplication::desktop()->height() - wid - 70;
dia->setGeometry ( x,y,wid,wid);
} else {
int si = 220;
if ( QApplication::desktop()->width() > 470 )
si = 400;
dia->resize(si,si/2);
}
dia->setBackgroundColor( QColor( 255, 255, 255 ) );
dia->show();
}
}
void CalendarView::showDay( QDate d )
{
dateNavigator()->blockSignals( true );
dateNavigator()->selectDate( d );
dateNavigator()->blockSignals( false );
mViewManager->showDayView();
//dateNavigator()->selectDate( d );
}
void CalendarView::timerAlarm()
{
//qDebug("CalendarView::timerAlarm() ");
computeAlarm(mAlarmNotification );
}
void CalendarView::suspendAlarm()
{
//qDebug(" CalendarView::suspendAlarm() ");
computeAlarm(mSuspendAlarmNotification );
}
void CalendarView::startAlarm( QString mess , QString filename)
{
topLevelWidget()->showNormal();
topLevelWidget()->setActiveWindow();
topLevelWidget()->raise();
mAlarmDialog->eventNotification( mess, KOPrefs::instance()->mAlarmPlayBeeps, filename, true,KOPrefs::instance()->mAlarmBeepInterval ,KOPrefs::instance()->mAlarmSuspendCount );
QTimer::singleShot( 2000, this, SLOT( checkNextTimerAlarm() ) );
}
void CalendarView::checkNextTimerAlarm()
{
mCalendar->checkAlarmForIncidence( 0, true );
}
void CalendarView::computeAlarm( QString msg )
{
QString mess = msg;
QString mAlarmMessage = mess.mid( 9 );
QString filename = MainWindow::resourcePath();
filename += "koalarm.wav";
QString tempfilename;
if ( mess.left( 13 ) == "suspend_alarm") {
bool error = false;
int len = mess.mid( 13 ).find("+++");
if ( len < 2 )
error = true;
else {
tempfilename = mess.mid( 13, len );
if ( !QFile::exists( tempfilename ) )
error = true;
}
if ( ! error ) {
filename = tempfilename;
}
mAlarmMessage = mess.mid( 13+len+3 );
//qDebug("suspend file %s ",tempfilename.latin1() );
startAlarm( mAlarmMessage, filename);
return;
}
if ( mess.left( 11 ) == "timer_alarm") {
//mTimerTime = 0;
startAlarm( mess.mid( 11 ), filename );
return;
}
if ( mess.left( 10 ) == "proc_alarm") {
bool error = false;
int len = mess.mid( 10 ).find("+++");
if ( len < 2 )
error = true;
else {
tempfilename = mess.mid( 10, len );
if ( !QFile::exists( tempfilename ) )
error = true;
}
if ( error ) {
mAlarmMessage = "Procedure Alarm\nError - File not found\n";
mAlarmMessage += mess.mid( 10+len+3+9 );
} else {
//QCopEnvelope e("QPE/Application/kopi", "-writeFileSilent");
//qDebug("-----system command %s ",tempfilename.latin1() );
#ifndef _WIN32_
if ( vfork () == 0 ) {
execl ( tempfilename.latin1(), 0 );
return;
}
#else
QProcess* p = new QProcess();
p->addArgument( tempfilename.latin1() );
p->start();
return;
#endif
return;
}
//qDebug("+++++++system command %s ",tempfilename.latin1() );
}
if ( mess.left( 11 ) == "audio_alarm") {
bool error = false;
int len = mess.mid( 11 ).find("+++");
if ( len < 2 )
error = true;
else {
tempfilename = mess.mid( 11, len );
if ( !QFile::exists( tempfilename ) )
error = true;
}
if ( ! error ) {
filename = tempfilename;
}
mAlarmMessage = mess.mid( 11+len+3+9 );
//qDebug("audio file command %s ",tempfilename.latin1() );
}
if ( mess.left( 9 ) == "cal_alarm") {
mAlarmMessage = mess.mid( 9 ) ;
}
startAlarm( mAlarmMessage, filename );
}
void CalendarView::addSuspendAlarm(const QDateTime &qdt, const QString &noti )
{
//qDebug("+++++addSUSPENDAlarm %s %s ", qdt.toString().latin1() , noti.latin1() );
mSuspendAlarmNotification = noti;
int ms = QDateTime::currentDateTime().secsTo( qdt )*1000;
//qDebug("Suspend Alarm timer started with secs: %d ", ms/1000);
mSuspendTimer->start( ms , true );
}
void CalendarView::addAlarm(const QDateTime &qdt, const QString &noti )
{
mNextAlarmDateTime = qdt;
//qDebug("+++++addAlarm %s %s ", qdt.toString().latin1() , noti.latin1() );
if ( ! KOPrefs::instance()->mUseInternalAlarmNotification ) {
#ifndef DESKTOP_VERSION
AlarmServer::addAlarm ( qdt,"koalarm", noti.utf8() );
#endif
return;
}
int maxSec;
//maxSec = 5; //testing only
maxSec = 86400+3600; // one day+1hour
mAlarmNotification = noti;
int sec = QDateTime::currentDateTime().secsTo( qdt );
if ( sec > maxSec ) {
mRecheckAlarmTimer->start( maxSec * 1000 );
// qDebug("recheck Alarm timer started with secs: %d next alarm in sec:%d", maxSec,sec );
return;
} else {
mRecheckAlarmTimer->stop();
}
//qDebug("Alarm timer started with secs: %d ", sec);
mAlarmTimer->start( sec *1000 , true );
}
// called by mRecheckAlarmTimer to get next alarm
// we need this, because a QTimer has only a max range of 25 days
void CalendarView::recheckTimerAlarm()
{
mAlarmTimer->stop();
mRecheckAlarmTimer->stop();
mCalendar->checkAlarmForIncidence( 0, true );
}
#ifndef DESKTOP_VERSION
void CalendarView::removeAlarm(const QDateTime &qdt, const QString &noti )
#else
void CalendarView::removeAlarm(const QDateTime &, const QString & )
#endif
{
//qDebug("-----removeAlarm %s %s ", qdt.toString().latin1() , noti.latin1() );
if ( ! KOPrefs::instance()->mUseInternalAlarmNotification ) {
#ifndef DESKTOP_VERSION
AlarmServer::deleteAlarm (qdt ,"koalarm" ,noti.utf8() );
#endif
return;
}
mAlarmTimer->stop();
}
void CalendarView::selectWeekNum ( int num )
{
dateNavigator()->blockSignals( true );
dateNavigator()->selectWeek( num );
dateNavigator()->blockSignals( false );
mViewManager->showWeekView();
}
KOViewManager *CalendarView::viewManager()
{
return mViewManager;
}
KODialogManager *CalendarView::dialogManager()
{
return mDialogManager;
}
QDate CalendarView::startDate()
{
DateList dates = mNavigator->selectedDates();
return dates.first();
}
QDate CalendarView::endDate()
{
DateList dates = mNavigator->selectedDates();
return dates.last();
}
void CalendarView::createPrinter()
{
#ifndef KORG_NOPRINTER
if (!mCalPrinter) {
mCalPrinter = new CalPrinter(this, mCalendar);
connect(this, SIGNAL(configChanged()), mCalPrinter, SLOT(updateConfig()));
}
#endif
}
//KOPrefs::instance()->mWriteBackFile
//KOPrefs::instance()->mWriteBackExistingOnly
// 0 syncPrefsGroup->addRadio(i18n("Take local entry on conflict"));
// 1 syncPrefsGroup->addRadio(i18n("Take remote entry on conflict"));
// 2 syncPrefsGroup->addRadio(i18n("Take newest entry on conflict"));
// 3 syncPrefsGroup->addRadio(i18n("Ask for every entry on conflict"));
// 4 syncPrefsGroup->addRadio(i18n("Force take local entry always"));
// 5 syncPrefsGroup->addRadio(i18n("Force take remote entry always"));
int CalendarView::takeEvent( Incidence* local, Incidence* remote, int mode , bool full )
{
// 0 equal
// 1 take local
// 2 take remote
// 3 cancel
QDateTime lastSync = mLastCalendarSync;
QDateTime localMod = local->lastModified();
QDateTime remoteMod = remote->lastModified();
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) {
bool remCh, locCh;
remCh = ( remote->getCsum(mCurrentSyncDevice) != local->getCsum(mCurrentSyncDevice) );
//if ( remCh )
//qDebug("loc %s rem %s", local->getCsum(mCurrentSyncDevice).latin1(), remote->getCsum(mCurrentSyncDevice).latin1() );
locCh = ( localMod > mLastCalendarSync );
if ( !remCh && ! locCh ) {
//qDebug("both not changed ");
lastSync = localMod.addDays(1);
if ( mode <= SYNC_PREF_ASK )
return 0;
} else {
if ( locCh ) {
//qDebug("loc changed %d %s %s", local->revision() , localMod.toString().latin1(), mLastCalendarSync.toString().latin1());
lastSync = localMod.addDays( -1 );
if ( !remCh )
remoteMod = ( lastSync.addDays( -1 ) );
} else {
//qDebug(" not loc changed ");
lastSync = localMod.addDays( 1 );
if ( remCh )
remoteMod =( lastSync.addDays( 1 ) );
}
}
full = true;
if ( mode < SYNC_PREF_ASK )
mode = SYNC_PREF_ASK;
} else {
if ( localMod == remoteMod )
// if ( local->revision() == remote->revision() )
return 0;
}
// qDebug(" %d %d conflict on %s %s ", mode, full, local->summary().latin1(), remote->summary().latin1() );
//qDebug("%s %d %s %d", localMod.toString().latin1() , local->revision(), remoteMod.toString().latin1(), remote->revision());
//qDebug("%d %d %d %d ", localMod.time().second(), localMod.time().msec(), remoteMod.time().second(), remoteMod.time().msec() );
//full = true; //debug only
if ( full ) {
bool equ = false;
if ( local->typeID() == eventID ) {
equ = (*((Event*) local) == *((Event*) remote));
}
else if ( local->typeID() == todoID )
equ = (*((Todo*) local) == (*(Todo*) remote));
else if ( local->typeID() == journalID )
equ = (*((Journal*) local) == *((Journal*) remote));
if ( equ ) {
//qDebug("equal ");
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) {
local->setCsum( mCurrentSyncDevice, remote->getCsum(mCurrentSyncDevice) );
}
if ( mode < SYNC_PREF_FORCE_LOCAL )
return 0;
}//else //debug only
//qDebug("not equal %s %s ", local->summary().latin1(), remote->summary().latin1());
}
int result;
bool localIsNew;
//qDebug("%s -- %s mLastCalendarSync %s lastsync %s --- local %s remote %s ",local->summary().latin1(), remote->summary().latin1(),mLastCalendarSync.toString().latin1() ,lastSync.toString().latin1() , localMod.toString().latin1() , remoteMod.toString().latin1() );
// ************************************************
// ************************************************
// ************************************************
// We may have that lastSync > remoteMod AND lastSync > localMod
// BUT remoteMod != localMod
if ( full && mode < SYNC_PREF_NEWEST )
mode = SYNC_PREF_ASK;
switch( mode ) {
case SYNC_PREF_LOCAL:
if ( lastSync > remoteMod )
return 1;
if ( lastSync > localMod )
return 2;
return 1;
break;
case SYNC_PREF_REMOTE:
if ( lastSync > localMod )
return 2;
if ( lastSync > remoteMod )
return 1;
return 2;
break;
case SYNC_PREF_NEWEST:
if ( localMod >= remoteMod )
return 1;
else
return 2;
break;
case SYNC_PREF_ASK:
qDebug("lsy %s --- lo %s --- re %s ", lastSync.toString().latin1(), localMod.toString().latin1(), remoteMod.toString().latin1() );
if ( lastSync > remoteMod && lastSync > localMod)
return 0;
if ( lastSync > remoteMod )
return 1;
if ( lastSync > localMod )
return 2;
qDebug("lsy %s --- lo %s --- re %s ", lastSync.toString().latin1(), localMod.toString().latin1(), remoteMod.toString().latin1() );
localIsNew = localMod >= remoteMod;
if ( localIsNew )
getEventViewerDialog()->setColorMode( 1 );
else
getEventViewerDialog()->setColorMode( 2 );
getEventViewerDialog()->setIncidence(local);
if ( localIsNew )
getEventViewerDialog()->setColorMode( 2 );
else
getEventViewerDialog()->setColorMode( 1 );
getEventViewerDialog()->addIncidence(remote);
getEventViewerDialog()->setColorMode( 0 );
//qDebug("local %d remote %d ",local->relatedTo(),remote->relatedTo() );
getEventViewerDialog()->setCaption( mCurrentSyncDevice +i18n(" : Conflict! Please choose entry!"));
getEventViewerDialog()->showMe();
result = getEventViewerDialog()->executeS( localIsNew );
return result;
break;
case SYNC_PREF_FORCE_LOCAL:
return 1;
break;
case SYNC_PREF_FORCE_REMOTE:
return 2;
break;
default:
// SYNC_PREF_TAKE_BOTH not implemented
break;
}
return 0;
}
Event* CalendarView::getLastSyncEvent()
{
Event* lse;
//qDebug("CurrentSyncDevice %s ",mCurrentSyncDevice .latin1() );
lse = mCalendar->event( "last-syncEvent-"+mCurrentSyncDevice );
if (!lse) {
lse = new Event();
lse->setUid( "last-syncEvent-"+mCurrentSyncDevice );
QString sum = "";
if ( mSyncManager->mExternSyncProfiles.contains( mCurrentSyncDevice ) )
sum = "E: ";
lse->setSummary(sum+mCurrentSyncDevice + i18n(" - sync event"));
lse->setDtStart( mLastCalendarSync );
lse->setDtEnd( mLastCalendarSync.addSecs( 7200 ) );
lse->setCategories( i18n("SyncEvent") );
lse->setReadOnly( true );
mCalendar->addEvent( lse );
}
return lse;
}
// we check, if the to delete event has a id for a profile
// if yes, we set this id in the profile to delete
void CalendarView::checkExternSyncEvent( QPtrList<Event> lastSync , Incidence* toDelete )
{
if ( lastSync.count() == 0 ) {
//qDebug(" lastSync.count() == 0");
return;
}
if ( toDelete->typeID() == journalID )
return;
Event* eve = lastSync.first();
while ( eve ) {
QString id = toDelete->getID( eve->uid().mid( 15 ) ); // this is the sync profile name
if ( !id.isEmpty() ) {
QString des = eve->description();
QString pref = "e";
if ( toDelete->typeID() == todoID )
pref = "t";
des += pref+ id + ",";
eve->setReadOnly( false );
eve->setDescription( des );
//qDebug("setdes %s ", des.latin1());
eve->setReadOnly( true );
}
eve = lastSync.next();
}
}
void CalendarView::checkExternalId( Incidence * inc )
{
QPtrList<Event> lastSync = mCalendar->getExternLastSyncEvents() ;
checkExternSyncEvent( lastSync, inc );
}
bool CalendarView::synchronizeCalendar( Calendar* local, Calendar* remote, int mode )
{
bool syncOK = true;
int addedEvent = 0;
int addedEventR = 0;
int deletedEventR = 0;
int deletedEventL = 0;
int changedLocal = 0;
int changedRemote = 0;
int filteredIN = 0;
int filteredOUT = 0;
//QPtrList<Event> el = local->rawEvents();
Event* eventR;
QString uid;
int take;
Event* eventRSync;
Event* eventLSync;
clearAllViews();
QPtrList<Event> eventRSyncSharp = remote->getExternLastSyncEvents();
QPtrList<Event> eventLSyncSharp = local->getExternLastSyncEvents();
bool fullDateRange = false;
local->resetTempSyncStat();
mLastCalendarSync = QDateTime::currentDateTime();
if ( mSyncManager->syncWithDesktop() ) {
remote->resetPilotStat(1);
if ( KSyncManager::mRequestedSyncEvent.isValid() ) {
mLastCalendarSync = KSyncManager::mRequestedSyncEvent;
qDebug("KO: using extern time for calendar sync: %s ", mLastCalendarSync.toString().latin1() );
} else {
qDebug("KSyncManager::mRequestedSyncEvent has invalid datatime ");
}
}
QDateTime modifiedCalendar = mLastCalendarSync;
eventLSync = getLastSyncEvent();
eventR = remote->event("last-syncEvent-"+mCurrentSyncName );
if ( eventR ) {
qDebug("last-syncEvent on remote found ");
eventRSync = (Event*) eventR->clone();
remote->deleteEvent(eventR );
} else {
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL || mSyncManager->syncWithDesktop()) {
eventRSync = (Event*)eventLSync->clone();
} else {
fullDateRange = true;
eventRSync = new Event();
eventRSync->setSummary(mCurrentSyncName + i18n(" - sync event"));
eventRSync->setUid("last-syncEvent-"+mCurrentSyncName );
eventRSync->setDtStart( mLastCalendarSync );
eventRSync->setDtEnd( mLastCalendarSync.addSecs( 7200 ) );
eventRSync->setCategories( i18n("SyncEvent") );
}
}
if ( eventLSync->dtStart() == mLastCalendarSync )
fullDateRange = true;
if ( ! fullDateRange ) {
if ( eventLSync->dtStart() != eventRSync->dtStart() ) {
qDebug("set fulldate to true %s %s" ,eventLSync->dtStart().toString().latin1(), eventRSync->dtStart().toString().latin1() );
//qDebug("%d %d %d %d ", eventLSync->dtStart().time().second(), eventLSync->dtStart().time().msec() , eventRSync->dtStart().time().second(), eventRSync->dtStart().time().msec());
fullDateRange = true;
}
}
if ( mSyncManager->syncWithDesktop() ) {
fullDateRange = ( eventLSync->dtStart() <= mLastCalendarSync && eventLSync->dtStart().addSecs(1) >= mLastCalendarSync );
}
if ( fullDateRange )
mLastCalendarSync = QDateTime::currentDateTime().addDays( -100*365);
else
mLastCalendarSync = eventLSync->dtStart();
// for resyncing if own file has changed
if ( mCurrentSyncDevice == "deleteaftersync" ) {
mLastCalendarSync = loadedFileVersion;
//qDebug("setting mLastCalendarSync ");
}
//qDebug("*************************** ");
qDebug("KO: mLastCalendarSync %s .Full: %d",mLastCalendarSync.toString().latin1(), fullDateRange);
QPtrList<Incidence> er = remote->rawIncidences();
Incidence* inR = er.first();
Incidence* inL;
QProgressBar bar( er.count(),0 );
bar.setCaption (i18n("Syncing - close to abort!") );
// ************** setting up filter *************
CalFilter *filterIN = 0;
CalFilter *filterOUT = 0;
CalFilter *filter = mFilters.first();
while(filter) {
if ( filter->name() == mSyncManager->mFilterInCal )
filterIN = filter;
if ( filter->name() == mSyncManager->mFilterOutCal )
filterOUT = filter;
filter = mFilters.next();
}
int w = 300;
if ( QApplication::desktop()->width() < 320 )
w = 220;
int h = bar.sizeHint().height() ;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
bar.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
bar.show();
int modulo = (er.count()/10)+1;
int incCounter = 0;
while ( inR ) {
if ( ! bar.isVisible() )
return false;
if ( incCounter % modulo == 0 )
bar.setProgress( incCounter );
++incCounter;
uid = inR->uid();
bool skipIncidence = false;
if ( uid.left(15) == QString("last-syncEvent-") )
skipIncidence = true;
QString idS;
qApp->processEvents();
if ( !skipIncidence ) {
inL = local->incidenceForUid( uid , false );
if ( inL ) { // maybe conflict - same uid in both calendars
if ( (take = takeEvent( inL, inR, mode, fullDateRange )) > 0 ) {
//qDebug("take %d %s ", take, inL->summary().latin1());
if ( take == 3 )
return false;
if ( take == 1 ) {// take local **********************
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL )
inL->setCsum( mCurrentSyncDevice, inR->getCsum(mCurrentSyncDevice) );
else
idS = inR->IDStr();
int calID = inR->calID();
remote->deleteIncidence( inR );
inR = inL->clone();
inR->setCalID( calID );
inR->setTempSyncStat( SYNC_TEMPSTATE_INITIAL );
if ( mGlobalSyncMode != SYNC_MODE_EXTERNAL )
inR->setIDStr( idS );
remote->addIncidence( inR );
if ( mSyncManager->syncWithDesktop() )
inR->setPilotId( 2 );
++changedRemote;
} else {// take remote **********************
if ( !inL->isReadOnly() ) {
idS = inL->IDStr();
int pid = inL->pilotId();
int calID = inL->calID();
local->deleteIncidence( inL );
inL = inR->clone();
inL->setCalID( calID );
if ( mSyncManager->syncWithDesktop() )
inL->setPilotId( pid );
inL->setIDStr( idS );
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) {
inL->setCsum( mCurrentSyncDevice, inR->getCsum(mCurrentSyncDevice) );
inL->setID( mCurrentSyncDevice, inR->getID(mCurrentSyncDevice) );
}
local->addIncidence( inL );
++changedLocal;
}
}
}
} else { // no conflict ********** add or delete remote
if ( !filterIN || filterIN->filterCalendarItem( inR ) ){
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) {
QString des = eventLSync->description();
QString pref = "e";
if ( inR->typeID() == todoID )
pref = "t";
if ( des.find(pref+ inR->getID(mCurrentSyncDevice) +"," ) >= 0 && mode != 5) { // delete it
inR->setTempSyncStat( SYNC_TEMPSTATE_DELETE );
//remote->deleteIncidence( inR );
++deletedEventR;
} else {
inR->setLastModified( modifiedCalendar );
inL = inR->clone();
inL->setIDStr( ":" );
inL->setCsum( mCurrentSyncDevice, inR->getCsum(mCurrentSyncDevice) );
inL->setID( mCurrentSyncDevice, inR->getID(mCurrentSyncDevice) );
inL->setCalID( 0 );// add to default cal
local->addIncidence( inL );
++addedEvent;
}
} else {
if ( inR->lastModified() > mLastCalendarSync || mode == 5 ) {
inR->setLastModified( modifiedCalendar );
inL = inR->clone();
inL->setIDStr( ":" );
inL->setCalID( 0 );// add to default cal
local->addIncidence( inL );
++addedEvent;
} else {
checkExternSyncEvent(eventRSyncSharp, inR);
remote->deleteIncidence( inR );
++deletedEventR;
}
}
} else {
++filteredIN;
}
}
}
inR = er.next();
}
QPtrList<Incidence> el = local->rawIncidences();
inL = el.first();
modulo = (el.count()/10)+1;
bar.setCaption (i18n("Add / remove events") );
bar.setTotalSteps ( el.count() ) ;
bar.show();
incCounter = 0;
while ( inL ) {
qApp->processEvents();
if ( ! bar.isVisible() )
return false;
if ( incCounter % modulo == 0 )
bar.setProgress( incCounter );
++incCounter;
uid = inL->uid();
bool skipIncidence = false;
if ( uid.left(15) == QString("last-syncEvent-") )
skipIncidence = true;
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL && inL->typeID() == journalID )
skipIncidence = true;
if ( !skipIncidence ) {
inR = remote->incidenceForUid( uid , true );
if ( ! inR ) {
if ( !filterOUT || filterOUT->filterCalendarItem( inL ) ){
// no conflict ********** add or delete local
if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) {
if ( !inL->getID(mCurrentSyncDevice).isEmpty() && mode != 4 ) {
checkExternSyncEvent(eventLSyncSharp, inL);
local->deleteIncidence( inL );
++deletedEventL;
} else {
if ( ! mSyncManager->mWriteBackExistingOnly ) {
inL->removeID(mCurrentSyncDevice );
++addedEventR;
//qDebug("remote added Incidence %s ", inL->summary().latin1());
inL->setLastModified( modifiedCalendar );
inR = inL->clone();
inR->setIDStr( ":" );
inR->setTempSyncStat( SYNC_TEMPSTATE_INITIAL );
inR->setCalID( 0 );// add to default cal
remote->addIncidence( inR );
}
}
} else {
if ( inL->lastModified() < mLastCalendarSync && mode != 4 ) {
checkExternSyncEvent(eventLSyncSharp, inL);
local->deleteIncidence( inL );
++deletedEventL;
} else {
if ( ! mSyncManager->mWriteBackExistingOnly ) {
++addedEventR;
inL->setLastModified( modifiedCalendar );
inR = inL->clone();
inR->setIDStr( ":" );
inR->setCalID( 0 );// add to default cal
remote->addIncidence( inR );
}
}
}
} else {
++filteredOUT;
}
}
}
inL = el.next();
}
int delFut = 0;
int remRem = 0;
if ( mSyncManager->mWriteBackInFuture ) {
er = remote->rawIncidences();
remRem = er.count();
inR = er.first();
QDateTime dt;
QDateTime cur = QDateTime::currentDateTime().addDays( -(mSyncManager->mWriteBackInPast * 7) );
QDateTime end = QDateTime::currentDateTime().addDays( (mSyncManager->mWriteBackInFuture ) *7 );
while ( inR ) {
if ( inR->typeID() == todoID ) {
Todo * t = (Todo*)inR;
if ( t->hasDueDate() )
dt = t->dtDue();
else
dt = cur.addSecs( 62 );
}
else if (inR->typeID() == eventID ) {
bool ok;
dt = inR->getNextOccurence( cur, &ok );
if ( !ok )
dt = cur.addSecs( -62 );
}
else
dt = inR->dtStart();
if ( dt < cur || dt > end ) {
remote->deleteIncidence( inR );
++delFut;
}
inR = er.next();
}
}
bar.hide();
mLastCalendarSync = QDateTime::currentDateTime().addSecs( 1 );
eventLSync->setReadOnly( false );
eventLSync->setDtStart( mLastCalendarSync );
eventRSync->setDtStart( mLastCalendarSync );
eventLSync->setDtEnd( mLastCalendarSync.addSecs( 3600 ) );
eventRSync->setDtEnd( mLastCalendarSync.addSecs( 3600 ) );
eventRSync->setLocation( i18n("Remote from: ")+mCurrentSyncName ) ;
eventLSync->setLocation(i18n("Local from: ") + mCurrentSyncName );
eventLSync->setReadOnly( true );
qDebug("KO: Normal sync: %d ",mGlobalSyncMode == SYNC_MODE_NORMAL );
if ( mGlobalSyncMode == SYNC_MODE_NORMAL && !mSyncManager->syncWithDesktop()) // kde is abnormal...
remote->addEvent( eventRSync );
else
delete eventRSync;
qDebug("KO: Sync with desktop %d ",mSyncManager->syncWithDesktop() );
QString mes;
mes .sprintf( i18n("Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n %d incoming filtered out\n %d outgoing filtered out\n"),addedEvent, addedEventR, changedLocal, changedRemote, deletedEventL, deletedEventR, filteredIN, filteredOUT );
QString delmess;
if ( delFut ) {
delmess.sprintf( i18n("%d items skipped on remote,\nbecause they are more\nthan %d weeks in the past or\nmore than %d weeks in the future.\nAfter skipping, remote has\n%d calendar/todo items."), delFut,mSyncManager->mWriteBackInPast,mSyncManager->mWriteBackInFuture, remRem-delFut);
mes += delmess;
}
mes = i18n("Local calendar changed!\n") +mes;
mCalendar->checkAlarmForIncidence( 0, true );
qDebug( mes );
if ( mSyncManager->mShowSyncSummary ) {
if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel(this, mes,
i18n("KO/Pi Synchronization"),i18n("Write back"))) {
qDebug("KO: WB cancelled ");
mSyncManager->mWriteBackFile = false;
return syncOK;
}
}
return syncOK;
}
void CalendarView::setSyncDevice( QString s )
{
mCurrentSyncDevice= s;
}
void CalendarView::setSyncName( QString s )
{
mCurrentSyncName= s;
}
bool CalendarView::syncCalendar(QString filename, int mode)
{
//qDebug("syncCalendar %s ", filename.latin1());
mGlobalSyncMode = SYNC_MODE_NORMAL;
CalendarLocal* calendar = new CalendarLocal();
calendar->setTimeZoneId(KPimGlobalPrefs::instance()->mTimeZoneId);
FileStorage* storage = new FileStorage( calendar );
bool syncOK = false;
storage->setFileName( filename );
// qDebug("loading ... ");
if ( storage->load() ) {
getEventViewerDialog()->setSyncMode( true );
syncOK = synchronizeCalendar( mCalendar, calendar, mode );
getEventViewerDialog()->setSyncMode( false );
if ( syncOK ) {
if ( mSyncManager->mWriteBackFile )
{
storage->setSaveFormat( new ICalFormat() );
storage->save();
}
}
setModified( true );
}
delete storage;
delete calendar;
if ( syncOK )
updateView();
return syncOK;
}
void CalendarView::syncExternal( int mode )
{
mGlobalSyncMode = SYNC_MODE_EXTERNAL;
qApp->processEvents();
CalendarLocal* calendar = new CalendarLocal();
calendar->setTimeZoneId(KPimGlobalPrefs::instance()->mTimeZoneId);
bool syncOK = false;
bool loadSuccess = false;
PhoneFormat* phoneFormat = 0;
emit tempDisableBR(true);
#ifndef DESKTOP_VERSION
SharpFormat* sharpFormat = 0;
if ( mode == 0 ) { // sharp
sharpFormat = new SharpFormat () ;
loadSuccess = sharpFormat->load( calendar, mCalendar );
} else
#endif
if ( mode == 1 ) { // phone
phoneFormat = new PhoneFormat (mCurrentSyncDevice,
mSyncManager->mPhoneDevice,
mSyncManager->mPhoneConnection,
mSyncManager->mPhoneModel);
loadSuccess = phoneFormat->load( calendar,mCalendar);
} else {
emit tempDisableBR(false);
return;
}
if ( loadSuccess ) {
getEventViewerDialog()->setSyncMode( true );
syncOK = synchronizeCalendar( mCalendar, calendar, mSyncManager->mSyncAlgoPrefs );
getEventViewerDialog()->setSyncMode( false );
qApp->processEvents();
if ( syncOK ) {
if ( mSyncManager->mWriteBackFile )
{
QPtrList<Incidence> iL = mCalendar->rawIncidences();
Incidence* inc = iL.first();
if ( phoneFormat ) {
while ( inc ) {
inc->removeID(mCurrentSyncDevice);
inc = iL.next();
}
}
#ifndef DESKTOP_VERSION
if ( sharpFormat )
sharpFormat->save(calendar);
#endif
if ( phoneFormat )
phoneFormat->save(calendar);
iL = calendar->rawIncidences();
inc = iL.first();
Incidence* loc;
while ( inc ) {
if ( inc->tempSyncStat() == SYNC_TEMPSTATE_NEW_ID ) {
loc = mCalendar->incidence(inc->uid() );
if ( loc ) {
loc->setID(mCurrentSyncDevice, inc->getID(mCurrentSyncDevice) );
loc->setCsum( mCurrentSyncDevice, inc->getCsum(mCurrentSyncDevice) );
}
}
inc = iL.next();
}
Incidence* lse = getLastSyncEvent();
if ( lse ) {
lse->setReadOnly( false );
lse->setDescription( "" );
lse->setReadOnly( true );
}
}
} else {
topLevelWidget()->setCaption( i18n("Sync cancelled or failed.") );
}
setModified( true );
} else {
QString question = i18n("Sorry, the database access\ncommand failed!\n\nNothing synced!\n") ;
QMessageBox::information( 0, i18n("KO/Pi Import - ERROR"),
question, i18n("Ok")) ;
}
delete calendar;
updateView();
emit tempDisableBR(false);
return ;//syncOK;
}
bool CalendarView::importBday()
{
#ifndef KORG_NOKABC
#ifdef DESKTOP_VERSION
int curCal = mCalendar->defaultCalendar();
int bd = mCalEditView->getBirtdayID();
if ( bd == 0 )
return false;
mCalendar->setDefaultCalendar( bd );
KABC::StdAddressBook* AddressBook = KABC::StdAddressBook::self( true );
KABC::AddressBook::Iterator it;
int count = 0;
for( it = AddressBook->begin(); it != AddressBook->end(); ++it ) {
++count;
}
QProgressBar bar(count,0 );
int w = 300;
if ( QApplication::desktop()->width() < 320 )
w = 220;
int h = bar.sizeHint().height() ;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
bar.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
bar.show();
bar.setCaption (i18n("Reading addressbook - close to abort!") );
qApp->processEvents();
count = 0;
int addCount = 0;
KCal::Attendee* a = 0;
for( it = AddressBook->begin(); it != AddressBook->end(); ++it ) {
if ( ! bar.isVisible() )
return false;
bar.setProgress( count++ );
qApp->processEvents();
//qDebug("add BDay %s %s", (*it).realName().latin1(),(*it).birthday().date().toString().latin1() );
if ( (*it).birthday().date().isValid() ){
a = new KCal::Attendee( (*it).realName(), (*it).preferredEmail(),false,KCal::Attendee::NeedsAction,KCal::Attendee::ReqParticipant,(*it).uid()) ;
if ( addAnniversary( (*it).birthday().date(), (*it).assembledName(), a, true ) )
++addCount;
}
QDate anni = KGlobal::locale()->readDate( (*it).custom("KADDRESSBOOK", "X-Anniversary" ), "%Y-%m-%d");
if ( anni.isValid() ){
a = new KCal::Attendee( (*it).realName(), (*it).preferredEmail(),false,KCal::Attendee::NeedsAction,KCal::Attendee::ReqParticipant,(*it).uid()) ;
if ( addAnniversary( anni, (*it).assembledName(), a, false ) )
++addCount;
}
}
mCalendar->setDefaultCalendar( curCal );
updateView();
topLevelWidget()->setCaption(QString::number( addCount )+ i18n(" birthdays/anniversaries added!"));
#else //DESKTOP_VERSION
ExternalAppHandler::instance()->requestBirthdayListFromKAPI("QPE/Application/kopi", this->name() /* name is here the unique uid*/);
// the result should now arrive through method insertBirthdays
#endif //DESKTOP_VERSION
#endif //KORG_NOKABC
return true;
}
// This method will be called from Ka/Pi as a response to requestBirthdayListFromKAPI
void CalendarView::insertBirthdays(const QString& uid, const QStringList& birthdayList,
const QStringList& anniversaryList, const QStringList& realNameList,
const QStringList& emailList, const QStringList& assembledNameList,
const QStringList& uidList)
{
//qDebug("KO::CalendarView::insertBirthdays");
if (uid == this->name())
{
int curCal = mCalendar->defaultCalendar();
int bd = mCalEditView->getBirtdayID();
if ( bd == 0 )
return;
mCalendar->setDefaultCalendar( bd );
int count = birthdayList.count();
int addCount = 0;
KCal::Attendee* a = 0;
//qDebug("CalView 1 %i", count);
QProgressBar bar(count,0 );
int w = 300;
if ( QApplication::desktop()->width() < 320 )
w = 220;
int h = bar.sizeHint().height() ;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
bar.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
bar.show();
bar.setCaption (i18n("inserting birthdays - close to abort!") );
qApp->processEvents();
QDate birthday;
QDate anniversary;
QString realName;
QString email;
QString assembledName;
QString uid;
bool ok = true;
for ( int i = 0; i < count; i++)
{
if ( ! bar.isVisible() )
return;
bar.setProgress( i );
qApp->processEvents();
birthday = KGlobal::locale()->readDate(birthdayList[i], KLocale::ISODate, &ok);
if (!ok) {
;//qDebug("CalendarView::insertBirthdays found invalid birthday: %s",birthdayList[i].latin1());
}
anniversary = KGlobal::locale()->readDate(anniversaryList[i], KLocale::ISODate, &ok);
if (!ok) {
;//qDebug("CalendarView::insertBirthdays found invalid anniversary: %s",anniversaryList[i].latin1());
}
realName = realNameList[i];
email = emailList[i];
assembledName = assembledNameList[i];
uid = uidList[i];
//qDebug("insert birthday in KO/Pi: %s,%s,%s,%s: %s, %s", realName.latin1(), email.latin1(), assembledName.latin1(), uid.latin1(), birthdayList[i].latin1(), anniversaryList[i].latin1() );
if ( birthday.isValid() ){
a = new KCal::Attendee( realName, email,false,KCal::Attendee::NeedsAction,
KCal::Attendee::ReqParticipant,uid) ;
if ( addAnniversary( birthday, assembledName, a, true ) )
++addCount;
}
if ( anniversary.isValid() ){
a = new KCal::Attendee( realName, email,false,KCal::Attendee::NeedsAction,
KCal::Attendee::ReqParticipant,uid) ;
if ( addAnniversary( anniversary, assembledName, a, false ) )
++addCount;
}
}
mCalendar->setDefaultCalendar( curCal );
updateView();
topLevelWidget()->setCaption(QString::number( addCount )+ i18n(" birthdays/anniversaries added!"));
}
}
bool CalendarView::addAnniversary( QDate date, QString name, KCal::Attendee* a, bool birthday)
{
//qDebug("addAnni ");
Event * ev = new Event();
ev->setOrganizer(KOPrefs::instance()->email());
if ( a ) {
ev->addAttendee( a );
}
QString kind;
if ( birthday ) {
kind = i18n( "Birthday" );
ev->setSummary( name + " (" + QString::number(date.year()) +")");
}
else {
kind = i18n( "Anniversary" );
ev->setSummary( name + " (" + QString::number(date.year()) +") " + kind );
}
ev->setCategories( kind );
ev->setDtStart( QDateTime(date) );
ev->setDtEnd( QDateTime(date) );
ev->setFloats( true );
Recurrence * rec = ev->recurrence();
rec->setYearly(Recurrence::rYearlyMonth,1,-1);
rec->addYearlyNum( date.month() );
if ( !mCalendar->addAnniversaryNoDup( ev ) ) {
delete ev;
return false;
}
return true;
}
bool CalendarView::importQtopia( const QString &categories,
const QString &datebook,
const QString &todolist )
{
QtopiaFormat qtopiaFormat;
qtopiaFormat.setCategoriesList ( &(KOPrefs::instance()->mCustomCategories));
if ( !categories.isEmpty() ) qtopiaFormat.load( mCalendar, categories );
if ( !datebook.isEmpty() ) qtopiaFormat.load( mCalendar, datebook );
if ( !todolist.isEmpty() ) qtopiaFormat.load( mCalendar, todolist );
updateView();
return true;
#if 0
mGlobalSyncMode = SYNC_MODE_QTOPIA;
mCurrentSyncDevice = "qtopia-XML";
if ( mSyncManager->mAskForPreferences )
edit_sync_options();
qApp->processEvents();
CalendarLocal* calendar = new CalendarLocal();
calendar->setTimeZoneId(KPimGlobalPrefs::instance()->mTimeZoneId);
bool syncOK = false;
QtopiaFormat qtopiaFormat;
qtopiaFormat.setCategoriesList ( &(KOPrefs::instance()->mCustomCategories));
bool loadOk = true;
if ( !categories.isEmpty() )
loadOk = qtopiaFormat.load( calendar, categories );
if ( loadOk && !datebook.isEmpty() )
loadOk = qtopiaFormat.load( calendar, datebook );
if ( loadOk && !todolist.isEmpty() )
loadOk = qtopiaFormat.load( calendar, todolist );
if ( loadOk ) {
getEventViewerDialog()->setSyncMode( true );
syncOK = synchronizeCalendar( mCalendar, calendar, mSyncManager->mSyncAlgoPrefs );
getEventViewerDialog()->setSyncMode( false );
qApp->processEvents();
if ( syncOK ) {
if ( mSyncManager->mWriteBackFile )
{
// write back XML file
}
setModified( true );
}
} else {
QString question = i18n("Sorry, the file loading\ncommand failed!\n\nNothing synced!\n") ;
QMessageBox::information( 0, i18n("KO/Pi Sync - ERROR"),
question, i18n("Ok")) ;
}
delete calendar;
updateView();
return syncOK;
#endif
}
void CalendarView::setSyncEventsReadOnly()
{
mCalendar->setSyncEventsReadOnly();
}
bool CalendarView::loadCalendars()
{
QPtrList<KopiCalendarFile> calendars = KOPrefs::instance()->mCalendars;
KopiCalendarFile * cal = calendars.first();
mCalendar->setDefaultCalendar( 1 );
openCalendar( MainWindow::defaultFileName(), false );
cal = calendars.next();
while ( cal ) {
addCalendar( cal );
cal = calendars.next();
}
restoreCalendarSettings();
return true;
}
bool CalendarView::restoreCalendarSettings()
{
QPtrList<KopiCalendarFile> calendars = KOPrefs::instance()->mCalendars;
KopiCalendarFile * cal = calendars.first();
while ( cal ) {
mCalendar->setCalendarEnabled( cal->mCalNumber,cal->isEnabled );
mCalendar->setAlarmEnabled( cal->mCalNumber, cal->isAlarmEnabled );
mCalendar->setReadOnly( cal->mCalNumber, cal->isReadOnly );
if ( cal->isStandard )
mCalendar->setDefaultCalendar( cal->mCalNumber );
cal = calendars.next();
}
setSyncEventsReadOnly();
mCalendar->reInitAlarmSettings();
updateUnmanagedViews();
updateView();
return true;
}
void CalendarView::addCalendarId( int id )
{
KopiCalendarFile * cal = KOPrefs::instance()->getCalendar( id );
if ( cal )
addCalendar( cal );
}
bool CalendarView::addCalendar( KopiCalendarFile * cal )
{
cal->mErrorOnLoad = false;
if ( mCalendar->addCalendarFile( cal->mFileName, cal->mCalNumber )) {
cal->mLoadDt = QDateTime::currentDateTime();
return true;
}
qDebug("KO: Error adding calendar file %s ",cal->mFileName.latin1() );
cal->mErrorOnLoad = true;
return false;
}
bool CalendarView::openCalendar(QString filename, bool merge)
{
if (filename.isEmpty()) {
return false;
}
if (!QFile::exists(filename)) {
KMessageBox::error(this,i18n("File does not exist:\n '%1'.").arg(filename));
return false;
}
globalFlagBlockAgenda = 1;
clearAllViews();
if (!merge) {
mViewManager->setDocumentId( filename );
mCalendar->close();
}
mStorage->setFileName( filename );
if ( mStorage->load() ) {
if ( merge ) ;//setModified( true );
else {
//setModified( true );
mViewManager->setDocumentId( filename );
mDialogManager->setDocumentId( filename );
mTodoList->setDocumentId( filename );
}
globalFlagBlockAgenda = 2;
// if ( getLastSyncEvent() )
// getLastSyncEvent()->setReadOnly( true );
mCalendar->reInitAlarmSettings();
setSyncEventsReadOnly();
updateUnmanagedViews();
updateView();
if ( filename != MainWindow::defaultFileName() ) {
saveCalendar( MainWindow::defaultFileName() );
} else {
QFileInfo finf ( MainWindow::defaultFileName());
if ( finf.exists() ) {
setLoadedFileVersion( finf.lastModified () );
}
}
return true;
} else {
// while failing to load, the calendar object could
// have become partially populated. Clear it out.
if ( !merge ) {
mCalendar->close();
mViewManager->setDocumentId( filename );
mDialogManager->setDocumentId( filename );
mTodoList->setDocumentId( filename );
}
//KMessageBox::error(this,i18n("Couldn't load calendar\n '%1'.").arg(filename));
QTimer::singleShot ( 1, this, SLOT ( showOpenError() ) );
globalFlagBlockAgenda = 2;
mCalendar->reInitAlarmSettings();
setSyncEventsReadOnly();
updateUnmanagedViews();
updateView();
}
return false;
}
void CalendarView::mergeFile( QString fn )
{
clearAllViews();
mCalendar->mergeCalendarFile( fn );
mCalendar->reInitAlarmSettings();
setSyncEventsReadOnly();
updateUnmanagedViews();
updateView();
}
void CalendarView::showOpenError()
{
KMessageBox::error(this,i18n("Couldn't load calendar\n."));
}
void CalendarView::setLoadedFileVersion(QDateTime dt)
{
loadedFileVersion = dt;
}
bool CalendarView::checkFileChanged(QString fn)
{
QFileInfo finf ( fn );
if ( !finf.exists() )
return true;
QDateTime dt = finf.lastModified ();
if ( dt <= loadedFileVersion )
return false;
return true;
}
void CalendarView::watchSavedFile()
{
QFileInfo finf ( MainWindow::defaultFileName());
if ( !finf.exists() )
return;
QDateTime dt = finf.lastModified ();
if ( dt < loadedFileVersion ) {
//qDebug("watch %s %s ", dt.toString().latin1(), loadedFileVersion.toString().latin1());
QTimer::singleShot( 1000 , this, SLOT ( watchSavedFile() ) );
return;
}
loadedFileVersion = dt;
}
bool CalendarView::checkAllFileVersions()
{
QPtrList<KopiCalendarFile> calendars = KOPrefs::instance()->mCalendars;
KopiCalendarFile * cal = calendars.first();
mCalendar->setDefaultCalendar( 1 );
mCalendar->setDefaultCalendarEnabledOnly();
if ( !cal->isReadOnly && !cal->mErrorOnLoad ) {
if ( !checkFileVersion(MainWindow::defaultFileName())) {
restoreCalendarSettings();
return false;
}
}
cal = calendars.next();
QDateTime storeTemp = loadedFileVersion;
while ( cal ) {
if ( !cal->isReadOnly && !cal->mErrorOnLoad ) {
mCalendar->setDefaultCalendar( cal->mCalNumber );
mCalendar->setDefaultCalendarEnabledOnly();
loadedFileVersion = cal->mLoadDt.addSecs( 15 );
if ( !checkFileVersion(cal->mFileName )) {
loadedFileVersion = storeTemp;
restoreCalendarSettings();
return false;
}
}
cal = calendars.next();
}
loadedFileVersion = storeTemp;
return true;
}
bool CalendarView::checkFileVersion(QString fn)
{
QFileInfo finf ( fn );
if ( !finf.exists() )
return true;
QDateTime dt = finf.lastModified ();
qDebug("loaded file version %s %s", fn.latin1(), loadedFileVersion.toString().latin1());
qDebug("file on disk version %s %s", fn.latin1(),dt.toString().latin1());
if ( dt <= loadedFileVersion )
return true;
int km = KMessageBox::warningYesNoCancel(this, i18n("\nThe file\n%1\non disk has changed!\nFile size: %2 bytes.\nLast modified: %3\nDo you want to:\n\n - Save and overwrite file?\n - Sync with file, then save?\n - Cancel without saving? \n").arg(KGlobal::formatMessage(fn,0)).arg( QString::number( finf.size())).arg( KGlobal::locale()->formatDateTime(finf.lastModified (), true, true)) ,
i18n("KO/Pi Warning"),i18n("Overwrite"),
i18n("Sync+save"));
if ( km == KMessageBox::Cancel )
return false;
if ( km == KMessageBox::Yes )
return true;
setSyncDevice("deleteaftersync" );
mSyncManager->mAskForPreferences = true;
mSyncManager->mSyncAlgoPrefs = 3;
mSyncManager->mWriteBackFile = false;
mSyncManager->mWriteBackExistingOnly = false;
mSyncManager->mShowSyncSummary = false;
syncCalendar( fn, 3 );
Event * e = getLastSyncEvent();
if ( e )
mCalendar->deleteEvent( e );
return true;
}
bool CalendarView::saveCalendars()
{
QPtrList<KopiCalendarFile> calendars = KOPrefs::instance()->mCalendars;
KopiCalendarFile * cal = calendars.first();
mCalendar->setDefaultCalendar( 1 );
mCalendar->setDefaultCalendarEnabledOnly();
saveCalendar( MainWindow::defaultFileName() );
cal = calendars.next();
while ( cal ) {
if ( !cal->isReadOnly && !cal->mErrorOnLoad ) {
mCalendar->setDefaultCalendar( cal->mCalNumber );
mCalendar->setDefaultCalendarEnabledOnly();
if ( saveCalendar( cal->mFileName ) )
cal->mLoadDt = QDateTime::currentDateTime();
}
cal = calendars.next();
}
restoreCalendarSettings();
return true;
}
bool CalendarView::saveCalendar( QString filename )
{
// Store back all unsaved data into calendar object
// qDebug("file %s %d ", filename.latin1() , mViewManager->currentView() );
if ( mViewManager->currentView() )
mViewManager->currentView()->flushView();
QDateTime lfv = QDateTime::currentDateTime().addSecs( -2);
mStorage->setSaveFormat( new ICalFormat() );
mStorage->setFileName( filename );
bool success;
success = mStorage->save();
if ( !success ) {
return false;
}
if ( filename == MainWindow::defaultFileName() ) {
setLoadedFileVersion( lfv );
watchSavedFile();
}
return true;
}
void CalendarView::closeCalendar()
{
// child windows no longer valid
clearAllViews();
emit closingDown();
mCalendar->close();
setModified(false);
updateView();
}
void CalendarView::archiveCalendar()
{
mDialogManager->showArchiveDialog();
}
void CalendarView::readSettings()
{
// mViewManager->showAgendaView();
QString str;
//qDebug("CalendarView::readSettings() ");
// read settings from the KConfig, supplying reasonable
// defaults where none are to be found
KConfig *config = KOGlobals::config();
#ifndef KORG_NOSPLITTER
config->setGroup("KOrganizer Geometry");
QValueList<int> sizes = config->readIntListEntry("Separator1");
if (sizes.count() != 2) {
sizes << mDateNavigator->minimumSizeHint().width();
sizes << 300;
}
mPanner->setSizes(sizes);
sizes = config->readIntListEntry("Separator2");
if ( ( mResourceView && sizes.count() == 4 ) ||
( !mResourceView && sizes.count() == 3 ) ) {
mLeftSplitter->setSizes(sizes);
}
#endif
globalFlagBlockAgenda = 1;
mViewManager->showAgendaView();
//mViewManager->readSettings( config );
mTodoList->restoreLayout(config,QString("Todo Layout"));
readFilterSettings(config);
#ifdef DESKTOP_VERSION
config->setGroup("WidgetLayout");
QStringList list;
list = config->readListEntry("MainLayout");
int x,y,w,h;
if ( ! list.isEmpty() ) {
x = list[0].toInt();
y = list[1].toInt();
w = list[2].toInt();
h = list[3].toInt();
KApplication::testCoords( &x,&y,&w,&h );
topLevelWidget()->setGeometry(x,y,w,h);
} else {
topLevelWidget()->setGeometry( 40 ,40 , 640, 440);
}
list = config->readListEntry("EditEventLayout");
if ( ! list.isEmpty() ) {
x = list[0].toInt();
y = list[1].toInt();
w = list[2].toInt();
h = list[3].toInt();
KApplication::testCoords( &x,&y,&w,&h );
mEventEditor->setGeometry(x,y,w,h);
}
list = config->readListEntry("EditTodoLayout");
if ( ! list.isEmpty() ) {
x = list[0].toInt();
y = list[1].toInt();
w = list[2].toInt();
h = list[3].toInt();
KApplication::testCoords( &x,&y,&w,&h );
mTodoEditor->setGeometry(x,y,w,h);
}
list = config->readListEntry("ViewerLayout");
if ( ! list.isEmpty() ) {
x = list[0].toInt();
y = list[1].toInt();
w = list[2].toInt();
h = list[3].toInt();
KApplication::testCoords( &x,&y,&w,&h );
getEventViewerDialog()->setGeometry(x,y,w,h);
}
#endif
config->setGroup( "Views" );
int dateCount = config->readNumEntry( "ShownDatesCount", 7 );
QValueList<int> sizes = config->readIntListEntry("Left Splitter Frame");
int resetval = 0;
int maxVal = 0;
if (sizes.count() != 3) {
if ( KOPrefs::instance()->mVerticalScreen ) {
resetval = mDateNavigator->sizeHint().width()+2;
} else {
resetval = mDateNavigator->sizeHint().height()+2;
}
}
if ( resetval ) {
sizes.clear();
if ( KOPrefs::instance()->mVerticalScreen ) {
maxVal = QApplication::desktop()->width() -10;
} else {
maxVal = QApplication::desktop()->height()-10;
}
sizes << resetval;
if ( maxVal < resetval + resetval)
resetval = maxVal - resetval;
sizes << resetval;
sizes << 100;
}
mLeftFrame->setSizes(sizes);
sizes = config->readIntListEntry("Main Splitter Frame");
resetval = 0;
maxVal = 0;
if (sizes.count() != 2) {
if ( !KOPrefs::instance()->mVerticalScreen ) {
resetval = mDateNavigator->sizeHint().width()+2;
} else {
resetval = mDateNavigator->sizeHint().height()+2;
}
}
if ( resetval ) {
sizes.clear();
if ( !KOPrefs::instance()->mVerticalScreen ) {
maxVal = QApplication::desktop()->width() -10;
} else {
maxVal = QApplication::desktop()->height()-10;
}
sizes << resetval;
if ( maxVal < resetval + resetval)
resetval = maxVal - resetval;
sizes << resetval;
}
mMainFrame->setSizes(sizes);
if ( dateCount == 5 ) mNavigator->selectWorkWeek();
else if ( dateCount == 7 ) mNavigator->selectWeek();
else mNavigator->selectDates( dateCount );
// mViewManager->readSettings( config );
updateConfig();
globalFlagBlockAgenda = 2;
mViewManager->readSettings( config );
QTimer::singleShot( 1, mDateNavigator, SLOT ( setResizeEnabled() ) );
}
void CalendarView::checkSuspendAlarm()
{
if ( mSuspendTimer->isActive() ) {
KMessageBox::information( this, i18n("<b>WARNING:</b> There is a pending suspended alarm!"), i18n("Pending Suspend Alarm"));
}
}
void CalendarView::writeSettings()
{
// kdDebug() << "CalendarView::writeSettings" << endl;
KConfig *config = KOGlobals::config();
mViewManager->writeSettings( config );
mTodoList->saveLayout(config,QString("Todo Layout"));
mDialogManager->writeSettings( config );
//KOPrefs::instance()->usrWriteConfig();
KOPrefs::instance()->writeConfig();
writeFilterSettings(config);
config->setGroup( "AppRun" );
QDateTime dt ( QDate (2005,1,1), QTime( 0,0,0 ) );
int days = dt.daysTo( QDate::currentDate() );
dt = dt.addDays( days );
int secs = dt.secsTo( QDateTime::currentDateTime() );
config->writeEntry( "LatestProgramStopDays", days );
config->writeEntry( "LatestProgramStopSecs", secs );
//qDebug("KO: Writing stop time: %d ", secs);
//qDebug("KO: Current Time %s ",QDateTime::currentDateTime().toString().latin1() );
//QDateTime latest = dt.addSecs ( secs );
//qDebug("KO: Termination on %s ", latest.toString().latin1());
config->setGroup( "Views" );
config->writeEntry( "ShownDatesCount", mNavigator->selectedDates().count() );
#if 0
qDebug("********************* ");
qDebug("Testcode secsto ");
QDateTime dt_nodaylight ( QDate (2005,3,26), QTime( 0,0,0 ) );
QDateTime dt_daylight ( QDate (2005,3,29), QTime( 0,0,0 ) );
int secsto = dt_nodaylight.secsTo( dt_daylight );
QDateTime dt_daylight_wrong = dt_nodaylight.addSecs( secsto );
qDebug("dt nodaylight %s ",dt_nodaylight.toString().latin1() );
qDebug("dt daylight %s ",dt_daylight.toString().latin1() );
qDebug("dt daylight_wrong %s ",dt_daylight_wrong.toString().latin1() );
qDebug("Computed secsTo %d . in minutes: %d . in hours: %d ", secsto, secsto/60, secsto/3600);
qDebug("********************* testcode end");
#endif
QValueList<int> listINT = mLeftFrame->sizes();
config->writeEntry("Left Splitter Frame",listINT);
QValueList<int> listINT2 = mMainFrame->sizes();
config->writeEntry("Main Splitter Frame",listINT2);
#ifdef DESKTOP_VERSION
config->setGroup("WidgetLayout");
QStringList list ;//= config->readListEntry("MainLayout");
int x,y,w,h;
QWidget* wid;
wid = topLevelWidget();
x = wid->geometry().x();
y = wid->geometry().y();
w = wid->width();
h = wid->height();
list.clear();
list << QString::number( x );
list << QString::number( y );
list << QString::number( w );
list << QString::number( h );
config->writeEntry("MainLayout",list );
wid = mEventEditor;
x = wid->geometry().x();
y = wid->geometry().y();
w = wid->width();
h = wid->height();
list.clear();
list << QString::number( x );
list << QString::number( y );
list << QString::number( w );
list << QString::number( h );
config->writeEntry("EditEventLayout",list );
wid = mTodoEditor;
x = wid->geometry().x();
y = wid->geometry().y();
w = wid->width();
h = wid->height();
list.clear();
list << QString::number( x );
list << QString::number( y );
list << QString::number( w );
list << QString::number( h );
config->writeEntry("EditTodoLayout",list );
wid = getEventViewerDialog();
x = wid->geometry().x();
y = wid->geometry().y();
w = wid->width();
h = wid->height();
list.clear();
list << QString::number( x );
list << QString::number( y );
list << QString::number( w );
list << QString::number( h );
config->writeEntry("ViewerLayout",list );
wid = mDialogManager->getSearchDialog();
if ( wid ) {
x = wid->geometry().x();
y = wid->geometry().y();
w = wid->width();
h = wid->height();
list.clear();
list << QString::number( x );
list << QString::number( y );
list << QString::number( w );
list << QString::number( h );
config->writeEntry("SearchLayout",list );
}
#endif
config->sync();
}
void CalendarView::readFilterSettings(KConfig *config)
{
// kdDebug() << "CalendarView::readFilterSettings()" << endl;
mFilters.clear();
config->setGroup("General");
QStringList filterList = config->readListEntry("CalendarFilters");
QStringList::ConstIterator it = filterList.begin();
QStringList::ConstIterator end = filterList.end();
while(it != end) {
// kdDebug() << " filter: " << (*it) << endl;
CalFilter *filter;
filter = new CalFilter(*it);
config->setGroup("Filter_" + (*it).utf8());
//qDebug("readFilterSettings %d ",config->readNumEntry("Criteria",0) );
filter->setCriteria(config->readNumEntry("Criteria",0));
filter->setCategoryList(config->readListEntry("CategoryList"));
mFilters.append(filter);
++it;
}
if (mFilters.count() == 0) {
CalFilter *filter = new CalFilter(i18n("Default"));
mFilters.append(filter);
}
mFilterView->updateFilters();
config->setGroup("FilterView");
mFilterView->blockSignals(true);
mFilterView->setFiltersEnabled(config->readBoolEntry("FilterEnabled"));
mFilterView->setSelectedFilter(config->readEntry("Current Filter"));
mFilterView->blockSignals(false);
// We do it manually to avoid it being done twice by the above calls
updateFilter();
}
void CalendarView::writeFilterSettings(KConfig *config)
{
// kdDebug() << "CalendarView::writeFilterSettings()" << endl;
QStringList filterList;
CalFilter *filter = mFilters.first();
while(filter) {
// kdDebug() << " fn: " << filter->name() << endl;
filterList << filter->name();
config->setGroup("Filter_" + filter->name().utf8());
config->writeEntry("Criteria",filter->criteria());
config->writeEntry("CategoryList",filter->categoryList());
filter = mFilters.next();
}
config->setGroup("General");
config->writeEntry("CalendarFilters",filterList);
config->setGroup("FilterView");
config->writeEntry("FilterEnabled",mFilterView->filtersEnabled());
config->writeEntry("Current Filter",mFilterView->selectedFilter()->name());
}
void CalendarView::goToday()
{
if ( mViewManager->currentView()->isMonthView() )
mNavigator->selectTodayMonth();
else
mNavigator->selectToday();
}
void CalendarView::goNext()
{
mNavigator->selectNext();
}
void CalendarView::goPrevious()
{
mNavigator->selectPrevious();
}
void CalendarView::goNextMonth()
{
mNavigator->selectNextMonth();
}
void CalendarView::goPreviousMonth()
{
mNavigator->selectPreviousMonth();
}
void CalendarView::updateConfig()
{
if ( KOPrefs::instance()->mUseAppColors )
QApplication::setPalette( QPalette (KOPrefs::instance()->mAppColor1, KOPrefs::instance()->mAppColor2), true );
emit configChanged();
mTodoList->updateConfig();
// mDateNavigator->setFont ( KOPrefs::instance()->mDateNavigatorFont);
mCalendar->setTimeZoneId(KPimGlobalPrefs::instance()->mTimeZoneId);
// To make the "fill window" configurations work
//mViewManager->raiseCurrentView();
}
void CalendarView::eventChanged(Event *event)
{
changeEventDisplay(event,KOGlobals::EVENTEDITED);
//updateUnmanagedViews();
}
void CalendarView::eventAdded(Event *event)
{
changeEventDisplay(event,KOGlobals::EVENTADDED);
}
void CalendarView::eventToBeDeleted(Event *)
{
kdDebug() << "CalendarView::eventToBeDeleted(): to be implemented" << endl;
}
void CalendarView::eventDeleted()
{
changeEventDisplay(0,KOGlobals::EVENTDELETED);
}
void CalendarView::changeTodoDisplay(Todo *which, int action)
{
changeIncidenceDisplay((Incidence *)which, action);
mDateNavigator->updateView(); //LR
//mDialogManager->updateSearchDialog();
if (which) {
mViewManager->updateWNview();
//mTodoList->updateView();
}
}
void CalendarView::changeIncidenceDisplay(Incidence *which, int action)
{
updateUnmanagedViews();
//qDebug(" CalendarView::changeIncidenceDisplay++++++++++++++++++++++++++ %d %d ",which, action );
if ( action == KOGlobals::EVENTDELETED ) { //delete
mCalendar->checkAlarmForIncidence( 0, true );
if ( mEventViewerDialog )
mEventViewerDialog->hide();
}
else
mCalendar->checkAlarmForIncidence( which , false );
}
// most of the changeEventDisplays() right now just call the view's
// total update mode, but they SHOULD be recoded to be more refresh-efficient.
void CalendarView::changeEventDisplay(Event *which, int action)
{
// kdDebug() << "CalendarView::changeEventDisplay" << endl;
changeIncidenceDisplay((Incidence *)which, action);
static bool clearallviews = false;
if ( KOPrefs::instance()->mGlobalUpdateDisabled ) {
if ( clearallviews ) {
clearAllViews();
clearallviews = false;
}
return;
}
clearallviews = true;
mDateNavigator->updateView();
//mDialogManager->updateSearchDialog();
if (which) {
// If there is an event view visible update the display
mViewManager->currentView()->changeEventDisplay(which,action);
// TODO: check, if update needed
// if (which->getTodoStatus()) {
mTodoList->updateView();
if ( action != KOGlobals::EVENTDELETED ) {
mConflictingEvent = which ;
int time = 1000;
#ifdef DESKTOP_VERSION
time = 500;
#endif
QTimer::singleShot( time, this, SLOT ( checkConflictForEvent() ) );
}
// }
} else {
mViewManager->currentView()->updateView();
}
}
void CalendarView::checkConflictForEvent()
{
if (!KOPrefs::instance()->mConfirm)
return;
if ( ! mConflictingEvent ) return;
Event * conflictingEvent = mConflictingEvent;
mConflictingEvent = 0;
QDateTime current = QDateTime::currentDateTime();
if ( ! conflictingEvent->matchTime( &current, 0 ) ) {
return;
}
QPtrList<Event> testlist = mCalendar->events();
Event * test = testlist.first();
QDateTime conflict;
QDateTime retVal;
bool found = false;
Event * cE = 0;
topLevelWidget()->setCaption( i18n("Checking conflicts ... please wait") );
while ( test ) {
qApp->processEvents();
bool skip = false;
if ( found )
skip = !test->matchTime( &current, &conflict );
else
skip = !test->matchTime( &current, 0 );
if ( !skip && !test->doesFloat() ) {
if ( conflictingEvent->isOverlapping ( test, &retVal, &current ) ) {
if ( ! found ) {
conflict = retVal;
cE = test;
} else {
if ( retVal < conflict ) {
conflict = retVal;
cE = test;
}
}
found = true;
}
}
test = testlist.next();
}
topLevelWidget()->setCaption( i18n("KO/Pi") );
if ( found ) {
QString mess = i18n("The event\n%1\nconflicts with event\n%2\nat date\n%3.\n").arg(KGlobal::formatMessage ( conflictingEvent->summary(),0 ) ).arg( KGlobal::formatMessage ( cE->summary(),0 )).arg(KGlobal::locale()->formatDate(conflict.date()) ) ;
qApp->processEvents();
int km = KMessageBox::warningContinueCancel(this,mess,
i18n("KO/Pi Conflict delected"),i18n("Show date"),i18n("No problem!"));
if ( km != KMessageBox::Continue ) {
return;
}
if ( mViewManager->currentView() != mViewManager->agendaView() || mNavigator->selectedDates().count() > 1 )
mViewManager->showDayView();
mNavigator->slotDaySelect( conflict.date() );
int hour = conflict.time().hour();
mViewManager->agendaView()->setStartHour( hour );
topLevelWidget()->setCaption( i18n("Conflict %1 <-> %2"). arg( conflictingEvent->summary().left( 20 ) ).arg( cE->summary().left( 20 ) ) );
} else
topLevelWidget()->setCaption( i18n("No conflict found") );
return;
}
void CalendarView::updateTodoViews()
{
mTodoList->updateView();
mViewManager->currentView()->updateView();
}
void CalendarView::clearAllViews()
{
mTodoList->clearList();
mViewManager->clearAllViews();
SearchDialog * sd = mDialogManager->getSearchDialog();
if ( sd ) {
KOListView* kol = sd->listview();
if ( kol )
kol->clearList();
}
}
void CalendarView::updateView()
{
static bool clearallviews = false;
if ( KOPrefs::instance()->mGlobalUpdateDisabled ) {
if ( clearallviews ) {
clearAllViews();
clearallviews = false;
}
return;
}
clearallviews = true;
DateList tmpList = mNavigator->selectedDates();
if ( KOPrefs::instance()->mHideNonStartedTodos )
mTodoList->updateView();
// We assume that the navigator only selects consecutive days.
updateView( tmpList.first(), tmpList.last() );
}
void CalendarView::updateUnmanagedViews()
{
mDateNavigator->updateDayMatrix();
}
int CalendarView::msgItemDelete(const QString name)
{
return KMessageBox::warningContinueCancel(this,name +"\n\n"+
i18n("This item will be\npermanently deleted."),
i18n("KO/Pi Confirmation"),i18n("Delete"));
}
void CalendarView::edit_cut()
{
Event *anEvent=0;
Incidence *incidence = mViewManager->currentView()->selectedIncidences().first();
if (mViewManager->currentView()->isEventView()) {
if ( incidence && incidence->typeID() == eventID ) {
anEvent = static_cast<Event *>(incidence);
}
}
if (!anEvent) {
KNotifyClient::beep();
return;
}
DndFactory factory( mCalendar );
factory.cutIncidence(anEvent);
changeEventDisplay(anEvent, KOGlobals::EVENTDELETED);
}
void CalendarView::edit_copy()
{
Event *anEvent=0;
Incidence *incidence = mViewManager->currentView()->selectedIncidences().first();
if (mViewManager->currentView()->isEventView()) {
if ( incidence && incidence->typeID() == eventID ) {
anEvent = static_cast<Event *>(incidence);
}
}
if (!anEvent) {
KNotifyClient::beep();
return;
}
DndFactory factory( mCalendar );
factory.copyIncidence(anEvent);
}
void CalendarView::edit_paste()
{
QDate date = mNavigator->selectedDates().first();
DndFactory factory( mCalendar );
Event *pastedEvent = (Event *)factory.pasteIncidence( date );
changeEventDisplay( pastedEvent, KOGlobals::EVENTADDED );
}
void CalendarView::edit_global_options()
{
QString tz = KPimGlobalPrefs::instance()->mTimeZoneId;
emit save();
emit saveStopTimer();
mDialogManager->showGlobalOptionsDialog();
if ( tz != KPimGlobalPrefs::instance()->mTimeZoneId) {
emit saveStopTimer();
if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel(this, i18n("The timezone has changed!\nShould the calendar be reloaded\nto shift the time of the events?\nPlease read Menu: Help->FAQ:\n\"How do I change the timezone?\"\nas well!"),
i18n("Timezone settings"),i18n("Reload"))) {
qDebug("KO: TZ reload cancelled ");
mCalendar->setTimeZoneId(KPimGlobalPrefs::instance()->mTimeZoneId);
return;
}
qDebug("KO: Timezone change ");
loadCalendars();
setModified(true);
}
else
qDebug("KO: No tz change ");
}
void CalendarView::edit_options()
{
mDialogManager->showOptionsDialog();
}
void CalendarView::slotSelectPickerDate( QDate d)
{
mDateFrame->hide();
if ( mDatePickerMode == 1 ) {
mNavigator->slotDaySelect( d );
} else if ( mDatePickerMode == 2 ) {
if ( mMoveIncidence->typeID() == todoID ) {
Todo * to = (Todo *) mMoveIncidence;
QTime tim;
int len = 0;
if ( to->hasStartDate() && to->hasDueDate() )
len = to->dtStart().secsTo( to->dtDue());
if ( to->hasDueDate() )
tim = to->dtDue().time();
else {
tim = QTime ( 0,0,0 );
to->setFloats( true );
to->setHasDueDate( true );
}
QDateTime dt ( d,tim );
to->setDtDue( dt );
if ( to->hasStartDate() ) {
if ( len>0 )
to->setDtStart(to->dtDue().addSecs( -len ));
else
if (to->dtStart() > to->dtDue() )
to->setDtStart(to->dtDue().addDays( -3 ));
}
todoChanged( to );
} else if ( mMoveIncidence->typeID() == eventID ) {
if ( mMoveIncidence->doesRecur() ) {
#if 0
// PENDING implement this
Incidence* newInc = mMoveIncidence->recreateCloneException( mMoveIncidenceOldDate );
mCalendar()->addIncidence( newInc );
if ( mMoveIncidence->typeID() == todoID )
emit todoMoved((Todo*)mMoveIncidence, KOGlobals::EVENTEDITED );
else
emit incidenceChanged(mMoveIncidence, KOGlobals::EVENTEDITED);
mMoveIncidence = newInc;
#endif
}
QTime tim = mMoveIncidence->dtStart().time();
int secs = mMoveIncidence->dtStart().secsTo( mMoveIncidence->dtEnd());
QDateTime dt ( d,tim );
mMoveIncidence->setDtStart( dt );
((Event*)mMoveIncidence)->setDtEnd( dt.addSecs( secs ) );
changeEventDisplay((Event*)mMoveIncidence, KOGlobals::EVENTEDITED);
} else if ( mMoveIncidence->typeID() == journalID ) {
QTime tim = mMoveIncidence->dtStart().time();
QDateTime dt ( d,tim );
mMoveIncidence->setDtStart( dt );
updateView();
}
mMoveIncidence->setRevision( mMoveIncidence->revision()+1 );
}
}
void CalendarView::removeCategories()
{
QPtrList<Incidence> incList = mCalendar->rawIncidences();
QStringList catList = KOPrefs::instance()->mCustomCategories;
QStringList catIncList;
QStringList newCatList;
Incidence* inc = incList.first();
uint i;
while ( inc ) {
newCatList.clear();
catIncList = inc->categories() ;
for( i = 0; i< catIncList.count(); ++i ) {
if ( catList.contains (catIncList[i]))
newCatList.append( catIncList[i] );
}
newCatList.sort();
inc->setCategories( newCatList.join(",") );
inc = incList.next();
}
}
int CalendarView::addCategories()
{
QPtrList<Incidence> incList = mCalendar->rawIncidences();
QStringList catList = KOPrefs::instance()->mCustomCategories;
QStringList catIncList;
Incidence* inc = incList.first();
uint i;
int count = 0;
while ( inc ) {
catIncList = inc->categories() ;
for( i = 0; i< catIncList.count(); ++i ) {
if ( !catList.contains (catIncList[i])) {
catList.append( catIncList[i] );
//qDebug("add cat %s ", catIncList[i].latin1());
++count;
}
}
inc = incList.next();
}
catList.sort();
KOPrefs::instance()->mCustomCategories = catList;
return count;
}
void CalendarView::editCategories()
{
qDebug("CalendarView::editCategories() ");
KPIM::CategoryEditDialog ced (KOPrefs::instance(),this );
ced.exec();
}
void CalendarView::manageCategories()
{
KOCatPrefs* cp = new KOCatPrefs();
cp->show();
int w =cp->sizeHint().width() ;
int h = cp->sizeHint().height() ;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
cp->setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
if ( !cp->exec() ) {
delete cp;
return;
}
int count = 0;
if ( cp->addCat() ) {
count = addCategories();
if ( count ) {
topLevelWidget()->setCaption(QString::number( count )+ i18n(" Categories added to list! "));
writeSettings();
} else
topLevelWidget()->setCaption(QString::number( 0 )+ i18n(" Categories added to list! "));
} else {
removeCategories();
updateView();
}
delete cp;
}
void CalendarView::beamIncidence(Incidence * Inc)
{
QPtrList<Incidence> delSel ;
delSel.append(Inc);
beamIncidenceList( delSel );
}
void CalendarView::beamCalendar()
{
QPtrList<Incidence> delSel = mCalendar->rawIncidences();
//qDebug("beamCalendar() ");
beamIncidenceList( delSel );
}
void CalendarView::beamFilteredCalendar()
{
QPtrList<Incidence> delSel = mCalendar->incidences();
//qDebug("beamFilteredCalendar() ");
beamIncidenceList( delSel );
}
void CalendarView::beamIncidenceList(QPtrList<Incidence> delSel )
{
KOBeamPrefs beamDialog;
if ( beamDialog.exec () == QDialog::Rejected )
return;
#ifdef DESKTOP_VERSION
QString fn = locateLocal( "tmp", "kopibeamfile" );
#else
QString fn = "/tmp/kopibeamfile";
#endif
QString mes;
bool createbup = true;
if ( createbup ) {
QString description = "\n";
CalendarLocal* cal = new CalendarLocal();
if ( beamDialog.beamLocal() )
cal->setLocalTime();
else
cal->setTimeZoneId(KPimGlobalPrefs::instance()->mTimeZoneId);
Incidence *incidence = delSel.first();
bool addText = false;
if ( delSel.count() < 10 )
addText = true;
else {
description.sprintf(i18n(" %d items?"),delSel.count() );
}
while ( incidence ) {
Incidence *in = incidence->clone();
if ( ! in->summary().isEmpty() ) {
in->setDescription("");
} else {
in->setSummary( in->description().left(20));
in->setDescription("");
}
if ( addText )
description += in->summary() + "\n";
cal->addIncidence( in );
incidence = delSel.next();
}
if ( beamDialog.beamVcal() ) {
fn += ".vcs";
FileStorage storage( cal, fn, new VCalFormat );
storage.save();
} else {
fn += ".ics";
FileStorage storage( cal, fn, new ICalFormat( ) );
storage.save();
}
delete cal;
mes = i18n("KO/Pi: Ready for beaming");
topLevelWidget()->setCaption(mes);
KApplication::convert2latin1( fn );
#ifndef DESKTOP_VERSION
Ir *ir = new Ir( this );
connect( ir, SIGNAL( done( Ir * ) ), this, SLOT( beamDone( Ir * ) ) );
ir->send( fn, description, "text/x-vCalendar" );
#endif
}
}
#ifndef DESKTOP_VERSION
void CalendarView::beamDone( Ir *ir )
{
delete ir;
topLevelWidget()->setCaption( i18n("KO/Pi: Beaming done.") );
topLevelWidget()->raise();
}
#else
void CalendarView::beamDone( Ir *){;}
#endif
void CalendarView::moveIncidence(Incidence * inc )
{
if ( !inc ) return;
showDatePickerPopup();
mDatePickerMode = 2;
mMoveIncidence = inc ;
QDate da;
if ( mMoveIncidence->typeID() == todoID ) {
Todo * to = (Todo *) mMoveIncidence;
if ( to->hasDueDate() )
da = to->dtDue().date();
else
da = QDate::currentDate();
} else {
da = mMoveIncidence->dtStart().date();
}
//PENDING set date for recurring incidence to date of recurrence
//mMoveIncidenceOldDate;
mDatePicker->setDate( da );
}
void CalendarView::showDatePickerPopup()
{
if ( mDateFrame->isVisible() )
mDateFrame->hide();
else {
int offX = 0, offY = 0;
#ifdef DESKTOP_VERSION
int w =mDatePicker->sizeHint().width() ;
int h = mDatePicker->sizeHint().height() ;
int dw = topLevelWidget()->width();
int dh = topLevelWidget()->height();
offX = topLevelWidget()->x();
offY = topLevelWidget()->y();
#else
int w =mDatePicker->sizeHint().width() ;
int h = mDatePicker->sizeHint().height() ;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
#endif
mDateFrame->setGeometry( (dw-w)/2+offX, (dh - h )/2+offY ,w,h );
mDateFrame->show();
}
}
void CalendarView::showDatePicker( )
{
showDatePickerPopup();
mDatePickerMode = 1;
mDatePicker->setDate( mNavigator->selectedDates().first() );
}
void CalendarView::showEventEditor()
{
#ifdef DESKTOP_VERSION
int x,y,w,h;
x = mEventEditor->geometry().x();
y = mEventEditor->geometry().y();
w = mEventEditor->width();
h = mEventEditor->height();
mEventEditor->show();
mEventEditor->setGeometry(x,y,w,h);
#else
if ( mEventEditor->width() < QApplication::desktop()->width() -60 || mEventEditor->width() > QApplication::desktop()->width() ) {
topLevelWidget()->setCaption( i18n("Recreating edit dialog. Please wait...") );
qDebug("KO: CalendarView: recreate mEventEditor %d %d", mEventEditor->width(), QApplication::desktop()->width() );
qApp->processEvents();
delete mEventEditor;
mEventEditor = mDialogManager->getEventEditor();
topLevelWidget()->setCaption( i18n("") );
}
mEventEditor->showMaximized();
#endif
}
void CalendarView::showTodoEditor()
{
#ifdef DESKTOP_VERSION
int x,y,w,h;
x = mTodoEditor->geometry().x();
y = mTodoEditor->geometry().y();
w = mTodoEditor->width();
h = mTodoEditor->height();
mTodoEditor->show();
mTodoEditor->setGeometry(x,y,w,h);
#else
if ( mTodoEditor->width() < QApplication::desktop()->width() -60|| mTodoEditor->width() > QApplication::desktop()->width() ) {
topLevelWidget()->setCaption( i18n("Recreating edit dialog. Please wait...") );
qDebug("KO: CalendarView: recreate mTodoEditor %d %d ", mTodoEditor->width() ,QApplication::desktop()->width() );
qApp->processEvents();
delete mTodoEditor;
mTodoEditor = mDialogManager->getTodoEditor();
topLevelWidget()->setCaption( i18n("") );
}
mTodoEditor->showMaximized();
#endif
}
void CalendarView::cloneIncidence()
{
Incidence *incidence = currentSelection();
if ( !incidence ) incidence = mTodoList->selectedIncidences().first();
if ( incidence ) {
cloneIncidence(incidence);
}
}
void CalendarView::moveIncidence()
{
Incidence *incidence = currentSelection();
if ( !incidence ) incidence = mTodoList->selectedIncidences().first();
if ( incidence ) {
moveIncidence(incidence);
}
}
void CalendarView::beamIncidence()
{
Incidence *incidence = currentSelection();
if ( !incidence ) incidence = mTodoList->selectedIncidences().first();
if ( incidence ) {
beamIncidence(incidence);
}
}
void CalendarView::toggleCancelIncidence()
{
Incidence *incidence = currentSelection();
if ( !incidence ) incidence = mTodoList->selectedIncidences().first();
if ( incidence ) {
cancelIncidence(incidence);
}
}
void CalendarView::cancelIncidence(Incidence * inc )
{
inc->setCancelled( ! inc->cancelled() );
changeIncidenceDisplay( inc,KOGlobals::EVENTEDITED );
updateView();
}
void CalendarView::cloneIncidence(Incidence * orgInc )
{
Incidence * newInc = orgInc->clone();
newInc->recreate();
if ( newInc->typeID() == todoID ) {
Todo* t = (Todo*) newInc;
bool cloneSub = false;
if ( orgInc->relations().count() ) {
int result = KMessageBox::warningYesNoCancel(this,
i18n("The todo\n%1\nwill be cloned!\nIt has subtodos!\nDo you want to clone\nall subtodos as well?").arg( KGlobal::formatMessage ( newInc->summary(),0 ) ),
i18n("Todo has subtodos"),
i18n("Yes"),
i18n("No"));
if ( result == KMessageBox::Cancel ) {
delete t;
return;
}
if (result == KMessageBox::Yes) cloneSub = true;
}
showTodoEditor();
mTodoEditor->editTodo( t );
if ( mTodoEditor->exec() ) {
if ( cloneSub ) {
orgInc->cloneRelations( t );
mCalendar->addIncidenceBranch( t );
updateView();
} else {
mCalendar->addTodo( t );
updateView();
}
} else {
delete t;
}
}
else if ( newInc->typeID() == eventID ) {
Event* e = (Event*) newInc;
showEventEditor();
mEventEditor->editEvent( e );
if ( mEventEditor->exec() ) {
mCalendar->addEvent( e );
updateView();
} else {
delete e;
}
} if ( newInc->typeID() == journalID ) {
mCalendar->addJournal( (Journal*) newInc );
editJournal( (Journal*) newInc );
}
setActiveWindow();
}
void CalendarView::newEvent()
{
// TODO: Replace this code by a common eventDurationHint of KOBaseView.
KOAgendaView *aView = mViewManager->agendaView();
if (aView) {
if (aView->selectionStart().isValid()) {
if (aView->selectedIsAllDay()) {
newEvent(aView->selectionStart(),aView->selectionEnd(),true);
} else {
newEvent(aView->selectionStart(),aView->selectionEnd());
}
return;
}
}
QDate date = mNavigator->selectedDates().first();
#if 0
QDateTime current = QDateTime::currentDateTime();
if ( date <= current.date() ) {
int hour = current.time().hour() +1;
newEvent( QDateTime( current.date(), QTime( hour, 0, 0 ) ),
QDateTime( current.date(), QTime( hour+ KOPrefs::instance()->mDefaultDuration, 0, 0 ) ) );
} else
#endif
newEvent( QDateTime( date, QTime( KOPrefs::instance()->mStartTime, 0, 0 ) ),
QDateTime( date, QTime( KOPrefs::instance()->mStartTime +
KOPrefs::instance()->mDefaultDuration, 0, 0 ) ) );
}
void CalendarView::newEvent(QDateTime fh)
{
newEvent(fh,
QDateTime(fh.addSecs(3600*KOPrefs::instance()->mDefaultDuration)));
}
void CalendarView::newEvent(QDate dt)
{
newEvent(QDateTime(dt, QTime(0,0,0)),
QDateTime(dt, QTime(0,0,0)), true);
}
void CalendarView::newEvent(QDateTime fromHint, QDateTime toHint)
{
newEvent(fromHint, toHint, false);
}
void CalendarView::newEvent(QDateTime fromHint, QDateTime toHint, bool allDay)
{
showEventEditor();
mEventEditor->newEvent(fromHint,toHint,allDay);
if ( mFilterView->filtersEnabled() ) {
CalFilter *filter = mFilterView->selectedFilter();
if (filter && filter->showCategories()) {
mEventEditor->setCategories(filter->categoryList().join(",") );
}
if ( filter )
mEventEditor->setSecrecy( filter->getSecrecy() );
}
mEventEditor->exec();
setActiveWindow();
}
void CalendarView::todoAdded(Todo * t)
{
changeTodoDisplay ( t ,KOGlobals::EVENTADDED);
updateTodoViews();
}
void CalendarView::todoChanged(Todo * t)
{
emit todoModified( t, 4 );
// updateTodoViews();
}
void CalendarView::todoToBeDeleted(Todo *)
{
//qDebug("todoToBeDeleted(Todo *) ");
updateTodoViews();
}
void CalendarView::todoDeleted()
{
//qDebug(" todoDeleted()");
updateTodoViews();
}
void CalendarView::newTodoDateTime( QDateTime dt, bool allday )
{
showTodoEditor();
mTodoEditor->newTodo(dt,0,allday);
if ( mFilterView->filtersEnabled() ) {
CalFilter *filter = mFilterView->selectedFilter();
if (filter && filter->showCategories()) {
mTodoEditor->setCategories(filter->categoryList().join(",") );
}
if ( filter )
mTodoEditor->setSecrecy( filter->getSecrecy() );
}
mTodoEditor->exec();
setActiveWindow();
}
void CalendarView::newTodo()
{
newTodoDateTime( QDateTime(),true );
}
void CalendarView::newSubTodo()
{
Todo *todo = selectedTodo();
if ( todo ) newSubTodo( todo );
}
void CalendarView::newSubTodo(Todo *parentEvent)
{
showTodoEditor();
mTodoEditor->newTodo(QDateTime(),parentEvent,true);
mTodoEditor->exec();
setActiveWindow();
}
void CalendarView::newFloatingEvent()
{
DateList tmpList = mNavigator->selectedDates();
QDate date = tmpList.first();
newEvent( QDateTime( date, QTime( 12, 0, 0 ) ),
QDateTime( date, QTime( 12, 0, 0 ) ), true );
}
void CalendarView::editEvent( Event *event )
{
if ( !event ) return;
if ( event->isReadOnly() ) {
showEvent( event );
return;
}
showEventEditor();
mEventEditor->editEvent( event , mFlagEditDescription);
mEventEditor->exec();
setActiveWindow();
}
void CalendarView::editJournal( Journal *jour )
{
if ( !jour ) return;
mDialogManager->hideSearchDialog();
mViewManager->showJournalView();
mNavigator->slotDaySelect( jour->dtStart().date() );
}
void CalendarView::editTodo( Todo *todo )
{
if ( !todo ) return;
if ( todo->isReadOnly() ) {
showTodo( todo );
return;
}
showTodoEditor();
mTodoEditor->editTodo( todo ,mFlagEditDescription);
mTodoEditor->exec();
setActiveWindow();
}
KOEventViewerDialog* CalendarView::getEventViewerDialog()
{
if ( !mEventViewerDialog ) {
mEventViewerDialog = new KOEventViewerDialog(0);
connect( mEventViewerDialog, SIGNAL( editIncidence( Incidence* )), this, SLOT(editIncidence( Incidence* ) ) );
connect( this, SIGNAL(configChanged()), mEventViewerDialog, SLOT(updateConfig()));
connect( mEventViewerDialog, SIGNAL(jumpToTime( const QDate &)),
dateNavigator(), SLOT( selectWeek( const QDate & ) ) );
connect( mEventViewerDialog, SIGNAL(showAgendaView( bool ) ),
viewManager(), SLOT( showAgendaView( bool ) ) );
connect( mEventViewerDialog, SIGNAL(signalViewerClosed()),
this, SLOT( slotViewerClosed() ) );
connect( mEventViewerDialog, SIGNAL( todoCompleted(Todo *) ),
this, SLOT( todoChanged(Todo *) ) );
connect( mEventViewerDialog, SIGNAL( showIncidence( QString ) ),SLOT( showIncidence( QString ) ));
mEventViewerDialog->resize( 640, 480 );
}
return mEventViewerDialog;
}
void CalendarView::showEvent(Event *event)
{
getEventViewerDialog()->setEvent(event);
getEventViewerDialog()->showMe();
}
void CalendarView::showTodo(Todo *event)
{
getEventViewerDialog()->setTodo(event);
getEventViewerDialog()->showMe();
}
void CalendarView::showJournal( Journal *jour )
{
getEventViewerDialog()->setJournal(jour);
getEventViewerDialog()->showMe();
}
// void CalendarView::todoModified (Todo *event, int changed)
// {
// // if (mDialogList.find (event) != mDialogList.end ()) {
// // kdDebug() << "Todo modified and open" << endl;
// // KOTodoEditor* temp = (KOTodoEditor *) mDialogList[event];
// // temp->modified (changed);
// // }
// mViewManager->updateView();
// }
void CalendarView::appointment_show()
{
Event *anEvent = 0;
Incidence *incidence = mViewManager->currentView()->selectedIncidences().first();
if (mViewManager->currentView()->isEventView()) {
if ( incidence && incidence->typeID() == eventID ) {
anEvent = static_cast<Event *>(incidence);
}
}
if (!anEvent) {
KNotifyClient::beep();
return;
}
showEvent(anEvent);
}
void CalendarView::appointment_edit()
{
Event *anEvent = 0;
Incidence *incidence = mViewManager->currentView()->selectedIncidences().first();
if (mViewManager->currentView()->isEventView()) {
if ( incidence && incidence->typeID() == eventID ) {
anEvent = static_cast<Event *>(incidence);
}
}
if (!anEvent) {
KNotifyClient::beep();
return;
}
editEvent(anEvent);
}
void CalendarView::appointment_delete()
{
Event *anEvent = 0;
Incidence *incidence = mViewManager->currentView()->selectedIncidences().first();
if (mViewManager->currentView()->isEventView()) {
if ( incidence && incidence->typeID() == eventID ) {
anEvent = static_cast<Event *>(incidence);
}
}
if (!anEvent) {
KNotifyClient::beep();
return;
}
deleteEvent(anEvent);
}
void CalendarView::todo_resub( Todo * parent, Todo * sub )
{
if (!sub) return;
if ( sub->relatedTo() == parent )
return;
sub->setRelatedTo(parent);
sub->updated();
setModified(true);
updateView();
}
void CalendarView::todo_unsub(Todo *anTodo )
{
todo_resub( 0, anTodo );
}
void CalendarView::deleteTodo(Todo *todo)
{
if (!todo) {
KNotifyClient::beep();
return;
}
if (KOPrefs::instance()->mConfirm) {
QString text = KGlobal::formatMessage ( todo->summary(),0 );
if (!todo->relations().isEmpty()) {
text += i18n("\nhas sub-todos.\nAll completed sub-todos\nwill be deleted as well!");
}
switch (msgItemDelete(i18n("Todo:") +"\n"+text)) {
case KMessageBox::Continue: // OK
bool deleteT = false;
if (!todo->relations().isEmpty()) {
deleteT = removeCompletedSubTodos( todo );
}
// deleteT == true: todo already deleted in removeCompletedSubTodos
if ( !deleteT ) {
checkExternalId( todo );
calendar()->deleteTodo(todo);
changeTodoDisplay( todo,KOGlobals::EVENTDELETED );
updateView();
}
break;
} // switch
} else {
checkExternalId( todo );
mCalendar->deleteTodo(todo);
changeTodoDisplay( todo,KOGlobals::EVENTDELETED );
updateView();
}
emit updateSearchDialog();
}
void CalendarView::deleteJournal(Journal *jour)
{
if (!jour) {
KNotifyClient::beep();
return;
}
if (KOPrefs::instance()->mConfirm) {
QString des;
if ( !jour->summary().isEmpty() ) {
des = jour->summary();
} else {
des = jour->description().left(30);
des = des.simplifyWhiteSpace ();
des.replace (QRegExp ("\\n"),"" );
des.replace (QRegExp ("\\r"),"" );
}
switch (msgItemDelete( i18n("Journal:") +"\n"+KGlobal::formatMessage ( des,0 ))) {
case KMessageBox::Continue: // OK
calendar()->deleteJournal(jour);
updateView();
break;
} // switch
} else {
calendar()->deleteJournal(jour);;
updateView();
}
emit updateSearchDialog();
}
void CalendarView::deleteEvent(Event *anEvent)
{
if (!anEvent) {
KNotifyClient::beep();
return;
}
- if (anEvent->recurrence()->doesRecur()) {
+ if (anEvent->doesRecur()) {
QDate itemDate = mViewManager->currentSelectionDate();
int km;
if (!itemDate.isValid()) {
//kdDebug() << "Date Not Valid" << endl;
if (KOPrefs::instance()->mConfirm) {
km = KMessageBox::warningContinueCancel(this,KGlobal::formatMessage ( anEvent->summary(),0 ) +
i18n("\nThis event recurs\nover multiple dates.\nAre you sure you want\nto delete this event\nand all its recurrences?"),
i18n("KO/Pi Confirmation"),i18n("Delete All"));
if ( km == KMessageBox::Continue )
km = KMessageBox::No; // No = all below
} else
km = KMessageBox::No;
} else {
km = KMessageBox::warningYesNoCancel(this,KGlobal::formatMessage ( anEvent->summary(),0 ) +
i18n("\nThis event recurs\nover multiple dates.\nDo you want to delete\nall it's recurrences,\nor only the current one on:\n")+
KGlobal::locale()->formatDate(itemDate)+i18n(" ?\n\nDelete:\n"),
i18n("KO/Pi Confirmation"),i18n("Current"),
i18n("All"));
}
switch(km) {
case KMessageBox::No: // Continue // all
//qDebug("KMessageBox::No ");
if (anEvent->organizer()==KOPrefs::instance()->email() && anEvent->attendeeCount()>0)
schedule(Scheduler::Cancel,anEvent);
checkExternalId( anEvent);
mCalendar->deleteEvent(anEvent);
changeEventDisplay(anEvent,KOGlobals::EVENTDELETED);
break;
// Disabled because it does not work
//#if 0
case KMessageBox::Yes: // just this one
//QDate qd = mNavigator->selectedDates().first();
//if (!qd.isValid()) {
// kdDebug() << "no date selected, or invalid date" << endl;
// KNotifyClient::beep();
// return;
//}
//while (!anEvent->recursOn(qd)) qd = qd.addDays(1);
if (itemDate!=QDate(1,1,1) || itemDate.isValid()) {
anEvent->addExDate(itemDate);
int duration = anEvent->recurrence()->duration();
if ( duration > 0 ) {
anEvent->recurrence()->setDuration( duration - 1 );
}
changeEventDisplay(anEvent, KOGlobals::EVENTEDITED);
}
break;
//#endif
} // switch
} else {
if (KOPrefs::instance()->mConfirm) {
switch (KMessageBox::warningContinueCancel(this,KGlobal::formatMessage ( anEvent->summary(),0 ) +
i18n("\nAre you sure you want\nto delete this event?"),
i18n("KO/Pi Confirmation"),i18n("Delete"))) {
case KMessageBox::Continue: // OK
if (anEvent->organizer()==KOPrefs::instance()->email() && anEvent->attendeeCount()>0)
schedule(Scheduler::Cancel,anEvent);
checkExternalId( anEvent);
mCalendar->deleteEvent(anEvent);
changeEventDisplay(anEvent, KOGlobals::EVENTDELETED);
break;
} // switch
} else {
if (anEvent->organizer()==KOPrefs::instance()->email() && anEvent->attendeeCount()>0)
schedule(Scheduler::Cancel,anEvent);
checkExternalId( anEvent);
mCalendar->deleteEvent(anEvent);
changeEventDisplay(anEvent, KOGlobals::EVENTDELETED);
}
} // if-else
emit updateSearchDialog();
}
bool CalendarView::deleteEvent(const QString &uid)
{
Event *ev = mCalendar->event(uid);
if (ev) {
deleteEvent(ev);
return true;
} else {
return false;
}
}
/*****************************************************************************/
void CalendarView::action_mail()
{
#ifndef KORG_NOMAIL
KOMailClient mailClient;
Incidence *incidence = currentSelection();
if (!incidence) {
KMessageBox::sorry(this,i18n("Can't generate mail:\nNo event selected."));
return;
}
if(incidence->attendeeCount() == 0 ) {
KMessageBox::sorry(this,
i18n("Can't generate mail:\nNo attendees defined.\n"));
return;
}
CalendarLocal cal_tmp;
Event *event = 0;
Event *ev = 0;
if ( incidence && incidence->typeID() == eventID ) {
event = static_cast<Event *>(incidence);
ev = new Event(*event);
cal_tmp.addEvent(ev);
}
ICalFormat mForm();
QString attachment = mForm.toString( &cal_tmp );
if (ev) delete(ev);
mailClient.mailAttendees(currentSelection(), attachment);
#endif
#if 0
Event *anEvent = 0;
if (mViewManager->currentView()->isEventView()) {
anEvent = dynamic_cast<Event *>((mViewManager->currentView()->selectedIncidences()).first());
}
if (!anEvent) {
KMessageBox::sorry(this,i18n("Can't generate mail:\nNo event selected."));
return;
}
if(anEvent->attendeeCount() == 0 ) {
KMessageBox::sorry(this,
i18n("Can't generate mail:\nNo attendees defined.\n"));
return;
}
mailobject.emailEvent(anEvent);
#endif
}
void CalendarView::schedule_publish(Incidence *incidence)
{
Event *event = 0;
Todo *todo = 0;
if (incidence == 0) {
incidence = mViewManager->currentView()->selectedIncidences().first();
if (incidence == 0) {
incidence = mTodoList->selectedIncidences().first();
}
}
if ( incidence && incidence->typeID() == eventID ) {
event = static_cast<Event *>(incidence);
} else {
if ( incidence && incidence->typeID() == todoID ) {
todo = static_cast<Todo *>(incidence);
}
}
if (!event && !todo) {
KMessageBox::sorry(this,i18n("No event selected."));
return;
}
PublishDialog *publishdlg = new PublishDialog();
if (incidence->attendeeCount()>0) {
QPtrList<Attendee> attendees = incidence->attendees();
attendees.first();
while ( attendees.current()!=0 ) {
publishdlg->addAttendee(attendees.current());
attendees.next();
}
}
bool send = true;
if ( KOPrefs::instance()->mMailClient == KOPrefs::MailClientSendmail ) {
if ( publishdlg->exec() != QDialog::Accepted )
send = false;
}
if ( send ) {
OutgoingDialog *dlg = mDialogManager->outgoingDialog();
if ( event ) {
Event *ev = new Event(*event);
ev->registerObserver(0);
ev->clearAttendees();
if (!dlg->addMessage(ev,Scheduler::Publish,publishdlg->addresses())) {
delete(ev);
}
} else {
if ( todo ) {
Todo *ev = new Todo(*todo);
ev->registerObserver(0);
ev->clearAttendees();
if (!dlg->addMessage(ev,Scheduler::Publish,publishdlg->addresses())) {
delete(ev);
}
}
}
}
delete publishdlg;
}
void CalendarView::schedule_request(Incidence *incidence)
{
schedule(Scheduler::Request,incidence);
}
void CalendarView::schedule_refresh(Incidence *incidence)
{
schedule(Scheduler::Refresh,incidence);
}
void CalendarView::schedule_cancel(Incidence *incidence)
{
schedule(Scheduler::Cancel,incidence);
}
void CalendarView::schedule_add(Incidence *incidence)
{
schedule(Scheduler::Add,incidence);
}
void CalendarView::schedule_reply(Incidence *incidence)
{
schedule(Scheduler::Reply,incidence);
}
void CalendarView::schedule_counter(Incidence *incidence)
{
schedule(Scheduler::Counter,incidence);
}
void CalendarView::schedule_declinecounter(Incidence *incidence)
{
schedule(Scheduler::Declinecounter,incidence);
}
void CalendarView::schedule_publish_freebusy(int daysToPublish)
{
QDateTime start = QDateTime::currentDateTime();
QDateTime end = start.addDays(daysToPublish);
FreeBusy *freebusy = new FreeBusy(mCalendar, start, end);
freebusy->setOrganizer(KOPrefs::instance()->email());
PublishDialog *publishdlg = new PublishDialog();
if ( publishdlg->exec() == QDialog::Accepted ) {
OutgoingDialog *dlg = mDialogManager->outgoingDialog();
if (!dlg->addMessage(freebusy,Scheduler::Publish,publishdlg->addresses())) {
delete(freebusy);
}
}
delete publishdlg;
}
void CalendarView::schedule(Scheduler::Method method, Incidence *incidence)
{
Event *event = 0;
Todo *todo = 0;
if (incidence == 0) {
incidence = mViewManager->currentView()->selectedIncidences().first();
if (incidence == 0) {
incidence = mTodoList->selectedIncidences().first();
}
}
if ( incidence && incidence->typeID() == eventID ) {
event = static_cast<Event *>(incidence);
}
if ( incidence && incidence->typeID() == todoID ) {
todo = static_cast<Todo *>(incidence);
}
if (!event && !todo) {
KMessageBox::sorry(this,i18n("No event selected."));
return;
}
if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) {
KMessageBox::sorry(this,i18n("The event has no attendees."));
return;
}
Event *ev = 0;
if (event) ev = new Event(*event);
Todo *to = 0;
if (todo) to = new Todo(*todo);
if (method == Scheduler::Reply || method == Scheduler::Refresh) {
Attendee *me = incidence->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email());
if (!me) {
KMessageBox::sorry(this,i18n("Could not find your attendee entry.\nPlease check the emails."));
return;
}
if (me->status()==Attendee::NeedsAction && me->RSVP() && method==Scheduler::Reply) {
StatusDialog *statdlg = new StatusDialog(this);
if (!statdlg->exec()==QDialog::Accepted) return;
me->setStatus( statdlg->status() );
delete(statdlg);
}
Attendee *menew = new Attendee(*me);
if (ev) {
ev->clearAttendees();
ev->addAttendee(menew,false);
} else {
if (to) {
todo->clearAttendees();
todo->addAttendee(menew,false);
}
}
}
OutgoingDialog *dlg = mDialogManager->outgoingDialog();
if (ev) {
if ( !dlg->addMessage(ev,method) ) delete(ev);
} else {
if (to) {
if ( !dlg->addMessage(to,method) ) delete(to);
}
}
}
void CalendarView::openAddressbook()
{
KRun::runCommand("kaddressbook");
}
void CalendarView::setModified(bool modified)
{
//qDebug("CalendarView::setModified %d ", modified);
if ( modified )
emit signalmodified();
mModified = modified;
if ( mModified )
emit modifiedChanged(mModified);
}
bool CalendarView::isReadOnly()
{
return mReadOnly;
}
void CalendarView::setReadOnly(bool readOnly)
{
if (mReadOnly != readOnly) {
mReadOnly = readOnly;
emit readOnlyChanged(mReadOnly);
}
}
bool CalendarView::isModified()
{
return mModified;
}
void CalendarView::slotprintSelInc()
{
if ( currentSelection() == 0 ) {
KMessageBox::sorry(this,i18n("There is nothing selected!"));
return;
}
showIncidence();
getEventViewerDialog()->print();
}
void CalendarView::printSetup()
{
#ifndef KORG_NOPRINTER
createPrinter();
mCalPrinter->setupPrinter();
#endif
}
void CalendarView::print()
{
#ifndef KORG_NOPRINTER
createPrinter();
DateList tmpDateList = mNavigator->selectedDates();
mCalPrinter->print(CalPrinter::Month,
tmpDateList.first(), tmpDateList.last());
#endif
}
void CalendarView::printPreview()
{
#ifndef KORG_NOPRINTER
kdDebug() << "CalendarView::printPreview()" << endl;
createPrinter();
DateList tmpDateList = mNavigator->selectedDates();
mViewManager->currentView()->printPreview(mCalPrinter,tmpDateList.first(),
tmpDateList.last());
#endif
}
void CalendarView::exportICalendar()
{
QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
// Force correct extension
if (filename.right(4) != ".ics") filename += ".ics";
FileStorage storage( mCalendar, filename, new ICalFormat() );
storage.save();
}
bool CalendarView::exportVCalendar( QString filename )
{
if (mCalendar->journals().count() > 0) {
int result = KMessageBox::warningContinueCancel(this,
i18n("The journal entries can not be\nexported to a vCalendar file."),
i18n("Data Loss Warning"),i18n("Proceed"),i18n("Cancel"),
true);
if (result != KMessageBox::Continue) return false;
}
//QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|VCalendars"),this);
// Force correct extension
if (filename.right(4) != ".vcs") filename += ".vcs";
FileStorage storage( mCalendar, filename, new VCalFormat );
return storage.save();
}
void CalendarView::eventUpdated(Incidence *)
{
setModified();
// Don't call updateView here. The code, which has caused the update of the
// event is responsible for updating the view.
// updateView();
}
void CalendarView::adaptNavigationUnits()
{
if (mViewManager->currentView()->isEventView()) {
int days = mViewManager->currentView()->currentDateCount();
if (days == 1) {
emit changeNavStringPrev(i18n("&Previous Day"));
emit changeNavStringNext(i18n("&Next Day"));
} else {
emit changeNavStringPrev(i18n("&Previous Week"));
emit changeNavStringNext(i18n("&Next Week"));
}
}
}
void CalendarView::processMainViewSelection( Incidence *incidence )
{
if ( incidence ) mTodoList->clearSelection();
processIncidenceSelection( incidence );
}
void CalendarView::processTodoListSelection( Incidence *incidence )
{
if ( incidence && mViewManager->currentView() ) {
mViewManager->currentView()->clearSelection();
}
processIncidenceSelection( incidence );
}
void CalendarView::processIncidenceSelection( Incidence *incidence )
{
emit incidenceSelected( incidence );
if ( incidence == mSelectedIncidence ) return;
mSelectedIncidence = incidence;
if ( incidence && incidence->typeID() == eventID ) {
Event *event = static_cast<Event *>( incidence );
if ( event->organizer() == KOPrefs::instance()->email() ) {
emit organizerEventsSelected( true );
} else {
emit organizerEventsSelected(false);
}
if (event->attendeeByMails( KOPrefs::instance()->mAdditionalMails,
KOPrefs::instance()->email() ) ) {
emit groupEventsSelected( true );
} else {
emit groupEventsSelected(false);
}
return;
} else {
if ( incidence && incidence->typeID() == todoID ) {
emit todoSelected( true );
Todo *event = static_cast<Todo *>( incidence );
if ( event->organizer() == KOPrefs::instance()->email() ) {
emit organizerEventsSelected( true );
} else {
emit organizerEventsSelected(false);
}
if (event->attendeeByMails( KOPrefs::instance()->mAdditionalMails,
KOPrefs::instance()->email() ) ) {
emit groupEventsSelected( true );
} else {
emit groupEventsSelected(false);
}
return;
} else {
emit todoSelected( false );
emit organizerEventsSelected(false);
emit groupEventsSelected(false);
}
return;
}
/* if ( incidence && incidence->typeID() == todoID ) {
emit todoSelected( true );
} else {
emit todoSelected( false );
}*/
}
void CalendarView::checkClipboard()
{
#ifndef KORG_NODND
if (ICalDrag::canDecode(QApplication::clipboard()->data())) {
emit pasteEnabled(true);
} else {
emit pasteEnabled(false);
}
#endif
}
void CalendarView::showDates(const DateList &selectedDates)
{
// kdDebug() << "CalendarView::selectDates()" << endl;
if ( !mBlockShowDates ) {
if ( mViewManager->currentView() ) {
updateView( selectedDates.first(), selectedDates.last() );
} else {
mViewManager->showAgendaView();
}
}
QDate date = selectedDates.first();
if ( ! date.isValid() ) {
topLevelWidget()->setCaption("");
return;
}
QString selDates;
selDates = KGlobal::locale()->formatDate( date, true);
if (selectedDates.first() < selectedDates.last() )
selDates += " - " + KGlobal::locale()->formatDate( selectedDates.last(),true);
else {
QString addString;
if ( date == QDateTime::currentDateTime().date() )
addString = i18n("Today");
else if ( date == QDateTime::currentDateTime().date().addDays(1) )
addString = i18n("Tomorrow");
else if ( date == QDateTime::currentDateTime().date().addDays(-1) )
addString = i18n("Yesterday");
else if ( date == QDateTime::currentDateTime().date().addDays(-2) )
addString = i18n("Day before yesterday");
else if ( date == QDateTime::currentDateTime().date().addDays(2) )
addString = i18n("Day after tomorrow");
if ( !addString.isEmpty() ) {
topLevelWidget()->setCaption( addString+", " + selDates );
return;
}
}
topLevelWidget()->setCaption( i18n("Dates: ") + selDates );
}
QPtrList<CalFilter> CalendarView::filters()
{
return mFilters;
}
void CalendarView::editFilters()
{
// kdDebug() << "CalendarView::editFilters()" << endl;
CalFilter *filter = mFilters.first();
while(filter) {
filter = mFilters.next();
}
mDialogManager->showFilterEditDialog(&mFilters);
updateFilter();
}
void CalendarView::toggleFilter()
{
if ( mLeftFrame->isHidden() ) {
toggleExpand();
showFilter( true );
} else
showFilter(! mCalEditView->isVisible());
}
KOFilterView *CalendarView::filterView()
{
return mFilterView;
}
void CalendarView::selectFilter( int fil )
{
mFilterView->setSelectedFilter( fil );
updateUnmanagedViews();
}
void CalendarView::showFilter(bool visible)
{
#if 1
if (visible) {
mCalEditView->readConfig();
mCalEditView->show();
QValueList<int> sizes;
sizes = mLeftFrame->sizes();
if ( sizes.count() == 4 && sizes[3] < 20 ) {
sizes.clear();
sizes << 100;
sizes << 0;
sizes << 0;
sizes << 100;
mLeftFrame->setSizes(sizes);
}
#if 0
sizes = mLeftFrame->sizes();
int ccc = 0;
while ( ccc < sizes.count()) {
qDebug("size %d %d ", ccc, sizes[ccc]);
++ccc;
}
#endif
}
else {
mCalEditView->hide();
}
#else
if (visible) mFilterView->show();
else mFilterView->hide();
#endif
}
void CalendarView::toggleFilerEnabled( )
{
mFilterView->setFiltersEnabled ( !mFilterView->filtersEnabled() );
if ( !mFilterView->filtersEnabled() )
topLevelWidget()->setCaption( i18n("Filter disabled ") );
updateUnmanagedViews();
}
void CalendarView::updateFilter()
{
CalFilter *filter = mFilterView->selectedFilter();
if (filter) {
QString mess;
if (mFilterView->filtersEnabled()) {
mess = i18n("Filter selected: ")+filter->name();
filter->setEnabled(true);
}
else filter->setEnabled(false);
mCalendar->setFilter(filter);
updateView();
if ( !mess.isEmpty() )
topLevelWidget()->setCaption( mess );
}
emit filtersUpdated();
}
void CalendarView::filterEdited()
{
mFilterView->updateFilters();
updateFilter();
writeSettings();
}
void CalendarView::takeOverEvent()
{
Incidence *incidence = currentSelection();
if (!incidence) return;
incidence->setOrganizer(KOPrefs::instance()->email());
incidence->recreate();
incidence->setReadOnly(false);
updateView();
}
void CalendarView::takeOverCalendar()
{
// TODO: Create Calendar::allIncidences() function and use it here
clearAllViews();
QPtrList<Event> events = mCalendar->events();
for(uint i=0; i<events.count(); ++i) {
events.at(i)->setOrganizer(KOPrefs::instance()->email());
events.at(i)->recreate();
events.at(i)->setReadOnly(false);
}
QPtrList<Todo> todos = mCalendar->todos();
for(uint i=0; i<todos.count(); ++i) {
todos.at(i)->setOrganizer(KOPrefs::instance()->email());
todos.at(i)->recreate();
todos.at(i)->setReadOnly(false);
}
QPtrList<Journal> journals = mCalendar->journals();
for(uint i=0; i<journals.count(); ++i) {
journals.at(i)->setOrganizer(KOPrefs::instance()->email());
journals.at(i)->recreate();
journals.at(i)->setReadOnly(false);
}
updateView();
}
void CalendarView::showIntro()
{
kdDebug() << "To be implemented." << endl;
}
QWidgetStack *CalendarView::viewStack()
{
return mRightFrame;
}
QWidget *CalendarView::leftFrame()
{
return ( QWidget *)mLeftFrame;
}
DateNavigator *CalendarView::dateNavigator()
{
return mNavigator;
}
KDateNavigator* CalendarView::dateNavigatorWidget()
{
return mDateNavigator->navigatorView();
}
void CalendarView::toggleDateNavigatorWidget()
{
KOPrefs::instance()->mShowDateNavigator = !KOPrefs::instance()->mShowDateNavigator ;
if (!KOPrefs::instance()->mShowDateNavigator )
mDateNavigator->hide();
else
mDateNavigator->show();
}
void CalendarView::addView(KOrg::BaseView *view)
{
mViewManager->addView(view);
}
void CalendarView::showView(KOrg::BaseView *view)
{
mViewManager->showView(view, mLeftFrame->isVisible());
}
Incidence *CalendarView::currentSelection()
{
return mViewManager->currentSelection();
}
void CalendarView::toggleAllDaySize()
{
/*
if ( KOPrefs::instance()->mAllDaySize > 47 )
KOPrefs::instance()->mAllDaySize = KOPrefs::instance()->mAllDaySize /2;
else
KOPrefs::instance()->mAllDaySize = KOPrefs::instance()->mAllDaySize *2;
*/
viewManager()->agendaView()->toggleAllDay();
}
void CalendarView::toggleExpand()
{
// if ( mLeftFrame->isHidden() ) {
// mLeftFrame->show();
// emit calendarViewExpanded( false );
// } else {
// mLeftFrame->hide();
// emit calendarViewExpanded( true );
// }
//qDebug(" CalendarView::toggleExpand()");
globalFlagBlockAgenda = 1;
emit calendarViewExpanded( !mLeftFrame->isHidden() );
globalFlagBlockAgenda = 5;
mViewManager->raiseCurrentView( !mLeftFrame->isHidden() );
//mViewManager->showView( 0, true );
}
void CalendarView::calendarModified( bool modified, Calendar * )
{
setModified( modified );
}
Todo *CalendarView::selectedTodo()
{
Incidence *incidence = currentSelection();
if ( incidence && incidence->typeID() == todoID ) {
return static_cast<Todo *>( incidence );
}
incidence = mTodoList->selectedIncidences().first();
if ( incidence && incidence->typeID() == todoID ) {
return static_cast<Todo *>( incidence );
}
return 0;
}
void CalendarView::showIncidence()
{
mViewerCallerIsSearchDialog = false;
Incidence *incidence = currentSelection();
if ( !incidence ) incidence = mTodoList->selectedIncidences().first();
if ( incidence ) {
ShowIncidenceVisitor v;
v.act( incidence, this );
}
}
void CalendarView::editIncidenceDescription()
{
mFlagEditDescription = true;
editIncidence();
mFlagEditDescription = false;
}
void CalendarView::editIncidence()
{
// qDebug("editIncidence() ");
Incidence *incidence = currentSelection();
if ( !incidence ) incidence = mTodoList->selectedIncidences().first();
if ( incidence ) {
EditIncidenceVisitor v;
v.act( incidence, this );
}
}
void CalendarView::deleteIncidence()
{
Incidence *incidence = currentSelection();
if ( !incidence ) incidence = mTodoList->selectedIncidences().first();
if ( incidence ) {
deleteIncidence(incidence);
}
}
void CalendarView::showIncidence(QString uid)
{
Incidence *inc = mCalendar->incidence( uid );
if ( inc )
showIncidence( inc );
}
void CalendarView::showIncidence(Incidence *incidence)
{
mViewerCallerIsSearchDialog = false;
//qDebug("%x %x ",sender (), mDialogManager->getSearchDialog() );
if ( sender() && mDialogManager->getSearchDialog() ) {
if ( sender () == mDialogManager->getSearchDialog()->listview() ) {
mViewerCallerIsSearchDialog = true;
}
}
if ( incidence ) {
ShowIncidenceVisitor v;
v.act( incidence, this );
}
}
void CalendarView::editIncidence(Incidence *incidence)
{
if ( incidence ) {
EditIncidenceVisitor v;
v.act( incidence, this );
}
}
void CalendarView::deleteIncidence(Incidence *incidence)
{
//qDebug(" CalendarView::deleteIncidence ");
if ( incidence == 0 ) {
updateView();
emit updateSearchDialog();
return;
}
if ( incidence ) {
DeleteIncidenceVisitor v;
v.act( incidence, this );
}
}
void CalendarView::lookForOutgoingMessages()
{
OutgoingDialog *ogd = mDialogManager->outgoingDialog();
ogd->loadMessages();
}
void CalendarView::lookForIncomingMessages()
{
IncomingDialog *icd = mDialogManager->incomingDialog();
icd->retrieve();
}
bool CalendarView::removeCompletedSubTodos( Todo* t )
{
bool deleteTodo = true;
QPtrList<Incidence> subTodos;
Incidence *aTodo;
subTodos = t->relations();
for (aTodo = subTodos.first(); aTodo; aTodo = subTodos.next()) {
if (! removeCompletedSubTodos( (Todo*) aTodo ))
deleteTodo = false;
}
if ( deleteTodo ) {
if ( t->isCompleted() && !t->doesRecur()) {
checkExternalId( t );
mCalendar->deleteTodo( t );
changeTodoDisplay( t,KOGlobals::EVENTDELETED );
}
else
deleteTodo = false;
}
return deleteTodo;
}
void CalendarView::purgeCompleted()
{
int result = KMessageBox::warningContinueCancel(this,
i18n("Delete all completed todos?\n(Completed recurring todos\nwill not be deleted!)"),i18n("Purge Todos"),i18n("Purge"));
if (result == KMessageBox::Continue) {
QPtrList<Todo> todoCal;
QPtrList<Todo> rootTodos;
//QPtrList<Incidence> rel;
Todo *aTodo;
todoCal = calendar()->todos();
for (aTodo = todoCal.first(); aTodo; aTodo = todoCal.next()) {
if ( !aTodo->relatedTo() )
rootTodos.append( aTodo );
}
for (aTodo = rootTodos.first(); aTodo; aTodo = rootTodos.next()) {
removeCompletedSubTodos( aTodo );
}
updateView();
}
}
void CalendarView::slotCalendarChanged()
{
;
}
void CalendarView::keyPressEvent ( QKeyEvent *e)
{
//qDebug("CalendarView::keyPressEvent ");
e->ignore();
}
bool CalendarView::sync(KSyncManager* manager, QString filename, int mode)
{
if ( manager != mSyncManager)
qDebug("KO: Internal error-1. SyncManager mismatch ");
if ( filename == QDir::homeDirPath ()+"/.kdecalendardump.ics" ) {
qDebug("KO: SyncKDE request detected!");
}
mCurrentSyncDevice = mSyncManager->getCurrentSyncDevice();
mCurrentSyncName = mSyncManager->getCurrentSyncName();
return syncCalendar( filename, mode );
}
bool CalendarView::syncExternal(KSyncManager* manager, QString resource)
{
//mSyncManager = manager;
if ( manager != mSyncManager)
qDebug("KO: Internal error-2. SyncManager mismatch ");
mCurrentSyncDevice = mSyncManager->getCurrentSyncDevice();
mCurrentSyncName = mSyncManager->getCurrentSyncName();
if ( resource == "sharp" )
syncExternal( 0 );
if ( resource == "phone" )
syncExternal( 1 );
// pending setmodified
return true;
}
void CalendarView::setSyncManager(KSyncManager* manager)
{
mSyncManager = manager;
}
void CalendarView::removeSyncInfo( QString syncProfile)
{
qDebug("KO: removeSyncInfo for profile %s ", syncProfile.latin1());
mCalendar->removeSyncInfo( syncProfile );
}
void CalendarView::undo_delete()
{
//qDebug("undo_delete() ");
Incidence* undo = mCalendar->undoIncidence();
if ( !undo ) {
KMessageBox::sorry(this,i18n("There is nothing to undo!"),
i18n("KO/Pi"));
return;
}
if ( KMessageBox::Continue ==KMessageBox::warningContinueCancel(this,KGlobal::formatMessage ( undo->summary(),0 ) +
i18n("\nAre you sure you want\nto restore this?"),
i18n("KO/Pi Confirmation"),i18n("Restore"))) {
mCalendar->undoDeleteIncidence();
updateView();
}
}
void CalendarView::slotViewerClosed()
{
QTimer::singleShot( 50, this, SLOT ( resetFocus() ) );
}
void CalendarView::resetFocus()
{
if ( mViewerCallerIsSearchDialog ) {
if ( mDialogManager->getSearchDialog()->isVisible() ){
mDialogManager->getSearchDialog()->raise();
mDialogManager->getSearchDialog()->setActiveWindow();
mDialogManager->getSearchDialog()->listview()->resetFocus();
} else
mViewerCallerIsSearchDialog = false;
}
if ( !mViewerCallerIsSearchDialog ) {
//mViewManager->currentView()->setFocus();
//qDebug("sssssssssssssssset focus ");
topLevelWidget()->raise();
setActiveWindow();
//setFocus();
}
mViewerCallerIsSearchDialog = false;
}
void CalendarView::showNextAlarms()
{
QString message;
QDateTime nextAl = mCalendar->nextAlarmEventDateTime();
if ( nextAl.isValid() && mNextAlarmDateTime > QDateTime::currentDateTime() ) {
QString sum = mCalendar->nextSummary();
QDateTime nextA = mNextAlarmDateTime;
QDateTime cur = QDateTime::currentDateTime();
int secs = cur.secsTo( nextA );
int min = secs /60;
int hours = min /60;
min = min % 60;
int days = hours /24;
hours = hours % 24;
//message = i18n("The next alarm is in:\n");
if ( days > 1 )
message += i18n("%1 days\n").arg( days );
else if ( days == 1 )
message += i18n("1 day\n");
if ( hours > 1 )
message += i18n("%1 hours\n").arg( hours );
else if ( hours == 1 )
message += i18n("1 hour\n");
if ( min > 1 )
message += i18n("%1 minutes\n").arg( min );
else if ( min == 1 )
message += i18n("1 minute\n");
if ( message.isEmpty() )
message = i18n("The next alarm is in\nless than one minute!");
else
message = i18n("The next alarm is in:\n") + message;
message += i18n("\n(%1)\n\n%2\n(%3)\n").arg( KGlobal::locale()->formatDateTime(nextA , false)).arg(sum ).arg( KGlobal::locale()->formatDateTime(nextAl , false)) ;
} else {
message = i18n("There is no next alarm.");
}
#ifdef DESKTOP_VERSION
if ( ! KOPrefs::instance()->mUseInternalAlarmNotification ) {
message += i18n("\nThe internal alarm notification is disabled!\n");
message += i18n("Enable it in the settings menu, TAB alarm.");
}
#endif
KMessageBox::information( this, message);
}
diff --git a/korganizer/koagenda.cpp b/korganizer/koagenda.cpp
index 0dd5ef5..c738f7e 100644
--- a/korganizer/koagenda.cpp
+++ b/korganizer/koagenda.cpp
@@ -1,2268 +1,2268 @@
/*
This file is part of KOrganizer.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
Marcus Bains line.
Copyright (c) 2001 Ali Rahimi
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 _WIN32_
#define protected public
#include <qwidget.h>
#undef protected
#endif
#include <qintdict.h>
#include <qdatetime.h>
#include <qapplication.h>
#include <qpopupmenu.h>
#include <qcursor.h>
#include <qpainter.h>
#include <kdebug.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kglobal.h>
#include "koagendaitem.h"
#include "koprefs.h"
#include "koglobals.h"
#include "koagenda.h"
#include <libkcal/event.h>
#include <libkcal/todo.h>
#ifndef DESKTOP_VERSION
#include <qpe/qpeapplication.h>
#endif
//extern bool globalFlagBlockPainting;
extern int globalFlagBlockAgenda;
extern int globalFlagBlockAgendaItemPaint;
extern int globalFlagBlockAgendaItemUpdate;
extern int globalFlagBlockStartup;
////////////////////////////////////////////////////////////////////////////
MarcusBains::MarcusBains(KOAgenda *_agenda,const char *name)
: QFrame(_agenda->viewport(),name), agenda(_agenda)
{
setLineWidth(0);
setMargin(0);
setBackgroundColor(Qt::red);
minutes = new QTimer(this);
connect(minutes, SIGNAL(timeout()), this, SLOT(updateLoc()));
minutes->start(0, true);
mTimeBox = new QLabel(this);
mTimeBox->setAlignment(Qt::AlignRight | Qt::AlignBottom);
QPalette pal = mTimeBox->palette();
pal.setColor(QColorGroup::Foreground, Qt::red);
mTimeBox->setPalette(pal);
//mTimeBox->setAutoMask(true);
agenda->addChild(mTimeBox);
oldToday = -1;
}
MarcusBains::~MarcusBains()
{
//delete minutes;
}
int MarcusBains::todayColumn()
{
QDate currentDate = QDate::currentDate();
DateList dateList = agenda->dateList();
DateList::ConstIterator it;
int col = 0;
for(it = dateList.begin(); it != dateList.end(); ++it) {
if((*it) == currentDate)
return KOGlobals::self()->reverseLayout() ?
agenda->columns() - 1 - col : col;
++col;
}
return -1;
}
void MarcusBains::updateLoc()
{
updateLocation();
}
void MarcusBains::updateLocation(bool recalculate)
{
QTime tim = QTime::currentTime();
//qDebug(" MarcusBains::updateLocation %s ", tim.toString().latin1());
if((tim.hour() == 0) && (oldTime.hour()==23))
recalculate = true;
int mins = tim.hour()*60 + tim.minute();
int minutesPerCell = 24 * 60 / agenda->rows();
int y = mins*agenda->gridSpacingY()/minutesPerCell;
int today = recalculate ? todayColumn() : oldToday;
int x = agenda->gridSpacingX()*today;
bool disabled = !(KOPrefs::instance()->mMarcusBainsEnabled);
oldTime = tim;
oldToday = today;
if(disabled || (today<0)) {
hide(); mTimeBox->hide();
return;
} else {
show(); mTimeBox->show();
}
if(recalculate)
setFixedSize(agenda->gridSpacingX(),1);
agenda->moveChild(this, x, y);
raise();
if(recalculate)
//mTimeBox->setFont(QFont("helvetica",10));
mTimeBox->setFont(KOPrefs::instance()->mMarcusBainsFont);
mTimeBox->setText(KGlobal::locale()->formatTime(tim, KOPrefs::instance()->mMarcusBainsShowSeconds));
mTimeBox->adjustSize();
// the -2 below is there because there is a bug in this program
// somewhere, where the last column of this widget is a few pixels
// narrower than the other columns.
int offs = (today==agenda->columns()-1) ? -4 : 0;
agenda->moveChild(mTimeBox,
x+agenda->gridSpacingX()-mTimeBox->width()+offs-1,
y-mTimeBox->height());
mTimeBox->raise();
//mTimeBox->setAutoMask(true);
int secs = QTime::currentTime().second();
minutes->start( (60 - secs +1)*1000 ,true);
}
////////////////////////////////////////////////////////////////////////////
/*
Create an agenda widget with rows rows and columns columns.
*/
KOAgenda::KOAgenda(int columns,int rows,int rowSize,QWidget *parent,
const char *name,WFlags f) :
QScrollView(parent,name,f)
{
mAllAgendaPopup = 0;
mColumns = columns;
mRows = rows;
mGridSpacingY = rowSize;
mAllDayMode = false;
#ifndef DESKTOP_VERSION
//QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold );
#endif
mHolidayMask = 0;
init();
connect ( this, SIGNAL (contentsMoving ( int , int ) ), this, SLOT ( slotContentMove(int,int)) );
}
/*
Create an agenda widget with columns columns and one row. This is used for
all-day events.
*/
KOAgenda::KOAgenda(int columns,QWidget *parent,const char *name,WFlags f) :
QScrollView(parent,name,f)
{
mAllAgendaPopup = 0;
blockResize = false;
mColumns = columns;
mRows = 1;
//qDebug("aaaaaaaaaaaaaaaaaaldays %d ", KOPrefs::instance()->mAllDaySize);
mGridSpacingY = KOPrefs::instance()->mAllDaySize;
mAllDayMode = true;
#ifndef DESKTOP_VERSION
//QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold );
#endif
mHolidayMask = 0;
init();
}
KOAgenda::~KOAgenda()
{
if(mMarcusBains) delete mMarcusBains;
}
Incidence *KOAgenda::selectedIncidence() const
{
return (mSelectedItem ? mSelectedItem->incidence() : 0);
}
QDate KOAgenda::selectedIncidenceDate() const
{
return (mSelectedItem ? mSelectedItem->itemDate() : QDate());
}
void KOAgenda::init()
{
mPopupTimer = new QTimer(this);
connect(mPopupTimer , SIGNAL(timeout()), this, SLOT(popupMenu()));
mNewItemPopup = new QPopupMenu( this );
connect ( mNewItemPopup, SIGNAL (activated ( int ) ), this, SLOT ( newItem(int)) );
QString pathString = "";
if ( !KOPrefs::instance()->mToolBarMiniIcons ) {
if ( QApplication::desktop()->width() < 480 )
pathString += "icons16/";
} else
pathString += "iconsmini/";
mNewItemPopup->insertItem ( SmallIcon( pathString +"newevent" ), i18n("New Event..."), 1 );
mNewItemPopup->insertItem ( SmallIcon( pathString +"newtodo" ), i18n("New Todo..."),2 );
mNewItemPopup->insertSeparator ( );
mNewItemPopup->insertItem ( SmallIcon( pathString +"day" ), i18n("Day view"),3 );
mNewItemPopup->insertItem ( SmallIcon( pathString +"xdays" ), i18n("Next days"),8 );
mNewItemPopup->insertItem ( SmallIcon( pathString +"week" ), i18n("Next week"),4 );
mNewItemPopup->insertItem ( SmallIcon( pathString +"week" ), i18n("Next two weeks"),5 );
mNewItemPopup->insertItem ( SmallIcon( pathString +"month" ), i18n("This month"),6 );
mNewItemPopup->insertItem ( SmallIcon( pathString +"journal" ), i18n("Journal view"),7 );
#ifndef _WIN32_
int wflags = viewport()-> getWFlags() |WRepaintNoErase;//WResizeNoErase
viewport()->setWFlags ( wflags);
#endif
mGridSpacingX = 80;
mResizeBorderWidth = 8;
mScrollBorderWidth = 8;
mScrollDelay = 30;
mScrollOffset = 10;
mPaintPixmap.resize( 20,20);
//enableClipper(true);
// Grab key strokes for keyboard navigation of agenda. Seems to have no
// effect. Has to be fixed.
setFocusPolicy(WheelFocus);
connect(&mScrollUpTimer,SIGNAL(timeout()),SLOT(scrollUp()));
connect(&mScrollDownTimer,SIGNAL(timeout()),SLOT(scrollDown()));
connect(&mResizeTimer,SIGNAL(timeout()),SLOT(finishResize()));
mStartCellX = 0;
mStartCellY = 0;
mCurrentCellX = 0;
mCurrentCellY = 0;
mSelectionCellX = 0;
mSelectionYTop = 0;
mSelectionHeight = 0;
mOldLowerScrollValue = -1;
mOldUpperScrollValue = -1;
mClickedItem = 0;
mActionItem = 0;
mActionType = NOP;
mItemMoved = false;
mSelectedItem = 0;
// mItems.setAutoDelete(true);
resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
viewport()->update();
setMinimumSize(30, 1);
// setMaximumHeight(mGridSpacingY * mRows + 5);
// Disable horizontal scrollbar. This is a hack. The geometry should be
// controlled in a way that the contents horizontally always fits. Then it is
// not necessary to turn off the scrollbar.
setHScrollBarMode(AlwaysOff);
if ( ! mAllDayMode )
setVScrollBarMode(AlwaysOn);
else
setVScrollBarMode(AlwaysOff);
setStartHour(KOPrefs::instance()->mDayBegins);
calculateWorkingHours();
connect(verticalScrollBar(),SIGNAL(valueChanged(int)),
SLOT(checkScrollBoundaries(int)));
// Create the Marcus Bains line.
if(mAllDayMode)
mMarcusBains = 0;
else {
mMarcusBains = new MarcusBains(this);
addChild(mMarcusBains);
}
mPopupKind = 0;
mPopupItem = 0;
mInvalidPixmap = false;
}
void KOAgenda::shrinkPixmap()
{
mPaintPixmap.resize( 20,20);
mInvalidPixmap = true;
}
void KOAgenda::slotContentMove(int,int)
{
emit sendPing();
if ( mActionType == NOP )
slotClearSelection();
if ( mSelectedItem && !mActionItem ) {
deselectItem();
emit incidenceSelected( 0 );
}
}
void KOAgenda::clear()
{
KOAgendaItem *item;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
mUnusedItems.append( item );
//item->hide();
}
mItems.clear();
mSelectedItem = 0;
clearSelection();
}
void KOAgenda::clearSelection()
{
mSelectionCellX = 0;
mSelectionYTop = 0;
mSelectionHeight = 0;
}
void KOAgenda::marcus_bains()
{
if(mMarcusBains) mMarcusBains->updateLocation(true);
}
void KOAgenda::changeColumns(int columns)
{
if (columns == 0) {
qDebug("KOAgenda::changeColumns() called with argument 0 ");
return;
}
clear();
mColumns = columns;
computeSizes();
}
/*
This is the eventFilter function, which gets all events from the KOAgendaItems
contained in the agenda. It has to handle moving and resizing for all items.
*/
bool KOAgenda::eventFilter ( QObject *object, QEvent *event )
{
// kdDebug() << "KOAgenda::eventFilter" << endl;
switch(event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove:
return eventFilter_mouse(object, static_cast<QMouseEvent *>(event));
case (QEvent::Leave):
if (!mActionItem)
setCursor(arrowCursor);
return true;
default:
return QScrollView::eventFilter(object,event);
}
}
void KOAgenda::popupMenu()
{
mPopupTimer->stop();
if ( mPopupKind == 1 || mPopupKind == 3 ) {
if (mActionItem ) {
endItemAction();
}
mLeftMouseDown = false; // no more leftMouse computation
if (mPopupItem) {
//mClickedItem = mPopupItem;
selectItem(mPopupItem);
if ( mAllAgendaPopup && KOPrefs::instance()->mBlockPopupMenu && mPopupKind == 1 )
mAllAgendaPopup->installEventFilter( this );
emit showIncidencePopupSignal(mPopupItem->incidence());
}
} else if ( mPopupKind == 2 || mPopupKind == 4 ) {
if ( mLeftMouseDown ) { // we have a simulated right click - clear left mouse action
endSelectAction( false ); // do not emit new event signal
mLeftMouseDown = false; // no more leftMouse computation
}
if ( KOPrefs::instance()->mBlockPopupMenu && mPopupKind == 2 )
mNewItemPopup->installEventFilter( this );
mNewItemPopup->popup( mPopupPos);
}
mLeftMouseDown = false;
mPopupItem = 0;
mPopupKind = 0;
}
void KOAgenda::categoryChanged(Incidence * inc)
{
KOAgendaItem *item;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
if ( item->incidence() == inc ) {
item->initColor ();
item->updateItem();
}
}
}
bool KOAgenda::eventFilter_mouse(QObject *object, QMouseEvent *me)
{
if ( mInvalidPixmap ) {
mInvalidPixmap = false;
qDebug("KO: Upsizing Pixmaps ");
computeSizes();
emit updateViewSignal();
return true;
}
emit sendPing();
static int startX = 0;
static int startY = 0;
int blockmoveDist = ( QApplication::desktop()->width() < 480 ? 7 : 9 );
static bool blockMoving = true;
//qDebug("KOAgenda::eventFilter_mous ");
if ( object == mNewItemPopup ) {
//qDebug("mNewItemPopup ");
if ( me->type() == QEvent::MouseButtonRelease ) {
mNewItemPopup->removeEventFilter( this );
int dX = me->globalPos().x() - mPopupPos.x();;
if ( dX < 0 )
dX = -dX;
int dY = me->globalPos().y() - mPopupPos.y();
if ( dY < 0 )
dY = -dY;
if ( dX > blockmoveDist || dY > blockmoveDist ) {
mNewItemPopup->hide();
}
}
return true;
}
if ( object == mAllAgendaPopup ) {
//qDebug(" mAllAgendaPopup ");
if ( me->type() == QEvent::MouseButtonRelease ) {
mAllAgendaPopup->removeEventFilter( this );
int dX = me->globalPos().x() - mPopupPos.x();;
if ( dX < 0 )
dX = -dX;
int dY = me->globalPos().y() - mPopupPos.y();
if ( dY < 0 )
dY = -dY;
if ( dX > blockmoveDist || dY > blockmoveDist ) {
mAllAgendaPopup->hide();
}
}
return true;
}
QPoint viewportPos;
if (object != viewport()) {
blockmoveDist = blockmoveDist*2;
viewportPos = ((QWidget *)object)->mapToParent(me->pos());
} else {
viewportPos = me->pos();
}
bool objIsNotViewport = (object != viewport());
bool leftButt = false;
#ifdef DESKTOP_VERSION
leftButt = (me->button() == LeftButton);
#endif
switch (me->type()) {
case QEvent::MouseButtonPress:
if (me->button() == LeftButton) {
mPopupTimer->start( 600 );
mLeftMouseDown = true;
}
blockMoving = true;
startX = viewportPos.x();
startY = viewportPos.y();
mPopupPos = me->globalPos();
if ( objIsNotViewport && !leftButt ) {
KOAgendaItem * tempItem = (KOAgendaItem *)object;
if (mAllDayMode) {
if ( tempItem->height() > 10 ) {
int minV = tempItem->height()/4;
if ( minV > (blockmoveDist/2)-2 ) {
if ( minV > blockmoveDist )
minV = blockmoveDist;
else
minV = (blockmoveDist/2);
}
bool border = false;
int diff = tempItem->y() - viewportPos.y();
if ( diff < 0 )
diff *= -1;
if ( diff < minV ) {
border = true;
objIsNotViewport = false;
}
if ( ! border ) {
diff = tempItem->y() + tempItem->height()- viewportPos.y();
if ( diff < 0 )
diff *= -1;
if ( diff < minV ) {
border = true;
objIsNotViewport = false;
}
}
}
} else { // not allday
if ( tempItem->width() > 10 ) {
int minH = tempItem->width()/4;
if ( minH > (blockmoveDist/2)-2 ) {
if ( minH > blockmoveDist )
minH = blockmoveDist;
else
minH = (blockmoveDist/2);
}
bool border = false;
int diff = tempItem->x() - viewportPos.x();
if ( diff < 0 )
diff *= -1;
if ( diff < minH ) {
border = true;
objIsNotViewport = false;
}
if ( ! border ) {
diff = tempItem->x() + tempItem->width() - viewportPos.x();
if ( diff < 0 )
diff *= -1;
if ( diff < minH ) {
border = true;
objIsNotViewport = false;
}
}
}
}
}
if ( objIsNotViewport ) {
mPopupItem = (KOAgendaItem *)object;
mPopupKind = 1;
if (me->button() == RightButton) {
mPopupKind = 3;
popupMenu();
} else if (me->button() == LeftButton) {
mActionItem = (KOAgendaItem *)object;
if (mActionItem) {
emit signalClearSelection();
slotClearSelection();
selectItem(mActionItem);
Incidence *incidence = mActionItem->incidence();
- if ( incidence->isReadOnly() /*|| incidence->recurrence()->doesRecur() */) {
+ if ( incidence->isReadOnly() /*|| incidence->doesRecur() */) {
mActionItem = 0;
} else {
startItemAction(viewportPos);
}
}
}
} else { // ---------- viewport()
mPopupItem = 0;
mPopupKind = 2;
selectItem(0);
mActionItem = 0;
if (me->button() == RightButton) {
int x,y;
viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
int gx,gy;
contentsToGrid(x,y,gx,gy);
mCurrentCellX = gx;
mCurrentCellY = gy;
mStartCellX = gx;
mStartCellY = gy;
mPopupKind = 4;
popupMenu();
} else if (me->button() == LeftButton) {
setCursor(arrowCursor);
startSelectAction(viewportPos);
}
}
break;
case QEvent::MouseButtonRelease:
if (me->button() == LeftButton ) {
mPopupTimer->stop();
}
if (object != viewport()) {
if (me->button() == LeftButton && mLeftMouseDown) {
if (mActionItem) {
QPoint clipperPos = clipper()->mapFromGlobal(viewport()->mapToGlobal(viewportPos));
//qDebug(" %d %d %d ",clipperPos.y(),visibleHeight() , 9 );
if ( mActionType == MOVE && (clipperPos.y() > visibleHeight()-2 ||clipperPos.y() < 0 ) ) {
mScrollUpTimer.stop();
mScrollDownTimer.stop();
mActionItem->resetMove();
placeSubCells( mActionItem );
// emit startDragSignal( mActionItem->incidence() );
setCursor( arrowCursor );
mActionItem = 0;
mActionType = NOP;
mItemMoved = 0;
mLeftMouseDown = false;
return true;
}
endItemAction();
}
}
} else { // ---------- viewport()
if (me->button() == LeftButton && mLeftMouseDown ) { //left click
endSelectAction( true ); // emit new event signal
}
}
if (me->button() == LeftButton)
mLeftMouseDown = false;
break;
case QEvent::MouseMove:
//qDebug("mm ");
if ( !mLeftMouseDown )
return false;
if ( blockMoving ) {
int dX, dY;
dX = startX - viewportPos.x();
if ( dX < 0 )
dX = -dX;
dY = viewportPos.y() - startY;
if ( dY < 0 )
dY = -dY;
//qDebug("%d %d %d ", dX, dY , blockmoveDist );
if ( dX > blockmoveDist || dY > blockmoveDist ) {
blockMoving = false;
}
}
if ( ! blockMoving )
mPopupTimer->stop();
if (object != viewport()) {
KOAgendaItem *moveItem = (KOAgendaItem *)object;
if (!moveItem->incidence()->isReadOnly() ) {
if (!mActionItem)
setNoActionCursor(moveItem,viewportPos);
else {
if ( !blockMoving )
performItemAction(viewportPos);
}
}
} else { // ---------- viewport()
mPopupPos = viewport()->mapToGlobal( me->pos() );
if ( mActionType == SELECT ) {
performSelectAction( viewportPos );
}
}
break;
case QEvent::MouseButtonDblClick:
mPopupTimer->stop();
if (object == viewport()) {
selectItem(0);
int x,y;
viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
int gx,gy;
contentsToGrid(x,y,gx,gy);
emit newEventSignal(gx,gy);
} else {
KOAgendaItem *doubleClickedItem = (KOAgendaItem *)object;
selectItem(doubleClickedItem);
if ( KOPrefs::instance()->mEditOnDoubleClick )
emit editIncidenceSignal(doubleClickedItem->incidence());
else
emit showIncidenceSignal(doubleClickedItem->incidence());
}
break;
default:
break;
}
return true;
}
void KOAgenda::newItem( int item )
{
if ( item == 1 ) { //new event
newEventSignal(mStartCellX ,mStartCellY );
} else
if ( item == 2 ) { //new event
newTodoSignal(mStartCellX ,mStartCellY );
} else
{
emit showDateView( item, mStartCellX );
// 3Day view
// 4Week view
// 5Month view
// 6Journal view
}
}
void KOAgenda::slotClearSelection()
{
if (mSelectionHeight) {
int selectionX = mSelectionCellX * mGridSpacingX;
int top = mSelectionYTop - 2 *mGridSpacingY;
int hei = mSelectionHeight + 4 *mGridSpacingY;
clearSelection();
repaintContents( selectionX, top,
mGridSpacingX, hei ,false );
}
}
void KOAgenda::startSelectAction(QPoint viewportPos)
{
emit signalClearSelection();
slotClearSelection();
mActionType = SELECT;
int x,y;
viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
int gx,gy;
contentsToGrid(x,y,gx,gy);
mStartCellX = gx;
mStartCellY = gy;
mCurrentCellX = gx;
mCurrentCellY = gy;
// Store new selection
mSelectionCellX = gx;
mSelectionYTop = gy * mGridSpacingY;
mSelectionHeight = mGridSpacingY;
// Paint new selection
repaintContents( mSelectionCellX * mGridSpacingX+1, mSelectionYTop,
mGridSpacingX-1, mSelectionHeight );
}
void KOAgenda::performSelectAction(QPoint viewportPos)
{
int x,y;
viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
int gx,gy;
contentsToGrid(x,y,gx,gy);
QPoint clipperPos = clipper()->
mapFromGlobal(viewport()->mapToGlobal(viewportPos));
// Scroll if cursor was moved to upper or lower end of agenda.
if (clipperPos.y() < mScrollBorderWidth) {
mScrollUpTimer.start(mScrollDelay);
} else if (visibleHeight() - clipperPos.y() <
mScrollBorderWidth) {
mScrollDownTimer.start(mScrollDelay);
} else {
mScrollUpTimer.stop();
mScrollDownTimer.stop();
}
if ( gy > mCurrentCellY ) {
mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop;
repaintContents( (KOGlobals::self()->reverseLayout() ?
mColumns - 1 - mSelectionCellX : mSelectionCellX) *
mGridSpacingX, mSelectionYTop,
mGridSpacingX, mSelectionHeight , false);
mCurrentCellY = gy;
} else if ( gy < mCurrentCellY ) {
if ( gy >= mStartCellY ) {
int selectionHeight = mSelectionHeight;
mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop;
repaintContents( (KOGlobals::self()->reverseLayout() ?
mColumns - 1 - mSelectionCellX : mSelectionCellX) *
mGridSpacingX, mSelectionYTop,
mGridSpacingX, selectionHeight,false );
mCurrentCellY = gy;
} else {
}
}
}
void KOAgenda::endSelectAction( bool emitNewEvent )
{
mActionType = NOP;
mScrollUpTimer.stop();
mScrollDownTimer.stop();
emit newTimeSpanSignal(mStartCellX,mStartCellY,mCurrentCellX,mCurrentCellY);
if ( emitNewEvent && mStartCellY < mCurrentCellY ) {
emit newEventSignal(mStartCellX,mStartCellY,mCurrentCellX,mCurrentCellY);
}
}
void KOAgenda::startItemAction(QPoint viewportPos)
{
int x,y;
viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
int gx,gy;
contentsToGrid(x,y,gx,gy);
mStartCellX = gx;
mStartCellY = gy;
mCurrentCellX = gx;
mCurrentCellY = gy;
if (mAllDayMode) {
int gridDistanceX = (x - gx * mGridSpacingX);
if (gridDistanceX < mResizeBorderWidth &&
mActionItem->cellX() == mCurrentCellX) {
mActionType = RESIZELEFT;
setCursor(sizeHorCursor);
} else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth &&
mActionItem->cellXWidth() == mCurrentCellX) {
mActionType = RESIZERIGHT;
setCursor(sizeHorCursor);
} else {
mActionType = MOVE;
mActionItem->startMove();
setCursor(sizeAllCursor);
}
} else {
int gridDistanceY = (y - gy * mGridSpacingY);
bool allowResize = ( mActionItem->incidence()->typeID() != todoID );
if (allowResize && gridDistanceY < mResizeBorderWidth &&
mActionItem->cellYTop() == mCurrentCellY &&
!mActionItem->firstMultiItem()) {
mActionType = RESIZETOP;
setCursor(sizeVerCursor);
} else if (allowResize &&(mGridSpacingY - gridDistanceY) < mResizeBorderWidth &&
mActionItem->cellYBottom() == mCurrentCellY &&
!mActionItem->lastMultiItem()) {
mActionType = RESIZEBOTTOM;
setCursor(sizeVerCursor);
} else {
mActionType = MOVE;
mActionItem->startMove();
setCursor(sizeAllCursor);
}
}
}
void KOAgenda::performItemAction(QPoint viewportPos)
{
// kdDebug() << "viewportPos: " << viewportPos.x() << "," << viewportPos.y() << endl;
// QPoint point = viewport()->mapToGlobal(viewportPos);
// kdDebug() << "Global: " << point.x() << "," << point.y() << endl;
// point = clipper()->mapFromGlobal(point);
// kdDebug() << "clipper: " << point.x() << "," << point.y() << endl;
// kdDebug() << "visible height: " << visibleHeight() << endl;
int x,y;
viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
// kdDebug() << "contents: " << x << "," << y << "\n" << endl;
int gx,gy;
contentsToGrid(x,y,gx,gy);
QPoint clipperPos = clipper()->
mapFromGlobal(viewport()->mapToGlobal(viewportPos));
// Cursor left active agenda area.
// This starts a drag.
if ( /*clipperPos.y() < 0 || clipperPos.y() > visibleHeight() ||*/
clipperPos.x() < 0 || clipperPos.x() > visibleWidth() ) {
if ( mActionType == MOVE ) {
mScrollUpTimer.stop();
mScrollDownTimer.stop();
mActionItem->resetMove();
placeSubCells( mActionItem );
// emit startDragSignal( mActionItem->incidence() );
setCursor( arrowCursor );
mActionItem = 0;
mActionType = NOP;
mItemMoved = 0;
return;
}
} else {
switch ( mActionType ) {
case MOVE:
setCursor( sizeAllCursor );
break;
case RESIZETOP:
case RESIZEBOTTOM:
setCursor( sizeVerCursor );
break;
case RESIZELEFT:
case RESIZERIGHT:
setCursor( sizeHorCursor );
break;
default:
setCursor( arrowCursor );
}
}
// Scroll if item was moved to upper or lower end of agenda.
if (clipperPos.y() < mScrollBorderWidth) {
mScrollUpTimer.start(mScrollDelay);
} else if (visibleHeight() - clipperPos.y() <
mScrollBorderWidth) {
mScrollDownTimer.start(mScrollDelay);
} else {
mScrollUpTimer.stop();
mScrollDownTimer.stop();
}
// Move or resize item if necessary
if (mCurrentCellX != gx || mCurrentCellY != gy) {
mItemMoved = true;
mActionItem->raise();
if (mActionType == MOVE) {
// Move all items belonging to a multi item
KOAgendaItem *moveItem = mActionItem->firstMultiItem();
bool isMultiItem = (moveItem || mActionItem->lastMultiItem());
if (!moveItem) moveItem = mActionItem;
while (moveItem) {
int dy;
if (isMultiItem) dy = 0;
else dy = gy - mCurrentCellY;
moveItem->moveRelative(gx - mCurrentCellX,dy);
int x,y;
gridToContents(moveItem->cellX(),moveItem->cellYTop(),x,y);
moveItem->resize(mGridSpacingX * moveItem->cellWidth(),
mGridSpacingY * moveItem->cellHeight());
moveItem->raise();
moveChild(moveItem,x,y);
moveItem = moveItem->nextMultiItem();
}
} else if (mActionType == RESIZETOP) {
if (mCurrentCellY <= mActionItem->cellYBottom()) {
mActionItem->expandTop(gy - mCurrentCellY);
mActionItem->resize(mActionItem->width(),
mGridSpacingY * mActionItem->cellHeight());
int x,y;
gridToContents(mCurrentCellX,mActionItem->cellYTop(),x,y);
//moveChild(mActionItem,childX(mActionItem),y);
QScrollView::moveChild( mActionItem,childX(mActionItem),y );
}
} else if (mActionType == RESIZEBOTTOM) {
if (mCurrentCellY >= mActionItem->cellYTop()) {
mActionItem->expandBottom(gy - mCurrentCellY);
mActionItem->resize(mActionItem->width(),
mGridSpacingY * mActionItem->cellHeight());
}
} else if (mActionType == RESIZELEFT) {
if (mCurrentCellX <= mActionItem->cellXWidth()) {
mActionItem->expandLeft(gx - mCurrentCellX);
mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(),
mActionItem->height());
int x,y;
gridToContents(mActionItem->cellX(),mActionItem->cellYTop(),x,y);
moveChild(mActionItem,x,childY(mActionItem));
}
} else if (mActionType == RESIZERIGHT) {
if (mCurrentCellX >= mActionItem->cellX()) {
mActionItem->expandRight(gx - mCurrentCellX);
mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(),
mActionItem->height());
}
}
mCurrentCellX = gx;
mCurrentCellY = gy;
}
}
void KOAgenda::endItemAction()
{
if ( mItemMoved ) {
KOAgendaItem *placeItem = mActionItem->firstMultiItem();
if ( !placeItem ) {
placeItem = mActionItem;
}
- if ( placeItem->incidence()->recurrence()->doesRecur() ) {
+ if ( placeItem->incidence()->doesRecur() ) {
Incidence* oldInc = placeItem->incidence();
placeItem->recreateIncidence();
emit addToCalSignal(placeItem->incidence(), oldInc );
}
int type = mActionType;
if ( mAllDayMode )
type = -1;
KOAgendaItem *modifiedItem = placeItem;
//emit itemModified( placeItem, mActionType /*KOGlobals::EVENTEDITED */);
QPtrList<KOAgendaItem> oldconflictItems ;//= placeItem->conflictItems();
KOAgendaItem *item;
if ( placeItem->incidence()->typeID() == todoID ) {
mSelectedItem = 0;
//qDebug("todo %d %d %d ", mCurrentCellX, modifiedItem->cellX() ,modifiedItem->cellXWidth());
modifiedItem->mLastMoveXPos = mCurrentCellX;
emit itemModified( modifiedItem, mActionType );
}
else {
globalFlagBlockAgendaItemPaint = 1;
for ( item=oldconflictItems.first(); item != 0;
item=oldconflictItems.next() ) {
placeSubCells(item);
}
while ( placeItem ) {
//qDebug("placeItem %s ", placeItem->incidence()->summary().latin1());
oldconflictItems = placeItem->conflictItems();
for ( item=oldconflictItems.first(); item != 0;
item=oldconflictItems.next() ) {
placeSubCells(item);
}
placeSubCells( placeItem );
placeItem = placeItem->nextMultiItem();
}
globalFlagBlockAgendaItemPaint = 0;
for ( item=oldconflictItems.first(); item != 0;
item=oldconflictItems.next() ) {
globalFlagBlockAgendaItemUpdate = 0;
item->repaintMe();
globalFlagBlockAgendaItemUpdate = 1;
item->repaint( false );
}
placeItem = modifiedItem;
while ( placeItem ) {
//qDebug("placeItem %s ", placeItem->incidence()->summary().latin1());
globalFlagBlockAgendaItemUpdate = 0;
placeItem->repaintMe();
globalFlagBlockAgendaItemUpdate = 1;
placeItem->repaint(false);
placeItem = placeItem->nextMultiItem();
}
emit itemModified( modifiedItem, mActionType );
placeItem = modifiedItem;
while ( placeItem ) {
oldconflictItems = placeItem->conflictItems();
for ( item=oldconflictItems.first(); item != 0;
item=oldconflictItems.next() ) {
placeSubCells(item);
}
placeSubCells( placeItem );
placeItem = placeItem->nextMultiItem();
}
placeItem = modifiedItem;
while ( placeItem ) {
oldconflictItems = placeItem->conflictItems();
for ( item=oldconflictItems.first(); item != 0;
item=oldconflictItems.next() ) {
globalFlagBlockAgendaItemUpdate = 0;
item->repaintMe();
globalFlagBlockAgendaItemUpdate = 1;
item->repaint(false);
}
placeItem = placeItem->nextMultiItem();
}
/*
oldconflictItems = modifiedItem->conflictItems();
for ( item=oldconflictItems.first(); item != 0;
item=oldconflictItems.next() ) {
globalFlagBlockAgendaItemUpdate = 0;
item->paintMe(false);
globalFlagBlockAgendaItemUpdate = 1;
item->repaint(false);
}
*/
}
}
if ( mActionItem )
emit incidenceSelected( mActionItem->incidence() );
mScrollUpTimer.stop();
mScrollDownTimer.stop();
setCursor( arrowCursor );
mActionItem = 0;
mActionType = NOP;
mItemMoved = 0;
}
void KOAgenda::setNoActionCursor(KOAgendaItem *moveItem,QPoint viewportPos)
{
// kdDebug() << "viewportPos: " << viewportPos.x() << "," << viewportPos.y() << endl;
// QPoint point = viewport()->mapToGlobal(viewportPos);
// kdDebug() << "Global: " << point.x() << "," << point.y() << endl;
// point = clipper()->mapFromGlobal(point);
// kdDebug() << "clipper: " << point.x() << "," << point.y() << endl;
int x,y;
viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
// kdDebug() << "contents: " << x << "," << y << "\n" << endl;
int gx,gy;
contentsToGrid(x,y,gx,gy);
// Change cursor to resize cursor if appropriate
if (mAllDayMode) {
int gridDistanceX = (x - gx * mGridSpacingX);
if (gridDistanceX < mResizeBorderWidth &&
moveItem->cellX() == gx) {
setCursor(sizeHorCursor);
} else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth &&
moveItem->cellXWidth() == gx) {
setCursor(sizeHorCursor);
} else {
setCursor(arrowCursor);
}
} else {
int gridDistanceY = (y - gy * mGridSpacingY);
if (gridDistanceY < mResizeBorderWidth &&
moveItem->cellYTop() == gy &&
!moveItem->firstMultiItem()) {
setCursor(sizeVerCursor);
} else if ((mGridSpacingY - gridDistanceY) < mResizeBorderWidth &&
moveItem->cellYBottom() == gy &&
!moveItem->lastMultiItem()) {
setCursor(sizeVerCursor);
} else {
setCursor(arrowCursor);
}
}
}
/*
Place item in cell and take care that multiple items using the same cell do
not overlap. This method is not yet optimal. It doesn´t use the maximum space
it can get in all cases.
At the moment the method has a bug: When an item is placed only the sub cell
widths of the items are changed, which are within the Y region the item to
place spans. When the sub cell width change of one of this items affects a
cell, where other items are, which do not overlap in Y with the item to place,
the display gets corrupted, although the corruption looks quite nice.
*/
void KOAgenda::placeSubCells(KOAgendaItem *placeItem)
{
QPtrList<KOAgendaItem> conflictItems;
int maxSubCells = 0;
QIntDict<KOAgendaItem> subCellDict(7);
KOAgendaItem *item;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
if (item != placeItem) {
if (placeItem->cellX() <= item->cellXWidth() &&
placeItem->cellXWidth() >= item->cellX()) {
if ((placeItem->cellYTop() <= item->cellYBottom()) &&
(placeItem->cellYBottom() >= item->cellYTop())) {
conflictItems.append(item);
if (item->subCells() > maxSubCells)
maxSubCells = item->subCells();
subCellDict.insert(item->subCell(),item);
}
}
}
}
if (conflictItems.count() > 0) {
// Look for unused sub cell and insert item
int i;
for(i=0;i<maxSubCells;++i) {
if (!subCellDict.find(i)) {
placeItem->setSubCell(i);
break;
}
}
if (i == maxSubCells) {
placeItem->setSubCell(maxSubCells);
maxSubCells++; // add new item to number of sub cells
}
// Prepare for sub cell geometry adjustment
int newSubCellWidth;
if (mAllDayMode) newSubCellWidth = mGridSpacingY / maxSubCells;
else newSubCellWidth = mGridSpacingX / maxSubCells;
conflictItems.append(placeItem);
// Adjust sub cell geometry of all direct conflict items
for ( item=conflictItems.first(); item != 0;
item=conflictItems.next() ) {
item->setSubCells(maxSubCells);
if (mAllDayMode) {
item->resize(item->cellWidth() * mGridSpacingX, newSubCellWidth);
} else {
item->resize(newSubCellWidth, item->cellHeight() * mGridSpacingY);
}
int x,y;
gridToContents(item->cellX(),item->cellYTop(),x,y);
if (mAllDayMode) {
y += item->subCell() * newSubCellWidth;
} else {
x += item->subCell() * newSubCellWidth;
}
moveChild(item,x,y);
// qDebug("moveChild %s %d %d ", item->incidence()->summary().latin1() ,x,y);
//item->updateItem();
}
// Adjust sub cell geometry of all conflict items of all conflict items
for ( item=conflictItems.first(); item != 0;
item=conflictItems.next() ) {
if ( placeItem != item ) {
KOAgendaItem *item2;
QPtrList<KOAgendaItem> conflictItems2 = item->conflictItems();
for ( item2=conflictItems2.first(); item2 != 0;
item2=conflictItems2.next() ) {
if ( item2->subCells() != maxSubCells) {
item2->setSubCells(maxSubCells);
if (mAllDayMode) {
item2->resize(item2->cellWidth() * mGridSpacingX, newSubCellWidth);
} else {
item2->resize(newSubCellWidth, item2->cellHeight() * mGridSpacingY);
}
int x,y;
gridToContents(item2->cellX(),item2->cellYTop(),x,y);
if (mAllDayMode) {
y += item2->subCell() * newSubCellWidth;
} else {
x += item2->subCell() * newSubCellWidth;
}
moveChild(item2,x,y);
//qDebug("setttttt %d %s",maxSubCells, item2->text().latin1() );
}
}
}
}
} else {
placeItem->setSubCell(0);
placeItem->setSubCells(1);
if (mAllDayMode) placeItem->resize(placeItem->width(),mGridSpacingY);
else placeItem->resize(mGridSpacingX,placeItem->height());
int x,y;
gridToContents(placeItem->cellX(),placeItem->cellYTop(),x,y);
moveChild(placeItem,x,y);
}
placeItem->setConflictItems(conflictItems);
// for ( item=conflictItems.first(); item != 0;
// item=conflictItems.next() ) {
// //item->updateItem();
// //qDebug("xxx item->updateItem() %s %d %d", item->incidence()->summary().latin1(),item->x(), item->y() );
// }
// placeItem->updateItem();
}
void KOAgenda::drawContents(QPainter* p, int cx, int cy, int cw, int ch)
{
if ( globalFlagBlockAgenda )
return;
if ( mInvalidPixmap ) {
mInvalidPixmap = false;
qDebug("KO: Upsizing Pixmaps ");
computeSizes();
emit updateViewSignal();
return;
}
if ( ! mAllDayMode ) {
// currently not working for
//qDebug("KOAgenda::drawContents ");
#if 0
if ( mCurPixWid != contentsWidth() || mCurPixHei != contentsHeight() ) {
qDebug("WAU ");
drawContentsToPainter();
}
#endif
QPaintDevice* pd = p->device();
p->end();
int vx, vy;
int selectionX = KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - mSelectionCellX) * mGridSpacingX :
mSelectionCellX * mGridSpacingX;
contentsToViewport ( cx, cy, vx,vy);
//qDebug(" %d %d %d %d %d", cx, cy, cw,ch,mGridSpacingX-1) ;
if ( !(selectionX == cx && cy == mSelectionYTop && cw ==mGridSpacingX && ch == mSelectionHeight ) ) {
if ( mGridSpacingX == cw && mSelectionHeight > 0 && ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) &&
( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) ) {
int vxSel, vySel;
contentsToViewport ( selectionX, mSelectionYTop, vxSel,vySel);
int off = mSelectionHeight;
if ( vySel < 0 )
off += vySel;
//qDebug("OFF %d %d %d", off,vySel, vy );
bitBlt ( pd, vx, vy+off, &mPaintPixmap, cx, cy+off, cw , ch-off ,CopyROP);
} else {
bitBlt ( pd, vx, vy, &mPaintPixmap, cx, cy, cw, ch ,CopyROP);
}
}
if ( mSelectionHeight > 0 ) {
//qDebug("---- %d %d %d %d ", selectionX, mSelectionYTop, mGridSpacingX, mSelectionHeight );
if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) &&
( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) {
contentsToViewport ( selectionX, mSelectionYTop, vx,vy);
// bitBlt ( pd, vx+1, vy, &mHighlightPixmap, 0, mSelectionYTop, mGridSpacingX-1, mSelectionHeight ,CopyROP);
int hei = mSelectionHeight;
int offset = 0;
while ( hei > 0 ) {
int p_hei = 5;
if ( hei < 5 ) p_hei = hei;
hei -= 5;
bitBlt ( pd, vx+1, vy+offset, &mHighlightPixmap, 0, 0, mGridSpacingX-1, p_hei ,CopyROP);
offset += 5;
}
}
}
p->begin( pd );
} else {
#if 0
qDebug("mCurPixWid %d %d ",mCurPixWid, contentsWidth() );
if ( mCurPixWid != contentsWidth() || mCurPixHei != contentsHeight() ) {
qDebug("WAUWAU ");
drawContentsToPainter();
}
#endif
QPaintDevice* pd = p->device();
p->end();
int vx, vy;
int selectionX = KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - mSelectionCellX) * mGridSpacingX :
mSelectionCellX * mGridSpacingX;
contentsToViewport ( cx, cy, vx,vy);
// qDebug(" %d %d %d %d ", cx, cy, cw,ch) ;
if ( !(selectionX == cx && cy == mSelectionYTop && cw ==mGridSpacingX && ch == mSelectionHeight ) )
bitBlt ( pd, vx, vy, &mPaintPixmap, cx, cy, cw, ch ,CopyROP);
if ( mSelectionHeight > 0 ) {
//qDebug("---- %d %d %d %d ", selectionX, mSelectionYTop, mGridSpacingX, mSelectionHeight );
if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) &&
( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) {
contentsToViewport ( selectionX, mSelectionYTop, vx,vy);
//bitBlt ( pd, vx+1, vy, &mHighlightPixmap, 0, mSelectionYTop, mGridSpacingX-1, mSelectionHeight ,CopyROP);
int hei = mSelectionHeight;
int offset = 0;
while ( hei > 0 ) {
int p_hei = 5;
if ( hei < 5 ) p_hei = hei;
hei -= 5;
bitBlt ( pd, vx+1, vy+offset, &mHighlightPixmap, 0, 0, mGridSpacingX-1, p_hei ,CopyROP);
offset += 5;
}
}
}
p->begin( pd );
}
}
void KOAgenda::finishUpdate()
{
KOAgendaItem *item;
globalFlagBlockAgendaItemPaint = 1;
// Adjust sub cell geometry of all conflict items of all conflict items of all conflict items ... of the conflict item with the max number of conflictitems
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
if ( !item->checkLayout() ) {
//qDebug(" conflictitem found ");
int newSubCellWidth;
if (mAllDayMode) newSubCellWidth = mGridSpacingY / item->subCells();
else newSubCellWidth = mGridSpacingX / item->subCells();
if (mAllDayMode) {
item->resize(item->cellWidth() * mGridSpacingX, newSubCellWidth);
} else {
item->resize(newSubCellWidth, item->cellHeight() * mGridSpacingY);
}
int x,y;
gridToContents(item->cellX(),item->cellYTop(),x,y);
if (mAllDayMode) {
y += item->subCell() * newSubCellWidth;
} else {
x += item->subCell() * newSubCellWidth;
}
moveChild(item,x,y);
}
}
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
if ( !item->isVisible() )
item->show();
}
globalFlagBlockAgendaItemUpdate = 0;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
item->repaintMe( );
}
globalFlagBlockAgendaItemUpdate = 1;
qApp->processEvents();
globalFlagBlockAgendaItemPaint = 0;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
item->repaint( false );
}
marcus_bains();
}
/*
Draw grid in the background of the agenda.
*/
void KOAgenda::drawContentsToPainter( QPainter* paint, bool backgroundOnly )// int cx, int cy, int cw, int ch)
{
if ( ! mGridSpacingX || ! mGridSpacingY ||! mHolidayMask )
return;
if ( globalFlagBlockAgenda > 1 && globalFlagBlockAgenda < 4 )
return;
int cx = 0, cy = 0, cw = contentsWidth(), ch = contentsHeight();
if ( ch < 1 )
ch = 1;
if ( mPaintPixmap.width() < contentsWidth()+42 || mPaintPixmap.height() < ch ) {
mPaintPixmap.resize( contentsWidth()+42, ch );
}
mCurPixWid = contentsWidth();
mCurPixHei = ch;
if ( mHighlightPixmap.width() < mGridSpacingX-1 ) {
mHighlightPixmap.resize( mGridSpacingX-1, 5 );
mHighlightPixmap.fill ( KOPrefs::instance()->mHighlightColor );
}
mPixPainter.begin( &mPaintPixmap) ;
//qDebug("wid %d hei %d ",mPaintPixmap.width(),mPaintPixmap.height() );
QPainter * p ;
if (paint == 0) {
mPaintPixmap.fill(KOPrefs::instance()->mAgendaBgColor);
p = &mPixPainter;
}
else
p = paint ;
// qDebug("++++++KOAgenda::drawContentsTo Painter %d %d %d %d ", cx, cy, cw, ch);
//--cx;++cw;
int lGridSpacingY = mGridSpacingY*2;
int selDay;
QDate curDate = QDate::currentDate();
if ( !backgroundOnly ) {
for ( selDay = 0; selDay < mSelectedDates.count(); ++selDay)
{
if ( mSelectedDates[selDay] == curDate && KOPrefs::instance()->mHighlightCurrentDay) {
int x1 = cx;
int y1 = 0;
if (y1 < cy) y1 = cy;
int x2 = cx+cw-1;
int y2 = contentsHeight();
if (y2 > cy+ch-1) y2=cy+ch-1;
if (x2 >= x1 && y2 >= y1) {
int gxStart = selDay;
int gxEnd = gxStart ;
int xStart = KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - gxStart)*mGridSpacingX :
gxStart*mGridSpacingX;
if (xStart < x1) xStart = x1;
int xEnd = KOGlobals::self()->reverseLayout() ?
(mColumns - gxStart)*mGridSpacingX-1 :
(gxStart+1)*mGridSpacingX-1;
if (xEnd > x2) xEnd = x2;
if ( KOPrefs::instance()->mUseHighlightLightColor )
p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
KOPrefs::instance()->mAgendaBgColor.light());
else
p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
KOPrefs::instance()->mAgendaBgColor.dark());
}
}
}
}
// Highlight working hours
if ( !backgroundOnly )
if (mWorkingHoursEnable) {
int x1 = cx;
int y1 = mWorkingHoursYTop;
if (y1 < cy) y1 = cy;
int x2 = cx+cw-1;
// int x2 = mGridSpacingX * 5 - 1;
// if (x2 > cx+cw-1) x2 = cx + cw - 1;
int y2 = mWorkingHoursYBottom;
if (y2 > cy+ch-1) y2=cy+ch-1;
if (x2 >= x1 && y2 >= y1) {
// qDebug("x1 %d mGridSpacingX %d ", x1, mGridSpacingX );
int gxStart = x1/mGridSpacingX;
int gxEnd = x2/mGridSpacingX;
while(gxStart <= gxEnd) {
if (gxStart < int(mHolidayMask->count()) &&
!mHolidayMask->at(gxStart)) {
int xStart = KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - gxStart)*mGridSpacingX :
gxStart*mGridSpacingX;
if (xStart < x1) xStart = x1;
int xEnd = KOGlobals::self()->reverseLayout() ?
(mColumns - gxStart)*mGridSpacingX-1 :
(gxStart+1)*mGridSpacingX-1;
if (xEnd > x2) xEnd = x2;
if ( mSelectedDates[gxStart] == curDate && KOPrefs::instance()->mHighlightCurrentDay ) {
if ( KOPrefs::instance()->mUseHighlightLightColor )
p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
KOPrefs::instance()->mWorkingHoursColor.light());
else
p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
KOPrefs::instance()->mWorkingHoursColor.dark());
} else {
p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
KOPrefs::instance()->mWorkingHoursColor);
}
}
++gxStart;
}
}
}
/*
int selectionX = KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - mSelectionCellX) * mGridSpacingX :
mSelectionCellX * mGridSpacingX;
// Draw selection
if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) &&
( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) {
// TODO: paint only part within cx,cy,cw,ch
p->fillRect( selectionX, mSelectionYTop, mGridSpacingX,
mSelectionHeight, KOPrefs::instance()->mHighlightColor );
}
*/
// Draw vertical lines of grid
int x = ((int)(cx/mGridSpacingX))*mGridSpacingX;
if ( mGridSpacingX > 0 ) {
while (x < cx + cw) {
p->drawLine(x,cy,x,cy+ch);
x+=mGridSpacingX;
}
}
// Draw horizontal lines of grid
int y = ((int)(cy/lGridSpacingY))*lGridSpacingY;
if ( lGridSpacingY > 0 ) {
while (y < cy + ch) {
p->setPen( SolidLine );
p->drawLine(cx,y,cx+cw,y);
y+=lGridSpacingY;
p->setPen( DotLine );
p->drawLine(cx,y,cx+cw,y);
y+=lGridSpacingY;
}
p->setPen( SolidLine );
}
mPixPainter.end() ;
}
/*
Convert srcollview contents coordinates to agenda grid coordinates.
*/
void KOAgenda::contentsToGrid (int x, int y, int& gx, int& gy)
{
gx = KOGlobals::self()->reverseLayout() ? mColumns - 1 - x/mGridSpacingX :
x/mGridSpacingX;
gy = y/mGridSpacingY;
}
/*
Convert agenda grid coordinates to scrollview contents coordinates.
*/
void KOAgenda::gridToContents (int gx, int gy, int& x, int& y)
{
x = KOGlobals::self()->reverseLayout() ? (mColumns - 1 - gx)*mGridSpacingX:
gx*mGridSpacingX;
y = gy*mGridSpacingY;
}
/*
Return Y coordinate corresponding to time. Coordinates are rounded to fit into
the grid.
*/
int KOAgenda::timeToY(const QTime &time)
{
int minutesPerCell = 24 * 60 / mRows;
int timeMinutes = time.hour() * 60 + time.minute();
int Y = (timeMinutes + (minutesPerCell / 2)) / minutesPerCell;
return Y;
}
/*
Return time corresponding to cell y coordinate. Coordinates are rounded to
fit into the grid.
*/
QTime KOAgenda::gyToTime(int gy)
{
int secondsPerCell = 24 * 60 * 60/ mRows;
int timeSeconds = secondsPerCell * gy;
QTime time( 0, 0, 0 );
if ( timeSeconds < 24 * 60 * 60 ) {
time = time.addSecs(timeSeconds);
} else {
time.setHMS( 23, 59, 59 );
}
return time;
}
void KOAgenda::setStartHour(int startHour)
{
int startCell = startHour * mRows / 24;
setContentsPos(0,startCell * gridSpacingY());
}
QTime KOAgenda::getEndTime()
{
int tim = (contentsY ()+viewport()->height())*24/contentsHeight ();
if ( tim > 23 )
return QTime ( 23,59,59);
return QTime ( tim,0,0);
}
void KOAgenda::hideUnused()
{
// experimental only
// return;
KOAgendaItem *item;
for ( item=mUnusedItems.first(); item != 0; item=mUnusedItems.next() ) {
item->hide();
}
}
KOAgendaItem *KOAgenda::getNewItem(Incidence * event,QDate qd, QWidget* view)
{
KOAgendaItem *fi;
for ( fi=mUnusedItems.first(); fi != 0; fi=mUnusedItems.next() ) {
if ( fi->incidence() == event ) {
mUnusedItems.remove();
fi->init( event, qd );
return fi;
}
}
fi=mUnusedItems.first();
if ( fi ) {
mUnusedItems.remove();
fi->init( event, qd );
return fi;
}
// qDebug("new KOAgendaItem ");
KOAgendaItem* agendaItem = new KOAgendaItem( event, qd, view, mAllDayMode );
agendaItem->installEventFilter(this);
addChild(agendaItem,0,0);
return agendaItem;
}
KOAgendaItem * KOAgenda::getItemForTodo ( Todo * todo )
{
KOAgendaItem *item;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
if ( item->incidence() == todo ) {
mItems.remove();
return item;
}
}
return 0;
}
void KOAgenda::updateTodo( Todo * todo, int days, bool remove)
{
// ( todo->hasCompletedDate() && todo->completed().date() == currentDate )||
KOAgendaItem *item;
item = getItemForTodo ( todo );
//qDebug("KOAgenda::updateTodo %d %d %d %d", this, todo, days, remove);
if ( item ) {
blockSignals( true );
//qDebug("item found ");
item->hide();
item->setCellX(-2, -1 );
item->select(false);
mUnusedItems.append( item );
mItems.remove( item );
QPtrList<KOAgendaItem> oldconflictItems = item->conflictItems();
KOAgendaItem *itemit;
//globalFlagBlockAgendaItemPaint = 1;
for ( itemit=oldconflictItems.first(); itemit != 0;
itemit=oldconflictItems.next() ) {
if ( itemit != item )
placeSubCells(itemit);
}
qApp->processEvents();
//globalFlagBlockAgendaItemPaint = 0;
for ( itemit=oldconflictItems.first(); itemit != 0;
itemit=oldconflictItems.next() ) {
globalFlagBlockAgendaItemUpdate = 0;
if ( itemit != item )
itemit->repaintMe();
globalFlagBlockAgendaItemUpdate = 1;
//qDebug("sigleshot ");
QTimer::singleShot( 0, itemit, SLOT ( repaintItem() ));
//itemit->repaint( false ); repaintItem()
}
blockSignals( false );
}
if ( remove ) {
//qDebug("remove****************************************** ");
return;
}
if ( todo->hasCompletedDate() && !KOPrefs::instance()->mShowCompletedTodoInAgenda )
return;
//qDebug("updateTodo+++++++++++++++++++++++++++++++++++++ ");
QDate currentDate = QDate::currentDate();
bool overdue = (!todo->isCompleted()) && (todo->dtDue() < currentDate)&& ( KOPrefs::instance()->mShowTodoInAgenda );
QDateTime dt;
if ( todo->hasCompletedDate() )
dt = todo->completed();
else
dt = todo->dtDue();
if ( overdue ) {
days += todo->dtDue().date().daysTo( currentDate );
}
else
currentDate = dt.date();
if (( todo->doesFloat() || overdue) && !todo->hasCompletedDate() ) {
if ( ! mAllDayMode ) return;
// aldayagenda
globalFlagBlockAgendaItemPaint = 1;
item = insertAllDayItem(todo, currentDate,days, days);
item->show();
}
else {
if ( mAllDayMode ) return;
// mAgenda
globalFlagBlockAgendaItemPaint = 1;
int endY = timeToY(dt.time()) - 1;
int hi = 12/KOPrefs::instance()->mHourSize;
int startY = endY - 1-hi;
item = insertItem(todo,currentDate,days,startY,endY);
item->show();
}
qApp->processEvents();
globalFlagBlockAgendaItemPaint = 0;
QPtrList<KOAgendaItem> oldconflictItems = item->conflictItems();
KOAgendaItem *itemit;
for ( itemit=oldconflictItems.first(); itemit != 0;
itemit=oldconflictItems.next() ) {
globalFlagBlockAgendaItemUpdate = 0;
itemit->repaintMe();
globalFlagBlockAgendaItemUpdate = 1;
itemit->repaint();
}
globalFlagBlockAgendaItemUpdate = 0;
item->repaintMe();
globalFlagBlockAgendaItemUpdate = 1;
item->repaint();
}
/*
Insert KOAgendaItem into agenda.
*/
KOAgendaItem *KOAgenda::insertItem (Incidence *event,QDate qd,int X,int YTop,int YBottom)
{
if (mAllDayMode) {
qDebug("KOAgenda: calling insertItem in all-day mode is illegal. ");
return 0;
}
KOAgendaItem *agendaItem = getNewItem(event,qd,viewport());
//agendaItem->setFrameStyle(WinPanel|Raised);
int YSize = YBottom - YTop + 1;
if (YSize < 0) {
YSize = 1;
}
int iheight = mGridSpacingY * YSize;
agendaItem->resize(mGridSpacingX,iheight );
agendaItem->setCellXY(X,YTop,YBottom);
agendaItem->setCellXWidth(X);
//addChild(agendaItem,X*mGridSpacingX,YTop*mGridSpacingY);
mItems.append(agendaItem);
placeSubCells(agendaItem);
//agendaItem->show();
return agendaItem;
}
/*
Insert all-day KOAgendaItem into agenda.
*/
KOAgendaItem *KOAgenda::insertAllDayItem (Incidence *event,QDate qd,int XBegin,int XEnd)
{
if (!mAllDayMode) {
return 0;
}
KOAgendaItem *agendaItem = getNewItem(event,qd,viewport());
agendaItem->setCellXY(XBegin,0,0);
agendaItem->setCellXWidth(XEnd);
agendaItem->resize(mGridSpacingX * agendaItem->cellWidth(),mGridSpacingY);
//addChild(agendaItem,XBegin*mGridSpacingX,0);
mItems.append(agendaItem);
placeSubCells(agendaItem);
//agendaItem->show();
return agendaItem;
}
void KOAgenda::insertMultiItem (Event *event,QDate qd,int XBegin,int XEnd,
int YTop,int YBottom)
{
if (mAllDayMode) {
;
return;
}
int cellX,cellYTop,cellYBottom;
QString newtext;
int width = XEnd - XBegin + 1;
int count = 0;
KOAgendaItem *current = 0;
QPtrList<KOAgendaItem> multiItems;
for (cellX = XBegin;cellX <= XEnd;++cellX) {
if (cellX == XBegin) cellYTop = YTop;
else cellYTop = 0;
if (cellX == XEnd) cellYBottom = YBottom;
else cellYBottom = rows() - 1;
newtext = QString("(%1/%2): ").arg(++count).arg(width);
newtext.append(event->summary());
current = insertItem(event,qd,cellX,cellYTop,cellYBottom);
current->setText(newtext);
multiItems.append(current);
}
KOAgendaItem *next = 0;
KOAgendaItem *last = multiItems.last();
KOAgendaItem *first = multiItems.first();
KOAgendaItem *setFirst,*setLast;
current = first;
while (current) {
next = multiItems.next();
if (current == first) setFirst = 0;
else setFirst = first;
if (current == last) setLast = 0;
else setLast = last;
current->setMultiItem(setFirst,next,setLast);
current = next;
}
}
//QSizePolicy KOAgenda::sizePolicy() const
//{
// Thought this would make the all-day event agenda minimum size and the
// normal agenda take the remaining space. But it doesn´t work. The QSplitter
// don´t seem to think that an Expanding widget needs more space than a
// Preferred one.
// But it doesn´t hurt, so it stays.
// if (mAllDayMode) {
// return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
// } else {
// return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
// }
//}
void KOAgenda::finishResize ( )
{
//qDebug("finishResize+++++++++++++++++++++++++++++++ ( ) ");
if ( globalFlagBlockAgenda == 0 ) {
finishUpdate();
//qDebug("finishUpdate() called ");
}
}
/*
Overridden from QScrollView to provide proper resizing of KOAgendaItems.
*/
void KOAgenda::resizeEvent ( QResizeEvent *ev )
{
mSelectionHeight = 0;
mResizeTimer.start( 150 , true );
computeSizes();
return;
}
void KOAgenda::computeSizes()
{
if ( globalFlagBlockStartup )
return;
int frameOffset = frameWidth() * 2 +1;
if (mAllDayMode) {
mGridSpacingX = (width()-frameOffset) / mColumns;
mGridSpacingY = height() - 2 * frameWidth() - 1;
resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY + 1);
// mGridSpacingY = height();
// resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
KOAgendaItem *item;
int subCellWidth;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
subCellWidth = mGridSpacingY / item->subCells();
item->resize(mGridSpacingX * item->cellWidth(),subCellWidth);
moveChild(item,KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - item->cellX()) * mGridSpacingX :
item->cellX() * mGridSpacingX,
item->subCell() * subCellWidth);
}
KOPrefs::instance()->mAllDaySize = mGridSpacingY;
} else {
mGridSpacingX = (width() - verticalScrollBar()->width()-frameOffset)/mColumns;
if (height() > mGridSpacingY * mRows + 1 ) {
KOPrefs::instance()->mHourSize = ((height())/mRows)+1;
mGridSpacingY = KOPrefs::instance()->mHourSize ;
resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
emit resizedSignal();
} else
resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
KOAgendaItem *item;
int subCellWidth;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
subCellWidth = mGridSpacingX / item->subCells();
item->resize(subCellWidth,item->height());
moveChild(item,(KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - item->cellX()) * mGridSpacingX :
item->cellX() * mGridSpacingX) +
item->subCell() * subCellWidth,childY(item));
}
}
int cw = contentsWidth();
int ch = contentsHeight();
if ( mAllDayMode ) {
QPixmap* paintPixAll = KOAgendaItem::paintPixAllday();
if ( (paintPixAll->width() < cw || paintPixAll->height() < ch) && cw > 0 && ch > 0 ) {
//qDebug("paintPixAll->resize ");
paintPixAll->resize( cw, ch );
}
} else {
QPixmap* paintPix = KOAgendaItem::paintPix();
if ( paintPix->width() < cw || paintPix->height() < ch ) {
//qDebug("paintPix->resize ");
paintPix->resize( cw , ch );
}
}
checkScrollBoundaries();
drawContentsToPainter();
viewport()->repaint(false);
}
void KOAgenda::scrollUp()
{
scrollBy(0,-mScrollOffset);
}
void KOAgenda::scrollDown()
{
scrollBy(0,mScrollOffset);
}
void KOAgenda::popupAlarm()
{
if (!mClickedItem) {
qDebug("KOAgenda::popupAlarm() called without having a clicked item ");
return;
}
// TODO: deal correctly with multiple alarms
Alarm* alarm;
QPtrList<Alarm> list(mClickedItem->incidence()->alarms());
for(alarm=list.first();alarm;alarm=list.next()) {
alarm->toggleAlarm();
}
emit itemModified( mClickedItem , KOGlobals::EVENTEDITED );
mClickedItem->paintMe( true );
mClickedItem->repaint( false );
}
/*
Calculates the minimum width
*/
int KOAgenda::minimumWidth() const
{
// TODO:: develop a way to dynamically determine the minimum width
int min = 100;
return min;
}
void KOAgenda::updateConfig()
{
if ( viewport()->backgroundColor() != KOPrefs::instance()->mAgendaBgColor)
viewport()->setBackgroundColor(KOPrefs::instance()->mAgendaBgColor);
if ( mAllDayMode ) {
mGridSpacingY = height() - 1 ;// KOPrefs::instance()->mAllDaySize;
//mGridSpacingY = KOPrefs::instance()->mAllDaySize;
resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY+1 );
// setMaximumHeight( mGridSpacingY+1 );
viewport()->repaint( false );
//setFixedHeight( mGridSpacingY+1 );
//qDebug("KOPrefs:aaaaa:instance()->mAllDaySize %d ", KOPrefs::instance()->mAllDaySize);
}
else {
mGridSpacingY = KOPrefs::instance()->mHourSize;
calculateWorkingHours();
}
}
void KOAgenda::checkScrollBoundaries()
{
// Invalidate old values to force update
mOldLowerScrollValue = -1;
mOldUpperScrollValue = -1;
checkScrollBoundaries(verticalScrollBar()->value());
}
void KOAgenda::checkScrollBoundaries(int v)
{
if ( mGridSpacingY == 0 )
return;
int yMin = v/mGridSpacingY;
int yMax = (v+visibleHeight())/mGridSpacingY;
// kdDebug() << "--- yMin: " << yMin << " yMax: " << yMax << endl;
if (yMin != mOldLowerScrollValue) {
mOldLowerScrollValue = yMin;
emit lowerYChanged(yMin);
}
if (yMax != mOldUpperScrollValue) {
mOldUpperScrollValue = yMax;
emit upperYChanged(yMax);
}
}
void KOAgenda::deselectItem()
{
if (mSelectedItem.isNull()) return;
mSelectedItem->select(false);
mSelectedItem = 0;
}
void KOAgenda::selectItem(KOAgendaItem *item)
{
if ((KOAgendaItem *)mSelectedItem == item) return;
deselectItem();
if (item == 0) {
emit incidenceSelected( 0 );
return;
}
mSelectedItem = item;
mSelectedItem->select();
emit incidenceSelected( mSelectedItem->incidence() );
}
// This function seems never be called.
void KOAgenda::keyPressEvent( QKeyEvent *kev )
{
switch(kev->key()) {
case Key_PageDown:
verticalScrollBar()->addPage();
break;
case Key_PageUp:
verticalScrollBar()->subtractPage();
break;
case Key_Down:
verticalScrollBar()->addLine();
break;
case Key_Up:
verticalScrollBar()->subtractLine();
break;
default:
;
}
}
void KOAgenda::calculateWorkingHours()
{
// mWorkingHoursEnable = KOPrefs::instance()->mEnableWorkingHours;
mWorkingHoursEnable = !mAllDayMode;
mWorkingHoursYTop = mGridSpacingY *
KOPrefs::instance()->mWorkingHoursStart * 4;
mWorkingHoursYBottom = mGridSpacingY *
KOPrefs::instance()->mWorkingHoursEnd * 4 - 1;
}
DateList KOAgenda::dateList() const
{
return mSelectedDates;
}
void KOAgenda::setDateList(const DateList &selectedDates)
{
mSelectedDates = selectedDates;
}
void KOAgenda::setHolidayMask(QMemArray<bool> *mask)
{
mHolidayMask = mask;
/*
kdDebug() << "HolidayMask: ";
for(uint i=0;i<mask->count();++i) {
kdDebug() << (mask->at(i) ? "*" : "o");
}
kdDebug() << endl;
*/
}
void KOAgenda::contentsMousePressEvent ( QMouseEvent *event )
{
QScrollView::contentsMousePressEvent(event);
}
void KOAgenda::storePosition()
{
//mContentPosition
int max = mGridSpacingY*4*24;
if ( contentsY() < 5 && max > viewport()->height()*3/2 )
mContentPosition = 0;
else if ( contentsY() + viewport()->height() > max - 5 && max > viewport()->height()*3/2)
mContentPosition = -1.0;
else
mContentPosition = ((float) max)/ ((float)(contentsY()+ ( viewport()->height()/2)));
//qDebug("mContentPosition %f %d %d %d",mContentPosition , max, contentsY() ,viewport()->height());
}
void KOAgenda::restorePosition()
{
int posY;
int max = mGridSpacingY*4*24;
if ( mContentPosition < 0 )
posY = max-viewport()->height();
else
if ( mContentPosition == 0 )
posY = 0;
else
posY = (max/mContentPosition)-(viewport()->height()/2);
setContentsPos (0, posY );
//qDebug("posY %d hei %d", posY, max);
}
void KOAgenda::moveChild( QWidget *w, int x , int y )
{
++x;
QScrollView::moveChild( w, x , y );
}
#include <qmessagebox.h>
#ifdef DESKTOP_VERSION
#include <qprinter.h>
#include <qpainter.h>
#include <qpaintdevicemetrics.h>
#endif
void KOAgenda::printSelection()
{
#ifdef DESKTOP_VERSION
if ( mStartCellY == mCurrentCellY ) {
int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),
i18n("Nothing selected!\n\nThis prints the full width of the Agenda view as you see it!\n\nTo determine the vertical range of the printing, please select\na vertical range (with the left mouse button down) in one column. "),
i18n("OK"), 0, 0,
0, 1 );
return;
}
float dx, dy;
int x,y,w,h;
x= 0;
w= contentsWidth()+2;
// h= contentsHeight();
y = mGridSpacingY*mStartCellY;
h = mGridSpacingY*(mCurrentCellY+1)-y+2;
//return;
QPrinter* printer = new QPrinter();
if ( !printer->setup()) {
delete printer;
return;
}
QPainter p( printer );
QPaintDeviceMetrics m = QPaintDeviceMetrics ( printer );
QString date = i18n("Date range: ")+KGlobal::locale()->formatDate( mSelectedDates.first() )+" - "+KGlobal::locale()->formatDate( mSelectedDates.last() );
//date += " --- printing time: " + KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), true );
int hei = p.boundingRect(0,0, 5, 5, Qt::AlignLeft, date ).height();
// p.drawText( 0, 0, date );
int offset = m.width()/8;
// compute the scale
dx = ((float) m.width()-offset) / (float)w;
dy = (float)(m.height() - ( 2 * hei )-offset ) / (float)h;
float scale;
// scale to fit the width or height of the paper
if ( dx < dy )
scale = dx;
else
scale = dy;
// set the scale
p.drawText( offset* scale, offset* scale*3/4, date );
int selDay;
float widOffset = ((float) m.width()-offset) / ((float)(mSelectedDates.count()));
float startX = 1;
for ( selDay = 0; selDay < mSelectedDates.count(); ++selDay)
{
QString text = KGlobal::locale()->formatDate( mSelectedDates[selDay],true );
p.setClipRect(offset* scale+startX , 0, widOffset-4, offset* scale+(2*hei* scale) );
p.drawText( offset* scale+startX, (offset+hei)* scale, text );
startX += widOffset;
}
p.translate( offset* scale,offset* scale+ (-y * scale)+(2*hei* scale));
p.scale( scale, scale );
p.setClipRect( offset* scale, offset* scale+(2*hei* scale), w*scale, h*scale );
// now printing with y offset: 2 hei
// p.translate( 0, -y*scale);
drawContentsToPainter(&p, true );
globalFlagBlockAgendaItemUpdate = false;
KOAgendaItem *item;
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
item->select(false);
item->paintMe( false, &p );
}
globalFlagBlockAgendaItemUpdate = true;
p.end();
delete printer;
#else
int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),
i18n("Not supported \non PDA!\n"),
i18n("OK"), 0, 0,
0, 1 );
#endif
}
diff --git a/korganizer/koagendaitem.cpp b/korganizer/koagendaitem.cpp
index 303a92a..49ad9b8 100644
--- a/korganizer/koagendaitem.cpp
+++ b/korganizer/koagendaitem.cpp
@@ -1,850 +1,850 @@
/*
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.
*/
#include <qlabel.h>
#include <qlayout.h>
#include <qhbox.h>
#include <qvbox.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qdragobject.h>
#include <qdrawutil.h>
#include <qpainter.h>
#include <kiconloader.h>
#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#ifndef DESKTOP_VERSION
#include <qpe/qpeapplication.h>
#define AGENDA_ICON_SIZE 5
#else
#include <qapplication.h>
#define AGENDA_ICON_SIZE 7
#endif
#include <libkcal/icaldrag.h>
#include <libkcal/vcaldrag.h>
#include <libkcal/kincidenceformatter.h>
extern int globalFlagBlockAgenda;
extern int globalFlagBlockAgendaItemPaint;
extern int globalFlagBlockAgendaItemUpdate;
#include "koprefs.h"
#include "koagendaitem.h"
//#include "koagendaitem.moc"
//--------------------------------------------------------------------------
QToolTipGroup *KOAgendaItem::mToolTipGroup = 0;
//--------------------------------------------------------------------------
class KOAgendaItemWhatsThis :public QWhatsThis
{
public:
KOAgendaItemWhatsThis( KOAgendaItem* view ) : QWhatsThis( view ),_view (view) { };
protected:
virtual QString text( const QPoint& )
{
return _view->getWhatsThisText() ;
}
private:
KOAgendaItem * _view;
};
KOAgendaItem::KOAgendaItem(Incidence *incidence, QDate qd, QWidget *parent,bool allday,
const char *name,WFlags) :
QWidget(parent, name), mIncidence(incidence), mDate(qd)
{
#ifndef DESKTOP_VERSION
//QPEApplication::setStylusOperation( this, QPEApplication::RightOnHold );
#endif
mKOAgendaItemWhatsThis = new KOAgendaItemWhatsThis(this);
int wflags = getWFlags() |WRepaintNoErase;// WResizeNoErase
setWFlags ( wflags);
mAllDay = allday;
init ( incidence, qd );
//setMouseTracking(true);
//setAcceptDrops(true);
xPaintCoord = -1;
yPaintCoord = -1;
}
QString KOAgendaItem::getWhatsThisText()
{
if ( mIncidence )
return KIncidenceFormatter::instance()->getFormattedText( mIncidence,
KOPrefs::instance()->mWTshowDetails,
KOPrefs::instance()->mWTshowCreated,
KOPrefs::instance()->mWTshowChanged);
return "KOAgendaItem::getWhatsThisText()::internal error";
}
void KOAgendaItem::initColor ()
{
if ( (mIncidence->typeID() == todoID ) &&
( !((static_cast<Todo*>(mIncidence))->isCompleted()) &&
((static_cast<Todo*>(mIncidence))->dtDue().date() <= QDate::currentDate()) ) ) {
if ( (static_cast<Todo*>(mIncidence))->dtDue() < QDateTime::currentDateTime().date())
mBackgroundColor = KOPrefs::instance()->mTodoOverdueColor ;
else
mBackgroundColor = KOPrefs::instance()->mTodoDueTodayColor;
}
else {
QStringList categories = mIncidence->categories();
QString cat = categories.first();
if (cat.isEmpty()) {
if ( (mIncidence->typeID() == todoID ) &&((static_cast<Todo*>(mIncidence))->isCompleted()) )
mBackgroundColor =KOPrefs::instance()->mTodoDoneColor;
else
mBackgroundColor =KOPrefs::instance()->defaultColor( mIncidence->calID() );
} else {
mBackgroundColor = *KOPrefs::instance()->categoryColor(cat);
if ( (mIncidence->typeID() == todoID ) &&((static_cast<Todo*>(mIncidence))->isCompleted()) ) {
if ( mBackgroundColor == KOPrefs::instance()->mEventColor )
mBackgroundColor = KOPrefs::instance()->mTodoDoneColor;
}
}
}
QColor BackgroundColor ( mBackgroundColor );
if ( mIncidence->calID() > 1 ) {
//BackgroundColor = KOPrefs::instance()->defaultColor( mIncidence->calID() );
}
mColorGroup = QColorGroup( BackgroundColor.light(),
BackgroundColor.dark(),BackgroundColor.light(),
BackgroundColor.dark(),BackgroundColor, black, BackgroundColor) ;
setBackgroundColor( mBackgroundColor );
mWhiteText = (mBackgroundColor.red() + mBackgroundColor.green() + mBackgroundColor.blue() < 250);
}
void KOAgendaItem::init ( Incidence *incidence, QDate qd )
{
mIncidence = incidence;
mDate = qd;
mFirstMultiItem = 0;
mNextMultiItem = 0;
mLastMultiItem = 0;
computeText();
initColor();
mConflictItems.clear();
setCellXY(0,0,1);
setCellXWidth(0);
setSubCell(0);
setSubCells(1);
setMultiItem(0,0,0);
startMove();
mSelected = true;
select(false);
QFontMetrics fontinf(KOPrefs::instance()->mAgendaViewFont);
mFontPixelSize = fontinf.height();;
hide();
xPaintCoord = -1;
yPaintCoord = -1;
}
KOAgendaItem::~KOAgendaItem()
{
#if QT_VERSION >= 0x030000
#else
delete mKOAgendaItemWhatsThis;
#endif
}
void KOAgendaItem::recreateIncidence()
{
#if 0
Incidence* newInc = mIncidence->clone();
newInc->recreate();
if ( mIncidence->doesRecur() ) {
mIncidence->addExDate( mDate );
newInc->recurrence()->unsetRecurs();
int len = mIncidence->dtStart().secsTo( ((Event*)mIncidence)->dtEnd());
QTime tim = mIncidence->dtStart().time();
newInc->setDtStart( QDateTime(mDate, tim) );
((Event*)newInc)->setDtEnd( newInc->dtStart().addSecs( len ) );
}
#endif
mIncidence = mIncidence->recreateCloneException( mDate );
}
bool KOAgendaItem::updateIcons(QPainter * p, bool horLayout)
{
int size = AGENDA_ICON_SIZE;
int yOff = 0;
int xOff = 0;
int x = pos().x();
if ( x < 0 ) x = 0;
x += 3;
int y;
if ( mAllDay )
y = pos().y()+3;
else
y = mCellYTop * ( height() / cellHeight() ) +3;
if ( mIncidence->calID() > 1 ) {
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, KOPrefs::instance()->defaultColor( mIncidence->calID() ) );
p->drawRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x-1, yOff*( 1 +AGENDA_ICON_SIZE)+y-1, AGENDA_ICON_SIZE+2, AGENDA_ICON_SIZE+2 );
if ( horLayout ){
++xOff;
++x;
}
else {
++yOff;
++y;
}
}
if (mIncidence->cancelled() && height() < 20 ) {
int xpos = xOff*( 1 +AGENDA_ICON_SIZE )+x;
int ypos = yOff*( 1 +AGENDA_ICON_SIZE)+y;
p->drawLine( xpos, ypos, xpos+AGENDA_ICON_SIZE-1, ypos+AGENDA_ICON_SIZE-1 );
p->drawLine( xpos, ypos+AGENDA_ICON_SIZE-1, xpos+AGENDA_ICON_SIZE-1, ypos );
if ( horLayout )
++xOff;
else
++yOff;
}
if (mIncidence->isAlarmEnabled() && mIncidence->alarmEnabled()) {
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, red );
if ( horLayout )
++xOff;
else
++yOff;
}
- if (mIncidence->recurrence()->doesRecur()) {
+ if (mIncidence->doesRecur()) {
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, blue );
if ( horLayout )
++xOff;
else
++yOff;
}
if (mIncidence->description().length() > 0) {
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, darkGreen );
if ( horLayout )
++xOff;
else
++yOff;
}
if (mIncidence->isReadOnly()) {
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, white );
if ( horLayout )
++xOff;
else
++yOff;
}
if (mIncidence->attendeeCount()>0) {
if (mIncidence->organizer() == KOPrefs::instance()->email()) {
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, black );
if ( horLayout )
++xOff;
else
++yOff;
} else {
Attendee *me = mIncidence->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email());
if (me!=0) {
} else {
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, yellow );
if ( horLayout )
++xOff;
else
++yOff;
}
p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, darkYellow );
if ( horLayout )
++xOff;
else
++yOff;
}
}
return ( yOff || xOff );
}
void KOAgendaItem::select(bool selected)
{
//qDebug("select %d %d",firstMultiItem(), nextMultiItem() );
if (mSelected == selected) return;
mSelected = selected;
if ( ! isVisible() )
return;
if ( firstMultiItem() )
firstMultiItem()->select( selected );
if ( !firstMultiItem() && nextMultiItem() ) {
KOAgendaItem * placeItem = nextMultiItem();
while ( placeItem ) {
placeItem->select( selected );
placeItem = placeItem->nextMultiItem();
}
}
globalFlagBlockAgendaItemUpdate = 0;
paintMe( selected );
globalFlagBlockAgendaItemUpdate = 1;
repaint( false );
}
/*
The eventFilter has to filter the mouse events of the agenda item childs. The
events are fed into the event handling method of KOAgendaItem. This allows the
KOAgenda to handle the KOAgendaItems by using an eventFilter.
*/
bool KOAgendaItem::eventFilter ( QObject *object, QEvent *e )
{
if (e->type() == QEvent::MouseButtonPress ||
e->type() == QEvent::MouseButtonDblClick ||
e->type() == QEvent::MouseButtonRelease ||
e->type() == QEvent::MouseMove) {
QMouseEvent *me = (QMouseEvent *)e;
QPoint itemPos = this->mapFromGlobal(((QWidget *)object)->
mapToGlobal(me->pos()));
QMouseEvent returnEvent (e->type(),itemPos,me->button(),me->state());
return event(&returnEvent);
} else {
return false;
}
}
void KOAgendaItem::repaintMe( )
{
paintMe ( mSelected );
}
void KOAgendaItem::paintMe( bool selected, QPainter* paint )
{
if ( globalFlagBlockAgendaItemUpdate && ! selected)
return;
QPainter pa;
if ( mSelected ) {
pa.begin( this );
} else {
if ( mAllDay )
pa.begin( paintPixAllday() );
else
pa.begin( paintPix() );
}
int x, yy, w, h;
float nfh = 7.0;
x = pos().x(); w = width(); h = height ();
if ( mAllDay )
yy = y();
else
yy = mCellYTop * ( height() / cellHeight() );
if ( mSelected ) {
pa.translate( -x, -yy );
}
xPaintCoord= x;
yPaintCoord = yy;
wPaintCoord = width();
hPaintCoord = height();
//qDebug("paintMe %s %d %d %d %d",incidence()->summary().latin1(), x, yy, width(), height());
if ( paint == 0 )
paint = &pa;
bool horLayout = ( w < h );
int maxhei = mFontPixelSize+4;
if ( horLayout )
maxhei += AGENDA_ICON_SIZE -4;
bool small = ( h < maxhei );
if ( ! small )
paint->setFont(KOPrefs::instance()->mAgendaViewFont);
else {
QFont f = KOPrefs::instance()->mAgendaViewFont;
f.setBold( false );
int fh = f.pointSize();
nfh = (((float)height())/(float)(mFontPixelSize+4))*fh;
if ( nfh < 6 )
nfh = 6;
f.setPointSize( nfh );
paint->setFont(f);
}
paint->fillRect ( x, yy, w, h, mBackgroundColor );
static const QPixmap completedPxmp = SmallIcon("greenhook16");
static const QPixmap overduePxmp = SmallIcon("redcross16");
if ( mIncidence->typeID() == todoID ) {
Todo* tempTodo = static_cast<Todo*>(mIncidence);
int xx = pos().x()+(width()-completedPxmp.width()-3 );
int yyy = yy+3;
if ( tempTodo->isCompleted() )
paint->drawPixmap ( xx, yyy, completedPxmp );
else {
paint->drawPixmap ( xx, yyy, overduePxmp );
}
}
bool addIcon = false;
if ( ! small || w > 3 * h || h > 3* w )
addIcon = updateIcons( paint, horLayout );
//qDrawShadePanel (paint, x, yy, w, h, mColorGroup, selected , 2, 0);
qDrawWinPanel (paint, x, yy, w, h, mColorGroup, selected ,0);
//qDebug("draw rect %d %d %d %d ",x, yy, w, h );
if ( ! small ) {
x += 3; yy += 3;w -= 6; h-= 5;
} else {
x += 2; yy += 1;w -= 4; h-= 4;
if ( nfh < 6.01 ) {
yy -= 2;
h += 4;
}
else
if ( nfh < h -2 )
++yy;
}
int align;
#ifndef DESKTOP_VERSION
align = ( AlignLeft|WordBreak|AlignTop);
#else
align = ( AlignLeft|BreakAnywhere|WordBreak|AlignTop);
#endif
if ( addIcon ) {
if ( ! horLayout ) {
x += AGENDA_ICON_SIZE+3;
w -= (AGENDA_ICON_SIZE+3);
}
else {
yy+= AGENDA_ICON_SIZE+2;
h -=(AGENDA_ICON_SIZE+3);
}
}
if ( mWhiteText )
paint->setPen ( white);
if ( x < 0 ) {
w = w+x-3;
x = 3;
if ( !horLayout && addIcon )
x += AGENDA_ICON_SIZE+3;
if ( w > parentWidget()->width() ){
w = parentWidget()->width() - 6;
#ifndef DESKTOP_VERSION
align = ( AlignHCenter|WordBreak|AlignTop);
#else
align = ( AlignHCenter|BreakAnywhere|WordBreak|AlignTop);
#endif
}
}
QRect dr;
if ( w + x > parentWidget()->width() )
w = parentWidget()->width()-x;
paint->drawText ( x, yy, w, h, align, mDisplayedText, -1, &dr );
//qDebug("%d %d %d %d ", x, yy, w, h );
if ( mIncidence->cancelled() ){
small = ( height() < 20 );
if ( ! small ) {
QFontMetrics fm ( paint->font() );
paint->drawLine(dr.left(), yy+fm.height()/2, dr.right()-2, yy+fm.height()/2);
}
}
pa.end();
}
QPixmap * KOAgendaItem::paintPix()
{
static QPixmap* mPaintPix = 0;
if ( ! mPaintPix ) {
int w = QApplication::desktop()->width();
int h = QApplication::desktop()->height();
mPaintPix = new QPixmap(w,h);
}
return mPaintPix ;
}
QPixmap * KOAgendaItem::paintPixAllday()
{
static QPixmap* mPaintPixA = 0;
if ( ! mPaintPixA ) {
int w = QApplication::desktop()->width();
int h = QApplication::desktop()->height()/5;
mPaintPixA = new QPixmap(w,h);
}
return mPaintPixA ;
}
void KOAgendaItem::repaintItem()
{
globalFlagBlockAgendaItemPaint = 0;
globalFlagBlockAgenda = 0;
repaint( false );
}
void KOAgendaItem::paintEvent ( QPaintEvent *e )
{
if ( globalFlagBlockAgendaItemPaint )
return;
if ( globalFlagBlockAgenda > 0 && globalFlagBlockAgenda < 5 )
return;
int yy;
if ( mAllDay )
yy = y();
else
yy = mCellYTop * ( height() / cellHeight() );
int xx = x();
if ( xPaintCoord != xx || yPaintCoord != yy ||
wPaintCoord != width() || hPaintCoord != height()) {
xPaintCoord= xx;
yPaintCoord = yy;
wPaintCoord = width();
hPaintCoord = height();
globalFlagBlockAgendaItemUpdate = 0;
paintMe( mSelected );
//qDebug("calling paintMe ");
globalFlagBlockAgendaItemUpdate = 1;
if ( mSelected )
return;
}
int rx, ry, rw, rh;
rx = e->rect().x();
ry = e->rect().y();
rw = e->rect().width();
rh = e->rect().height();
//qDebug(" paintevent %s %d %d %d %d", mIncidence->summary().latin1(), x(), yy, width(), height());
QPixmap* paintFrom ;
if ( mSelected ) {
paintMe( mSelected );
return;
} else {
if ( mAllDay )
paintFrom = paintPixAllday();
else
paintFrom = paintPix();
}
xx += rx;
if ( xx < 0 ) {
rw = rw + xx;
rx -= xx;
xx = 0;
if ( rw <= 1 ) {
//qDebug("KOAgendaItem::Width1 <= 1 (%d). Returning. %s",rw,mDisplayedText.latin1());
return;
}
}
if ( paintFrom->width() < xx+rw ) {
rw = paintFrom->width() - xx;
if ( rw <= 1 ) {
//qDebug("KOAgendaItem::Width2 <= 1 (%d). Returning.%s ",rw,mDisplayedText.latin1() );
return;
}
}
//qDebug("%d %d %d %d %d %d %d",rx, ry, paintFrom, xx ,yPaintCoord+ry, rw, rh);
bitBlt (this, rx, ry, paintFrom, xx ,yPaintCoord+ry, rw, rh ,CopyROP);
}
void KOAgendaItem::computeText()
{
mDisplayedText = mIncidence->summary();
if ( (mIncidence->typeID() == todoID ) ) {
if ( static_cast<Todo*>(mIncidence)->hasDueDate() ) {
if ( static_cast<Todo*>(mIncidence)->dtDue().date() < QDate::currentDate() )
mDisplayedText += i18n(" (") +KGlobal::locale()->formatDate((static_cast<Todo*>(mIncidence))->dtDue().date(), true)+")";
else if ( !(mIncidence->doesFloat()))
mDisplayedText += i18n(" (") +KGlobal::locale()->formatTime((static_cast<Todo*>(mIncidence))->dtDue().time())+")";
}
} else {
if ( !(mIncidence->doesFloat()) && KOPrefs::instance()->mShowTimeInAgenda)
mDisplayedText += ": " +KGlobal::locale()->formatTime((static_cast<Event*>(mIncidence))->dtStart().time()) + " - " + KGlobal::locale()->formatTime((static_cast<Event*>(mIncidence))->dtEnd().time()) ;
if ( mAllDay ) {
if ( mIncidence->dtStart().date().addDays(3) < mIncidence->dtEnd().date() ) {
if ( mIncidence->doesRecur() ) {
mDisplayedText += " (" + mIncidence->recurrence()->recurrenceText() + ")";
} else {
mDisplayedText += ": " +KGlobal::locale()->formatDate((static_cast<Event*>(mIncidence))->dtStart().date(), true) + " - " + KGlobal::locale()->formatDate((static_cast<Event*>(mIncidence))->dtEnd().date(), true) ;
}
}
}
}
if ( !mIncidence->location().isEmpty() ) {
if ( mAllDay )
mDisplayedText += " (";
else
mDisplayedText += "\n(";
mDisplayedText += mIncidence->location() +")";
}
#ifdef DESKTOP_VERSION
QString tipText = mIncidence->summary();
if ( !mIncidence->doesFloat() ) {
if ( mIncidence->typeID() == eventID ) {
if ( (static_cast<Event*>(mIncidence))->isMultiDay() ) {
tipText += "\n"+i18n("From: ")+mIncidence->dtStartStr();
tipText += "\n"+i18n("To: ")+(static_cast<Event*>(mIncidence))->dtEndStr();
}
else {
tipText += "\n"+i18n("Time: ")+mIncidence->dtStartTimeStr();
tipText += " - "+(static_cast<Event*>(mIncidence))->dtEndTimeStr();
}
}
else if ( mIncidence->typeID() == todoID ) {
if (mIncidence->hasStartDate())
tipText += "\n"+i18n("Start: ")+ (static_cast<Todo*>(mIncidence))->dtStartStr();
if (((Todo*)mIncidence)->hasDueDate())
tipText += "\n"+i18n("Due: ")+ (static_cast<Todo*>(mIncidence))->dtDueStr();
}
} else if ( mIncidence->typeID() == todoID ) {
if (mIncidence->hasStartDate())
tipText += "\n"+i18n("Start: ")+ (static_cast<Todo*>(mIncidence))->dtStartDateStr();
if (((Todo*)mIncidence)->hasDueDate())
tipText += "\n"+i18n("Due: ")+ (static_cast<Todo*>(mIncidence))->dtDueDateStr();
}
if (!mIncidence->location().isEmpty()) {
tipText += "\n"+i18n("Location: ")+mIncidence->location();
}
QToolTip::add(this,tipText,toolTipGroup(),"");
#endif
}
void KOAgendaItem::updateItem()
{
computeText();
//qDebug("KOAgendaItem:: updateItem() %s %d %d ",incidence()->summary().latin1(), x(), y());
paintMe( mSelected );
repaint( false);
}
void KOAgendaItem::resizeEvent ( QResizeEvent *ev )
{
//qDebug("KOAgendaItem::resizeEvent %s ", mIncidence->summary().latin1());
paintMe( mSelected );
repaint( false );
}
/*
Return height of item in units of agenda cells
*/
int KOAgendaItem::cellHeight()
{
int ret = mCellYBottom - mCellYTop + 1;
if ( ret <= 0 ) {
ret = 1;
mCellYBottom = 0;
mCellYTop = 0;
}
return ret;
}
/*
Return height of item in units of agenda cells
*/
int KOAgendaItem::cellWidth()
{
return mCellXWidth - mCellX + 1;
}
void KOAgendaItem::setItemDate(QDate qd)
{
mDate = qd;
}
void KOAgendaItem::setCellXY(int X, int YTop, int YBottom)
{
mCellX = X;
mCellYTop = YTop;
mCellYBottom = YBottom;
}
void KOAgendaItem::setCellXWidth(int xwidth)
{
mCellXWidth = xwidth;
}
void KOAgendaItem::setCellX(int XLeft, int XRight)
{
mCellX = XLeft;
mCellXWidth = XRight;
}
void KOAgendaItem::setCellY(int YTop, int YBottom)
{
mCellYTop = YTop;
mCellYBottom = YBottom;
}
void KOAgendaItem::setSubCell(int subCell)
{
mSubCell = subCell;
}
void KOAgendaItem::setSubCells(int subCells)
{
mSubCells = subCells;
}
void KOAgendaItem::setMultiItem(KOAgendaItem *first,KOAgendaItem *next,
KOAgendaItem *last)
{
mFirstMultiItem = first;
mNextMultiItem = next;
mLastMultiItem = last;
}
void KOAgendaItem::startMove()
{
mStartCellX = mCellX;
mStartCellXWidth = mCellXWidth;
mStartCellYTop = mCellYTop;
mStartCellYBottom = mCellYBottom;
}
void KOAgendaItem::resetMove()
{
mCellX = mStartCellX;
mCellXWidth = mStartCellXWidth;
mCellYTop = mStartCellYTop;
mCellYBottom = mStartCellYBottom;
}
void KOAgendaItem::moveRelative(int dx, int dy)
{
int newX = cellX() + dx;
int newXWidth = cellXWidth() + dx;
int newYTop = cellYTop() + dy;
int newYBottom = cellYBottom() + dy;
setCellXY(newX,newYTop,newYBottom);
setCellXWidth(newXWidth);
}
void KOAgendaItem::expandTop(int dy)
{
int newYTop = cellYTop() + dy;
int newYBottom = cellYBottom();
if (newYTop > newYBottom) newYTop = newYBottom;
setCellY(newYTop, newYBottom);
}
void KOAgendaItem::expandBottom(int dy)
{
int newYTop = cellYTop();
int newYBottom = cellYBottom() + dy;
if (newYBottom < newYTop) newYBottom = newYTop;
setCellY(newYTop, newYBottom);
}
void KOAgendaItem::expandLeft(int dx)
{
int newX = cellX() + dx;
int newXWidth = cellXWidth();
if (newX > newXWidth) newX = newXWidth;
setCellX(newX,newXWidth);
}
void KOAgendaItem::expandRight(int dx)
{
int newX = cellX();
int newXWidth = cellXWidth() + dx;
if (newXWidth < newX) newXWidth = newX;
setCellX(newX,newXWidth);
}
QToolTipGroup *KOAgendaItem::toolTipGroup()
{
if (!mToolTipGroup) mToolTipGroup = new QToolTipGroup(0);
return mToolTipGroup;
}
void KOAgendaItem::dragEnterEvent( QDragEnterEvent *e )
{
#ifndef KORG_NODND
if ( ICalDrag::canDecode( e ) || VCalDrag::canDecode( e ) ||
!QTextDrag::canDecode( e ) ) {
e->ignore();
return;
}
e->accept();
#endif
}
void KOAgendaItem::dropEvent( QDropEvent *e )
{
#ifndef KORG_NODND
QString text;
if(QTextDrag::decode(e,text))
{
kdDebug() << "Dropped : " << text << endl;
QStringList emails = QStringList::split(",",text);
for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) {
kdDebug() << " Email: " << (*it) << endl;
int pos = (*it).find("<");
QString name = (*it).left(pos);
QString email = (*it).mid(pos);
if (!email.isEmpty()) {
mIncidence->addAttendee(new Attendee(name,email));
}
}
}
#endif
}
QPtrList<KOAgendaItem> KOAgendaItem::conflictItems()
{
return mConflictItems;
}
void KOAgendaItem::setConflictItems(QPtrList<KOAgendaItem> ci)
{
mConflictItems = ci;
KOAgendaItem *item;
for ( item=mConflictItems.first(); item != 0;
item=mConflictItems.next() ) {
item->addConflictItem(this);
}
}
void KOAgendaItem::addConflictItem(KOAgendaItem *ci)
{
if (mConflictItems.find(ci)<0)
mConflictItems.append(ci);
}
bool KOAgendaItem::checkLayout()
{
if ( !mConflictItems.count() )
return true;
int max = 0;
KOAgendaItem *item;
for ( item=mConflictItems.first(); item != 0;
item=mConflictItems.next() ) {
if ( item->subCells() > max )
max = item->subCells();
}
if ( max > subCells() ) {
setSubCells( max );
return false;
}
return true;
}
diff --git a/korganizer/koagendaview.cpp b/korganizer/koagendaview.cpp
index a01323a..04f30bb 100644
--- a/korganizer/koagendaview.cpp
+++ b/korganizer/koagendaview.cpp
@@ -1,1690 +1,1690 @@
/*
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.
*/
#include <qhbox.h>
#include <qvbox.h>
#include <qlabel.h>
#include <qframe.h>
#include <qlayout.h>
#ifndef KORG_NOSPLITTER
#include <qsplitter.h>
#endif
#include <qfont.h>
#include <qfontmetrics.h>
#include <qpopupmenu.h>
#include <qtooltip.h>
#include <qpainter.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <kapplication.h>
#include <KDGanttMinimizeSplitter.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kconfig.h>
#include <kglobal.h>
#include "calendarview.h"
#include "koviewmanager.h"
#include <libkcal/calendar.h>
#include <libkcal/icaldrag.h>
#include <libkcal/dndfactory.h>
#include <kcalendarsystem.h>
#include "koglobals.h"
#ifndef KORG_NOPLUGINS
#include "kocore.h"
#endif
#include "koprefs.h"
#include "koagenda.h"
#include "koagendaitem.h"
#ifndef KORG_NOPRINTER
#include "calprinter.h"
#endif
#include "koagendaview.h"
//#include "koagendaview.moc"
//extern bool globalFlagBlockPainting;
extern int globalFlagBlockAgenda;
extern int globalFlagBlockStartup;
extern int globalFlagBlockAgendaItemPaint;
extern int globalFlagBlockAgendaItemUpdate;
extern int globalFlagBlockLabel;
using namespace KOrg;
#define IDLETIMEOUT 45
TimeLabels::TimeLabels(int rows,QWidget *parent,const char *name,WFlags f) :
QScrollView(parent,name,f)
{
myPix.resize( 1, 1 );
mRows = rows;
mRedrawNeeded = true;
setMinimumHeight( 20 );
mCellHeight = KOPrefs::instance()->mHourSize*4;
enableClipper(true);
setHScrollBarMode(AlwaysOff);
setVScrollBarMode(AlwaysOff);
resizeContents(50,mRows * mCellHeight);
viewport()->setBackgroundMode( PaletteBackground );
}
void TimeLabels::setCellHeight(int height)
{
mCellHeight = height;
}
/*
Optimization so that only the "dirty" portion of the scroll view
is redrawn. Unfortunately, this is not called by default paintEvent() method.
*/
void TimeLabels::drawContents(QPainter *p,int cx, int cy, int cw, int ch)
{
cx = contentsX() + frameWidth()*2;
cw = contentsWidth() ;
// end of workaround
int cell = ((int)(cy/mCellHeight));
int y = cell * mCellHeight;
QFontMetrics fm = fontMetrics();
QString hour;
QString suffix = "am";
int timeHeight = fm.ascent();
QFont nFont = font();
p->setFont( font());
if (!KGlobal::locale()->use12Clock()) {
suffix = "00";
} else
if (cell > 11) suffix = "pm";
if ( timeHeight > mCellHeight ) {
timeHeight = mCellHeight-1;
int pointS = nFont.pointSize();
while ( pointS > 4 ) {
nFont.setPointSize( pointS );
fm = QFontMetrics( nFont );
if ( fm.ascent() < mCellHeight )
break;
-- pointS;
}
fm = QFontMetrics( nFont );
timeHeight = fm.ascent();
}
//timeHeight -= (timeHeight/4-2);
QFont sFont = nFont;
sFont.setPointSize( sFont.pointSize()/2 );
QFontMetrics fmS( sFont );
int sHei = fmS.ascent() ;
//sHei -= (sHei/4-2);
int startW = mMiniWidth - frameWidth()-2 ;
int tw2 = fmS.width(suffix);
timeHeight = (timeHeight-1) /2 -1;
//testline
//p->drawLine(0,0,0,contentsHeight());
while (y < cy + ch+mCellHeight) {
p->drawLine(startW-tw2+1 ,y,cw+2,y);
hour.setNum(cell);
// handle 24h and am/pm time formats
if (KGlobal::locale()->use12Clock()) {
if (cell == 12) suffix = "pm";
if (cell == 0) hour.setNum(12);
if (cell > 12) hour.setNum(cell - 12);
}
// center and draw the time label
int timeWidth = fm.width(hour);
int offset = startW - timeWidth - tw2 -1 ;
p->setFont( nFont );
p->drawText( offset, y+ timeHeight, hour);
p->setFont( sFont );
offset = startW - tw2;
p->drawText( offset, y -1, suffix);
// increment indices
y += mCellHeight;
cell++;
}
}
/**
Calculates the minimum width.
*/
int TimeLabels::minimumWidth() const
{
return mMiniWidth;
}
/** updates widget's internal state */
void TimeLabels::updateConfig()
{
mRedrawNeeded = true;
// set the font
// config->setGroup("Fonts");
// QFont font = config->readFontEntry("TimeBar Font");
setFont(KOPrefs::instance()->mTimeBarFont);
QString test = "20";
if (KGlobal::locale()->use12Clock())
test = "12";
mMiniWidth = fontMetrics().width(test);
if (KGlobal::locale()->use12Clock())
test = "pm";
else {
test = "00";
}
QFont sFont = font();
sFont.setPointSize( sFont.pointSize()/2 );
QFontMetrics fmS( sFont );
mMiniWidth += fmS.width( test ) + frameWidth()*2+4 ;
// update geometry restrictions based on new settings
setFixedWidth( mMiniWidth );
// update HourSize
mCellHeight = KOPrefs::instance()->mHourSize*4;
resizeContents(mMiniWidth,mRows * mCellHeight+1);
}
/** update time label positions */
void TimeLabels::positionChanged()
{
int adjustment = mAgenda->contentsY();
setContentsPos(0, adjustment);
}
/** */
void TimeLabels::setAgenda(KOAgenda* agenda)
{
mAgenda = agenda;
}
void TimeLabels::contentsMousePressEvent ( QMouseEvent * e)
{
mMouseDownY = e->pos().y();
mOrgCap = topLevelWidget()->caption();
}
void TimeLabels::contentsMouseMoveEvent ( QMouseEvent * e )
{
int diff = mMouseDownY - e->pos().y();
if ( diff < 10 && diff > -10 )
return;
int tSize = KOPrefs::instance()->mHourSize + (diff/10) ;
if ( tSize < 4 )
tSize = 4;
if ( tSize > 22 )
tSize = 22;
tSize = (tSize-2)/2;
topLevelWidget()->setCaption(i18n("New Agendasize: %1").arg(tSize));
}
void TimeLabels::contentsMouseReleaseEvent ( QMouseEvent * e )
{
topLevelWidget()->setCaption( mOrgCap );
int diff = mMouseDownY - e->pos().y();
if ( diff < 10 && diff > -10 )
return;
int tSize = KOPrefs::instance()->mHourSize + (diff/10);
if ( tSize < 4 )
tSize = 4;
if ( tSize > 22 )
tSize = 22;
tSize = (tSize/2)*2;
if ( tSize == KOPrefs::instance()->mHourSize )
return;
KOPrefs::instance()->mHourSize = tSize;
emit scaleChanged();
}
/** This is called in response to repaint() */
void TimeLabels::paintEvent(QPaintEvent*)
{
// kdDebug() << "paintevent..." << endl;
// this is another hack!
// QPainter painter(this);
//QString c
repaintContents(contentsX(), contentsY(), visibleWidth(), visibleHeight());
}
////////////////////////////////////////////////////////////////////////////
EventIndicator::EventIndicator(Location loc,QWidget *parent,const char *name)
: QFrame(parent,name)
{
mColumns = 1;
mTopBox = 0;
mLocation = loc;
mTopLayout = 0;
mPaintWidget = 0;
mXOffset = 0;
if (mLocation == Top) mPixmap = SmallIcon("1uparrow");
else mPixmap = SmallIcon("1downarrow");
mEnabled.resize(mColumns);
mEnabled.fill( false );
setMinimumHeight(mPixmap.height());
}
EventIndicator::~EventIndicator()
{
}
void EventIndicator::drawContents(QPainter *p)
{
// kdDebug() << "======== top: " << contentsRect().top() << " bottom " << // contentsRect().bottom() << " left " << contentsRect().left() << " right " << contentsRect().right() << endl;
KDGanttSplitterHandle* han = 0;
if ( mPaintWidget )
han = mPaintWidget->firstHandle();
if ( ! han ) {
int i;
for(i=0;i<mColumns;++i) {
if (mEnabled[i]) {
int cellWidth = contentsRect().right()/mColumns;
int xOffset = KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - i)*cellWidth + (cellWidth -mPixmap.width())/2 :
i*cellWidth + (cellWidth -mPixmap.width()) /2;
p->drawPixmap(QPoint(1+xOffset,0),mPixmap);
}
}
} else {
han->repaint();
//mPaintWidget->setBackgroundColor( red );
QPainter pa( han );
int i;
bool setColor = false;
for(i=0;i<mColumns;++i) {
if (mEnabled[i]) {
setColor = true;
int cellWidth = contentsRect().right()/mColumns;
int xOffset = KOGlobals::self()->reverseLayout() ?
(mColumns - 1 - i)*cellWidth + cellWidth/2 -mPixmap.width()/2 :
i*cellWidth + cellWidth/2 -mPixmap.width()/2;
pa.drawPixmap(QPoint(mXOffset + xOffset,0),mPixmap);
//qDebug("222draw pix %d ",xOffset );
}
}
pa.end();
}
}
void EventIndicator::setXOffset( int x )
{
mXOffset = x;
}
void EventIndicator::setPaintWidget( KDGanttMinimizeSplitter * w )
{
mPaintWidget = w;
setMaximumHeight(0);
setMinimumHeight(0);
}
void EventIndicator::changeColumns(int columns)
{
mColumns = columns;
mEnabled.resize(mColumns);
update();
}
void EventIndicator::enableColumn(int column, bool enable)
{
mEnabled[column] = enable;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
KOAgendaView::KOAgendaView(Calendar *cal,QWidget *parent,const char *name) :
KOEventView (cal,parent,name)
{
mBlockUpdating = true;
mStartHour = 8;
mSelectedDates.append(QDate::currentDate());
mLayoutDayLabels = 0;
mDayLabelsFrame = 0;
mDayLabels = 0;
bool isRTL = KOGlobals::self()->reverseLayout();
QPixmap expandPix;
if ( KOPrefs::instance()->mVerticalScreen ) {
expandPix = SmallIcon( "1updownarrow" );
} else {
expandPix = SmallIcon("1leftrightarrow" );
}
QBoxLayout *topLayout = new QVBoxLayout(this);
// Create day name labels for agenda columns
// Create agenda splitter
mSplitterAgenda = new KDGanttMinimizeSplitter( Qt::Vertical, this);
mSplitterAgenda->setMinimizeDirection ( KDGanttMinimizeSplitter::Up );
topLayout->addWidget( mSplitterAgenda );
mAllDayFrame = new QHBox(mSplitterAgenda);
mAllDayFrame->setFocusPolicy(NoFocus);
QWidget *agendaFrame = new QWidget(mSplitterAgenda);
agendaFrame->setFocusPolicy(NoFocus);
// Create all-day agenda widget
mDummyAllDayLeft = new QVBox( mAllDayFrame );
mExpandButton = new QPushButton(mDummyAllDayLeft);
mExpandButton->setPixmap( expandPix );
int widebut = mExpandButton->sizeHint().width()+4;
int heibut = mExpandButton->sizeHint().height()+4;
if ( heibut > widebut )
widebut = heibut ;
//mExpandButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed,
// QSizePolicy::Fixed ) );
mExpandButton->setFixedSize( widebut, widebut);
connect( mExpandButton, SIGNAL( clicked() ), SIGNAL( toggleExpand() ) );
mExpandButton->setFocusPolicy(NoFocus);
mAllDayAgenda = new KOAgenda(1,mAllDayFrame);
mAllDayAgenda->setFocusPolicy(NoFocus);
QLabel *dummyAllDayRight = new QLabel (mAllDayFrame);
// Create event context menu for all day agenda
//mAllDayAgendaPopup = eventPopup();
// Create agenda frame
QGridLayout *agendaLayout = new QGridLayout(agendaFrame,4,3);
// QHBox *agendaFrame = new QHBox(splitterAgenda);
// create event indicator bars
mEventIndicatorTop = new EventIndicator(EventIndicator::Top,agendaFrame);
#ifndef DESKTOP_VERSION
mEventIndicatorTop->setPaintWidget( mSplitterAgenda );
#endif
mDayLabelsFrame = new QHBox(agendaFrame);
//topLayout->addWidget(mDayLabelsFrame);
mDayLabels = new QFrame (mDayLabelsFrame);
mLayoutDayLabels = new QHBoxLayout(mDayLabels);
agendaLayout->addMultiCellWidget(mDayLabelsFrame ,0,0,0,2);
agendaLayout->addWidget(mEventIndicatorTop,1,1);
mEventIndicatorBottom = new EventIndicator(EventIndicator::Bottom,
agendaFrame);
agendaLayout->addWidget(mEventIndicatorBottom,3,1);
QWidget *dummyAgendaRight = new QWidget(agendaFrame);
agendaLayout->addWidget(dummyAgendaRight,1,2);
// Create time labels
mTimeLabels = new TimeLabels(24,agendaFrame);
agendaLayout->addWidget(mTimeLabels,2,0);
connect(mTimeLabels,SIGNAL( scaleChanged()),
this,SLOT(updateConfig()));
// Create agenda
mAgenda = new KOAgenda(1,96,KOPrefs::instance()->mHourSize,agendaFrame);
agendaLayout->addMultiCellWidget(mAgenda,2,2,1,2);
agendaLayout->setColStretch(1,1);
mAgenda->setFocusPolicy(NoFocus);
// Create event context menu for agenda
mAllAgendaPopup = eventPopup();
#if 0
mAllAgendaPopup->addAdditionalItem(QIconSet(SmallIcon("bell")),
i18n("Toggle Alarm"),mAgenda,
SLOT(popupAlarm()),true);
#endif
connect(mAgenda,SIGNAL(showIncidencePopupSignal(Incidence *)),
mAllAgendaPopup,SLOT(showIncidencePopup(Incidence *)));
connect(mAllDayAgenda,SIGNAL(showIncidencePopupSignal(Incidence *)),
mAllAgendaPopup,SLOT(showIncidencePopup(Incidence *)));
connect(mAllAgendaPopup,SIGNAL(categoryChanged(Incidence *)),
this,SLOT(categoryChanged(Incidence *)));
mAgenda->setPopup( mAllAgendaPopup );
mAllDayAgenda->setPopup( mAllAgendaPopup );
// make connections between dependent widgets
mTimeLabels->setAgenda(mAgenda);
// Update widgets to reflect user preferences
// updateConfig();
// createDayLabels();
// these blank widgets make the All Day Event box line up with the agenda
dummyAllDayRight->setFixedWidth(mAgenda->verticalScrollBar()->width());
dummyAgendaRight->setFixedWidth(mAgenda->verticalScrollBar()->width());
mDummyAllDayLeft->setFixedWidth(mTimeLabels->width());
// Scrolling
connect(mAgenda->verticalScrollBar(),SIGNAL(valueChanged(int)),
mTimeLabels, SLOT(positionChanged()));
connect(mTimeLabels->verticalScrollBar(),SIGNAL(valueChanged(int)),
SLOT(setContentsPos(int)));
connect(mAgenda,SIGNAL(showDateView( int, int)),SLOT(slotShowDateView( int, int )));
connect(mAllDayAgenda,SIGNAL(showDateView( int, int )), SLOT(slotShowDateView( int, int ) ));
// Create/Show/Edit/Delete Event
connect(mAgenda,SIGNAL(newEventSignal(int,int)),
SLOT(newEvent(int,int)));
connect(mAgenda,SIGNAL(newTodoSignal(int,int)),
SLOT(newTodo(int,int)));
connect(mAgenda,SIGNAL(newEventSignal(int,int,int,int)),
SLOT(newEvent(int,int,int,int)));
connect(mAllDayAgenda,SIGNAL(newEventSignal(int,int)),
SLOT(newEventAllDay(int,int)));
connect(mAllDayAgenda,SIGNAL(newTodoSignal(int,int)),
SLOT(newTodoAllDay(int,int)));
connect(mAllDayAgenda,SIGNAL(newEventSignal(int,int,int,int)),
SLOT(newEventAllDay(int,int)));
connect(mAgenda,SIGNAL(newTimeSpanSignal(int,int,int,int)),
SLOT(newTimeSpanSelected(int,int,int,int)));
connect(mAllDayAgenda,SIGNAL(newTimeSpanSignal(int,int,int,int)),
SLOT(newTimeSpanSelectedAllDay(int,int,int,int)));
connect(mAgenda,SIGNAL(newStartSelectSignal()),SLOT(updateView()));
connect(mAllDayAgenda,SIGNAL(newStartSelectSignal()),SLOT(updateView()));
connect(mAgenda,SIGNAL(editIncidenceSignal(Incidence *)),
SIGNAL(editIncidenceSignal(Incidence *)));
connect(mAllDayAgenda,SIGNAL(editIncidenceSignal(Incidence *)),
SIGNAL(editIncidenceSignal(Incidence *)));
connect(mAgenda,SIGNAL(showIncidenceSignal(Incidence *)),
SIGNAL(showIncidenceSignal(Incidence *)));
connect(mAllDayAgenda,SIGNAL(showIncidenceSignal(Incidence *)),
SIGNAL(showIncidenceSignal(Incidence *)));
connect(mAgenda,SIGNAL(deleteIncidenceSignal(Incidence *)),
SIGNAL(deleteIncidenceSignal(Incidence *)));
connect(mAllDayAgenda,SIGNAL(deleteIncidenceSignal(Incidence *)),
SIGNAL(deleteIncidenceSignal(Incidence *)));
connect(mAgenda,SIGNAL(itemModified(KOAgendaItem *, int )),
SLOT(updateEventDates(KOAgendaItem *, int )));
connect(mAllDayAgenda,SIGNAL(itemModified(KOAgendaItem *, int )),
SLOT(updateEventDates(KOAgendaItem *, int)));
// event indicator update
connect(mAgenda,SIGNAL(lowerYChanged(int)),
SLOT(updateEventIndicatorTop(int)));
connect(mAgenda,SIGNAL(upperYChanged(int)),
SLOT(updateEventIndicatorBottom(int)));
// drag signals
/*
connect(mAgenda,SIGNAL(startDragSignal(Event *)),
SLOT(startDrag(Event *)));
connect(mAllDayAgenda,SIGNAL(startDragSignal(Event *)),
SLOT(startDrag(Event *)));
*/
// synchronize selections
connect( mAgenda, SIGNAL( incidenceSelected( Incidence * ) ),
mAllDayAgenda, SLOT( deselectItem() ) );
connect( mAllDayAgenda, SIGNAL( incidenceSelected( Incidence * ) ),
mAgenda, SLOT( deselectItem() ) );
connect( mAgenda, SIGNAL( incidenceSelected( Incidence * ) ),
SIGNAL( incidenceSelected( Incidence * ) ) );
connect( mAllDayAgenda, SIGNAL( incidenceSelected( Incidence * ) ),
SIGNAL( incidenceSelected( Incidence * ) ) );
connect( mAgenda, SIGNAL( resizedSignal() ),
SLOT( updateConfig( ) ) );
connect( mAgenda, SIGNAL( addToCalSignal(Incidence *, Incidence *) ),
SLOT( addToCalSlot(Incidence *, Incidence * ) ) );
connect( mAllDayAgenda, SIGNAL( addToCalSignal(Incidence * ,Incidence *) ),
SLOT( addToCalSlot(Incidence * , Incidence *) ) );
// connect( mAgenda, SIGNAL( cloneIncidenceSignal(Incidence *) ), SIGNAL( cloneIncidenceSignal(Incidence *) ) );
//connect( mAllDayAgenda, SIGNAL( cloneIncidenceSignal(Incidence *) ), SIGNAL( cloneIncidenceSignal(Incidence *) ) );
connect( mAllDayAgenda, SIGNAL( signalClearSelection() ),mAgenda, SLOT( slotClearSelection()) );
connect( mAgenda, SIGNAL( signalClearSelection() ),mAllDayAgenda, SLOT( slotClearSelection()) );
#ifndef DESKTOP_VERSION
connect( mAllDayAgenda, SIGNAL( updateViewSignal() ),this, SLOT( fillAgenda()) );
connect( mAgenda, SIGNAL( updateViewSignal() ), this, SLOT( fillAgenda()) );
connect( mAllDayAgenda, SIGNAL( sendPing() ),this, SLOT( startIdleTimeout()) );
connect( mAgenda, SIGNAL( sendPing() ), this, SLOT( startIdleTimeout()) );
mIdleTimer = new QTimer ( this );;
connect(mIdleTimer,SIGNAL(timeout()),SLOT(slotIdleTimeout()));
#endif
}
void KOAgendaView::startIdleTimeout()
{
#ifndef DESKTOP_VERSION
mIdleStart = QDateTime::currentDateTime();
mIdleTimer->start( IDLETIMEOUT * 1000 );
#endif
}
void KOAgendaView::slotIdleTimeout()
{
#ifndef DESKTOP_VERSION
//qDebug("SECS TO %d ",mIdleStart.secsTo( QDateTime::currentDateTime() ) );
int secsfromstart = mIdleStart.secsTo( QDateTime::currentDateTime() );
mIdleTimer->stop();
bool isActice = topLevelWidget()->isActiveWindow();
//qDebug("KO: Active Window %d %d", isActice, isVisible());
// we do nothing if we wake up from a suspend
if ( secsfromstart > IDLETIMEOUT + 30 && isActice ) {
qDebug("KO: Wakeup from suspend ");
startIdleTimeout();
return;
}
qDebug("KO: Downsizing Pixmaps ");
mAgenda->shrinkPixmap();
mAllDayAgenda->shrinkPixmap();
KOAgendaItem::paintPix()->resize( 20,20);
KOAgendaItem::paintPixAllday()->resize( 20,20);
#endif
}
void KOAgendaView::toggleAllDay()
{
if ( mSplitterAgenda->firstHandle() )
mSplitterAgenda->firstHandle()->toggle();
}
void KOAgendaView::addToCalSlot(Incidence * inc, Incidence * incOld )
{
calendar()->addIncidence( inc );
if ( incOld ) {
if ( incOld->typeID() == todoID )
emit todoMoved((Todo*)incOld, KOGlobals::EVENTEDITED );
else
emit incidenceChanged(incOld, KOGlobals::EVENTEDITED);
}
}
void KOAgendaView::categoryChanged(Incidence * inc)
{
mAgenda->categoryChanged( inc );
mAllDayAgenda->categoryChanged( inc );
}
KOAgendaView::~KOAgendaView()
{
delete mAllAgendaPopup;
//delete mAllDayAgendaPopup;
delete KOAgendaItem::paintPix();
delete KOAgendaItem::paintPixAllday();
}
void KOAgendaView::resizeEvent( QResizeEvent* e )
{
//qDebug("KOAgendaView::resizeEvent( QResizeEvent* e ) %d ", e->size().width());
bool uc = false;
int ow = e->oldSize().width();
int oh = e->oldSize().height();
int w = e->size().width();
int h = e->size().height();
if ( (ow > oh && w< h ) || (ow < oh && w > h ) ) {
if ( ! mBlockUpdating && !globalFlagBlockStartup && !globalFlagBlockAgenda )
uc = true;
//qDebug("view changed %d %d %d %d ", ow, oh , w , h);
}
mUpcomingWidth = e->size().width() ;
if ( mBlockUpdating || uc ) {
mBlockUpdating = false;
//mAgenda->setMinimumSize(800 , 600 );
//qDebug("mAgenda->resize+++++++++++++++ ");
updateConfig();
//qDebug("KOAgendaView::Updating now possible ");
} else
createDayLabels();
//qDebug("resizeEvent end ");
}
void KOAgendaView::slotDaylabelClicked( int num )
{
QDate firstDate = mSelectedDates.first();
if ( num == -1 )
emit showDateView( 6, firstDate );
else if (num >= 0 ) {
if ( mSelectedDates.count() == 1)
emit showDateView( 9, firstDate.addDays( num ) );
else
emit showDateView( 3, firstDate.addDays( num ) );
}
else
showDateView( 10, firstDate.addDays(1) );
}
KOAgendaButton* KOAgendaView::getNewDaylabel()
{
KOAgendaButton * dayLabel = new KOAgendaButton(mDayLabels);
connect( dayLabel, SIGNAL( numClicked(int) ), this, SLOT ( slotDaylabelClicked(int) ) );
mDayLabelsList.append( dayLabel );
mLayoutDayLabels->addWidget(dayLabel);
return dayLabel ;
}
void KOAgendaView::createDayLabels()
{
if ( mBlockUpdating || globalFlagBlockLabel == 1) {
// qDebug(" KOAgendaView::createDayLabels() blocked ");
return;
}
int newHight;
if ( !mSelectedDates.count())
return;
// ### Before deleting and recreating we could check if mSelectedDates changed...
// It would remove some flickering and gain speed (since this is called by
// each updateView() call)
int maxWid = mUpcomingWidth - mTimeLabels->width()- mAgenda->verticalScrollBar()->width() - mAgenda->frameWidth()*2;
mDayLabelsFrame->setMaximumWidth( mUpcomingWidth );
if ( maxWid < 20 )
maxWid = 20;
QFont dlf = KOPrefs::instance()->mTimeLabelsFont;
QFontMetrics fm ( dlf );
dlf.setBold( true );
int selCount = mSelectedDates.count();
int widModulo = maxWid - (mAgenda->gridSpacingX() * selCount)+1;
QString dayTest = "Mon 20";
//QString dayTest = "Mon 20";
int wid = fm.width( dayTest );
//maxWid -= ( selCount * 3 ); //working for QLabels
if ( QApplication::desktop()->width() <= 320 )
maxWid -= ( selCount * 3 ); //working for QPushButton
else
maxWid -= ( selCount * 4 ); //working for QPushButton
if ( maxWid < 0 )
maxWid = 20;
int needWid = wid * selCount;
//qDebug("++++++++Needed : %d MaxWidth: %d", needWid, maxWid );
//if ( needWid > maxWid )
// qDebug("DAYLABELS TOOOOOOO BIG ");
while ( needWid > maxWid ) {
dayTest = dayTest.left( dayTest.length() - 1 );
wid = fm.width( dayTest );
needWid = wid * selCount;
}
int maxLen = dayTest.length();
int fontPoint = dlf.pointSize();
if ( maxLen < 2 ) {
int fontPoint = dlf.pointSize();
while ( fontPoint > 4 ) {
--fontPoint;
dlf.setPointSize( fontPoint );
QFontMetrics f( dlf );
wid = f.width( "30" );
needWid = wid * selCount;
if ( needWid < maxWid )
break;
}
maxLen = 2;
}
//qDebug("Max len %d ", dayTest.length() );
if ( !KOPrefs::instance()->mTimeLabelsFont.bold() )
dlf.setBold( false );
QFontMetrics tempF( dlf );
newHight = tempF.height();
mDayLabels->setFont( dlf );
// mLayoutDayLabels = new QHBoxLayout(mDayLabels);;
// mLayoutDayLabels->addSpacing(mTimeLabels->width());
//mLayoutDayLabels->addSpacing( 2 );
// QFont lFont = dlf;
bool appendLabels = false;
KOAgendaButton *dayLabel;
dayLabel = mDayLabelsList.first();
if ( !dayLabel ) {
appendLabels = true;
dayLabel = getNewDaylabel();
}
dayLabel->setFixedWidth( mTimeLabels->width()+mAgenda->frameWidth() );
dayLabel->setFont( dlf );
dayLabel->setNum( -1 );
//dayLabel->setAlignment(QLabel::AlignHCenter);
dayLabel->setText( KOGlobals::self()->calendarSystem()->monthName( mSelectedDates.first(), true ) );
dayLabel->show();
DateList::ConstIterator dit;
bool oneday = (mSelectedDates.first() == mSelectedDates.last() );
int counter = -1;
for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) {
++counter;
QDate date = *dit;
// QBoxLayout *dayLayout = new QVBoxLayout(mLayoutDayLabels);
if ( ! appendLabels ) {
dayLabel = mDayLabelsList.next();
if ( !dayLabel )
appendLabels = true;
}
if ( appendLabels ) {
dayLabel = getNewDaylabel();
}
dayLabel->setMinimumWidth( 1 );
dayLabel->setMaximumWidth( 10240 );
dayLabel->setFont( dlf );
dayLabel->show();
dayLabel->setAutoRepeat( false );
dayLabel->setNum( counter );
QString str;
int dW = KOGlobals::self()->calendarSystem()->dayOfWeek(date);
QString dayName = KOGlobals::self()->calendarSystem()->weekDayName( dW, true );
switch ( maxLen ) {
case 2:
str = QString::number( date.day() );
break;
case 3:
str = dayName.left( 1 ) +QString::number( date.day());
break;
case 4:
str = dayName.left( 1 ) + " " +QString::number( date.day());
break;
case 5:
str = dayName.left( 2 ) + " " +QString::number( date.day());
break;
case 6:
str = dayName.left( 3 ) + " " +QString::number( date.day());
break;
default:
break;
}
if ( oneday ) {
QString addString;
if ( mSelectedDates.first() == QDateTime::currentDateTime().date() )
addString = i18n("Today");
else if ( mSelectedDates.first() == QDateTime::currentDateTime().date().addDays(1) )
addString = i18n("Tomorrow");
else if ( mSelectedDates.first() == QDateTime::currentDateTime().date().addDays(-1) )
addString = i18n("Yesterday");
else if ( mSelectedDates.first() == QDateTime::currentDateTime().date().addDays(-2) )
addString = i18n("Day before yesterday");
else if ( mSelectedDates.first() == QDateTime::currentDateTime().date().addDays(2) )
addString = i18n("Day after tomorrow");
if ( !addString.isEmpty() ) {
if ( QApplication::desktop()->width() < 640 )
str = addString+", " + str;
else
str = addString+", "+ KGlobal::locale()->formatDate( date, false);
} else {
str = KGlobal::locale()->formatDate( date, KOPrefs::instance()->mShortDateInViewer);
}
}
dayLabel->setText(str);
//dayLabel->setAlignment(QLabel::AlignHCenter);
if (date == QDate::currentDate()) {
QFont bFont = dlf;
bFont.setBold( true );
dayLabel->setFont(bFont);
}
//dayLayout->addWidget(dayLabel);
#ifndef KORG_NOPLUGINS
CalendarDecoration::List cds = KOCore::self()->calendarDecorations();
CalendarDecoration *it;
for(it = cds.first(); it; it = cds.next()) {
QString text = it->shortText( date );
if ( !text.isEmpty() ) {
QLabel *label = new QLabel(text,mDayLabels);
label->setAlignment(AlignCenter);
dayLayout->addWidget(label);
}
}
for(it = cds.first(); it; it = cds.next()) {
QWidget *wid = it->smallWidget(mDayLabels,date);
if ( wid ) {
// wid->setHeight(20);
dayLayout->addWidget(wid);
}
}
#endif
}
if ( ! appendLabels ) {
dayLabel = mDayLabelsList.next();
if ( !dayLabel )
appendLabels = true;
}
if ( appendLabels ) {
dayLabel = getNewDaylabel();
}
//dayLabel->hide();//test only
dayLabel->setText(">");
dayLabel->setFont( dlf );
dayLabel->setAutoRepeat( true );
dayLabel->show();
dayLabel->setNum( -2 );
dayLabel->setFixedWidth( mAgenda->verticalScrollBar()->width()+ widModulo );
//mLayoutDayLabels->addSpacing(mAgenda->verticalScrollBar()->width()+ offset+2);
if ( !appendLabels ) {
dayLabel = mDayLabelsList.next();
while ( dayLabel ) {
//qDebug("!dayLabel %d",dayLabel );
dayLabel->hide();
dayLabel = mDayLabelsList.next();
}
}
mDayLabelsFrame->setFixedHeight( newHight + 4 );
}
int KOAgendaView::maxDatesHint()
{
// Not sure about the max number of events, so return 0 for now.
return 0;
}
int KOAgendaView::currentDateCount()
{
return mSelectedDates.count();
}
QPtrList<Incidence> KOAgendaView::selectedIncidences()
{
QPtrList<Incidence> selected;
Incidence *incidence;
incidence = mAgenda->selectedIncidence();
if (incidence) selected.append(incidence);
incidence = mAllDayAgenda->selectedIncidence();
if (incidence) selected.append(incidence);
return selected;
}
DateList KOAgendaView::selectedDates()
{
DateList selected;
QDate qd;
qd = mAgenda->selectedIncidenceDate();
if (qd.isValid()) selected.append(qd);
qd = mAllDayAgenda->selectedIncidenceDate();
if (qd.isValid()) selected.append(qd);
return selected;
}
void KOAgendaView::updateView()
{
if ( mBlockUpdating )
return;
// kdDebug() << "KOAgendaView::updateView()" << endl;
fillAgenda();
}
/*
Update configuration settings for the agenda view. This method is not
complete.
*/
void KOAgendaView::updateConfig()
{
if ( mBlockUpdating )
return;
if ( mAgenda->height() > 96 * KOPrefs::instance()->mHourSize ) {
int old = KOPrefs::instance()->mHourSize;
KOPrefs::instance()->mHourSize = mAgenda->height()/96 +1;
//qDebug("KOPrefs::instance()->mHourSize adjusted %d to %d ", old,KOPrefs::instance()->mHourSize );
}
// update config for children
mTimeLabels->updateConfig();
mAgenda->storePosition();
mAgenda->updateConfig();
mAllDayAgenda->updateConfig();
// widget synchronization
//TODO: find a better way, maybe signal/slot
mTimeLabels->positionChanged();
// for some reason, this needs to be called explicitly
mTimeLabels->repaint();
mDummyAllDayLeft->setFixedWidth(mTimeLabels->width());
// ToolTips displaying summary of events
KOAgendaItem::toolTipGroup()->setEnabled(KOPrefs::instance()
->mEnableToolTips);
//setHolidayMasks();
//createDayLabels(); called by via updateView();
mEventIndicatorTop->setXOffset(mTimeLabels->width() + mAgenda->frameWidth());
updateView();
mAgenda->restorePosition();
}
void KOAgendaView::updateEventDates(KOAgendaItem *item, int type)
{
int xxx = item->cellX();
//qDebug("KOAgendaView::updateEventDates %d %d %d %d %d", xxx, mMinY.at(xxx),mMaxY.at(xxx),item->cellYTop(),item->cellYBottom() );
if ( mMinY.at(xxx) > item->cellYTop() )
mMinY.at(xxx) = item->cellYTop();
if ( mMaxY.at(xxx) < item->cellYBottom() )
mMaxY.at(xxx) = item->cellYBottom();
QDateTime startDt,endDt;
QDate startDate;
int lenInSecs;
// if ( type == KOAgenda::RESIZETOP )
// qDebug("RESIZETOP ");
// if ( type == KOAgenda::RESIZEBOTTOM )
// qDebug("RESIZEBOTTOM ");
// if ( type == KOAgenda::MOVE )
// qDebug("MOVE ");
if ( item->incidence()->typeID() == eventID ) {
startDt =item->incidence()->dtStart();
endDt = item->incidence()->dtEnd();
lenInSecs = startDt.secsTo( endDt );
}
// emit incidenceItemChanged( item->incidence(), KOGlobals::EVENTEDITED );
if ( item->incidence()->typeID()== todoID && item->mLastMoveXPos > 0 ) {
startDate = mSelectedDates[item->mLastMoveXPos];
} else {
if (item->cellX() < 0) {
startDate = (mSelectedDates.first()).addDays(item->cellX());
} else {
startDate = mSelectedDates[item->cellX()];
}
}
startDt.setDate(startDate);
if (item->incidence()->doesFloat()) {
endDt.setDate(startDate.addDays(item->cellWidth() - 1));
} else {
if ( type == KOAgenda::RESIZETOP || type == KOAgenda::MOVE )
startDt.setTime(mAgenda->gyToTime(item->cellYTop()));
if ( item->incidence()->typeID() == eventID ) {
if ( type == KOAgenda::MOVE ) {
endDt = startDt.addSecs(lenInSecs);
} else if ( type == KOAgenda::RESIZEBOTTOM ) {
if (item->lastMultiItem()) {
endDt.setTime(mAgenda->gyToTime(item->lastMultiItem()->cellYBottom()+1));
endDt.setDate(startDate.
addDays(item->lastMultiItem()->cellX() - item->cellX()));
} else {
endDt.setTime(mAgenda->gyToTime(item->cellYBottom()+1));
endDt.setDate(startDate);
}
}
} else {
// todo
if (item->lastMultiItem()) {
endDt.setTime(mAgenda->gyToTime(item->lastMultiItem()->cellYBottom()+1));
endDt.setDate(startDate.
addDays(item->lastMultiItem()->cellX() - item->cellX()));
} else {
//qDebug("tem->cellYBottom() %d",item->cellYBottom() );
if ( item->cellYBottom() > 0 )
endDt.setTime(mAgenda->gyToTime(item->cellYBottom()+1));
else
endDt.setTime((static_cast<Todo*>(item->incidence()))->dtDue().time());
endDt.setDate(startDate);
}
}
}
if ( item->incidence()->typeID() == eventID ) {
item->incidence()->setDtStart(startDt);
(static_cast<Event*>(item->incidence()))->setDtEnd(endDt);
} else if ( item->incidence()->typeID() == todoID ) {
Todo* to = static_cast<Todo*>(item->incidence());
to->setDtDue(endDt);
if ( to->hasStartDate() ) {
if (to->dtStart() >= to->dtDue() )
to->setDtStart(to->dtDue().addDays( -2 ));
}
}
//qDebug("KOAgendaView::updateEventDates stsart %s end %s ", startDt.toString().latin1(), endDt.toString().latin1() );
item->incidence()->setRevision(item->incidence()->revision()+1);
item->setItemDate(startDt.date());
//item->updateItem();
if ( item->incidence()->typeID() == todoID ) {
emit todoMoved((Todo*)item->incidence(), KOGlobals::EVENTEDITED );
}
else
emit incidenceChanged(item->incidence(), KOGlobals::EVENTEDITED);
item->updateItem();
}
void KOAgendaView::showDates( const QDate &start, const QDate &end )
{
// kdDebug() << "KOAgendaView::selectDates" << endl;
mSelectedDates.clear();
// qDebug("KOAgendaView::showDates ");
QDate d = start;
while (d <= end) {
mSelectedDates.append(d);
d = d.addDays( 1 );
}
// and update the view
fillAgenda();
}
void KOAgendaView::showEvents(QPtrList<Event>)
{
kdDebug() << "KOAgendaView::showEvents() is not yet implemented" << endl;
}
void KOAgendaView::changeEventDisplay(Event *, int)
{
// qDebug("KOAgendaView::changeEventDisplay ");
// kdDebug() << "KOAgendaView::changeEventDisplay" << endl;
// this should be re-written to be MUCH smarter. Right now we
// are just playing dumb.
fillAgenda();
}
void KOAgendaView::fillAgenda(const QDate &)
{
// qDebug("KOAgendaView::fillAgenda ");
fillAgenda();
}
void KOAgendaView::fillAgenda()
{
if ( globalFlagBlockStartup )
return;
if ( globalFlagBlockAgenda == 1 )
return;
static bool onlyOne = false;
if ( onlyOne )
return;
onlyOne = true;
//if ( globalFlagBlockAgenda == 2 )
//globalFlagBlockAgenda = 0;
// globalFlagBlockPainting = false;
if ( globalFlagBlockAgenda == 0 )
globalFlagBlockAgenda = 1;
// clearView();
//qDebug("fillAgenda()++++ ");
globalFlagBlockAgendaItemPaint = 1;
mAllDayAgenda->changeColumns(mSelectedDates.count());
mAgenda->changeColumns(mSelectedDates.count());
qApp->processEvents();
mEventIndicatorTop->changeColumns(mSelectedDates.count());
mEventIndicatorBottom->changeColumns(mSelectedDates.count());
setHolidayMasks();
mMinY.resize(mSelectedDates.count());
mMaxY.resize(mSelectedDates.count());
QPtrList<Event> dayEvents;
// ToDo items shall be displayed for the day they are due, but only showed today if they are already overdue.
// Therefore, gtodoset all of them.
QPtrList<Todo> todos = calendar()->todos();
mAgenda->setDateList(mSelectedDates);
QDate today = QDate::currentDate();
DateList::ConstIterator dit;
int curCol = 0;
int maxCol = mSelectedDates.count()-1;
for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) {
QDate currentDate = *dit;
// kdDebug() << "KOAgendaView::fillAgenda(): " << currentDate.toString()
// << endl;
dayEvents = calendar()->events(currentDate,false);
// Default values, which can never be reached
mMinY[curCol] = mAgenda->timeToY(QTime(23,59)) + 1;
mMaxY[curCol] = mAgenda->timeToY(QTime(0,0)) - 1;
unsigned int numEvent;
//qDebug("+++++NUMEVENT %d", dayEvents.count());
for(numEvent=0;numEvent<dayEvents.count();++numEvent) {
Event *event = dayEvents.at(numEvent);
if ( !KOPrefs::instance()->mShowSyncEvents && event->uid().left(2) == QString("la") )
if ( event->uid().left(15) == QString("last-syncEvent-") )
continue;
// kdDebug() << " Event: " << event->summary() << endl;
int beginX = currentDate.daysTo(event->dtStart().date()) + curCol;
int endX = currentDate.daysTo(event->dtEnd().date()) + curCol;
// kdDebug() << " beginX: " << beginX << " endX: " << endX << endl;
if (event->doesFloat()) {
- if (event->recurrence()->doesRecur()) {
+ if (event->doesRecur()) {
if (event->isMultiDay() ) {
endX = endX - beginX;// endX is now number of days
if ( event->recursOn( currentDate ) ) {
endX += curCol;
beginX = curCol;
mAllDayAgenda->insertAllDayItem(event,currentDate,beginX,endX);
} else {
//qDebug("days endX %d curCol %d max Col %d %s",endX ,curCol, maxCol, currentDate.toString().latin1());
if ( curCol == maxCol && maxCol+1 < endX ) {
int i;
for ( i = 1; i< endX; ++i ) {
if ( event->recursOn( currentDate.addDays( -i ) ) )
break;
}
if ( i > maxCol ) {
mAllDayAgenda->insertAllDayItem(event,currentDate,0,curCol);
//qDebug("BINGO ");
}
} else {
QDate dateit = currentDate.addDays( -endX );
if ( event->recursOn( dateit ) ) {
//qDebug("found %d %d %d %s", endX,curCol, curCol-endX ,dateit.toString().latin1() );
if ( curCol-endX < 0 ) {
mAllDayAgenda->insertAllDayItem(event,currentDate,0,curCol);
}
}
}
}
} else {
mAllDayAgenda->insertAllDayItem(event,currentDate,curCol,curCol);
}
} else {
if (beginX <= 0 && curCol == 0) {
mAllDayAgenda->insertAllDayItem(event,currentDate,beginX,endX);
} else if (beginX == curCol) {
mAllDayAgenda->insertAllDayItem(event,currentDate,beginX,endX);
}
}
} else if (event->isMultiDay()) {
if ( event->doesRecur () ) {
QDate dateit = currentDate;
int count = 0;
int max = event->dtStart().daysTo( event->dtEnd() ) +2;
while (! event->recursOn( dateit ) && count <= max ) {
++count;
dateit = dateit.addDays( -1 );
}
bool ok;
QDateTime nextOcstart = event->getNextOccurence( QDateTime(dateit) ,&ok );
if ( ok )
{
int secs = event->dtStart().secsTo( event->dtEnd() );
QDateTime nextOcend =nextOcstart.addSecs( secs ); ;
beginX = currentDate.daysTo(nextOcstart.date()) + curCol;
endX = currentDate.daysTo(nextOcend.date()) + curCol;
}
}
int startY = mAgenda->timeToY(event->dtStart().time());
int endY = mAgenda->timeToY(event->dtEnd().time()) - 1;
//qDebug("insert %d %d %d %d %d ",beginX,endX,startY,endY , curCol );
if ((beginX <= 0 && curCol == 0) || beginX == curCol) {
//qDebug("insert!!! ");
mAgenda->insertMultiItem(event,currentDate,beginX,endX,startY,endY);
}
if (beginX == curCol) {
mMaxY[curCol] = mAgenda->timeToY(QTime(23,59));
if (startY < mMinY[curCol]) mMinY[curCol] = startY;
} else if (endX == curCol) {
mMinY[curCol] = mAgenda->timeToY(QTime(0,0));
if (endY > mMaxY[curCol]) mMaxY[curCol] = endY;
} else {
mMinY[curCol] = mAgenda->timeToY(QTime(0,0));
mMaxY[curCol] = mAgenda->timeToY(QTime(23,59));
}
} else {
int startY = mAgenda->timeToY(event->dtStart().time());
int endY = mAgenda->timeToY(event->dtEnd().time()) - 1;
if (endY < startY) endY = startY;
mAgenda->insertItem(event,currentDate,curCol,startY,endY);
if (startY < mMinY[curCol]) mMinY[curCol] = startY;
if (endY > mMaxY[curCol]) mMaxY[curCol] = endY;
}
}
// ---------- [display Todos --------------
unsigned int numTodo;
for (numTodo = 0; numTodo < todos.count(); ++numTodo) {
Todo *todo = todos.at(numTodo);
if ( ! todo->hasDueDate() && !todo->hasCompletedDate()) continue; // todo shall not be displayed if it has no date
if ( todo->hasCompletedDate() && !KOPrefs::instance()->mShowCompletedTodoInAgenda ) continue;
// ToDo items shall be displayed for the day they are due, but only showed today if they are already overdue.
// Already completed items can be displayed on their original due date
//if not KOPrefs::instance()->mShowTodoInAgenda, show overdue in agenda
bool overdue = (!todo->isCompleted()) && (todo->dtDue() < today) && KOPrefs::instance()->mShowTodoInAgenda;
bool fillIn = false;
if ( todo->hasCompletedDate() && todo->completed().date() == currentDate )
fillIn = true;
if ( ! fillIn && !todo->hasCompletedDate() )
fillIn = ((todo->dtDue().date() == currentDate) && !overdue) || ((currentDate == today) && overdue);
if ( fillIn ) {
if ( (todo->doesFloat() || overdue ) && !todo->hasCompletedDate() ) { // Todo has no due-time set or is already overdue
if ( KOPrefs::instance()->mShowTodoInAgenda )
mAllDayAgenda->insertAllDayItem(todo, currentDate, curCol, curCol);
}
else {
QDateTime dt;
if ( todo->hasCompletedDate() )
dt = todo->completed();
else
dt = todo->dtDue();;
int endY = mAgenda->timeToY(dt.time()) - 1;
int hi = (18/KOPrefs::instance()->mHourSize);
//qDebug("hei %d ",KOPrefs::instance()->mHourSize);
int startY = endY -hi;
mAgenda->insertItem(todo,currentDate,curCol,startY,endY);
if (startY < mMinY[curCol]) mMinY[curCol] = startY;
if (endY > mMaxY[curCol]) mMaxY[curCol] = endY;
}
}
}
// ---------- display Todos] --------------
++curCol;
}
mAgenda->hideUnused();
mAllDayAgenda->hideUnused();
mAgenda->checkScrollBoundaries();
deleteSelectedDateTime();
createDayLabels();
emit incidenceSelected( 0 );
if ( globalFlagBlockAgenda == 2 ) {
if ( KOPrefs::instance()->mSetTimeToDayStartAt )
setStartHour( KOPrefs::instance()->mDayBegins );
else if ( KOPrefs::instance()->mCenterOnCurrentTime )
setStartHour( QTime::currentTime ().hour() );
}
qApp->processEvents();
globalFlagBlockAgenda = 0;
mAllDayAgenda->drawContentsToPainter();
mAgenda->drawContentsToPainter();
repaintAgenda();
startIdleTimeout();
onlyOne = false;
}
void KOAgendaView::repaintAgenda()
{
mAgenda->viewport()->repaint( false );
mAllDayAgenda->viewport()->repaint( false );
mAgenda->finishUpdate();
mAllDayAgenda->finishUpdate();
}
void KOAgendaView::clearView()
{
mAllDayAgenda->clear();
mAgenda->clear();
}
void KOAgendaView::clearList()
{
clearView();
mAllDayAgenda->hideUnused();
mAgenda->hideUnused();
}
void KOAgendaView::printPreview(CalPrinter *calPrinter, const QDate &fd,
const QDate &td)
{
#ifndef KORG_NOPRINTER
if (fd == td)
calPrinter->preview(CalPrinter::Day, fd, td);
else
calPrinter->preview(CalPrinter::Week, fd, td);
#endif
}
// void KOAgendaView::updateMovedTodo()
// {
// // updateConfig();
// // emit updateTodoViews();
// }
void KOAgendaView::slotShowDateView( int mode , int d )
{
if ( d >= mSelectedDates.count() ) {
qDebug("KOAgendaView::slotShowDateView datecounterror %d %d ", d, mSelectedDates.count() );
} else {
QDate day = mSelectedDates[d];
emit showDateView(mode , day );
}
}
void KOAgendaView::newEvent(int gx, int gy)
{
if (!mSelectedDates.count()) return;
QDate day = mSelectedDates[gx];
QTime time = mAgenda->gyToTime(gy);
QDateTime dt(day,time);
// if ( dt < QDateTime::currentDateTime () )
// dt = QDateTime::currentDateTime ().addSecs( 3600 );
emit newEventSignal(dt);
}
void KOAgendaView::newEvent(int gxStart, int gyStart, int gxEnd, int gyEnd)
{
if (!mSelectedDates.count()) return;
QDate dayStart = mSelectedDates[gxStart];
QDate dayEnd = mSelectedDates[gxEnd];
QTime timeStart = mAgenda->gyToTime(gyStart);
QTime timeEnd = mAgenda->gyToTime( gyEnd + 1 );
QDateTime dtStart(dayStart,timeStart);
QDateTime dtEnd(dayEnd,timeEnd);
emit newEventSignal(dtStart,dtEnd);
}
void KOAgendaView::newEventAllDay(int gx, int )
{
if (!mSelectedDates.count()) return;
QDate day = mSelectedDates[gx];
emit newEventSignal(day);
}
void KOAgendaView::newTodoAllDay(int gx, int )
{
if (!mSelectedDates.count()) return;
QDateTime day (mSelectedDates[gx] );
emit newTodoSignal(day, true);
}
void KOAgendaView::newTodo(int gx, int gy )
{
if (!mSelectedDates.count()) return;
QDate dayStart = mSelectedDates[gx];
QTime timeStart = mAgenda->gyToTime(gy);
QDateTime dt (dayStart,timeStart);
emit newTodoSignal( dt, false );
}
void KOAgendaView::updateEventIndicatorTop(int newY)
{
uint i;
for(i=0;i<mMinY.size();++i) {
if (newY >= mMinY.at(i)) mEventIndicatorTop->enableColumn(i,true);
else mEventIndicatorTop->enableColumn(i,false);
}
mEventIndicatorTop->update();
}
void KOAgendaView::updateEventIndicatorBottom(int newY)
{
uint i;
for(i=0;i<mMaxY.size();++i) {
if (newY <= mMaxY.at(i)) mEventIndicatorBottom->enableColumn(i,true);
else mEventIndicatorBottom->enableColumn(i,false);
}
mEventIndicatorBottom->update();
}
void KOAgendaView::startDrag(Event *event)
{
#ifndef KORG_NODND
DndFactory factory( calendar() );
ICalDrag *vd = factory.createDrag(event,this);
if (vd->drag()) {
kdDebug() << "KOAgendaView::startDrag(): Delete drag source" << endl;
}
#endif
}
void KOAgendaView::readSettings()
{
readSettings(KOGlobals::config());
}
void KOAgendaView::readSettings(KConfig *config)
{
// kdDebug() << "KOAgendaView::readSettings()" << endl;
config->setGroup("Views");
//#ifndef KORG_NOSPLITTER
QValueList<int> sizes = config->readIntListEntry("Separator AgendaView");
if (sizes.count() == 2) {
if ( sizes[0] < 20 ) {
sizes[1] = sizes[1] +20 - sizes[0];
sizes[0] = 20;
}
mSplitterAgenda->setSizes(sizes);
// qDebug("read %d %d ",sizes[0],sizes[1] );
}
//#endif
// updateConfig();
}
void KOAgendaView::writeSettings(KConfig *config)
{
// kdDebug() << "KOAgendaView::writeSettings()" << endl;
config->setGroup("Views");
//#ifndef KORG_NOSPLITTER
QValueList<int> list = mSplitterAgenda->sizes();
config->writeEntry("Separator AgendaView",list);
//qDebug("write %d %d ", list[0],list[1] );
//#endif
}
void KOAgendaView::setHolidayMasks()
{
mHolidayMask.resize(mSelectedDates.count());
uint i;
for(i=0;i<mSelectedDates.count();++i) {
QDate date = mSelectedDates[i];
bool showSaturday = KOPrefs::instance()->mExcludeSaturdays && (date.dayOfWeek() == 6);
bool showSunday = KOPrefs::instance()->mExcludeHolidays && (date.dayOfWeek() == 7);
bool showHoliday = false;
if ( KOPrefs::instance()->mExcludeHolidays ) {
QPtrList<Event> events = calendar()->events( date, true );
Event *event;
for( event = events.first(); event; event = events.next() ) {
if ( event->isHoliday()) {
showHoliday = true;
break;
}
}
}
#ifndef KORG_NOPLUGINS
bool showHoliday = KOPrefs::instance()->mExcludeHolidays &&
!KOCore::self()->holiday(date).isEmpty();
#endif
bool showDay = showSaturday || showSunday || showHoliday;
if (showDay) {
mHolidayMask.at(i) = true;
} else {
mHolidayMask.at(i) = false;
}
}
mAgenda->setHolidayMask(&mHolidayMask);
mAllDayAgenda->setHolidayMask(&mHolidayMask);
}
void KOAgendaView::setContentsPos(int y)
{
mAgenda->setContentsPos(0,y);
}
void KOAgendaView::clearSelection()
{
mAgenda->deselectItem();
mAllDayAgenda->deselectItem();
}
void KOAgendaView::newTimeSpanSelectedAllDay(int gxStart, int gyStart,
int gxEnd, int gyEnd)
{
mTimeSpanInAllDay = true;
newTimeSpanSelected(gxStart,gyStart,gxEnd,gyEnd);
}
void KOAgendaView::newTimeSpanSelected(int gxStart, int gyStart,
int gxEnd, int gyEnd)
{
if (!mSelectedDates.count()) return;
QDate dayStart = mSelectedDates[gxStart];
QDate dayEnd = mSelectedDates[gxEnd];
QTime timeStart = mAgenda->gyToTime(gyStart);
QTime timeEnd = mAgenda->gyToTime( gyEnd + 1 );
QDateTime dtStart(dayStart,timeStart);
QDateTime dtEnd(dayEnd,timeEnd);
mTimeSpanBegin = dtStart;
mTimeSpanEnd = dtEnd;
}
void KOAgendaView::deleteSelectedDateTime()
{
mTimeSpanBegin.setDate(QDate());
mTimeSpanEnd.setDate(QDate());
mTimeSpanInAllDay = false;
}
void KOAgendaView::keyPressEvent ( QKeyEvent * e )
{
e->ignore();
}
void KOAgendaView::scrollOneHourUp()
{
mAgenda->scrollBy ( 0, -mAgenda->contentsHeight () / 24 );
}
void KOAgendaView::scrollOneHourDown()
{
mAgenda->scrollBy ( 0, mAgenda->contentsHeight () / 24 );
}
void KOAgendaView::setStartHour( int h )
{
mAgenda->setStartHour( h );
}
void KOAgendaView::setInitStartHour()
{
if ( KOPrefs::instance()->mCenterOnCurrentTime )
setStartHour( QTime::currentTime ().hour() );
else
setStartHour( KOPrefs::instance()->mDayBegins );
}
void KOAgendaView::updateTodo( Todo * t, int )
{
if ( !isVisible() )
return;
bool remove = false;
bool removeAD = false;
QDate da;
if ( t->hasCompletedDate() )
da = t->completed().date();
else
da = t->dtDue().date();
if ( ! t->hasDueDate() && !t->hasCompletedDate() ) {
remove = true;
removeAD = true;
}
else {
bool overdue = (!t->isCompleted()) && (t->dtDue() < QDate::currentDate()) && KOPrefs::instance()->mShowTodoInAgenda ;
if ( overdue &&
QDate::currentDate() >= mSelectedDates.first() &&
QDate::currentDate() <= mSelectedDates.last()) {
removeAD = false;
remove = true;
}
else {
if ( da < mSelectedDates.first() ||
da > mSelectedDates.last() ) {
remove = true;
removeAD = true;
} else {
remove = t->doesFloat() && !t->hasCompletedDate();
removeAD = !remove;
}
}
}
int days = mSelectedDates.first().daysTo( da );
//qDebug("daysto %d %d %d", days, remove,removeAD );
mAgenda->updateTodo( t , days, remove);
if ( KOPrefs::instance()->mShowTodoInAgenda )
mAllDayAgenda->updateTodo( t , days, removeAD);
//qDebug("KOAgendaView::updateTodo( Todo *, int ) ");
}
diff --git a/korganizer/kodaymatrix.cpp b/korganizer/kodaymatrix.cpp
index ec1154a..057df0d 100644
--- a/korganizer/kodaymatrix.cpp
+++ b/korganizer/kodaymatrix.cpp
@@ -1,1217 +1,1217 @@
/*
This file is part of KOrganizer.
Copyright (c) 2001 Eitzenberger Thomas <thomas.eitzenberger@siemens.at>
Parts of the source code have been copied from kdpdatebutton.cpp
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 ode for Qt in the source distribution.
*/
#include <qevent.h>
#include <qpainter.h>
#include <qptrlist.h>
#include <qtimer.h>
#include <qwhatsthis.h>
#include <kglobal.h>
#include <kdebug.h>
#include <klocale.h>
#include <libkcal/vcaldrag.h>
#include <libkcal/icaldrag.h>
#include <libkcal/dndfactory.h>
#include <libkcal/calendarresources.h>
#include <libkcal/resourcecalendar.h>
#include <kresources/resourceselectdialog.h>
#include <kcalendarsystem.h>
#ifndef KORG_NOPLUGINS
#include "kocore.h"
#endif
#include "koprefs.h"
#include "koglobals.h"
#include "kodaymatrix.h"
// ============================================================================
// D Y N A M I C T I P
// ============================================================================
DynamicTip::DynamicTip( QWidget * parent )
: QToolTip( parent )
{
matrix = (KODayMatrix*)parent;
}
class KODaymatrixWhatsThis :public QWhatsThis
{
public:
KODaymatrixWhatsThis( KODayMatrix* view ) : QWhatsThis( view ),_view (view) { ;};
~KODaymatrixWhatsThis() { ; };
protected:
virtual QString text( const QPoint& p )
{
return _view->getWhatsThisText( p ) ;
}
private:
KODayMatrix * _view;
};
void DynamicTip::maybeTip( const QPoint &pos )
{
//calculate which cell of the matrix the mouse is in
QRect sz = matrix->frameRect();
int dheight = sz.height()*7 / 42;
int dwidth = sz.width() / 7;
int row = pos.y()/dheight;
int col = pos.x()/dwidth;
QRect rct(col*dwidth, row*dheight, dwidth, dheight);
// kdDebug() << "DynamicTip::maybeTip matrix cell index [" <<
// col << "][" << row << "] => " <<(col+row*7) << endl;
//show holiday names only
QString str = matrix->getHolidayLabel(col+row*7);
if (str.isEmpty()) return;
tip(rct, str);
}
// ============================================================================
// K O D A Y M A T R I X
// ============================================================================
const int KODayMatrix::NOSELECTION = -1000;
const int KODayMatrix::NUMDAYS = 42;
KODayMatrix::KODayMatrix( QWidget *parent, const char *name )
: QFrame( parent, name , Qt::WRepaintNoErase ), mCalendar( 0 )
{
mLastView = -1;
oldW = 0;
oldH = 0;
myPix.resize( 150, 120 );
mRedrawNeeded = true;
mKODaymatrixWhatsThis = new KODaymatrixWhatsThis(this);
mPendingUpdateBeforeRepaint = false;
mouseDown = false;
// initialize dynamic arrays
bDays.resize ( NUMDAYS );
pDays.resize ( NUMDAYS );
hDays.resize ( NUMDAYS );
eDays.resize ( NUMDAYS );
days = new QDate[NUMDAYS];
daylbls = new QString[NUMDAYS];
//events = new int[NUMDAYS];
mToolTip = new DynamicTip(this);
// set default values used for drawing the matrix
mDefaultBackColor = palette().active().base();
mDefaultTextColor = palette().active().foreground();
mDefaultTextColorShaded = getShadedColor(mDefaultTextColor);
mHolidayColorShaded = getShadedColor(KOPrefs::instance()->mHolidayColor);
mSelectedDaysColor = QColor("white");
mTodayMarginWidth = 2;
mSelEnd = mSelStart = NOSELECTION;
setAcceptDrops(true);
//setFont( QFont("Arial", 10) );
mUpdateTimer = new QTimer( this );
connect (mUpdateTimer ,SIGNAL(timeout()), this, SLOT ( updateViewTimed() ));
mRepaintTimer = new QTimer( this );
connect (mRepaintTimer ,SIGNAL(timeout()), this, SLOT ( repaintViewTimed() ));
mDayChanged = false;
updateView();
}
QString KODayMatrix::getWhatsThisText( QPoint p )
{
int tmp = getDayIndexFrom(p.x(), p.y());
if ( tmp < 0 || tmp > NUMDAYS-1 || !mCalendar )
return QString();
QDate mDate = days[tmp];
QPtrList<Event> eventlist = mCalendar->events(mDate);
Event *event;
QStringList mToolTip;
for(event=eventlist.first();event != 0;event=eventlist.next()) {
QString mToolTipText;
QString text;
int multiday = 0;// 1 = start, 2 = midddle, 3 = end day
if (event->isMultiDay()) {
QString prefix = "<->";multiday = 2;
QString time;
if ( event->doesRecur() ) {
if ( event->recursOn( mDate) ) {
prefix ="->" ;multiday = 1;
}
else {
int days = event->dtStart().date().daysTo ( event->dtEnd().date() );
if ( event->recursOn( mDate.addDays( -days)) ) {
prefix ="<-" ;multiday = 3;
}
}
} else {
if (mDate == event->dtStart().date()) {
prefix ="->" ;multiday = 1;
} else if (mDate == event->dtEnd().date()) {
prefix ="<-" ;multiday = 3;
}
}
if ( !event->doesFloat() ) {
if ( mDate == event->dtStart().date () )
time = KGlobal::locale()->formatTime(event->dtStart().time())+" ";
else if ( mDate == event->dtEnd().date () )
time = KGlobal::locale()->formatTime(event->dtEnd().time())+" ";
}
text = time + event->summary();
mToolTipText += prefix + text;
} else {
if (event->doesFloat()) {
text = event->summary();
mToolTipText += text;
}
else {
text = KGlobal::locale()->formatTime(event->dtStart().time());
text += " " + event->summary();
mToolTipText += KGlobal::locale()->formatTime(event->dtStart().time()) +"-"+KGlobal::locale()->formatTime(event->dtEnd().time())+" " + event->summary();
}
}
if ( !event->location().isEmpty() )
mToolTipText += " (" + event->location() + ")";
//qDebug("TTT: %s ", mToolTipText.latin1());
mToolTip.append( deTag( mToolTipText ) );
}
mToolTip.sort();
if ( KOPrefs::instance()->mCurrentDisplayedView == VIEW_T_VIEW ) {
QPtrList<Todo> todolist = mCalendar->todos(mDate);
Todo *todo;
for(todo=todolist.first();todo != 0;todo=todolist.next()) {
QString mToolTipText;
if ( !todo->doesFloat() )
mToolTipText += KGlobal::locale()->formatTime(todo->dtDue().time())+" ";
mToolTipText += todo->summary();
if ( !todo->location().isEmpty() )
mToolTipText += " (" + todo->location() + ")";
mToolTipText = deTag( mToolTipText);
mToolTipText = "<b>" + i18n("Todo: ") + "</b>"+ mToolTipText;
mToolTip.append( mToolTipText );
}
}
if (KOPrefs::instance()->mCurrentDisplayedView == VIEW_J_VIEW ) {
QPtrList<Journal> j_list = mCalendar->journals4Date( mDate );
Journal *j = j_list.first();
while ( j ) {
QString mToolTipText;
if ( !j->summary().isEmpty() ) {
mToolTipText = j->summary().left(30);
if ( j->summary().length() > 30 )
mToolTipText += " ...";
} else {
mToolTipText = j->description().left(25);
if ( j->description().length() > 25 )
mToolTipText += " ...";
mToolTipText = deTag( mToolTipText);
}
mToolTipText = "<b>" + i18n("Journal: ") + "</b>"+ mToolTipText;
mToolTip.append( mToolTipText );
j = j_list.next();
}
}
return "<b>"+KGlobal::locale()->formatDate(days[tmp]) + "</b><br>" + mToolTip.join("<br>");
}
QString KODayMatrix::deTag( QString mToolTipText )
{
#if QT_VERSION >= 0x030000
mToolTipText.replace( '<' , "&lt;" );
mToolTipText.replace( '>' , "&gt;" );
#else
if ( mToolTipText.find ('<') >= 0 ) {
mToolTipText.replace( QRegExp("<") , "&lt;" );
}
if ( mToolTipText.find ('>') >= 0 ) {
mToolTipText.replace( QRegExp(">") , "&gt;" );
}
#endif
return mToolTipText;
}
void KODayMatrix::setCalendar( Calendar *cal )
{
mCalendar = cal;
setAcceptDrops( mCalendar );
updateEvents();
}
QColor KODayMatrix::getShadedColor(QColor color)
{
QColor shaded;
int h=0;
int s=0;
int v=0;
color.hsv(&h,&s,&v);
s = s/4;
v = 192+v/4;
shaded.setHsv(h,s,v);
return shaded;
}
KODayMatrix::~KODayMatrix()
{
#if QT_VERSION >= 0x030000
#else
delete mKODaymatrixWhatsThis;
#endif
// delete mKODaymatrixWhatsThis;
delete [] days;
delete [] daylbls;
//delete [] events;
delete mToolTip;
}
/*
void KODayMatrix::setStartDate(QDate start)
{
updateView(start);
}
*/
void KODayMatrix::addSelectedDaysTo(DateList& selDays)
{
if (mSelStart == NOSELECTION) {
return;
}
//cope with selection being out of matrix limits at top (< 0)
int i0 = mSelStart;
if (i0 < 0) {
for (int i = i0; i < 0; i++) {
selDays.append(days[0].addDays(i));
}
i0 = 0;
}
//cope with selection being out of matrix limits at bottom (> NUMDAYS-1)
if (mSelEnd > NUMDAYS-1) {
for (int i = i0; i <= NUMDAYS-1; i++) {
selDays.append(days[i]);
}
for (int i = NUMDAYS; i < mSelEnd; i++) {
selDays.append(days[0].addDays(i));
}
// apply normal routine to selection being entirely within matrix limits
} else {
for (int i = i0; i <= mSelEnd; i++) {
selDays.append(days[i]);
}
}
}
bool KODayMatrix::setSelectedDaysFrom(const QDate& start, const QDate& end)
{
mRedrawNeeded = true;
bool noSel = (mSelEnd == NOSELECTION && mSelStart == NOSELECTION );
mSelStart = startdate.daysTo(start);
if ( mSelStart < 0 )
mSelStart = 0;
mSelEnd = startdate.daysTo(end);
if ( mSelEnd > NUMDAYS-1 )
mSelEnd = NUMDAYS-1;
if ( mSelEnd < 0 || mSelStart > NUMDAYS-1 ) {
clearSelection();
if ( noSel )
return false;
}
return true;
}
void KODayMatrix::clearSelection()
{
mSelEnd = mSelStart = NOSELECTION;
}
void KODayMatrix::recalculateToday()
{
today = -1;
for (int i=0; i<NUMDAYS; i++) {
//events[i] = 0;
days[i] = startdate.addDays(i);
daylbls[i] = QString::number( KOGlobals::self()->calendarSystem()->day( days[i] ));
// if today is in the currently displayed month, hilight today
if (days[i].year() == QDate::currentDate().year() &&
days[i].month() == QDate::currentDate().month() &&
days[i].day() == QDate::currentDate().day()) {
today = i;
}
}
// qDebug(QString("Today is visible at %1.").arg(today));
}
void KODayMatrix::updateView()
{
updateView(startdate);
}
void KODayMatrix::repaintViewTimed()
{
mRedrawNeeded = true;
// bDays.fill( false);
//pDays.fill( false);
//hDays.fill( false);
//eDays.fill( false);
mRepaintTimer->stop();
int startDay = days[0].dayOfWeek(); // 1...7 7 = sunday
int i;
for(i = 0; i < NUMDAYS; i++) {
if ( ( (i+startDay) % 7 == 0 ) ) {
pDays.setBit(i);
}
}
repaint(false);
}
void KODayMatrix::computeEvent(Event *event, int i )
{
QString holiStr = mHolidays[i];
if ( event->isHoliday()) {
pDays.setBit(i);
hDays.setBit(i);
if ( !holiStr.isEmpty() )
holiStr += "\n";
holiStr += event->summary();
if ( !event->location().isEmpty() )
holiStr += " (" + event->location() + ")";
mHolidays[i] =holiStr ;
eDays.setBit(i);
}
if ( KOPrefs::instance()->mCurrentDisplayedView != VIEW_T_VIEW && KOPrefs::instance()->mCurrentDisplayedView != VIEW_J_VIEW ) {
if ( event->isBirthday()) {
pDays.setBit(i);
if ( !holiStr.isEmpty() )
holiStr += "\n";
holiStr += i18n("Birthday") + ": "+event->summary();
if ( !event->location().isEmpty() )
holiStr += " (" + event->location() + ")";
bDays.setBit(i);
mHolidays[i] =holiStr ;
}
}
if ( KOPrefs::instance()->mCurrentDisplayedView != VIEW_J_VIEW )
eDays.setBit(i);
}
void KODayMatrix::updateViewTimed()
{
mUpdateTimer->stop();
if ( !mCalendar ) {
qDebug("NOT CAL ");
return;
}
#if 1
int i;
int timeSpan = NUMDAYS-1;
QPtrList<Event> events = mCalendar->events();
Event *event;
QDateTime dt;
bool ok;
bDays.fill( false);
pDays.fill( false);
hDays.fill( false);
eDays.fill( false);
mHolidays.clear();
QDate mStartDate = days[0];
QDate endDate = mStartDate.addDays( timeSpan );
for( event = events.first(); event; event = events.next() ) { // for event
- ushort recurType = event->recurrence()->doesRecur();
+ ushort recurType = event->doesRecur();
if ((recurType == Recurrence::rDaily && !KOPrefs::instance()->mDailyRecur) ||
(recurType == Recurrence::rWeekly && !KOPrefs::instance()->mWeeklyRecur)) {
continue;
}
if ( event->doesRecur() ) {
bool last;
QDateTime incidenceStart = event->recurrence()->getPreviousDateTime( QDateTime( mStartDate ) , &last );
QDateTime incidenceEnd;
int eventlen = event->dtStart().date().daysTo ( event->dtEnd().date() );
bool invalid = false;
while( true ) {
if ( incidenceStart.isValid() ) {
incidenceEnd = incidenceStart.addDays( eventlen );
int st = incidenceStart.date().daysTo( endDate );
if ( st >= 0 ) { // start before timeend
int end = mStartDate.daysTo( incidenceEnd.date() );
if ( end >= 0 ) { // end after timestart --- got one!
//normalize
st = timeSpan - st;
if ( st < 0 ) st = 0;
if ( end > timeSpan ) end = timeSpan;
int iii;
//qDebug("found %s %d %d ",event->summary().latin1(), st, end );
for ( iii = st;iii<= end;++iii) {
computeEvent( event, iii );
}
}
}
} else {
if ( invalid )
break;
invalid = true;
//qDebug("invalid %s", event->summary().latin1());
incidenceStart = QDateTime( mStartDate ).addSecs( -2 );;
}
if ( last )
break;
bool ok;
incidenceStart = event->getNextOccurence( incidenceStart.addSecs( 1 ) ,&ok );
if ( ! ok )
break;
if ( incidenceStart.date() > endDate )
break;
}
} else { // no recur
int st = event->dtStart().date().daysTo( endDate );
if ( st >= 0 ) { // start before timeend
int end = mStartDate.daysTo( event->dtEnd().date() );
if ( end >= 0 ) { // end after timestart --- got one!
//normalize
st = timeSpan - st;
if ( st < 0 ) st = 0;
if ( end > timeSpan ) end = timeSpan;
int iii;
for ( iii = st;iii<= end;++iii)
computeEvent( event, iii );
}
}
}
}
int startDay = days[0].dayOfWeek(); // 1...7 7 = sunday
for(i = 0; i < NUMDAYS; i++) {
if ( ( (i+startDay) % 7 == 0 ) ) {
pDays.setBit(i);
}
}
if ( KOPrefs::instance()->mCurrentDisplayedView == VIEW_T_VIEW ) {
bDays.fill( false);
// insert due todos
QPtrList<Todo> todos = mCalendar->todos( );
Todo *todo;
for(todo = todos.first(); todo; todo = todos.next()) {
//insertTodo( todo );
if ( todo->hasDueDate() ) {
int day = mStartDate.daysTo( todo->dtDue().date() );
if ( day >= 0 && day < timeSpan + 1) {
int i = day;
QString holiStr = mHolidays[i];
pDays.setBit(i);
if ( !holiStr.isEmpty() )
holiStr += "\n";
holiStr += i18n("Todo") + ": "+todo->summary();
if ( !todo->location().isEmpty() )
holiStr += " (" + todo->location() + ")";
bDays.setBit(i);
mHolidays[i] =holiStr ;
eDays.setBit(i);
}
}
}
}
if ( KOPrefs::instance()->mCurrentDisplayedView == VIEW_J_VIEW ) {
bDays.fill( false);
// insert due todos
QPtrList<Journal> todos = mCalendar->journals( );
Journal *todo;
for(todo = todos.first(); todo; todo = todos.next()) {
int day = mStartDate.daysTo( todo->dtStart().date() );
if ( day >= 0 && day < timeSpan + 1) {
int i = day;
QString holiStr = mHolidays[i];
pDays.setBit(i);
if ( !holiStr.isEmpty() )
holiStr += "\n";
holiStr += i18n("Journal: ")+todo->summary().left(25);
if ( todo->summary().length() > 25 )
holiStr +="...";
bDays.setBit(i);
mHolidays[i] =holiStr ;
eDays.setBit(i);
}
}
}
#else
//qDebug("KODayMatrix::updateViewTimed ");
for(int i = 0; i < NUMDAYS; i++) {
// if events are set for the day then remember to draw it bold
QPtrList<Event> eventlist = mCalendar->events(days[i]);
Event *event;
int numEvents = eventlist.count();
QString holiStr = "";
bDays.clearBit(i);
hDays.clearBit(i);
eDays.clearBit(i);
for(event=eventlist.first();event != 0;event=eventlist.next()) {
ushort recurType = event->recurrence()->doesRecur();
if ((recurType == Recurrence::rDaily && !KOPrefs::instance()->mDailyRecur) ||
(recurType == Recurrence::rWeekly && !KOPrefs::instance()->mWeeklyRecur)) {
numEvents--;
}
if ( event->isHoliday()) {
hDays.setBit(i);
if ( !holiStr.isEmpty() )
holiStr += "\n";
holiStr += event->summary();
if ( !event->location().isEmpty() )
holiStr += " (" + event->location() + ")";
}
if ( event->isBirthday()) {
if ( !holiStr.isEmpty() )
holiStr += "\n";
holiStr += i18n("Birthday") + ": "+event->summary();
if ( !event->location().isEmpty() )
holiStr += " (" + event->location() + ")";
bDays.setBit(i);
}
}
if ( numEvents )
eDays.setBit(i);
//if it is a holy day then draw it red. Sundays are consider holidays, too
if ( (KOGlobals::self()->calendarSystem()->dayOfWeek(days[i]) == KOGlobals::self()->calendarSystem()->weekDayOfPray()) ||
!holiStr.isEmpty()) {
mHolidays[i] = holiStr;
} else {
mHolidays[i] = QString::null;
}
}
#endif
mRedrawNeeded = true;
if ( ! mPendingUpdateBeforeRepaint )
repaint(false);
}
void KODayMatrix::updateView(QDate actdate)
{
if ( mLastView != KOPrefs::instance()->mCurrentDisplayedView )
mRedrawNeeded = true;
mLastView = KOPrefs::instance()->mCurrentDisplayedView;
if ( ! actdate.isValid() ) {
//qDebug("date not valid ");
return;
}
mDayChanged = false;
//flag to indicate if the starting day of the matrix has changed by this call
//mDayChanged = false;
// if a new startdate is to be set then apply Cornelius's calculation
// of the first day to be shown
if (actdate != startdate) {
// reset index of selection according to shift of starting date from startdate to actdate
if (mSelStart != NOSELECTION) {
int tmp = actdate.daysTo(startdate);
//kdDebug() << "Shift of Selection1: " << mSelStart << " - " << mSelEnd << " -> " << tmp << "(" << offset << ")" << endl;
// shift selection if new one would be visible at least partly !
if (mSelStart+tmp < NUMDAYS && mSelEnd+tmp >= 0) {
// nested if is required for next X display pushed from a different month - correction required
// otherwise, for month forward and backward, it must be avoided
if( mSelStart > NUMDAYS || mSelStart < 0 )
mSelStart = mSelStart + tmp;
if( mSelEnd > NUMDAYS || mSelEnd < 0 )
mSelEnd = mSelEnd + tmp;
}
}
startdate = actdate;
mDayChanged = true;
recalculateToday();
mRedrawNeeded = true;
}
//qDebug("restart Timer %d vis: %d", mDayChanged, isVisible() );
if ( !isVisible() ) {
mPendingUpdateBeforeRepaint = true;
} else {
#ifdef DESKTOP_VERSION
//mRepaintTimer->start( 100 );
//updateViewTimed();
mUpdateTimer->start( 50 );
#else
mRepaintTimer->start( 350 );
mUpdateTimer->start( 800 );
#endif
}
}
void KODayMatrix::updateEvents()
{
if ( !mCalendar ) return;
for( int i = 0; i < NUMDAYS; i++ ) {
// if events are set for the day then remember to draw it bold
QPtrList<Event> eventlist = mCalendar->events( days[ i ] );
int numEvents = eventlist.count();
Event *event;
for( event = eventlist.first(); event != 0;event=eventlist.next()) {
ushort recurType = event->doesRecur();
if ( ( recurType == Recurrence::rDaily &&
!KOPrefs::instance()->mDailyRecur ) ||
( recurType == Recurrence::rWeekly &&
!KOPrefs::instance()->mWeeklyRecur ) ) {
numEvents--;
}
}
if ( numEvents )
eDays.setBit(i);
else
eDays.clearBit(i);
}
}
const QDate& KODayMatrix::getDate(int offset)
{
if (offset < 0 || offset > NUMDAYS-1) {
qDebug("Wrong offset2 %d", offset);
return days[0];
}
return days[offset];
}
QString KODayMatrix::getHolidayLabel(int offset)
{
if (offset < 0 || offset > NUMDAYS-1) {
qDebug("Wrong offset1 %d", offset);
return QString();
}
return mHolidays[offset];
}
int KODayMatrix::getDayIndexFrom(int x, int y)
{
int colModulo = (width()-2) % 7;
int rowModulo = (height()-2) % 6;
#if 0
return 7*(y/daysize.height()) + (KOGlobals::self()->reverseLayout() ?
6 - x/daysize.width() : x/daysize.width());
#endif
int xVal = (x-colModulo/2-2)/daysize.width();
int yVal = (y-rowModulo/2-2)/daysize.height();
return 7*(yVal) + xVal;
}
// ----------------------------------------------------------------------------
// M O U S E E V E N T H A N D L I N G
// ----------------------------------------------------------------------------
void KODayMatrix::mousePressEvent (QMouseEvent* e)
{
if ( e->button() == LeftButton )
mouseDown = true;
mSelStart = getDayIndexFrom(e->x(), e->y());
if (mSelStart > NUMDAYS-1) mSelStart=NUMDAYS-1;
mSelInit = mSelStart;
mSelEnd = mSelStart;
mRedrawNeeded = true;
repaint(false);
}
void KODayMatrix::mouseReleaseEvent (QMouseEvent* e)
{
mRedrawNeeded = true;
if ( e->button() == LeftButton )
if ( ! mouseDown ) {
return;
}
else
mouseDown = false;
int tmp = getDayIndexFrom(e->x(), e->y());
if (tmp > NUMDAYS-1) tmp=NUMDAYS-1;
if (mSelInit > tmp) {
mSelEnd = mSelInit;
if (tmp != mSelStart) {
mSelStart = tmp;
repaint(false);
}
} else {
mSelStart = mSelInit;
//repaint only if selection has changed
if (tmp != mSelEnd) {
mSelEnd = tmp;
repaint(false);
}
}
DateList daylist;
if ( mSelStart < 0 )
mSelStart = 0;
for (int i = mSelStart; i <= mSelEnd; i++) {
daylist.append(days[i]);
}
emit selected((const DateList)daylist);
}
void KODayMatrix::mouseMoveEvent (QMouseEvent* e)
{
if ( ! mouseDown ) {
return;
}
mRedrawNeeded = true;
int tmp = getDayIndexFrom(e->x(), e->y());
if (tmp > NUMDAYS-1) tmp=NUMDAYS-1;
if (mSelInit > tmp) {
mSelEnd = mSelInit;
if (tmp != mSelStart) {
mSelStart = tmp;
repaint(false);
}
} else {
mSelStart = mSelInit;
//repaint only if selection has changed
if (tmp != mSelEnd) {
mSelEnd = tmp;
repaint(false);
}
}
}
// ----------------------------------------------------------------------------
// D R A G ' N D R O P H A N D L I N G
// ----------------------------------------------------------------------------
void KODayMatrix::dragEnterEvent(QDragEnterEvent *e)
{
#ifndef KORG_NODND
if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) {
e->ignore();
return;
}
// some visual feedback
// oldPalette = palette();
// setPalette(my_HilitePalette);
// update();
#endif
}
void KODayMatrix::dragMoveEvent(QDragMoveEvent *e)
{
#ifndef KORG_NODND
if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) {
e->ignore();
return;
}
e->accept();
#endif
}
void KODayMatrix::dragLeaveEvent(QDragLeaveEvent */*dl*/)
{
#ifndef KORG_NODND
// setPalette(oldPalette);
// update();
#endif
}
void KODayMatrix::dropEvent(QDropEvent *e)
{
#ifndef KORG_NODND
// kdDebug() << "KODayMatrix::dropEvent(e) begin" << endl;
if (!mCalendar || !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) {
e->ignore();
return;
}
DndFactory factory( mCalendar );
Event *event = factory.createDrop(e);
if (event) {
e->acceptAction();
Event *existingEvent = mCalendar->event(event->uid());
if(existingEvent) {
// uniquify event
event->recreate();
/*
KMessageBox::sorry(this,
i18n("Event already exists in this calendar."),
i18n("Drop Event"));
delete event;
return;
*/
}
// kdDebug() << "Drop new Event" << endl;
// Adjust date
QDateTime start = event->dtStart();
QDateTime end = event->dtEnd();
int duration = start.daysTo(end);
int idx = getDayIndexFrom(e->pos().x(), e->pos().y());
start.setDate(days[idx]);
end.setDate(days[idx].addDays(duration));
event->setDtStart(start);
event->setDtEnd(end);
mCalendar->addEvent(event);
emit eventDropped(event);
} else {
// kdDebug() << "KODayMatrix::dropEvent(): Event from drop not decodable" << endl;
e->ignore();
}
#endif
}
// ----------------------------------------------------------------------------
// P A I N T E V E N T H A N D L I N G
// ----------------------------------------------------------------------------
void KODayMatrix::paintEvent(QPaintEvent * pevent)
{
if ( width() <= 0 || height() <= 0 )
return;
if ( mPendingUpdateBeforeRepaint ) {
updateViewTimed();
mPendingUpdateBeforeRepaint = false;
}
#if 0
if ( myPix.width() != width() || myPix.height()!=height() ) {
myPix.resize(size() );
mRedrawNeeded = true;
}
#endif
if ( oldW != width() || oldH !=height() )
mRedrawNeeded = true;
oldH = height() ;
oldW = width();
if ( myPix.width() < width() || myPix.height() < height() ) {
myPix.resize(size() );
mRedrawNeeded = true;
}
if ( mRedrawNeeded ) {
//qDebug("REDRAW ");
QPainter p(&myPix);
p.setFont(font());
int dheight = daysize.height();
int dwidth = daysize.width();
int row,col;
int selw, selh;
int xyOff = frameWidth();
int colModulo = (width()-2) % 7;
int rowModulo = (height()-2) % 6;
//qDebug("col %d row %d ",colModulo,rowModulo );
bool isRTL = KOGlobals::self()->reverseLayout();
// draw background and topleft frame
p.fillRect(0,0,width(),height(), mDefaultBackColor);
//p.setPen(mDefaultTextColor);
//p.drawRect(0, 0, width(), height());
int mSelStartT = mSelStart;
int mSelEndT = mSelEnd;
if ( mSelEndT >= NUMDAYS )
mSelEndT = NUMDAYS-1;
// draw selected days with highlighted background color
if (mSelStart != NOSELECTION) {
bool skip = false;
if ( ! mouseDown ) {
int mo = days[20].month();
//qDebug("-- %d %d ", mSelStartT, mSelEndT);
//qDebug("%d %d %d - d %d", mo, days[mSelStartT].month() , days[mSelEndT].month(), days[mSelEndT].day() );
int startMo = days[mSelStartT].month();
int endMo = days[mSelEndT].month();
if ( startMo == 12 && mo == 1 && endMo <= 2 )
startMo = 1;
if ( endMo == 1 && mo == 12 )
endMo = 12;
if ( mo == 12 && startMo == 1 )
startMo = 13;
if ( (startMo > mo || endMo < mo) ) {
skip = true;
} else {
if ( days[mSelStartT].month() != mo ) {
int add = days[mSelStartT].daysInMonth ()-days[mSelStartT].day();
mSelStartT += add +1;
}
if ( days[mSelEndT].month() != mo ) {
int sub = days[mSelEndT].day();
mSelEndT -= sub ;
}
}
}
//qDebug("SKIP %d ", skip);
if ( ! skip ) {
row = mSelStartT/7;
col = mSelStartT -row*7;
QColor selcol = KOPrefs::instance()->mHighlightColor;
int addCol = 0;
int addRow = 0;
int addRow2 = 0;
int addCol2 = 0;
if (row == mSelEndT/7) {
if ( rowModulo ) {
if ( row >= 6 - rowModulo )
addRow = row - 5 + rowModulo;
}
if ( colModulo ) {
int colt1 = mSelEndT%7;
//qDebug("colt1 %d ", colt1 );
if ( colt1 >= 7 - colModulo )
addCol = colt1 - 7 + colModulo+1;
int colt = mSelStartT%7;
if ( colt >= 7 - colModulo )
addCol2 = colt - 7 + colModulo;
addCol -= addCol2;
//qDebug("COL %d %d %d %d ",col , colt1 ,addCol ,addCol2 );
}
// Single row selection
//if ( row == 0)
// addRow = 1;
p.fillRect(isRTL ? (7 - (mSelEndT-mSelStartT+1) - col)*dwidth : col*dwidth+1+addCol2,
row*dheight+addRow, (mSelEndT-mSelStartT+1)*dwidth+addCol, dheight+1, selcol);
} else {
// draw first row to the right
if ( colModulo ) {
if ( col >= 7 - colModulo )
addCol2 = col - 7 + colModulo;
}
if ( rowModulo ) {
if ( row >= 6 - rowModulo )
addRow = row - 5 + rowModulo;
}
//if ( row == 0)
// addRow = 1;
int drawWid = width()-(col*dwidth+1+addCol2)-1;
p.fillRect(isRTL ? 0 : col*dwidth+1+addCol2, row*dheight+addRow, drawWid,
dheight+1, selcol);
// draw full block till last line
selh = mSelEndT/7-row;
addRow = 0;
if ( rowModulo ) {
if ( mSelEndT/7 >= 6 - rowModulo )
addRow = mSelEndT/7 - 5 + rowModulo;
}
//qDebug("%d %d %d ",selh, row, addRow );
int addrow2 = addRow-selh+1;
if ( addrow2 < 0 )
addrow2 = 0;
if (selh > 1) {
p.fillRect(1, (row+1)*dheight+addrow2, 7*dwidth+colModulo, (selh-1)*dheight+addRow,selcol);
}
// draw last block from left to mSelEndT
selw = mSelEndT-7*(mSelEndT/7)+1;
//qDebug("esl %d ",selw );
int add = 0;
if ( colModulo ) {
add = 7 - colModulo;
if ( selw > add )
add = selw - add;
else
add = 0;
}
//qDebug("add %d ", add);
p.fillRect(isRTL ? (7-selw)*dwidth : 1, (row+selh)*dheight+addRow,
selw*dwidth+add, dheight+1, selcol);
}
}
}
// iterate over all days in the matrix and draw the day label in appropriate colors
QColor actcol = mDefaultTextColorShaded;
p.setPen(actcol);
QPen tmppen;
for(int i = 0; i < NUMDAYS; i++) {
row = i/7;
col = isRTL ? 6-(i-row*7) : i-row*7;
// if it is the first day of a month switch color from normal to shaded and vice versa
if ( KOGlobals::self()->calendarSystem()->day( days[i] ) == 1) {
if (actcol == mDefaultTextColorShaded) {
actcol = mDefaultTextColor;
} else {
actcol = mDefaultTextColorShaded;
}
p.setPen(actcol);
}
if (actcol == mDefaultTextColorShaded) {
if ( ! mouseDown ) {
continue;
}
}
//Reset pen color after selected days block
if (i == mSelEndT+1) {
p.setPen(actcol);
}
// if today then draw rectangle around day
if (today == i) {
tmppen = p.pen();
QPen mTodayPen(p.pen());
if ( daysize.width() < 20 )
mTodayPen.setWidth(1);
else
mTodayPen.setWidth(mTodayMarginWidth);
//draw red rectangle for holidays
if (pDays.testBit(i)) {
if (actcol == mDefaultTextColor) {
mTodayPen.setColor(KOPrefs::instance()->mHolidayColor);
} else {
mTodayPen.setColor(mHolidayColorShaded);
}
}
//draw gray rectangle for today if in selection
if (i >= mSelStartT && i <= mSelEndT) {
QColor grey("grey");
mTodayPen.setColor(grey);
}
p.setPen(mTodayPen);
int addCol = 0;
int addRow = 0;
if (rowModulo) {
if ( row >= 6 - rowModulo )
addRow = row - 5 + rowModulo;
}
if ( colModulo ) {
if ( col >= 7 - colModulo )
addCol = col - 6 + colModulo-1;
}
addCol += 1;
if ( row == 0 )
addRow = 1;
p.drawRect(col*dwidth+addCol, row*dheight+addRow, dwidth+1, dheight+1);
p.setPen(tmppen);
}
// if any events are on that day then draw it using a bold font
if ( eDays.testBit(i) ) {
QFont myFont = font();
myFont.setBold(true);
p.setFont(myFont);
}
// if it is a holiday then use the default holiday color
if ( pDays.testBit(i)) {
if ( bDays.testBit(i) ) {
if ( hDays.testBit(i) )
p.setPen(QColor(0,200,0));
else
p.setPen(QColor(Qt::blue));
} else {
if (actcol == mDefaultTextColor ) {
p.setPen(KOPrefs::instance()->mHolidayColor);
} else {
p.setPen(mHolidayColorShaded);
}
}
}
// draw selected days with special color
// DO NOT specially highlight holidays in selection !
if (i >= mSelStartT && i <= mSelEndT) {
;//p.setPen(mSelectedDaysColor);
}
int addCol = 0;
int addRow = 0;
if ( colModulo ) {
if ( col >= 7 - colModulo )
addCol = col - 7 + colModulo;
}
if ( rowModulo ) {
if ( row >= 6 - rowModulo )
addRow = row - 5 + rowModulo;
}
//qDebug("add %d %d -- %d %d ", col, addCol, row, addRow);
++addCol;//++addCol;
if ( row == 0)
addRow = 1;
p.drawText(col*dwidth+addCol, row*dheight+addRow, dwidth, dheight,
Qt::AlignHCenter | Qt::AlignVCenter, daylbls[i]);
// reset color to actual color
if (pDays.testBit(i)) {
p.setPen(actcol);
}
// reset bold font to plain font
if ( eDays.testBit(i)) {
QFont myFont = font();
myFont.setBold(false);
p.setFont(myFont);
}
}
p.setPen(mDefaultTextColor);
p.drawRect(0, 0, width(), height());
} else {
//qDebug("NO redraw ");
}
bitBlt (this, pevent->rect().topLeft(), &myPix , pevent->rect() ,CopyROP);
mRedrawNeeded = false;
}
// ----------------------------------------------------------------------------
// R E SI Z E E V E N T H A N D L I N G
// ----------------------------------------------------------------------------
void KODayMatrix::resizeEvent(QResizeEvent * e)
{
QRect sz = frameRect();
daysize.setHeight(sz.height()*7 / NUMDAYS);
daysize.setWidth(sz.width() / 7);
QFrame::resizeEvent( e );
}
QSize KODayMatrix::sizeHint() const
{
QFontMetrics fm ( font() );
int wid = fm.width( "30") *7+3;
int hei = fm.height() * 6+3;
//qDebug("KODayMatrix::sizeHint()********************* %d %d", wid , hei);
return QSize ( wid, hei );
}
diff --git a/korganizer/koeditorrecurrence.cpp b/korganizer/koeditorrecurrence.cpp
index de4e4f7..89504db 100644
--- a/korganizer/koeditorrecurrence.cpp
+++ b/korganizer/koeditorrecurrence.cpp
@@ -1,1120 +1,1126 @@
/*
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() );
topLayout->setMargin( KDialog::marginHintSmall() );
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->setMargin( KDialog::marginHintSmall() );
//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 );
int left = 1;
if ( QApplication::desktop()->width() > 480 ) {
++left;
if ( QApplication::desktop()->width() > 640 )
++left;
}
mDayBoxes[ i ] = new QCheckBox( weekDayName.left( left ), dayBox );
}
topLayout->addStretch( );
}
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() );
topLayout->setMargin( KDialog::marginHintSmall() );
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() );
buttonLayout->setMargin( KDialog::marginHintSmall() );
QString recurOnText;
if ( QApplication::desktop()->width() > 320 ) {
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() );
topLayout->setMargin( KDialog::marginHintSmall() );
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() );
rangeLayout->setMargin( KDialog::marginHintSmall() );
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 );
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() ) );
}
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() );
topLayout->setMargin( KDialog::marginHintSmall() );
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("Time"),
this );
topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
if ( QApplication::desktop()->width() <= 640 ) {
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 );
//mTimeGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum ) );
//mDateTimeLabel->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum) );
mRuleBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Rule"), this );
topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
connect( mRecurrenceChooser, SIGNAL( chosen( int ) ),
SLOT( showCurrentRule( int ) ) );
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() );
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() ) );
}
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::setDefaultsDates( QDateTime from, QDateTime to )
{
setDateTimes( from, to );
QBitArray days( 7 );
days.fill( 0 );
days.setBit( from.date().dayOfWeek()- 1);
mWeekly->setDays( days );
bool byPos = mMonthly->byPos();
if ( byPos )
mMonthly->setByDay( from.date().day()-1 );
mMonthly->setByPos((from.date().day()/7), from.date().dayOfWeek()-1 );
if ( ! byPos)
mMonthly->setByDay( from.date().day()-1 );
bool byDay = mYearly->byDay();
if ( ! byDay )
mYearly->setByDay( from.date().dayOfYear() );
mYearly->setByMonth( from.date().month(), from.date().day() );
if ( byDay )
mYearly->setByDay( from.date().dayOfYear() );
}
void KOEditorRecurrence::setDefaults( QDateTime from, QDateTime to )
{
// 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 );
mMonthly->setFrequency( 1 );
mYearly->setFrequency( 1 );
setDefaultsDates( from, to );
}
void KOEditorRecurrence::readEvent(Incidence *event)
{
QDateTime dtEnd;
if ( event->typeID() == eventID )
dtEnd = ((Event*)event)->dtEnd();
else
dtEnd = ((Todo*)event)->dtDue();
setDefaults( event->dtStart(), dtEnd );
QBitArray rDays( 7 );
QPtrList<Recurrence::rMonthPos> rmp;
QPtrList<int> rmd;
int day = 0;
int count = 0;
int month = 0;
setDateTimes( event->dtStart(), dtEnd );
- Recurrence *r = event->recurrence();
- int f = r->frequency();
+
- int recurs = r->doesRecur();
+ int recurs = event->doesRecur();
mEnabledCheck->setChecked( recurs );
setEnabled( recurs );
int recurrenceType = RecurrenceChooser::Weekly;
-
- switch ( recurs ) {
- case Recurrence::rNone:
- setDefaults( event->dtStart(), dtEnd );
- 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 ( recurs ) {
+ Recurrence *r = event->recurrence();
+ int f = r->frequency();
+ switch ( recurs ) {
+ case Recurrence::rNone:
+ setDefaults( event->dtStart(), dtEnd );
+ 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 );
+ //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 );
- }
+ 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(), dtEnd );
- break;
+ break;
+ case Recurrence::rYearlyDay:
+ //qDebug("Recurrence::rYearlyDay: ");
+ recurrenceType = RecurrenceChooser::Yearly;
+ mYearly->setByDay( event->dtStart().date().dayOfYear() );
+ mYearly->setFrequency( f );
+ break;
+ default:
+ setDefaults( event->dtStart(), dtEnd );
+ break;
+ }
}
-
mRecurrenceChooser->setType( recurrenceType );
showCurrentRule( recurrenceType );
mRecurrenceRange->setDateTimes( event->dtStart() );
- if ( r->doesRecur() ) {
+ if ( event->doesRecur() ) {
+ Recurrence *r = event->recurrence();
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( Incidence *event )
{
- Recurrence *r = event->recurrence();
+
- // clear out any old settings;
- r->unsetRecurs();
+ if ( !mEnabledCheck->isChecked() ) {
+ if ( event->doesRecur() )
+ event->recurrence()->unsetRecurs();
+ } else {
+ Recurrence *r = event->recurrence();
- if ( mEnabledCheck->isChecked() ) {
+ // clear out any old settings;
+ r->unsetRecurs();
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/koeventviewer.cpp b/korganizer/koeventviewer.cpp
index a690ab1..db695f5 100644
--- a/korganizer/koeventviewer.cpp
+++ b/korganizer/koeventviewer.cpp
@@ -1,831 +1,831 @@
/*
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.
*/
#include <qcstring.h>
#include <qwhatsthis.h>
#include <qdialog.h>
#include <qapplication.h>
#include <qlabel.h>
#include <qlayout.h>
#include <klocale.h>
#include <kapplication.h>
#include <libkcal/event.h>
#include <libkcal/todo.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <krun.h>
#include <kglobal.h>
#include <kprocess.h>
#include "koprefs.h"
#include <kabc/stdaddressbook.h>
#ifndef KORG_NODCOP
#include <dcopclient.h>
#include "korganizer.h"
#include "koprefs.h"
#include "actionmanager.h"
#endif
#include "koeventviewer.h"
//#ifndef KORG_NOKABC
//#include <kabc/stdaddressbook.h>
//#define size count
//#endif
#ifdef DESKTOP_VERSION
#include <kabc/addresseedialog.h>
#include <kabc/addresseeview.h>
#include <qprinter.h>
#include <qpainter.h>
#include <qpaintdevicemetrics.h>
#else //DESKTOP_VERSION
#include <externalapphandler.h>
#include <qtopia/qcopenvelope_qws.h>
#endif //DESKTOP_VERSION
KOEventViewer::KOEventViewer(QWidget *parent,const char *name)
: QTextBrowser(parent,name)
{
mSyncMode = false;
mColorMode = 0;
}
KOEventViewer::~KOEventViewer()
{
}
void KOEventViewer::printMe()
{
#ifdef DESKTOP_VERSION
KOPrintPrefs pp ( this );
if (!pp.exec() )
return;
int scaleval = pp.printMode() ;
QPrinter printer;
if (!printer.setup() )
return;
QPainter p;
p.begin ( &printer );
QPaintDeviceMetrics m = QPaintDeviceMetrics ( &printer );
float dx, dy;
int wid = (m.width() * 9)/10;
dx = (float) wid/(float)contentsWidth ();
dy = (float)(m.height()) / (float)contentsHeight ();
float scale;
// scale to fit the width or height of the paper
if ( dx < dy )
scale = dx;
else
scale = dy;
p.translate( m.width()/10,0 );
if ( scaleval == 2 || scaleval == 1 && scale < 1.0 ) {
p.scale( scale, scale );
}
drawContents ( &p, 0,0, contentsWidth (), contentsHeight () );
p.end();
#endif
}
void KOEventViewer::setSource(const QString& n)
{
if ( n.left(8) == "todo_uid" ) {
int midstr = 9;
#ifdef DESKTOP_VERSION
midstr = 11;
#endif
//qDebug("-%s- ", n.mid(midstr).latin1());
emit showIncidence( n.mid(midstr) );
return;
}
if ( n.left(3) == "uid" )
#ifdef DESKTOP_VERSION
{
KABC::StdAddressBook* AddressBook = KABC::StdAddressBook::self( true );
KABC::AddressBook::Iterator it;
for( it = AddressBook->begin(); it != AddressBook->end(); ++it ) {
// LR I do not understand, why the uid string is different on zaurus and desktop
QString uid = "uid://"+(*it).uid();
//qDebug("for *%s* +%s+ ", n.latin1(), uid.latin1());
if (n == uid ) {
//qDebug("found %s ",(*it).mobileHomePhone().latin1() );
QDialog dia( this,"dia123", true );
dia.setCaption( i18n("Details of attendee") );
QVBoxLayout lay ( &dia );
KABC::AddresseeView av ( &dia );
av.setAddressee( (*it) );
lay.addWidget( &av );
if ( QApplication::desktop()->width() < 480 )
dia.resize( 220, 240);
else {
dia.resize( 400,400);
}
dia.exec();
break;
}
}
return;
}
#else
{
if ( "uid:organizer" == n ) {
ExternalAppHandler::instance()->requestDetailsFromKAPI("", mCurrentIncidence->organizer(),"");
return;
}
QPtrList<Attendee> attendees = mCurrentIncidence->attendees();
if (attendees.count()) {
Attendee *a;
for(a=attendees.first();a;a=attendees.next()) {
if ( "uid:"+a->uid() == n ) {
bool res = ExternalAppHandler::instance()->requestDetailsFromKAPI(a->name(), a->email(), a->uid());
return;
}
}
}
return;
}
//requestNameEmailUidListFromKAPI("QPE/Application/kopi", this->name() /* name is here the unique uid*/);
// the result should now arrive through method insertAttendees
//QString uid = "uid:"+(*it).uid();
#endif
if ( n.left(6) == "mailto" ) {
// qDebug("KOEventViewer::setSource %s ", n.mid(7).latin1());
#ifndef DESKTOP_VERSION
if ( n.mid(7,3) == "ALL" ) {
mailToAttendees( true );
} else if ( n.mid(7,4) == "RSVP" ) {
mailToAttendees( false );
} else {
QCopEnvelope e("QPE/Application/ompi", "newMail(QString)" );
e << n.mid(7);
}
#endif
}
#ifndef KORG_NODCOP
kdDebug() << "KOEventViewer::setSource(): " << n << endl;
QString tmpStr;
if (n.startsWith("mailto:")) {
KApplication::kApplication()->invokeMailer(n.mid(7),QString::null);
//emit showIncidence(n);
return;
} else if (n.startsWith("uid:")) {
DCOPClient *client = KApplication::kApplication()->dcopClient();
const QByteArray noParamData;
const QByteArray paramData;
QByteArray replyData;
QCString replyTypeStr;
#define PING_ABBROWSER (client->call("kaddressbook", "KAddressBookIface", "interfaces()", noParamData, replyTypeStr, replyData))
bool foundAbbrowser = PING_ABBROWSER;
if (foundAbbrowser) {
//KAddressbook is already running, so just DCOP to it to bring up the contact editor
//client->send("kaddressbook","KAddressBookIface",
QDataStream arg(paramData, IO_WriteOnly);
arg << n.mid(6);
client->send("kaddressbook", "KAddressBookIface", "showContactEditor( QString )", paramData);
return;
} else {
/*
KaddressBook is not already running. Pass it the UID of the contact via the command line while starting it - its neater.
We start it without its main interface
*/
KIconLoader* iconLoader = new KIconLoader();
QString iconPath = iconLoader->iconPath("go",KIcon::Small);
ActionManager::setStartedKAddressBook(true);
tmpStr = "kaddressbook --editor-only --uid ";
tmpStr += KProcess::quote(n.mid(6));
KRun::runCommand(tmpStr,"KAddressBook",iconPath);
return;
}
} else {
//QTextBrowser::setSource(n);
}
#endif
}
void KOEventViewer::mailToAttendees( bool all )
{
QPtrList<Attendee> attendees = mCurrentIncidence->attendees();
if (attendees.count() == 0) return;
QStringList nameList;
QStringList emailList;
QStringList uidList;
Attendee* a;
for(a=attendees.first();a;a=attendees.next()) {
if ( !all && !a->RSVP() ) continue;
if (!a->email().isEmpty()) {
nameList.append (a->name() );
emailList.append (a->email() );
uidList.append (a->uid() );
}
}
QString uid = "ComposeMailUIpick2"+mMailSubject;
#ifndef DESKTOP_VERSION
bool res = ExternalAppHandler::instance()->returnNameEmailUidListFromKAPI("QPE/Application/ompi", uid, nameList, emailList, uidList);
#endif
}
void KOEventViewer::addTag(const QString & tag,const QString & text)
{
int number=text.contains("\n");
QString str = "<" + tag + ">";
QString tmpText=text;
QString tmpStr=str;
if(number !=-1)
{
if (number > 0) {
int pos=0;
QString tmp;
for(int i=0;i<=number;i++) {
pos=tmpText.find("\n");
tmp=tmpText.left(pos);
tmpText=tmpText.right(tmpText.length()-pos-1);
tmpStr+=tmp+"<br>";
}
}
else tmpStr += tmpText;
tmpStr+="</" + tag + ">";
mText.append(tmpStr);
}
else
{
str += text + "</" + tag + ">";
mText.append(str);
}
}
void KOEventViewer::setColorMode( int m )
{
mColorMode = m;
}
void KOEventViewer::appendEvent(Event *event, int mode )
{
mMailSubject = "";
mCurrentIncidence = event;
bool shortDate = KOPrefs::instance()->mShortDateInViewer;
bool wideScreen = ( QApplication::desktop()->width() >= 640 );
topLevelWidget()->setCaption(i18n("Event Viewer"));
if ( mode == 0 ) {
addTag("h2",deTag(event->summary()));
formatReadOnly(event);
}
else {
if ( mColorMode == 1 ) {
mText +="<font color=\"#00A000\">";
}
if ( mColorMode == 2 ) {
mText +="<font color=\"#C00000\">";
}
// mText +="<font color=\"#F00000\">" + i18n("O-due!") + "</font>";
if ( mode == 1 ) {
addTag("h2",i18n( "Local: " ) +deTag(event->summary()));
} else {
addTag("h2",i18n( "Remote: " ) +deTag(event->summary()));
}
formatReadOnly(event);
addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) );
if ( mColorMode )
mText += "</font>";
}
mMailSubject += i18n( "Meeting " )+ event->summary();
if (event->cancelled ()) {
mText +="<font color=\"#B00000\">";
addTag("i",i18n("This event has been cancelled!"));
mText.append("<br>");
mText += "</font>";
mMailSubject += i18n("(cancelled)");
}
if (event->doesFloat()) {
if (event->isMultiDay()) {
mText.append(i18n("<p><b>From:</b> %1 </p><p><b>To:</b> %2</p>")
.arg(event->dtStartDateStr(shortDate))
.arg(event->dtEndDateStr(shortDate)));
} else {
mText.append(i18n("<p><b>On:</b> %1</p>").arg(event->dtStartDateStr( shortDate )));
}
} else {
if (event->isMultiDay()) {
mText.append(i18n("<p><b>From:</b> %1</p> ")
.arg(event->dtStartStr( shortDate)));
mText.append(i18n("<p><b>To:</b> %1</p>")
.arg(event->dtEndStr(shortDate)));
} else {
mText.append(i18n("<p><b>From:</b> %1 <b>To:</b> %2</p>")
.arg(event->dtStartTimeStr())
.arg(event->dtEndTimeStr()));
mText.append(i18n("<p><b>On:</b> %1</p> ")
.arg(event->dtStartDateStr( shortDate )));
}
}
if (!event->location().isEmpty()) {
addTag("p","<b>"+i18n("Location: ")+"</b>"+ deTag(event->location() ) );
mMailSubject += i18n(" at ") + event->location();
}
- if (event->recurrence()->doesRecur()) {
+ if (event->doesRecur()) {
- QString recurText = event->recurrence()->recurrenceText();
+ QString recurText = event->recurrenceText();
addTag("p","<em>" + i18n("This is a %1 recurring event.").arg(recurText ) + "</em>");
bool ok;
QDate start = QDate::currentDate();
QDateTime next;
next = event->getNextOccurence( QDateTime::currentDateTime() , &ok );
if ( ok ) {
if ( wideScreen ){
addTag("p",i18n("<b>Next recurrence is on:</b>") +" " + KGlobal::locale()->formatDate( next.date(), shortDate ) );
} else {
addTag("p",i18n("<b>Next recurrence is on:</b>") );
addTag("p", KGlobal::locale()->formatDate( next.date(), shortDate ));
}
mMailSubject += i18n(" - " )+ KGlobal::locale()->formatDateTime( next, true );
} else {
bool last;
QDate nextd;
nextd = event->recurrence()->getPreviousDate( QDate::currentDate() , &last );
if ( last ) {
if ( wideScreen ){
addTag("p",i18n("<b>Last recurrence was on:</b>") +" " + KGlobal::locale()->formatDate( nextd, shortDate ));
} else{
addTag("p",i18n("<b>Last recurrence was on:</b>") );
addTag("p", KGlobal::locale()->formatDate( nextd, shortDate ));
}
}
}
} else {
mMailSubject += i18n(" - " )+event->dtStartStr( true );
}
if (event->isAlarmEnabled()) {
Alarm *alarm =event->alarms().first() ;
QDateTime t = alarm->time();
QString s =i18n("( %1 before )").arg( alarm->offsetText() );
if(wideScreen ){
addTag("p",i18n("<b>Alarm on: ") + s +" </b>"+ KGlobal::locale()->formatDateTime( t, shortDate ));
}else{
addTag("p",i18n("<b>Alarm on: ") + s +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( t, shortDate ));
}
//addTag("p",s);
}
addTag("p","<b>"+i18n("Access: ") + "</b>" + event->secrecyStr());
formatCategories(event);
formatAttendees(event);
if ( KOPrefs::instance()->mEVshowCreated ) {
if(wideScreen ){
addTag("p",i18n("<b>Created: ") +" </b>"+KGlobal::locale()->formatDateTime( event->created(), shortDate ));
}else{
addTag("p",i18n("<b>Created: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->created(), shortDate ));
}
}
if ( KOPrefs::instance()->mEVshowChanged ) {
if(wideScreen ){
addTag("p",i18n("<b>Last modified: ") +" </b>" + KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ) );
}else{
addTag("p",i18n("<b>Last modified: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ));
}
}
if ( KOPrefs::instance()->mEVshowDetails ) {
if (!event->description().isEmpty()) {
addTag("p",i18n("<b>Details: </b>"));
addTag("p",deTag(event->description()));
}
}
setText(mText);
//QWhatsThis::add(this,mText);
}
void KOEventViewer::appendTodo(Todo *event, int mode )
{
mMailSubject = "";
mCurrentIncidence = event;
topLevelWidget()->setCaption(i18n("Todo Viewer"));
bool shortDate = KOPrefs::instance()->mShortDateInViewer;
bool wideScreen = ( QApplication::desktop()->width() >= 640 );
if (mode == 0 ) {
addTag("h2",deTag(event->summary()));
formatReadOnly(event);
}
else {
if ( mColorMode == 1 ) {
mText +="<font color=\"#00A000\">";
}
if ( mColorMode == 2 ) {
mText +="<font color=\"#B00000\">";
}
if ( mode == 1 ) {
addTag("h2",i18n( "Local: " ) +deTag(event->summary()));
} else {
addTag("h2",i18n( "Remote: " ) +deTag(event->summary()));
}
formatReadOnly(event);
addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) );
if ( mColorMode )
mText += "</font>";
}
mMailSubject += i18n( "Todo " )+ event->summary();
if ( event->percentComplete() == 100 && event->hasCompletedDate() ) {
mText +="<font color=\"#B00000\">";
addTag("i", i18n("<p><i>Completed on %1</i></p>").arg( event->completedStr(KOPrefs::instance()->mShortDateInViewer) ) );
mText += "</font>";
} else {
mText.append(i18n("<p><i>%1 % completed</i></p>")
.arg(event->percentComplete()));
}
if (event->cancelled ()) {
mText +="<font color=\"#B00000\">";
addTag("i",i18n("This todo has been cancelled!"));
mText.append("<br>");
mText += "</font>";
mMailSubject += i18n("(cancelled)");
}
- if (event->recurrence()->doesRecur()) {
+ if (event->doesRecur()) {
QString recurText = event->recurrence()->recurrenceText();
addTag("p","<em>" + i18n("This is a %1 recurring todo.").arg(recurText ) + "</em>");
}
if (event->hasStartDate()) {
mText.append(i18n("<p><b>Start on:</b> %1</p>").arg(event->dtStartStr(KOPrefs::instance()->mShortDateInViewer)));
}
if (event->hasDueDate()) {
mText.append(i18n("<p><b>Due on:</b> %1</p>").arg(event->dtDueStr(KOPrefs::instance()->mShortDateInViewer)));
mMailSubject += i18n(" - " )+event->dtDueStr( true );
}
if (!event->location().isEmpty()) {
addTag("p","<b>"+i18n("Location: ")+"</b>"+ deTag(event->location() ) );
mMailSubject += i18n(" at ") + event->location();
}
mText.append(i18n("<p><b>Priority:</b> %2</p>")
.arg(QString::number(event->priority())));
if (event->isAlarmEnabled()) {
Alarm *alarm =event->alarms().first() ;
QDateTime t = alarm->time();
QString s =i18n("( %1 before )").arg( alarm->offsetText() );
if ( wideScreen ) {
addTag("p",i18n("<b>Alarm on: ") + s +" </b>"+ KGlobal::locale()->formatDateTime( t, shortDate ));
} else {
addTag("p",i18n("<b>Alarm on: ") + s +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( t, shortDate ));
}
}
addTag("p","<b>"+i18n("Access: ") + "</b>" + event->secrecyStr());
formatCategories(event);
formatAttendees(event);
if ( KOPrefs::instance()->mEVshowCreated ) {
if(wideScreen ){
addTag("p",i18n("<b>Created: ") +" </b>"+KGlobal::locale()->formatDateTime( event->created(), shortDate ));
} else {
addTag("p",i18n("<b>Created: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->created(), shortDate ));
}
}
if ( KOPrefs::instance()->mEVshowChanged ) {
if(wideScreen ){
addTag("p",i18n("<b>Last modified: ") +" </b>" +KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ) );
} else {
addTag("p",i18n("<b>Last modified: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ));
}
}
if ( event->relatedTo() ) {
addTag("b",i18n("Parent todo:<br>"));
QString t_name = "[" +QString::number(event->relatedTo()->priority()) + "/" + QString::number(((Todo*)event->relatedTo())->percentComplete())+"%] ";// +event->relatedTo()->summary());
mText += t_name;
mText += "<a href=\"todo_uid:" + event->relatedTo()->uid() + "\">";
mText += deTag(event->relatedTo()->summary());
mText += "</a><br>";
// mText.append(deTag("[" +QString::number(event->relatedTo()->priority()) + "/" + QString::number(((Todo*)event->relatedTo())->percentComplete())+"%] " +event->relatedTo()->summary()) +"<br>");
}
QPtrList<Incidence> Relations = event->relations();
Incidence *to;
if ( Relations.first() )
addTag("b",i18n("Sub todos:<br>"));
for (to=Relations.first();to;to=Relations.next()) {
QString t_name = "[" +QString::number(((Todo*)to)->priority()) + "/" + QString::number(((Todo*)to)->percentComplete())+"%] ";// +to->relatedTo()->summary());
mText += t_name;
mText += "<a href=\"todo_uid:" + to->uid() + "\">";
mText += deTag(to->summary());
mText += "</a><br>";
}
if ( KOPrefs::instance()->mEVshowDetails ) {
if (!event->description().isEmpty()) {
addTag("p",i18n("<b>Details: </b>"));
addTag("p",deTag(event->description()));
}
}
setText(mText);
}
void KOEventViewer::formatCategories(Incidence *event)
{
if (!event->categoriesStr().isEmpty()) {
if (event->categories().count() == 1) {
addTag("p","<b>"+i18n("Category") + ":</b> " + event->categoriesStrWithSpace());
} else {
addTag("p","<b>"+i18n("Categories")+":</b> " + event->categoriesStrWithSpace() ) ;
}
}
}
void KOEventViewer::formatAttendees(Incidence *event)
{
QPtrList<Attendee> attendees = event->attendees();
if (attendees.count()) {
QString iconPath = KGlobal::iconLoader()->iconPath("mailappt",KIcon::Small);
QString NOiconPath = KGlobal::iconLoader()->iconPath("nomailappt",KIcon::Small);
addTag("h3",i18n("Organizer"));
mText.append("<ul><li>");
#ifndef KORG_NOKABC
#ifdef DESKTOP_VERSION
KABC::AddressBook *add_book = KABC::StdAddressBook::self();
KABC::Addressee::List addressList;
addressList = add_book->findByEmail(event->organizer());
KABC::Addressee o = addressList.first();
if (!o.isEmpty() && addressList.size()<2) {
mText += "<a href=\"uid:" + o.uid() + "\">";
mText += o.formattedName();
mText += "</a>\n";
} else {
mText.append(event->organizer());
}
#else //DESKTOP_VERSION
mText += "<a href=\"uid:organizer\">";
mText += event->organizer();
mText += "</a>\n";
#endif //DESKTOP_VERSION
#else
mText.append(event->organizer());
#endif
if (iconPath) {
mText += " <a href=\"mailto:" + event->organizer() + "\">";
mText += "<IMG src=\"" + iconPath + "\">";
mText += "</a>\n";
}
mText.append("</li></ul>");
addTag("h3",i18n("Attendees"));
Attendee *a;
mText.append("<ul>");
int a_count = 0;
int a_count_nr = 0;
for(a=attendees.first();a;a=attendees.next()) {
#ifndef KORG_NOKABC
#ifdef DESKTOP_VERSION
if (a->name().isEmpty()) {
addressList = add_book->findByEmail(a->email());
KABC::Addressee o = addressList.first();
if (!o.isEmpty() && addressList.size()<2) {
mText += "<a href=\"uid:" + o.uid() + "\">";
mText += o.formattedName();
mText += "</a>\n";
} else {
mText += "<li>";
mText.append(a->email());
mText += "\n";
}
} else {
mText += "<li><a href=\"uid:" + a->uid() + "\">";
if (!a->name().isEmpty()) mText += a->name();
else mText += a->email();
mText += "</a>\n";
}
#else //DESKTOP_VERSION
mText += "<li><a href=\"uid:" + a->uid() + "\">";
if (!a->name().isEmpty()) mText += a->name();
else mText += a->email();
mText += "</a>\n";
#endif //DESKTOP_VERSION
#else
//qDebug("nokabc ");
mText += "<li><a href=\"uid:" + a->uid() + "\">";
if (!a->name().isEmpty()) mText += a->name();
else mText += a->email();
mText += "</a>\n";
#endif
if (!a->email().isEmpty()) {
if (iconPath) {
mText += "<a href=\"mailto:" + a->name() +" <" + a->email() + ">:" + mMailSubject + "\">";
if ( a->RSVP() ) {
++a_count_nr;
mText += "<IMG src=\"" + iconPath + "\">";
}
else {
++a_count;
mText += "<IMG src=\"" + NOiconPath + "\">";
}
mText += "</a>\n";
}
}
if (a->status() != Attendee::NeedsAction )
mText +="[" + a->statusStr() + "] ";
if (a->role() == Attendee::Chair )
mText +="(" + a->roleStr().left(1) + ".)";
}
mText.append("</li></ul>");
if ( (a_count+a_count_nr) > 1 ) {
mText += "<a href=\"mailto:ALL\">";
mText += i18n( "Mail to all" );
mText += "</a> ( ";
mText += "<IMG src=\"" + iconPath + "\">";
mText += i18n( " and " );
mText += "<IMG src=\"" + NOiconPath + "\"> )";
mText += "<br>\n";
}
if ( a_count_nr > 1 ) {
mText += "<a href=\"mailto:RSVP\">";
mText += i18n( "Mail to selected" );
mText += "</a> ( ";
mText += i18n( "<IMG src=\"%1\"> only )").arg ( iconPath );
mText += "<br>\n";
}
}
}
void KOEventViewer::appendJournal(Journal *jour, int mode )
{
bool shortDate = KOPrefs::instance()->mShortDateInViewer;
QString text_d = i18n("Journal from: ");
if ( !jour->summary().isEmpty() )
text_d = jour->summary();
if (mode == 0 ) {
addTag("h2", text_d );
}
else {
if ( mode == 1 ) {
addTag("h3",i18n( "Local: " ) + text_d );
} else {
addTag("h3",i18n( "Remote: " ) + text_d );
}
}
topLevelWidget()->setCaption(i18n("Journal viewer"));
mText.append(i18n("<h3> %1 </h3> ").arg(jour->dtStartDateStr(KOPrefs::instance()->mShortDateInViewer)));
formatReadOnly(jour);
addTag("p","<b>"+i18n( "Last modified: " ) + "</b>"+KGlobal::locale()->formatDateTime(jour->lastModified(),shortDate ) );
if (!jour->description().isEmpty()) {
addTag("p",deTag(jour->description()));
}
setText(mText);
}
void KOEventViewer::formatReadOnly(Incidence *event)
{
int id = event->calID();
if ( id > 1 ) {
addTag("p", "<em>("+i18n("Calendar:")+" " + KOPrefs::instance()->getCalendar( id )->mName + ")</em>");
}
if (event->isReadOnly()) {
addTag("p","<em>(" + i18n("read-only") + ")</em>");
}
}
void KOEventViewer::setSyncMode( bool b )
{
mSyncMode = b;
}
void KOEventViewer::setTodo(Todo *event, bool clearV )
{
if ( clearV )
clearEvents();
if ( mSyncMode ) {
if ( clearV )
appendTodo(event,1 );
else
appendTodo(event,2);
} else
appendTodo(event);
}
void KOEventViewer::setJournal(Journal *event, bool clearV )
{
if ( clearV )
clearEvents();
if ( mSyncMode ) {
if ( clearV )
appendJournal(event, 1);
else
appendJournal(event, 2);
} else
appendJournal(event);
}
void KOEventViewer::setEvent(Event *event)
{
clearEvents();
if ( mSyncMode )
appendEvent(event, 1);
else
appendEvent(event);
}
void KOEventViewer::addEvent(Event *event)
{
if ( mSyncMode )
appendEvent(event, 2);
else
appendEvent(event);
}
void KOEventViewer::clearEvents(bool now)
{
mText = "";
if (now) setText(mText);
}
void KOEventViewer::addText(QString text)
{
mText.append(text);
setText(mText);
}
QString KOEventViewer::deTag(QString text)
{
#if QT_VERSION >= 0x030000
text.replace( '<' , "&lt;" );
text.replace( '>' , "&gt;" );
#else
if ( text.find ('<') >= 0 ) {
text.replace( QRegExp("<") , "&lt;" );
}
if ( text.find ('>') >= 0 ) {
text.replace( QRegExp(">") , "&gt;" );
}
#endif
return text;
}
void KOEventViewer::keyPressEvent ( QKeyEvent * e )
{
switch ( e->key() ) {
case Qt::Key_Return:
case Qt::Key_Enter :
e->ignore();
break;
default:
QTextBrowser::keyPressEvent ( e );
break;
}
}
diff --git a/korganizer/kolistview.cpp b/korganizer/kolistview.cpp
index d25f671..e7a5e0e 100644
--- a/korganizer/kolistview.cpp
+++ b/korganizer/kolistview.cpp
@@ -1,1447 +1,1447 @@
/*
This file is part of KOrganizer.
Copyright (c) 1999 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 <qlistview.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qpopupmenu.h>
#include <qprogressbar.h>
#include <qfileinfo.h>
#include <qmessagebox.h>
#include <qdialog.h>
#include <qtextstream.h>
#include <qdir.h>
#include <qwhatsthis.h>
#include <qregexp.h>
#include <qpainter.h>
#include <qpaintdevicemetrics.h>
#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kglobal.h>
#include <libkdepim/kpimglobalprefs.h>
#include <libkcal/calendar.h>
#include <libkcal/calendarlocal.h>
#include <libkcal/icalformat.h>
#include <libkcal/vcalformat.h>
#include <libkcal/recurrence.h>
#include <libkcal/filestorage.h>
#include <libkdepim/categoryselectdialog.h>
#include <libkcal/kincidenceformatter.h>
#ifndef DESKTOP_VERSION
#include <qpe/qpeapplication.h>
#else
#include <qapplication.h>
#endif
#ifndef KORG_NOPRINTER
#include "calprinter.h"
#endif
#include "koglobals.h"
#include "koprefs.h"
#include "kfiledialog.h"
#include "kolistview.h"
#include "koeventviewer.h"
extern QPixmap* sgListViewCompletedPix[6];
extern QPixmap* sgListViewJournalPix;
class KOListViewWhatsThis :public QWhatsThis
{
public:
KOListViewWhatsThis( QWidget *wid, KOListView* view ) : QWhatsThis( wid ), _wid(wid),_view (view) { };
protected:
virtual QString text( const QPoint& p)
{
return _view->getWhatsThisText(p) ;
}
private:
QWidget* _wid;
KOListView * _view;
};
ListItemVisitor::ListItemVisitor(KOListViewItem *item, QDate date )
{
mItem = item;
mDate = date;
}
ListItemVisitor::~ListItemVisitor()
{
}
bool ListItemVisitor::visit(Event *e)
{
bool ok = false;
QString start, end;
QDate ds, de;
if ( e->doesRecur() ) {
ds = e->getNextOccurence( QDateTime( mDate, QTime(0,0,0)), &ok ).date();
if ( ok ) {
int days = e->dtStart().date().daysTo(e->dtEnd().date() );
start = KGlobal::locale()->formatDate(ds,true);
de = ds.addDays( days);
end = KGlobal::locale()->formatDate(de,true);
}
}
if ( ! ok ) {
start =e->dtStartDateStr();
end = e->dtEndDateStr();
ds = e->dtStart().date();
de = e->dtEnd().date();
}
mItem->setText(0,e->summary());
mItem->setText(1,start);
if ( e->doesFloat() )
mItem->setText(2,"---");
else
mItem->setText(2,e->dtStartTimeStr());
mItem->setText(3,end);
if ( e->doesFloat() )
mItem->setText(4,"---");
else
mItem->setText(4,e->dtEndTimeStr());
if ( e->isAlarmEnabled() ) {
mItem->setText(5,e->alarms().first()->offsetText() );
} else {
mItem->setText(5, i18n("No"));
}
- mItem->setText(6, e->recurrence()->recurrenceText());
+ mItem->setText(6, e->recurrenceText());
if( ! e->doesRecur() )
mItem->setSortKey( 6, "-" );
mItem->setText(7,"---");
mItem->setText(8,"---");
mItem->setText(9, e->cancelled() ? i18n("Yes") : i18n("No"));
mItem->setText(10,e->categoriesStr());
mItem->setText(11, KOPrefs::instance()->calName( e->calID() ));
mItem->setText(12, KGlobal::locale()->formatDateTime( e->lastModified(), true, true ));
QString key;
QDate d = e->lastModified().date();
QTime t = e->lastModified().time();
key.sprintf("%04d%02d%02d%02d%02d%02d",d.year(),d.month(),d.day(),t.hour(),t.minute(),t.second() );
mItem->setSortKey(12,key);
t = e->doesFloat() ? QTime(0,0) : e->dtStart().time();
key.sprintf("%04d%02d%02d%02d%02d",ds.year(),ds.month(),ds.day(),t.hour(),t.minute());
mItem->setSortKey(1,key);
t = e->doesFloat() ? QTime(0,0) : e->dtEnd().time();
key.sprintf("%04d%02d%02d%02d%02d",de.year(),de.month(),de.day(),t.hour(),t.minute());
mItem->setSortKey(3,key);
return true;
}
bool ListItemVisitor::visit(Todo *t)
{
mItem->setText(0,t->summary());
if ( t->isCompleted() ) {
mItem->setSortKey(0,"99"+ t->summary().left(10));
} else
mItem->setSortKey(0,QString::number( t->percentComplete()+1 )+ t->summary().left(10));
mItem->setPixmap( 0, *(sgListViewCompletedPix[t->percentComplete()/20]));
if (t->hasStartDate()) {
mItem->setText(1,t->dtStartDateStr());
if (t->doesFloat()) {
mItem->setText(2,"---");
} else {
mItem->setText(2,t->dtStartTimeStr());
}
} else {
mItem->setText(1,"---");
mItem->setText(2,"---");
}
mItem->setText(3,"---");
mItem->setText(4,"---");
if ( t->isAlarmEnabled() ) {
mItem->setText(5,t->alarms().first()->offsetText() );
} else {
mItem->setText(5, i18n("No"));
}
- mItem->setText(6, t->recurrence()->recurrenceText());
+ mItem->setText(6, t->recurrenceText());
if( ! t->doesRecur() )
mItem->setSortKey( 6, "-" );
if (t->hasDueDate()) {
mItem->setText(7,t->dtDueDateStr());
if (t->doesFloat()) {
mItem->setText(8,"---");
} else {
mItem->setText(8,t->dtDueTimeStr());
}
} else {
mItem->setText(7,"---");
mItem->setText(8,"---");
}
mItem->setText(9, t->cancelled() ? i18n("Yes") : i18n("No"));
mItem->setText(10,t->categoriesStr());
mItem->setText(11, KOPrefs::instance()->calName( t->calID() ));
mItem->setText(12, KGlobal::locale()->formatDateTime( t->lastModified(), true, true ));
QString key;
QDate d = t->lastModified().date();
QTime tm = t->lastModified().time();
key.sprintf("%04d%02d%02d%02d%02d%02d",d.year(),d.month(),d.day(),tm.hour(),tm.minute(),tm.second() );
mItem->setSortKey(12,key);
if (t->hasDueDate()) {
d = t->dtDue().date();
tm = t->doesFloat() ? QTime(0,0) : t->dtDue().time();
key.sprintf("%04d%02d%02d%02d%02d",d.year(),d.month(),d.day(),tm.hour(),tm.minute());
mItem->setSortKey(7,key);
}
if ( t->hasStartDate() ) {
d = t->dtStart().date();
tm = t->doesFloat() ? QTime(0,0) : t->dtStart().time();
key.sprintf("%04d%02d%02d%02d%02d",d.year(),d.month(),d.day(),tm.hour(),tm.minute());
mItem->setSortKey(1,key);
}
return true;
}
bool ListItemVisitor::visit(Journal * j)
{
QString des;
mItem->setPixmap( 0, *sgListViewJournalPix);
if ( !j->summary().isEmpty() ) {
des = j->summary();
} else {
des = j->description().left(30);
des = des.simplifyWhiteSpace ();
des.replace (QRegExp ("\\n"),"" );
des.replace (QRegExp ("\\r"),"" );
}
mItem->setText(0,des.left(25));
mItem->setSortKey(0,"0"+ des.left(25));
mItem->setText(1,j->dtStartDateStr());
mItem->setText(2,"---");
mItem->setText(3,"---");
mItem->setText(4,"---");
mItem->setText(5,"---");
mItem->setText(6,"---");
mItem->setText(7,j->dtStartDateStr());
mItem->setText(8,"---");
mItem->setText(9,"---");
mItem->setText(10,j->categoriesStr());
mItem->setText(11, KOPrefs::instance()->calName( j->calID() ));
mItem->setText(12, KGlobal::locale()->formatDateTime( j->lastModified(), true, true ));
QString key;
QDate d = j->lastModified().date();
QTime tm = j->lastModified().time();
key.sprintf("%04d%02d%02d%02d%02d%02d",d.year(),d.month(),d.day(),tm.hour(),tm.minute(),tm.second() );
mItem->setSortKey(12,key);
d = j->dtStart().date();
key.sprintf("%04d%02d%02d",d.year(),d.month(),d.day());
mItem->setSortKey(1,key);
mItem->setSortKey(7,key);
return true;
}
KOListView::KOListView(Calendar *calendar, QWidget *parent,
const char *name)
: KOEventView(calendar, parent, name)
{
mActiveItem = 0;
mForceShowCompletedTodos = false;
mListView = new KOListViewListView(this);
mListView->addColumn(i18n("Summary"));
mListView->addColumn(i18n("Start Date"));
mListView->addColumn(i18n("Start Time"));
mListView->addColumn(i18n("End Date"));
mListView->addColumn(i18n("End Time"));
mListView->addColumn(i18n("Alarm")); // alarm set?
mListView->addColumn(i18n("Recurs")); // recurs?
mListView->addColumn(i18n("Due Date"));
mListView->addColumn(i18n("Due Time"));
mListView->addColumn(i18n("Cancelled"));
mListView->addColumn(i18n("Categories"));
mListView->addColumn(i18n("Calendar"));
mListView->addColumn(i18n("Last Modified"));
mListView->setColumnAlignment(0,AlignLeft);
mListView->setColumnAlignment(1,AlignLeft);
mListView->setColumnAlignment(2,AlignHCenter);
mListView->setColumnAlignment(3,AlignLeft);
mListView->setColumnAlignment(4,AlignHCenter);
mListView->setColumnAlignment(5,AlignLeft);
mListView->setColumnAlignment(6,AlignLeft);
mListView->setColumnAlignment(7,AlignLeft);
mListView->setColumnAlignment(8,AlignLeft);
mListView->setColumnAlignment(9,AlignLeft);
mListView->setColumnAlignment(10,AlignLeft);
mListView->setColumnAlignment(11,AlignLeft);
mListView->setColumnAlignment(12,AlignLeft);
mKOListViewWhatsThis = new KOListViewWhatsThis(mListView->viewport(),this);
int iii = 0;
for ( iii = 0; iii< 13 ; ++iii )
mListView->setColumnWidthMode( iii, QListView::Manual );
QBoxLayout *layoutTop = new QVBoxLayout(this);
layoutTop->addWidget(mListView);
mListView->setFont ( KOPrefs::instance()->mListViewFont );
mPopupMenu = eventPopup();
QPopupMenu* selPopup = new QPopupMenu ( this );
mPopupMenu->insertSeparator();
selPopup->insertItem(i18n("All"),this,
SLOT(allSelection()));
selPopup->insertItem(i18n("None"),this,
SLOT(clearSelection()));
selPopup->insertItem(i18n("Delete selected..."),this,
SLOT(deleteAll()));
mPopupMenu->insertItem(i18n("Selection"), selPopup );
mPopupMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("Hide all selected"),this,
SLOT(hideAll()),true);
selPopup->insertSeparator();
QPopupMenu * exportPO = new QPopupMenu ( this );
selPopup->insertItem( i18n("Export"), exportPO );
#ifdef DESKTOP_VERSION
mPopupMenu->insertSeparator();
mPopupMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("Print complete list..."),this,
SLOT(printList()),true);
#endif
mCalPopup = new QPopupMenu ( this );
selPopup->insertItem( i18n("Set Calendar"), mCalPopup );
selPopup->insertItem(i18n("Set categories")+"...",this,
SLOT(setCat()) );
selPopup->insertItem( i18n("Set alarm..."),this,
SLOT(setAlarm()));
#if 0
mPopupMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("Set categories")+"...",this,
SLOT(setCat()),true);
mPopupMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("Set alarm..."),this,
SLOT(setAlarm()),true);
#endif
QObject::connect(mCalPopup,SIGNAL(aboutToShow()),this,
SLOT( populateCalPopup() ));
QObject::connect(mCalPopup,SIGNAL(activated( int )),this,
SLOT( setCalendar( int ) ));
QObject::connect(mPopupMenu,SIGNAL(categoryChanged( Incidence * )),this,
SLOT( catChanged( Incidence * ) ));
exportPO->insertItem( i18n("As iCal (ics) file..."),this,
SLOT(saveToFile()));
exportPO->insertItem( i18n("As vCal (vcs) file..."),this,
SLOT(saveToFileVCS()));
exportPO->insertItem( i18n("Journal/Details..."),this,
SLOT(saveDescriptionToFile()));
// mPopupMenu->insertSeparator();
// mPopupMenu->addAdditionalItem(QIconSet(QPixmap()),
// i18n("Add Categ. to selected..."),this,
// SLOT(addCat()),true);
//mPopupMenu->insertSeparator();
#ifndef DESKTOP_VERSION
selPopup->insertSeparator();
selPopup->insertItem( i18n("Beam via IR..."),this,
SLOT(beamSelected()));
#if 0
mPopupMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("Beam via IR"),this,
SLOT(beamSelected()),true);
#endif
#endif
/*
mPopupMenu = new QPopupMenu;
mPopupMenu->insertItem(i18n("Edit Event"), this,
SLOT (editEvent()));
mPopupMenu->insertItem(SmallIcon("delete"), i18n("Delete Event"), this,
SLOT (deleteEvent()));
mPopupMenu->insertSeparator();
mPopupMenu->insertItem(i18n("Show Dates"), this,
SLOT(showDates()));
mPopupMenu->insertItem(i18n("Hide Dates"), this,
SLOT(hideDates()));
*/
QObject::connect(mListView,SIGNAL( newEvent()),
this,SIGNAL(signalNewEvent()));
QObject::connect(mListView,SIGNAL(doubleClicked(QListViewItem *)),
this,SLOT(defaultItemAction(QListViewItem *)));
QObject::connect(mListView,SIGNAL(rightButtonPressed( QListViewItem *,
const QPoint &, int )),
this,SLOT(popupMenu(QListViewItem *,const QPoint &,int)));
QObject::connect(mListView,SIGNAL(currentChanged(QListViewItem *)),
SLOT(processSelectionChange(QListViewItem *)));
QObject::connect(mListView,SIGNAL(showIncidence(Incidence *)),
SIGNAL(showIncidenceSignal(Incidence *)) );
readSettings(KOGlobals::config(),"KOListView Layout");
}
KOListView::~KOListView()
{
delete mPopupMenu;
#if QT_VERSION >= 0x030000
#else
delete mKOListViewWhatsThis;
#endif
}
void KOListView::catChanged( Incidence* inc)
{
KOListViewItem* item = getItemForEvent(inc);
if (item) {
ListItemVisitor v(item, mStartDate );
inc->accept(v);
}
}
QString KOListView::getWhatsThisText(QPoint p)
{
KOListViewItem* item = ( KOListViewItem* ) mListView->itemAt( p );
if ( item )
return KIncidenceFormatter::instance()->getFormattedText( item->data(),
KOPrefs::instance()->mWTshowDetails,
KOPrefs::instance()->mWTshowCreated,
KOPrefs::instance()->mWTshowChanged);
return i18n("That is the list view" );
}
void KOListView::setCalendar( int c )
{
int result = QMessageBox::warning( this, i18n("KO/Pi: Information!"),
i18n("This adds the selected\nitems to the calendar\n%1\nand removes them from\ntheir current calendar!").arg( KOPrefs::instance()->calName( c ) ),
i18n("Continue"), i18n("Cancel"), 0,
0, 1 );
if ( result != 0 ) {
return;
}
QPtrList<Incidence> delSel = getSelectedIncidences() ;
int icount = delSel.count();
if ( icount ) {
Incidence *incidence = delSel.first();
while ( incidence ) {
incidence->setCalID( c );
KOListViewItem * item = getItemForEvent( incidence );
if ( item ) {
ListItemVisitor v(item, mStartDate );
incidence->accept(v);
}
incidence = delSel.next();
}
}
QPtrList<KopiCalendarFile> calendars = KOPrefs::instance()->mCalendars;
KopiCalendarFile * cal = calendars.first();
while ( cal ) {
mCalendar->setCalendarEnabled( cal->mCalNumber,cal->isEnabled );
mCalendar->setAlarmEnabled( cal->mCalNumber, cal->isAlarmEnabled );
mCalendar->setReadOnly( cal->mCalNumber, cal->isReadOnly );
if ( cal->isStandard )
mCalendar->setDefaultCalendar( cal->mCalNumber );
cal = calendars.next();
}
mCalendar->setSyncEventsReadOnly();
mCalendar->reInitAlarmSettings();
}
void KOListView::populateCalPopup()
{
mCalPopup->clear();
KopiCalendarFile * kkf = KOPrefs::instance()->mCalendars.first();
while ( kkf ) {
int index = mCalPopup->insertItem( kkf->mName+"...", kkf->mCalNumber);
if ( kkf->mErrorOnLoad || kkf->isReadOnly )
mCalPopup->setItemEnabled( index, false );
kkf = KOPrefs::instance()->mCalendars.next();
}
}
void KOListView::updateList()
{
// qDebug(" KOListView::updateList() ");
}
void KOListView::clearList()
{
clear ();
}
void KOListView::setCat()
{
bool set = true;
int result = KMessageBox::warningYesNoCancel(this,
i18n("Do you want to <b>add</b> categories to the selected items or <b>reset</b> the list (i.e. remove current categories)?"),
i18n("Set categories"),
i18n("Add"),
i18n("Reset"));
if (result == KMessageBox::Cancel) return;
if (result == KMessageBox::Yes) set = false;
setCategories( set );
}
void KOListView::setAlarm()
{
KOAlarmPrefs kap( this);
if ( !kap.exec() )
return;
QPtrList<Incidence> delSel = getSelectedIncidences( true, true, false, true ); // no journals, only due todos
Incidence* inc = delSel.first();
int count = 0;
while ( inc ) {
++count;
if (kap.mAlarmButton->isChecked()) {
if (inc->alarms().count() == 0)
inc->newAlarm();
Alarm *alarm = inc->alarms().first();
alarm->setEnabled(true);
int j = kap.mAlarmTimeEdit->value()* -60;
if (kap.mAlarmIncrCombo->currentItem() == 1)
j = j * 60;
else if (kap.mAlarmIncrCombo->currentItem() == 2)
j = j * (60 * 24);
alarm->setStartOffset( j );
if (!kap.mAlarmProgram.isEmpty() && kap.mAlarmProgramButton->isOn()) {
alarm->setProcedureAlarm(kap.mAlarmProgram);
}
else if (!kap.mAlarmSound.isEmpty() && kap.mAlarmSoundButton->isOn())
alarm->setAudioAlarm(kap.mAlarmSound);
else
alarm->setType(Alarm::Invalid);
} else {
QPtrList<Alarm> alarms = inc->alarms();
Alarm *alarm;
for (alarm = alarms.first(); alarm; alarm = alarms.next() ) {
alarm->setEnabled(false);
alarm->setType(Alarm::Invalid);
}
}
KOListViewItem* item = getItemForEvent(inc);
if (item) {
ListItemVisitor v(item, mStartDate );
inc->accept(v);
}
inc = delSel.next();
}
topLevelWidget()->setCaption( i18n("Changed alarm for %1 items").arg( count ) );
qDebug("KO: Set alarm for %d items", count);
calendar()->reInitAlarmSettings();
QTimer::singleShot( 1, this, SLOT ( resetFocus() ) );
}
void KOListView::setCategories( bool removeOld )
{
KPIM::CategorySelectDialog* csd = new KPIM::CategorySelectDialog( KOPrefs::instance(), 0 );
csd->setColorEnabled();
if (! csd->exec()) {
delete csd;
return;
}
QStringList catList = csd->selectedCategories();
delete csd;
QPtrList<Incidence> delSel = getSelectedIncidences(); // all inc allowed;
Incidence* inc = delSel.first();
while ( inc ) {
if ( removeOld ) {
inc->setCategories( catList, false );
} else {
inc->addCategories( catList, false );
}
KOListViewItem* item = getItemForEvent(inc);
if (item) {
ListItemVisitor v(item, mStartDate );
inc->accept(v);
}
inc = delSel.next();
}
QTimer::singleShot( 1, this, SLOT ( resetFocus() ) );
}
void KOListView::beamSelected()
{
QPtrList<Incidence> delSel = getSelectedIncidences() ;
if ( delSel.count() )
emit beamIncidenceList( delSel );
}
void KOListView::saveDescriptionToFile()
{
int result = QMessageBox::warning( this, i18n("KO/Pi: Information!"),
i18n("This saves the text/details of selected\nJournals and Events/Todos\nto a text file."),
i18n("Continue"), i18n("Cancel"), 0,
0, 1 );
if ( result != 0 ) {
return;
}
QPtrList<Incidence> delSel = getSelectedIncidences() ;
int icount = delSel.count();
if ( icount ) {
QString fn = KOPrefs::instance()->mLastSaveFile;
fn = KFileDialog::getSaveFileName( fn, i18n("Save filename"), this );
if ( fn == "" )
return;
QFileInfo info;
info.setFile( fn );
QString mes;
bool createbup = true;
if ( info. exists() ) {
mes = i18n("File already exists!\nOld file from:\n%1\nOverwrite?\n").arg (KGlobal::locale()->formatDateTime(info.lastModified (), true, false ) );
int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),mes,
i18n("Overwrite!"), i18n("Cancel"), 0,
0, 1 );
if ( result != 0 ) {
createbup = false;
}
}
if ( createbup ) {
QString text = i18n("KO/Pi Description/Journal save file.\nSave date: ") +
KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), false);
Incidence *incidence = delSel.first();
icount = 0;
while ( incidence ) {
if ( incidence->typeID() == journalID ) {
text += "\n************************************\n";
if ( !incidence->summary().isEmpty() )
text += i18n("Journal: %1 from ").arg( incidence->summary() ) +incidence->dtStartDateStr( false );
else
text += i18n("Journal from: ") +incidence->dtStartDateStr( false );
if ( !incidence->location().isEmpty() )
text +="\n(" + i18n("Location: ") + incidence->location()+ ")";
text +="\n" + i18n("Last modified: ") +KGlobal::locale()->formatDateTime(incidence->lastModified(), false);
text +="\n" + i18n("Description: ") + "\n"+ incidence->description();
++icount;
} else {
if ( !incidence->description().isEmpty() ) {
text += "\n************************************\n";
if ( incidence->typeID() == todoID )
text += i18n("To-Do: ");
text += incidence->summary();
if ( !incidence->location().isEmpty() )
text +="\n(" + i18n("Location: ") + incidence->location()+ ")";
if ( incidence->hasStartDate() )
text +="\n"+ i18n("Start Date: ") + incidence->dtStartStr( false );
text +="\n"+ i18n("Last modified: ") +KGlobal::locale()->formatDateTime(incidence->lastModified(), false);
text += "\n" + i18n("Description: ") + "\n" + incidence->description();
++icount;
}
}
incidence = delSel.next();
}
QFile file( fn );
if (!file.open( IO_WriteOnly ) ) {
topLevelWidget()->setCaption(i18n("File open error - nothing saved!") );
return;
}
QTextStream ts( &file );
ts << text;
file.close();
//qDebug("%s ", text.latin1());
mes = i18n("KO/Pi:Saved %1 descriptions/journals").arg(icount );
KOPrefs::instance()->mLastSaveFile = fn;
topLevelWidget()->setCaption(mes);
}
}
}
void KOListView::saveToFileVCS()
{
writeToFile( false );
}
void KOListView::saveToFile()
{
writeToFile( true );
}
QPtrList<Incidence> KOListView::getSelectedIncidences( bool includeEvents, bool includeTodos, bool includeJournals, bool onlyDueTodos )
{
QPtrList<Incidence> delSel ;
bool addSubTodos = false;
bool askSubTodos = true;
QListViewItem *item = mListView->firstChild ();
while ( item ) {
if ( item->isSelected() ) {
Incidence* inc = ((KOListViewItem *)item)->data();
if ( ( addSubTodos && delSel.findRef( inc ) == -1) || !addSubTodos ) {
if ( (inc->typeID() == todoID && includeTodos) ||
(inc->typeID() == eventID && includeEvents) ||
(inc->typeID() == journalID && includeJournals) ) {
if ( inc->typeID() == todoID && onlyDueTodos ) {
if ( ((Todo*)inc)->hasDueDate() )
delSel.append( inc );
} else
delSel.append( inc );
}
}
if ( inc->typeID() == todoID ) {
Todo * todo = (Todo*) inc;
if ( todo->relations().count() ) {
if ( askSubTodos ) {
int result = KMessageBox::warningYesNoCancel(this,
i18n("One (or more) selected\ntodo has subtodos!\nDo you want to select\nall subtodos of all\nselected todos as well?"),
i18n("Todo has subtodos"),
i18n("Yes"),
i18n("No"));
if ( result == KMessageBox::Cancel ) {
delSel.clear();
return delSel;
}
if (result == KMessageBox::Yes)
addSubTodos = true;
askSubTodos = false;
}
if ( addSubTodos ) {
QPtrList<Incidence> tempSel ;
inc->addRelationsToList( &tempSel );
Incidence* tempinc = tempSel.first();
while ( tempinc ) {
if ( delSel.findRef( tempinc ) == -1 ) {
if ( tempinc->typeID() == todoID && onlyDueTodos ) {
if ( ((Todo*)tempinc)->hasDueDate() )
delSel.append( tempinc );
} else
delSel.append( tempinc );
}
tempinc = tempSel.next();
}
}
}
}
}
item = item->nextSibling();
}
return delSel;
}
void KOListView::writeToFile( bool iCal )
{
QPtrList<Incidence> delSel = getSelectedIncidences(); // all inc allowed;
if ( !iCal ) {
bool journal = false;
Incidence *incidence = delSel.first();
while ( incidence ) {
if ( incidence->typeID() == journalID ) {
journal = true;
break;
}
incidence = delSel.next();
}
if ( journal ) {
int result = KMessageBox::warningContinueCancel(this,
i18n("The journal entries can not be\nexported to a vCalendar file."),
i18n("Data Loss Warning"),i18n("Proceed"),i18n("Cancel"),
true);
if (result != KMessageBox::Continue) return;
}
}
if ( delSel.count() ) {
QString fn = KOPrefs::instance()->mLastSaveFile;
QString extension;
if ( iCal ) {
if ( fn.right( 4 ).lower() == ".vcs" ) {
fn = fn.left( fn.length() -3) + "ics";
}
} else {
if ( fn.right( 4 ).lower() == ".ics" ) {
fn = fn.left( fn.length() -3) + "vcs";
}
}
fn = KFileDialog::getSaveFileName( fn, i18n("Save filename"), this );
if ( fn == "" )
return;
QFileInfo info;
info.setFile( fn );
QString mes;
bool createbup = true;
if ( info. exists() ) {
mes = i18n("File already exists!\nOld file from:\n%1\nOverwrite?\n").arg (KGlobal::locale()->formatDateTime(info.lastModified (), true, false ) );
int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),mes,
i18n("Overwrite!"), i18n("Cancel"), 0,
0, 1 );
if ( result != 0 ) {
createbup = false;
}
}
if ( createbup ) {
CalendarLocal cal;
cal.setTimeZoneId(KPimGlobalPrefs::instance()->mTimeZoneId);
Incidence *incidence = delSel.first();
while ( incidence ) {
cal.addIncidence( incidence->clone() );
incidence = delSel.next();
}
if ( iCal ) {
ICalFormat format;
format.save( &cal, fn );
} else {
VCalFormat format;
format.save( &cal, fn );
}
mes = i18n("KO/Pi:Saved %1").arg(fn );
KOPrefs::instance()->mLastSaveFile = fn;
topLevelWidget()->setCaption(mes);
}
}
QTimer::singleShot( 1, this, SLOT ( resetFocus() ) );
}
void KOListView::hideAll()
{
QPtrList<QListViewItem> delSel ;
QListViewItem *item = mListView->firstChild ();
while ( item ) {
if ( item->isSelected() ) {
delSel.append(item);
}
item = item->nextSibling();
}
item = delSel.first() ;
while ( item ) {
QListViewItem * del = item;
item = delSel.next();
delete del;
}
}
void KOListView::printList()
{
mListView->printList();
}
void KOListView::deleteAll()
{
QPtrList<Incidence> delSel = getSelectedIncidences(); // all inc allowed;;
if ( delSel.count() ) {
int icount = delSel.count();
Incidence *incidence = delSel.first();
Incidence *toDelete;
KOPrefs *p = KOPrefs::instance();
bool confirm = p->mConfirm;
QString mess;
mess = mess.sprintf( i18n("You have %d item(s) selected.\n"), icount );
if ( KMessageBox::Continue == KMessageBox::warningContinueCancel(this, mess + i18n("All selected items will be\npermanently deleted.\n(Deleting items will take\nsome time on a PDA)\n"), i18n("KO/Pi Confirmation"),i18n("Delete")) ) {
p->mConfirm = false;
int delCounter = 0;
QDialog dia ( this, "p-dialog", true );
QLabel lab (i18n("Close dialog to abort deletion!"), &dia );
QVBoxLayout lay( &dia );
lay.setMargin(7);
lay.setSpacing(7);
lay.addWidget( &lab);
QProgressBar bar( icount, &dia );
lay.addWidget( &bar);
int w = 220;
int h = 50;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
dia.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
//dia.resize( 240,50 );
dia.show();
KOPrefs::instance()->mGlobalUpdateDisabled = true;
while ( incidence ) {
bar.setProgress( delCounter );
mess = mess.sprintf( i18n("Deleting item %d ..."), ++delCounter );
dia.setCaption( mess );
qApp->processEvents();
toDelete = (incidence);
incidence = delSel.next();
emit deleteIncidenceSignal(toDelete );
if ( dia.result() != 0 )
break;
}
KOPrefs::instance()->mGlobalUpdateDisabled = false;
emit deleteIncidenceSignal( 0 );
mess = mess.sprintf( i18n("%d items remaining in list."), count() );
topLevelWidget ()->setCaption( mess );
p->mConfirm = confirm;
}
}
}
int KOListView::maxDatesHint()
{
return 0;
}
int KOListView::currentDateCount()
{
return 0;
}
QPtrList<Incidence> KOListView::selectedIncidences()
{
QPtrList<Incidence> eventList;
QListViewItem *item = mListView->firstChild ();
while ( item ) {
if ( item->isSelected() ) {
eventList.append(((KOListViewItem *)item)->data());
}
item = item->nextSibling();
}
// // QListViewItem *item = mListView->selectedItem();
//if (item) eventList.append(((KOListViewItem *)item)->data());
return eventList;
}
DateList KOListView::selectedDates()
{
DateList eventList;
return eventList;
}
void KOListView::showDates(bool show)
{
// Shouldn't we set it to a value greater 0? When showDates is called with
// show == true at first, then the columnwidths are set to zero.
static int oldColWidth1 = 0;
static int oldColWidth3 = 0;
if (!show) {
oldColWidth1 = mListView->columnWidth(1);
oldColWidth3 = mListView->columnWidth(3);
mListView->setColumnWidth(1, 0);
mListView->setColumnWidth(3, 0);
} else {
mListView->setColumnWidth(1, oldColWidth1);
mListView->setColumnWidth(3, oldColWidth3);
}
mListView->repaint();
}
void KOListView::printPreview(CalPrinter *calPrinter, const QDate &fd,
const QDate &td)
{
#ifndef KORG_NOPRINTER
calPrinter->preview(CalPrinter::Day, fd, td);
#endif
}
void KOListView::showDates()
{
showDates(true);
}
void KOListView::hideDates()
{
showDates(false);
}
void KOListView::resetFocus()
{
topLevelWidget()->setActiveWindow();
topLevelWidget()->raise();
mListView->setFocus();
}
void KOListView::updateView()
{
mListView->setFocus();
if ( mListView->firstChild () ) {
mListView->setCurrentItem( mListView->firstChild () );
}
processSelectionChange( mListView->firstChild () );
}
void KOListView::updateConfig()
{
mListView->setFont ( KOPrefs::instance()->mListViewFont );
updateView();
}
void KOListView::setStartDate(const QDate &start)
{
mStartDate = start;
}
void KOListView::showDates(const QDate &start, const QDate &end)
{
clear();
mStartDate = start;
QDate date = start;
while( date <= end ) {
addEvents(calendar()->events(date));
addTodos(calendar()->todos(date));
addJournals( calendar()->journals4Date(date) );
date = date.addDays( 1 );
}
//emit incidenceSelected( 0 );
updateView();
}
void KOListView::addEvents(QPtrList<Event> eventList)
{
Event *ev;
for(ev = eventList.first(); ev; ev = eventList.next()) {
addIncidence(ev);
}
if ( !mListView->currentItem() ){
updateView();
}
}
void KOListView::addTodos(QPtrList<Todo> eventList)
{
Todo *ev;
for(ev = eventList.first(); ev; ev = eventList.next()) {
addIncidence(ev);
}
if ( !mListView->currentItem() ){
updateView();
}
}
void KOListView::addJournals(QPtrList<Journal> eventList)
{
Journal *ev;
for(ev = eventList.first(); ev; ev = eventList.next()) {
addIncidence(ev);
}
if ( !mListView->currentItem() ){
updateView();
}
}
void KOListView::showCompletedTodos()
{
mForceShowCompletedTodos = true;
}
void KOListView::addIncidence(Incidence *incidence)
{
if ( mUidDict.find( incidence->uid() ) ) return;
// mListView->setFont ( KOPrefs::instance()->mListViewFont );
if ( incidence->typeID() == todoID ) {
if ( ! mForceShowCompletedTodos ) {
if ( !KOPrefs::instance()->mShowCompletedTodo && ((Todo*)incidence)->isCompleted() )
return;
}
}
mUidDict.insert( incidence->uid(), incidence );
KOListViewItem *item = new KOListViewItem( incidence, mListView );
ListItemVisitor v(item, mStartDate );
if (incidence->accept(v)) {
return;
}
else delete item;
}
void KOListView::showEvents(QPtrList<Event> eventList)
{
clear();
addEvents(eventList);
// After new creation of list view no events are selected.
emit incidenceSelected( 0 );
}
int KOListView::count()
{
return mListView->childCount();
}
void KOListView::changeEventDisplay(Event *event, int action)
{
KOListViewItem *item;
switch(action) {
case KOGlobals::EVENTADDED:
addIncidence( event );
break;
case KOGlobals::EVENTEDITED:
item = getItemForEvent(event);
if (item) {
ListItemVisitor v(item, mStartDate );
((Incidence*)event)->accept(v);
}
break;
case KOGlobals::EVENTDELETED:
item = getItemForEvent(event);
if (item) {
mUidDict.remove( event->uid() );
delete item;
}
break;
default:
;
}
}
KOListViewItem *KOListView::getItemForEvent(Incidence *event)
{
KOListViewItem *item = (KOListViewItem *)mListView->firstChild();
while (item) {
if (item->data() == event) return item;
item = (KOListViewItem *)item->nextSibling();
}
return 0;
}
void KOListView::defaultItemAction(QListViewItem *i)
{
KOListViewItem *item = static_cast<KOListViewItem *>( i );
if ( item ) defaultAction( item->data() );
}
void KOListView::popupMenu(QListViewItem *item,const QPoint &,int)
{
mActiveItem = (KOListViewItem *)item;
if (mActiveItem) {
Incidence *incidence = mActiveItem->data();
mPopupMenu->enableDefault( !mListView->hasMultiSelection( item ) );
mPopupMenu->showIncidencePopup(incidence);
/*
if ( incidence && incidence->type() == "Event" ) {
Event *event = static_cast<Event *>( incidence );
mPopupMenu->showEventPopup(event);
}
*/
}
}
void KOListView::readSettings(KConfig *config, QString setting)
{
// qDebug("KOListView::readSettings ");
mListView->restoreLayout(config,setting);
}
void KOListView::writeSettings(KConfig *config, QString setting)
{
// qDebug("KOListView::writeSettings ");
mListView->saveLayout(config, setting);
}
void KOListView::processSelectionChange(QListViewItem *)
{
KOListViewItem *item =
static_cast<KOListViewItem *>( mListView->currentItem() );
if ( !item ) {
emit incidenceSelected( 0 );
} else {
emit incidenceSelected( item->data() );
}
}
void KOListView::clearSelection()
{
mListView->selectAll( false );
}
void KOListView::allSelection()
{
mListView->selectAll( true );
}
void KOListView::clear()
{
mListView->clear();
mUidDict.clear();
}
Incidence* KOListView::currentItem()
{
if ( mListView->currentItem() )
return ((KOListViewItem*) mListView->currentItem())->data();
return 0;
}
void KOListView::keyPressEvent ( QKeyEvent *e)
{
if ( e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace ) {
deleteAll();
return;
}
e->ignore();
}
void KOListViewListView::keyPressEvent ( QKeyEvent *e)
{
switch ( e->key() ) {
case Qt::Key_Down:
if ( e->state() == ShiftButton ) {
QListViewItem* cn = currentItem();
if ( !cn )
cn = firstChild();
if ( !cn )
return;
while ( cn->nextSibling() )
cn = cn->nextSibling();
setCurrentItem ( cn );
ensureItemVisible ( cn );
e->accept();
return;
}
if ( e->state() == ControlButton ) {
int count = childCount ();
int jump = count / 5;
QListViewItem* cn;
cn = currentItem();
if ( ! cn )
return;
if ( jump == 0 )
jump = 1;
while ( jump && cn->nextSibling() ) {
cn = cn->nextSibling();
--jump;
}
setCurrentItem ( cn );
ensureItemVisible ( cn );
} else
QListView::keyPressEvent ( e ) ;
e->accept();
break;
case Qt::Key_Up:
if ( e->state() == ShiftButton ) {
QListViewItem* cn = firstChild();
if ( cn ) {
setCurrentItem ( cn );
ensureItemVisible ( cn );
}
e->accept();
return;
}
if ( e->state() == ControlButton ) {
int count = childCount ();
int jump = count / 5;
QListViewItem* cn;
cn = currentItem();
if ( ! cn )
return;
if ( jump == 0 )
jump = 1;
while ( jump && cn->itemAbove ()) {
cn = cn->itemAbove ();
--jump;
}
setCurrentItem ( cn );
ensureItemVisible ( cn );
} else
QListView::keyPressEvent ( e ) ;
e->accept();
break;
case Qt::Key_I: {
QListViewItem* cn;
cn = currentItem();
if ( cn ) {
KOListViewItem* ci = (KOListViewItem*)( cn );
if ( ci ){
//emit showIncidence( ci->data());
cn = cn->nextSibling();
if ( cn ) {
setCurrentItem ( cn );
ensureItemVisible ( cn );
}
emit showIncidence( ci->data());
}
}
e->accept();
}
break;
case Qt::Key_Return:
case Qt::Key_Enter:
{
QListViewItem* cn;
cn = currentItem();
if ( cn ) {
KOListViewItem* ci = (KOListViewItem*)( cn );
if ( ci ){
if ( e->state() == ShiftButton )
ci->setSelected( false );
else
ci->setSelected( true );
cn = cn->nextSibling();
if ( cn ) {
setCurrentItem ( cn );
ensureItemVisible ( cn );
}
}
}
e->accept();
}
break;
default:
e->ignore();
}
}
KOListViewListView::KOListViewListView(KOListView * lv )
: KListView( lv, "kolistlistview", false )
{
mYMousePos = 0;
mPopupTimer = new QTimer(this);
connect(mPopupTimer , SIGNAL(timeout()), this, SLOT(popupMenu()));
#ifndef DESKTOP_VERSION
//QPEApplication::setStylusOperation(viewport(), QPEApplication::RightOnHold );
#endif
setSelectionMode( QListView::Multi );
setMultiSelection( true);
}
bool KOListViewListView::hasMultiSelection(QListViewItem* item)
{
QListViewItem *qitem = firstChild ();
while ( qitem ) {
if ( qitem->isSelected() && item != qitem )
return true;
qitem = qitem->nextSibling();
}
return false;
}
void KOListViewListView::contentsMouseDoubleClickEvent(QMouseEvent *e)
{
if (!e) return;
QPoint vp = contentsToViewport(e->pos());
QListViewItem *item = itemAt(vp);
if (!item) {
emit newEvent();
return;
}
KListView::contentsMouseDoubleClickEvent(e);
}
#if 0
void KOListViewListView::contentsMousePressEvent(QMouseEvent *e)
{
//qDebug("contentsMousePressEvent++++ ");
KListView::contentsMousePressEvent( e );
if ( e->button() == RightButton ) {
QListViewItem* ci = currentItem();
clearSelection () ;
if ( ci )
ci->setSelected( true );
}
}
void KOListViewListView::contentsMouseReleaseEvent(QMouseEvent *e)
{
KListView::contentsMouseReleaseEvent(e);
}
void KOListViewListView::contentsMouseMoveEvent(QMouseEvent *e)
{
KListView::contentsMouseMoveEvent(e);
}
#endif
void KOListViewListView::popupMenu()
{
mPopupTimer->stop();
QMouseEvent* e = new QMouseEvent( QEvent::MouseButtonPress, mEventPos ,mEventGlobalPos, RightButton , RightButton );
QApplication::postEvent( this->viewport(), e );
}
void KOListViewListView::contentsMousePressEvent(QMouseEvent *e)
{
//qDebug("contentsMousePressEvent++++ %d %d", e->pos().y(), e->globalPos().y());
mYMousePos = mapToGlobal( (e->pos())).y();
if ( e->button() == LeftButton ) {
mPopupTimer->start( 600 );
mEventPos = contentsToViewport(e->pos());
mEventGlobalPos = e->globalPos();
}
KListView::contentsMousePressEvent( e );
if ( e->button() == RightButton ) {
QListViewItem* ci = currentItem();
//clearSelection();
if ( ci )
ci->setSelected( true );
}
}
void KOListViewListView::contentsMouseReleaseEvent(QMouseEvent *e)
{
mPopupTimer->stop();
KListView::contentsMouseReleaseEvent(e);
}
void KOListViewListView::contentsMouseMoveEvent(QMouseEvent *e)
{
// qDebug("contentsMouseMoveEv....... ");
// qDebug("start: %d current %d ",mYMousePos , mapToGlobal( (e->pos())).y() );
int diff = mYMousePos - mapToGlobal( (e->pos())).y();
if ( diff < 0 ) diff = -diff;
if ( diff > 15 )
mPopupTimer->stop();
else {
mEventPos = contentsToViewport(e->pos());
mEventGlobalPos = e->globalPos();
}
KListView::contentsMouseMoveEvent(e);
}
#define protected public
#include <qheader.h>
#undef protected
void KOListViewListView::printList()
{
#ifdef DESKTOP_VERSION
KOPrintPrefs pp ( this );
if (!pp.exec() )
return;
int scaleval = pp.printMode() ;
QPrinter printer;
if (!printer.setup() )
return;
clearSelection ();
QPainter p;
p.begin ( &printer );
QPaintDeviceMetrics m = QPaintDeviceMetrics ( &printer );
float dx, dy;
int wid = (m.width() * 9)/10;
dx = (float) wid/(float)contentsWidth ();
dy = (float)(m.height()) / (float)contentsHeight ();
float scale;
// scale to fit the width or height of the paper
if ( dx < dy )
scale = dx;
else
scale = dy;
p.translate( m.width()/10,m.width()/10 );
if ( scaleval == 2 || scaleval == 1 && scale < 1.0 ) {
p.scale( scale, scale );
}
int cou = header()->count();
int iii;
QRect rect ( 0,0,0, header()->height());
for ( iii = 0; iii < cou; ++iii ) {
rect.setLeft ( header()->sectionPos( iii ) );
rect.setRight ( header()->sectionPos( iii ) + header()->sectionSize (iii));
header()->paintSection ( & p, header()->mapToIndex (iii), rect );
}
p.translate( 0, header()->height());
drawContentsOffset ( &p, 0,0, 0,0, contentsWidth (), contentsHeight () );
p.end();
#endif
}
diff --git a/korganizer/komonthview.cpp b/korganizer/komonthview.cpp
index 498d9b0..eea9a4d 100644
--- a/korganizer/komonthview.cpp
+++ b/korganizer/komonthview.cpp
@@ -1,2324 +1,2326 @@
/*
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.
*/
#include <qpopupmenu.h>
#include <qfont.h>
#include <qfontmetrics.h>
#include <qkeycode.h>
#include <qhbox.h>
#include <qvbox.h>
#include <qwidgetstack.h>
#include <qpushbutton.h>
#include <qtooltip.h>
#include <qpainter.h>
#include <qtimer.h>
#include <qwhatsthis.h>
#ifndef DESKTOP_VERSION
#include <qpe/qpeapplication.h>
#else
#include <qapplication.h>
#endif
#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kiconloader.h>
#include <kcalendarsystem.h>
#ifndef KORG_NOPRINTER
#include "calprinter.h"
#endif
#include "koprefs.h"
#ifndef KORG_NOPLUGINS
#include "kocore.h"
#endif
#include "koglobals.h"
#include <libkcal/kincidenceformatter.h>
#include "komonthview.h"
#define PIXMAP_SIZE 5
#ifdef DESKTOP_VERSION
QToolTipGroup *MonthViewCell::mToolTipGroup = 0;
#endif
class KNOWhatsThis :public QWhatsThis
{
public:
KNOWhatsThis( KNoScrollListBox* sbox ) : QWhatsThis( sbox ), _wid( sbox) { };
//~KNOWhatsThis( ) {qDebug("~KNOWhatsThis( ) "); };
protected:
virtual QString text( const QPoint& p)
{
return _wid->getWhatsThisText(p) ;
};
private:
KNoScrollListBox* _wid;
};
KNoScrollListBox::KNoScrollListBox(QWidget *parent,const char *name)
: QListBox(parent, name, WRepaintNoErase)
{
#ifndef DESKTOP_VERSION
QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold );
#endif
mWT = new KNOWhatsThis(this);
resetOnFocusIn = true;
setVScrollBarMode(QScrollView::AlwaysOff);
setHScrollBarMode(QScrollView::AlwaysOff);
}
KNoScrollListBox::~KNoScrollListBox()
{
#if QT_VERSION >= 0x030000
#else
delete mWT;
#endif
}
void KNoScrollListBox::focusInEvent ( QFocusEvent * e )
{
QListBox::focusInEvent ( e );
if ( count() ){
int ci = currentItem();
if ( ci < 0 ) ci = 0;
setCurrentItem( ci );
setSelected ( ci, true );
emit highlighted( item ( ci ) );
resetOnFocusIn = true;
if ( KOPrefs::instance()->mEnableMonthScroll || KOPrefs::instance()->mMonthViewWeek ) {
QListBoxItem *fi = firstItem ();
if (fi ) {
int ihei = fi->height( this );
int hei = numRows () * ihei;
if ( hei < height() - horizontalScrollBar()->height () ) {
setVScrollBarMode(QScrollView::AlwaysOff);
}
else
setVScrollBarMode(QScrollView::Auto);
if ( ihei *3 > height() ) {
setHScrollBarMode(QScrollView::AlwaysOff);
}
else {
setHScrollBarMode(QScrollView::Auto);
}
} else {
setVScrollBarMode(QScrollView::Auto);
setHScrollBarMode(QScrollView::Auto);
}
}
}
}
void KNoScrollListBox::focusOutEvent ( QFocusEvent * e )
{
int i = currentItem ();
if ( i >= 0 ) {
setSelected ( i, false );
}
QListBox::focusOutEvent ( e );
setVScrollBarMode(QScrollView::AlwaysOff);
setHScrollBarMode(QScrollView::AlwaysOff);
emit highlightIncidence( 0, (MonthViewCell*)this, 0 );
}
QString KNoScrollListBox::getWhatsThisText(QPoint p)
{
QListBoxItem* item = itemAt ( p );
if ( ! item ) {
return i18n("Click in the cell\nto add an event!");
}
return KIncidenceFormatter::instance()->getFormattedText(((MonthViewItem*) item)->incidence(),
KOPrefs::instance()->mWTshowDetails,
KOPrefs::instance()->mWTshowCreated,
KOPrefs::instance()->mWTshowChanged);
}
void KNoScrollListBox::keyPressEvent(QKeyEvent *e)
{
//qDebug("KNoScrollListBox::keyPressEvent ");
switch(e->key()) {
case Key_Right:
if ( e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton )
{
e->ignore();
return;
}
scrollBy(10,0);
break;
case Key_Left:
if (e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton )
{
e->ignore();
return;
}
scrollBy(-10,0);
break;
case Key_Up:
if( e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton) {
e->ignore();
break;
}
if ( count() ) {
if ( currentItem() == 0 ) {
emit prevCell();
} else {
setCurrentItem((currentItem()+count()-1)%count());
if(!itemVisible(currentItem())) {
if((unsigned int) currentItem() == (count()-1)) {
setTopItem(currentItem()-numItemsVisible()+1);
} else {
setTopItem(topItem()-1);
}
}
}
}
break;
case Key_Down:
if(e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton) {
e->ignore();
break;
}
if ( count () ) {
if ( ((uint)currentItem()+1) == count () ) {
emit nextCell();
} else {
setCurrentItem((currentItem()+1)%count());
if(!itemVisible(currentItem())) {
if(currentItem() == 0) {
setTopItem(0);
} else {
setTopItem(topItem()+1);
}
}
}
}
break;
case Key_I:
QTimer::singleShot( 1, this, SLOT ( oneDown() ) );
e->ignore();
break;
case Key_Return:
case Key_Enter:
{
if ( currentItem() >= 0 ) {
emit doubleClicked( item( currentItem() ) );
e->accept();
} else {
e->ignore();
}
}
break;
case Key_Shift:
emit shiftDown();
break;
default:
e->ignore();
break;
}
}
void KNoScrollListBox::oneDown()
{
if ( count () ) {
if ( ((uint)currentItem()+1) == count () ) {
emit nextCell();
} else {
resetOnFocusIn = false;
setCurrentItem((currentItem()+1)%count());
if(!itemVisible(currentItem())) {
if(currentItem() == 0) {
setTopItem(0);
} else {
setTopItem(topItem()+1);
}
}
}
}
}
void KNoScrollListBox::keyReleaseEvent(QKeyEvent *e)
{
switch(e->key()) {
case Key_Shift:
emit shiftUp();
break;
default:
break;
}
}
void KNoScrollListBox::mousePressEvent(QMouseEvent *e)
{
QListBox::mousePressEvent(e);
if(e->button() == RightButton) {
emit rightClick();
}
}
MonthViewItem::MonthViewItem( Incidence *incidence, const QString & s)
: QListBoxItem()
{
mblockRepaint = true;
isWeekItem = KOPrefs::instance()->mMonthViewWeek;
recycle( incidence, s );
}
void MonthViewItem::recycle( Incidence *incidence, const QString & s)
{
mDisplayHighlighted = false;
setText( s );
mMultiday = 0;
mIncidence = incidence;
mRecur = false;
mAlarm = false;
mReply = false;
mInfo = false;
mdayPos = 0;
}
bool MonthViewItem::setHighlightedFalse()
{
if ( !mDisplayHighlighted )
return false;
mDisplayHighlighted = false;
return true;
}
bool MonthViewItem::setHighlighted( Incidence * inc )
{
if ( inc == mIncidence ) {
if ( mDisplayHighlighted )
return false;
mDisplayHighlighted = true;
return true;
} else {
if ( !mDisplayHighlighted )
return false;
mDisplayHighlighted = false;
return true;
}
return false;
}
void MonthViewItem::paint(QPainter *p)
{
if ( mblockRepaint || !mIncidence ) {
return;
}
#if QT_VERSION >= 0x030000
bool sel = isSelected();
#else
bool sel = selected();
#endif
int heihei = height( listBox () );
int x = 1;
if (KOPrefs::instance()->mMonthViewUsesCategoryColor || mDisplayHighlighted || sel )
{
p->setBackgroundColor( palette().color( QPalette::Normal, \
sel ||mDisplayHighlighted ? QColorGroup::Highlight : QColorGroup::Background ) );
p->eraseRect( 0, 0, listBox()->maxItemWidth(), heihei );
}
//int y = 3;//(height() - mRecurPixmap.height()) /2;
int size = PIXMAP_SIZE;
if ( QApplication::desktop()->width() < 300 )
size = 3;
int y = (heihei - size -1 ) /2;
if ( mIncidence->calID() > 1 ) {
p->fillRect ( x, y-2,size,size+4, KOPrefs::instance()->defaultColor( mIncidence->calID() ) );
p->drawRect ( x, y-2,size,size+4);
x += size + 1;
}
if ( KOPrefs::instance()->mMonthShowIcons ) {
if ( mInfo ) {
p->fillRect ( x, y,size,size, Qt::darkGreen );
x += size + 1;
}
if ( mRecur ) {
p->fillRect ( x, y,size,size, Qt::blue );
x += size + 1;
}
if ( mAlarm ) {
p->fillRect ( x, y,size,size, Qt::red );
x += size + 1;
}
if ( mReply ) {
p->fillRect ( x, y,size,size, Qt::yellow );
x += size + 1;
}
}
if ( sel ) p->setPen( Qt::white );
else p->setPen( palette().color( QPalette::Normal,QColorGroup::Foreground ) );
#if 0
p->setPen( palette().color( QPalette::Normal, sel ? \
QColorGroup::HighlightedText : QColorGroup::Foreground ) );
#endif
QColor textColor = p->pen().color();
if ( mMultiday ) {
int yyy = y+(size/2);
int sizeM = size+2;
p->setBrush( QBrush( textColor ) );
p->drawLine ( x+1, yyy, x +sizeM +sizeM/2-1, yyy ) ;
if ( mMultiday == 2 || mMultiday == 3 ) {
QPointArray pa ( 3 );
pa.setPoint (0, x, yyy );
pa.setPoint (1, x+sizeM/2, yyy+sizeM/2 );
pa.setPoint (2, x+sizeM/2, yyy-sizeM/2 );
p->drawPolygon( pa );
}
if ( mMultiday == 2 || mMultiday == 1 ) {
QPointArray pa ( 3 );
pa.setPoint (0, x+sizeM +sizeM/2, yyy );
pa.setPoint (1, x+sizeM, yyy+sizeM/2 );
pa.setPoint (2, x+sizeM, yyy-sizeM/2 );
p->drawPolygon( pa );
}
if ( mMultiday == 1 ) {
// p->fillRect ( x, yyy-sizeM/2+1, sizeM/2, size, QBrush ( QBrush::SolidPattern ) );
p->drawLine ( x+1, yyy-sizeM/2, x+1, yyy+sizeM/2 );
}
if ( mMultiday == 3 ) {
// p->fillRect ( x+sizeM, yyy-sizeM/2+1, sizeM/2, size, QBrush ( QBrush::SolidPattern ) );
p->drawLine ( x+sizeM +sizeM/2-1, yyy-sizeM/2, x+sizeM +sizeM/2-1, yyy+sizeM/2 );
}
x += sizeM/2 + 1;
x += sizeM + 1;
}
if ( mIncidence->typeID() == todoID ){
Todo* td = ( Todo* ) mIncidence;
if ( td->isCompleted() ) {
int half = size/2;
p->drawLine ( x, heihei/2, x +half , heihei/2 +half ) ;
p->drawLine ( x +half , heihei/2 +half , x +half+half +2 , heihei/2 -2 ) ;
x += half+half + 4;
} else {
int val = td->percentComplete()/20;
p->fillRect ( x+1, y-2, val ,size+4,textColor );
p->drawRect ( x, y-2,7,size+4);
x += size + 3;
}
}
QFontMetrics fm = p->fontMetrics();
int yPos;
int pmheight = size;
if( pmheight < fm.height() )
yPos = fm.ascent() + fm.leading()/2;
else
yPos = pmheight/2 - fm.height()/2 + fm.ascent();
if ( KOPrefs::instance()->mMonthShowTimes || isWeekItem) {
p->drawText( x, yPos, text() );
if ( mIncidence->cancelled() ) {
int wid = fm.width( text() );
p->drawLine( x, heihei/2 ,x+wid, heihei/2 );
}
} else {
QString pText = text();
if( pText.mid(2,1) == ":" )
pText = pText.mid( 6 );
p->drawText( x, yPos, pText );
if ( mIncidence->cancelled() ) {
int wid = fm.width( pText );
p->drawLine( x, heihei/2 ,x+wid, heihei/2 );
}
}
}
int MonthViewItem::height(const QListBox *lb) const
{
int ret = 10;
if ( lb )
ret = lb->fontMetrics().lineSpacing()+1;
return ret;
}
int MonthViewItem::width(const QListBox *lb) const
{
if( KOPrefs::instance()->mEnableMonthScroll || isWeekItem ) {
int size = PIXMAP_SIZE;
if ( QApplication::desktop()->width() < 300 )
size = 3;
int x = 1;
if ( KOPrefs::instance()->mMonthShowIcons ) {
if ( mInfo ) {
x += size + 1;
}
if( mRecur ) {
x += size+1;
}
if( mAlarm ) {
x += size+1;
}
if( mReply ) {
x += size+1;
}
}
if( mMultiday ) {
x += size+1+2+size/2;
}
return( x + lb->fontMetrics().width( text() ) + 1 );
}
if ( ! lb )
return 10;
return lb->width();
}
MonthViewCell::MonthViewCell( KOMonthView *parent,QWidget* par )
: KNoScrollListBox( par ),
mMonthView( parent )
{
//QVBoxLayout *topLayout = new QVBoxLayout( this );
currentPalette = 0;
// mLabel = new QLabel( this );QPushButton
mLabel = new QPushButton( this );
//mLabel->setFrameStyle( QFrame::Panel | QFrame::Plain );
//mLabel->setLineWidth( 1 );
//mLabel->setAlignment( AlignCenter );
mLabel->setFlat( true );
mLabel->setFocusPolicy(NoFocus);
//mItemList = new KNoScrollListBox( this );
setMinimumSize( 10, 10 );
setFrameStyle( QFrame::Panel | QFrame::Plain );
setLineWidth( 1 );
//topLayout->addWidget( mItemList );
mLabel->raise();
// QColor( 0,0,255 ) QColor( 160,1600,255 )
mStandardPalette = palette();
mStandardPalette.setColor(QColorGroup::Base, mStandardPalette.color( QPalette::Normal, QColorGroup::Background ) );
enableScrollBars( false );
updateConfig();
//connect( mLabel, SIGNAL( clicked( )), SLOT( newEvent() ));
connect( mLabel, SIGNAL( clicked( )), SLOT( showDay() ));
connect( this , SIGNAL( doubleClicked( QListBoxItem *) ),
SLOT( defaultAction( QListBoxItem * ) ) );
connect( this, SIGNAL( rightButtonPressed( QListBoxItem *,
const QPoint &) ),
SLOT( contextMenu( QListBoxItem * ) ) );
connect( this, SIGNAL( highlighted( QListBoxItem *) ),
SLOT( selection( QListBoxItem * ) ) );
/*
connect( this, SIGNAL( clicked( QListBoxItem * ) ),
SLOT( selection( QListBoxItem * ) ) );
*/
}
#ifdef DESKTOP_VERSION
QToolTipGroup *MonthViewCell::toolTipGroup()
{
if (!mToolTipGroup) mToolTipGroup = new QToolTipGroup(0);
return mToolTipGroup;
}
#endif
void MonthViewCell::setDate( const QDate &date )
{
// kdDebug() << "MonthViewCell::setDate(): " << date.toString() << endl;
mDate = date;
//resizeEvent( 0 );
}
QDate MonthViewCell::date() const
{
return mDate;
}
void MonthViewCell::setPrimary( bool primary )
{
mPrimary = primary;
//setMyPalette();
}
void MonthViewCell::setMyPalette()
{
if ( mHoliday) {
if ( currentPalette == 1 ) return;
mLabel->setPalette( QPalette ( mHolidayPalette.color( QPalette::Normal,QColorGroup::Base),mHolidayPalette.color(QPalette::Normal,QColorGroup::Base ) ));
setPalette( mHolidayPalette );
//mLabel->setPalette( mHolidayPalette );
currentPalette = 1;
} else {
if ( mPrimary ) {
if ( currentPalette == 2 ) return;
mLabel->setPalette( QPalette ( mPrimaryPalette.color( QPalette::Normal,QColorGroup::Base),mPrimaryPalette.color(QPalette::Normal,QColorGroup::Base ) ));
//mLabel->setPalette( mPrimaryPalette );
setPalette( mPrimaryPalette );
currentPalette = 2;
} else {
if ( currentPalette == 3 ) return;
setPalette( mNonPrimaryPalette );
mLabel->setPalette( QPalette ( mNonPrimaryPalette.color( QPalette::Normal,QColorGroup::Base),mNonPrimaryPalette.color(QPalette::Normal,QColorGroup::Base ) ));
//mLabel->setPalette( mNonPrimaryPalette );;
currentPalette = 3;
}
}
//QPalette pal = palette();
//mLabel->setPalette( QPalette ( pal.color( QPalette::Normal,QColorGroup::Base),pal.color(QPalette::Normal,QColorGroup::Base ) ));
}
QPalette MonthViewCell::getPalette ()
{
if ( !KOPrefs::instance()->mMonthViewUsesDayColors )
return mStandardPalette;
if ( mHoliday) {
return mHolidayPalette ;
} else {
if ( mPrimary ) {
return mPrimaryPalette ;
}
}
return mNonPrimaryPalette;
}
bool MonthViewCell::isPrimary() const
{
return mPrimary;
}
void MonthViewCell::setHoliday( bool holiday )
{
mHoliday = holiday;
//setMyPalette();
}
void MonthViewCell::setHoliday( const QString &holiday )
{
mHolidayString = holiday;
if ( !holiday.isEmpty() ) {
setHoliday( true );
}
}
void MonthViewCell::startUpdateCell()
{
blockSignals( true );
mdayCount = 0;
setFocusPolicy(NoFocus);
if ( !mMonthView->isUpdatePossible() )
return;
MonthViewItem *mitem = (MonthViewItem*) firstItem ();
while ( mitem ) {
mitem->setBlockRepaint( true );
mitem = (MonthViewItem *)mitem->next();
}
if ( mAvailItemList.count() > 20 ) {
mAvailItemList.setAutoDelete( true );
mAvailItemList.clear();
mAvailItemList.setAutoDelete( false );
clear();
}
setPrimary( mDate.month()%2 );
setHoliday( KOGlobals::self()->calendarSystem()->dayOfWeek(mDate) == KOGlobals::self()->calendarSystem()->weekDayOfPray() || ( mDate.dayOfWeek() == 6 ) && KOPrefs::instance()-> mExcludeSaturdays);
if ( mDate == QDate::currentDate() ) {
setLineWidth( 3 );
} else {
setLineWidth( 1 );
}
MonthViewItem* CurrentAvailItem = (MonthViewItem*) firstItem ();
//clear();
while ( CurrentAvailItem ) {
MonthViewItem *item = CurrentAvailItem;
//item->setHighlightedFalse();
item->recycle( 0, "");
CurrentAvailItem = (MonthViewItem *)item->next();
mAvailItemList.append( item );
takeItem ( item );
}
#ifdef DESKTOP_VERSION
QToolTip::remove(this);
#endif
mToolTip.clear();
//qApp->processEvents();
#if 0
if ( !mHolidayString.isEmpty() ) {
MonthViewItem *item = new MonthViewItem( 0, mDate, mHolidayString );
item->setPalette( mHolidayPalette );
insertItem( item );
mToolTip.append ( mHolidayString );
}
#endif
}
int MonthViewCell::insertEvent(Event *event)
{
bool useToolTips = true;
#ifndef DESKTOP_VERSION
useToolTips = false;
#endif
QString mToolTipText;
setFocusPolicy(WheelFocus);
if ( !(event->doesRecur() == Recurrence::rNone) ) {
if ( !KOPrefs::instance()->mMonthDailyRecur && event->doesRecur() == Recurrence::rDaily )
return mdayCount;
else
if ( !KOPrefs::instance()->mMonthWeeklyRecur && event->doesRecur() == Recurrence::rWeekly )
return mdayCount;
}
if ( event->isHoliday()) {
setHoliday( true );
if ( mDate.dayOfWeek() == 7 )
setLineWidth( 3 );
}
QString text;
int multiday = 0;// 1 = start, 2 = midddle, 3 = end day
if (event->isMultiDay()) {
QString prefix = "<->";multiday = 2;
QString time;
if ( event->doesRecur() ) {
if ( event->recursOn( mDate) ) {
prefix ="->" ;multiday = 1;
}
else {
int days = event->dtStart().date().daysTo ( event->dtEnd().date() );
if ( event->recursOn( mDate.addDays( -days)) ) {
prefix ="<-" ;multiday = 3;
}
}
} else {
if (mDate == event->dtStart().date()) {
prefix ="->" ;multiday = 1;
} else if (mDate == event->dtEnd().date()) {
prefix ="<-" ;multiday = 3;
}
}
if ( !event->doesFloat() ) {
if ( mDate == event->dtStart().date () )
time = KGlobal::locale()->formatTime(event->dtStart().time())+" ";
else if ( mDate == event->dtEnd().date () )
time = KGlobal::locale()->formatTime(event->dtEnd().time())+" ";
}
text = time + event->summary();
if ( useToolTips )
mToolTipText += prefix + text;
} else {
if (event->doesFloat()) {
text = event->summary();
if ( useToolTips )
mToolTipText += text;
}
else {
text = KGlobal::locale()->formatTime(event->dtStart().time());
text += " " + event->summary();
if ( useToolTips )
mToolTipText += KGlobal::locale()->formatTime(event->dtStart().time()) +"-"+KGlobal::locale()->formatTime(event->dtEnd().time())+" " + event->summary();
}
}
if ( useToolTips && ! event->location().isEmpty() ) {
mToolTipText += " (" + event->location() +")";
}
MonthViewItem *item ;
if ( mAvailItemList.count() ) {
item = mAvailItemList.first();
mAvailItemList.remove( item );
item->recycle( event, text );
} else {
item = new MonthViewItem( event, text );
}
QPalette pal;
if (KOPrefs::instance()->mMonthViewUsesCategoryColor) {
QStringList categories = event->categories();
QString cat = categories.first();
if ( KOPrefs::instance()->mMonthViewUsesForegroundColor ) {
pal = getPalette();
if (cat.isEmpty()) {
//pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->mEventColor);
pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->defaultColor( event->calID() ));
} else {
pal.setColor(QColorGroup::Foreground, *(KOPrefs::instance()->categoryColor(cat)));
}
} else {
if (cat.isEmpty()) {
//pal = QPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor);
pal = QPalette( KOPrefs::instance()->defaultColor( event->calID() ), KOPrefs::instance()->defaultColor( event->calID() ));
} else {
pal = QPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat)));
}
}
} else {
pal = mStandardPalette ;
}
pal.setColor(QColorGroup::Highlight, KOPrefs::instance()->mHighlightColor);
item->setPalette( pal );
- item->setRecur( event->recurrence()->doesRecur() );
+ item->setRecur( event->doesRecur() );
item->setAlarm( event->isAlarmEnabled() && multiday < 2 && event->alarmEnabled() );
item->setMoreInfo( event->description().length() > 0 );
#ifdef DESKTOP_VERSION
Attendee *me = event->attendeeByMails(KOPrefs::instance()->mAdditionalMails,
KOPrefs::instance()->email());
if ( me != 0 ) {
if ( me->status() == Attendee::NeedsAction && me->RSVP())
item->setReply(true && multiday < 2);
else
item->setReply(false);
} else
item->setReply(false);
#endif
item->setMultiDay( multiday );
if ( multiday ) {
insertItem( item ,mdayCount);
++mdayCount;
} else {
uint i = mdayCount;
uint pos = mdayCount;
uint itcount = count();
if ( itcount > 1000 ) {
qDebug("KO: Bug in MonthViewCell::insertEvent %u ", itcount);
itcount = 0;
}
for ( i = pos; i < itcount;++i ) {
// qDebug("i %d mday %u count %d ",i,itcount,mdayCount );
QListBoxItem* it = this->item ( i );
if ( it && text < it->text() ) {
pos = i;
break;
}
++pos;
}
insertItem( item ,pos);
}
if ( useToolTips ) {
mToolTip.append( mToolTipText );
}
return mdayCount;
}
void MonthViewCell::insertTodo(Todo *todo)
{
setFocusPolicy(WheelFocus);
QString text;
if (todo->hasDueDate()) {
if (!todo->doesFloat()) {
text += KGlobal::locale()->formatTime(todo->dtDue().time());
text += " ";
}
}
text += todo->summary();
MonthViewItem *item ;
if ( mAvailItemList.count() ) {
item = mAvailItemList.first();
mAvailItemList.remove( item );
item->recycle( todo, text );
} else {
item = new MonthViewItem( todo, text );
}
//MonthViewItem *item = new MonthViewItem( todo, mDate, text );
//item->setPalette( mStandardPalette );
QPalette pal;
if (KOPrefs::instance()->mMonthViewUsesCategoryColor) {
QStringList categories = todo->categories();
QString cat = categories.first();
if ( KOPrefs::instance()->mMonthViewUsesForegroundColor ) {
pal = getPalette();
if (cat.isEmpty()) {
//pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->mEventColor);
pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->defaultColor( todo->calID() ));
} else {
pal.setColor(QColorGroup::Foreground, *(KOPrefs::instance()->categoryColor(cat)));
}
} else {
if (cat.isEmpty()) {
//pal = QPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor);
pal = QPalette(KOPrefs::instance()->defaultColor( todo->calID() ), KOPrefs::instance()->defaultColor( todo->calID() ));
} else {
pal = QPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat)));
}
}
} else {
pal = mStandardPalette ;
}
pal.setColor(QColorGroup::Highlight, KOPrefs::instance()->mHighlightColor);
item->setPalette( pal );
- item->setRecur( todo->recurrence()->doesRecur() );
+ item->setRecur( todo->doesRecur() );
item->setAlarm( todo->isAlarmEnabled() && todo->alarmEnabled() );
item->setMoreInfo( todo->description().length() > 0 );
insertItem( item , count());
#ifdef DESKTOP_VERSION
mToolTip.append( text );
#endif
}
void MonthViewCell::repaintfinishUpdateCell()
{
MonthViewItem *mitem = (MonthViewItem*) firstItem ();
while ( mitem ) {
mitem->setBlockRepaint( false );
updateItem ( mitem );
mitem = (MonthViewItem *)mitem->next();
}
blockSignals( false );
}
void MonthViewCell::finishUpdateCell()
{
#ifdef DESKTOP_VERSION
if (mToolTip.count() > 0 ) {
mToolTip.sort();
QToolTip::add(this,mToolTip.join("\n"),toolTipGroup(),"");
}
#endif
//sort();
//setMyPalette();
setMyPalette();
resizeEvent( 0 );
}
void MonthViewCell::updateCell()
{
if ( !mMonthView->isUpdatePossible() )
return;
startUpdateCell();
//mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2);
QPtrList<Event> events = mMonthView->calendar()->events( mDate, true );
Event *event;
for( event = events.first(); event; event = events.next() ) { // for event
insertEvent(event);
}
// insert due todos
QPtrList<Todo> todos = mMonthView->calendar()->todos( mDate );
Todo *todo;
for(todo = todos.first(); todo; todo = todos.next()) {
insertTodo( todo );
}
finishUpdateCell();
// if ( isVisible())
//qApp->processEvents();
}
void MonthViewCell::updateConfig( bool bigFont ) // = false
{
if ( bigFont ) {
QFont fo = KOPrefs::instance()->mMonthViewFont;
int ps = fo.pointSize() + 2;
if ( ps < 18 )
ps += 2;
fo.setPointSize( ps );
setFont( fo );
} else
setFont( KOPrefs::instance()->mMonthViewFont );
QFontMetrics fm( font() );
mLabelSize = fm.size( 0, "30" ) + QSize( 4, 2 );
mLabelBigSize = fm.size( 0, "Mag 30" ) + QSize( 2, 2 );
mHolidayPalette = mStandardPalette;
mPrimaryPalette = mStandardPalette;
mNonPrimaryPalette = mStandardPalette;
if ( KOPrefs::instance()->mMonthViewUsesDayColors ) {
mHolidayPalette.setColor(QColorGroup::Base, KOPrefs::instance()->mMonthViewHolidayColor );
mHolidayPalette.setColor(QColorGroup::Background, KOPrefs::instance()->mMonthViewHolidayColor );
mHolidayPalette.setColor(QColorGroup::Foreground, KOPrefs::instance()->mMonthViewHolidayColor.dark());
mPrimaryPalette.setColor(QColorGroup::Foreground,KOPrefs::instance()->mMonthViewOddColor.dark());
mPrimaryPalette.setColor(QColorGroup::Base,KOPrefs::instance()->mMonthViewOddColor);
mPrimaryPalette.setColor(QColorGroup::Background,KOPrefs::instance()->mMonthViewOddColor);
mNonPrimaryPalette.setColor(QColorGroup::Foreground,KOPrefs::instance()->mMonthViewEvenColor.dark());
mNonPrimaryPalette.setColor(QColorGroup::Base,KOPrefs::instance()->mMonthViewEvenColor);
mNonPrimaryPalette.setColor(QColorGroup::Background,KOPrefs::instance()->mMonthViewEvenColor);
}
//updateCell();
}
void MonthViewCell::enableScrollBars( bool enabled )
{
return;
if ( enabled ) {
QListBoxItem *fi = firstItem ();
if (fi ) {
int ihei = fi->height( this );
int hei = numRows () * ihei;
if ( hei < height() - horizontalScrollBar()->height () ) {
setVScrollBarMode(QScrollView::AlwaysOff);
}
else
setVScrollBarMode(QScrollView::Auto);
if ( ihei *3 > height() ) {
setHScrollBarMode(QScrollView::AlwaysOff);
}
else {
setHScrollBarMode(QScrollView::Auto);
}
} else {
setVScrollBarMode(QScrollView::Auto);
setHScrollBarMode(QScrollView::Auto);
}
} else {
setVScrollBarMode(QScrollView::AlwaysOff);
setHScrollBarMode(QScrollView::AlwaysOff);
}
}
Incidence *MonthViewCell::selectedIncidence()
{
int index = currentItem();
if ( index < 0 ) return 0;
MonthViewItem *mitem =
static_cast<MonthViewItem *>( item( index ) );
if ( !mitem ) return 0;
return mitem->incidence();
}
QDate MonthViewCell::selectedIncidenceDate()
{
QDate qd;
int index = currentItem();
if ( index < 0 ) return qd;
return mDate;
}
void MonthViewCell::deselect()
{
clearSelection();
enableScrollBars( false );
// updateCell();
}
void MonthViewCell::select()
{
;// updateCell();
}
void MonthViewCell::resizeEvent ( QResizeEvent * e )
{
if ( !mMonthView->isUpdatePossible() )
return;
//qDebug("++++++++++++++MonthViewCell::resizeEvent %d %d ", width(), height());
deselect();
mLabel->setMaximumHeight( height() - lineWidth()*2 );
QString text;
//mLabel->setText( text );
bool smallDisplay = QApplication::desktop()->width() < 320 && KOPrefs::instance()->mMonthViewSatSunTog;
if ( KOPrefs::instance()->mMonthViewWeek || KOGlobals::self()->calendarSystem()->day( mDate ) == 1 || (mDate.dayOfWeek() == 7 && !smallDisplay ) || KOPrefs::instance()->mMonthShowShort) {
text = KOGlobals::self()->calendarSystem()->monthName( mDate, true ) + " " + QString::number( mDate.day() );
mLabel->resize( mLabelBigSize );
} else {
mLabel->resize( mLabelSize );
text = QString::number( mDate.day() );
}
mLabel->setText( text );
int size = height() - mLabel->height() - lineWidth()-1;
//qDebug("LW %d ", lineWidth());
if ( size > 0 )
verticalScrollBar()->setMaximumHeight( size );
size = width() - mLabel->width() -lineWidth()-1;
if ( size > 0 )
horizontalScrollBar()->setMaximumWidth( size );
mLabel->move( width()-lineWidth() - mLabel->width(), height()-lineWidth() - mLabel->height() );
//mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2);
// mItemList->resize ( width(), height () );
if ( e )
KNoScrollListBox::resizeEvent ( e );
}
void MonthViewCell::defaultAction( QListBoxItem *item )
{
if ( !item ) {
QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
emit newEventSignal( dt );
return;
}
MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
Incidence *incidence = eventItem->incidence();
if ( incidence ) mMonthView->defaultAction( incidence );
}
void MonthViewCell::showDay()
{
emit showDaySignal( date() );
}
void MonthViewCell::newEvent()
{
QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
emit newEventSignal( dt );
}
void MonthViewCell::cellClicked( QListBoxItem *item )
{
mMonthView->setSelectedCell( this );
if ( item == 0 ) {
QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
emit newEventSignal( dt );
return;
}
}
void MonthViewCell::contextMenu( QListBoxItem *item )
{
mMonthView->setPopupCell( this );
if ( !item ) {
mMonthView->showContextMenu( 0 );
return;
}
+ //selection( item );
+ //qApp->processEvents();
MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
Incidence *incidence = eventItem->incidence();
if ( incidence ) mMonthView->showContextMenu( incidence );
}
void MonthViewCell::selection( QListBoxItem *item )
{
if ( !item ) {
emit highlightIncidence( 0 , this, 0 );
return;
}
MonthViewItem * it = (static_cast<MonthViewItem *>( item ));
emit highlightIncidence( it->incidence(), this, it->multiDay() );
mMonthView->setSelectedCell( this );
}
void MonthViewCell::deHighLight()
{
MonthViewItem *mitem = (MonthViewItem*) firstItem ();
while ( mitem ) {
if ( mitem->setHighlightedFalse() )
updateItem ( mitem );
mitem = (MonthViewItem *)mitem->next();
}
}
// returns true if no inc found
bool MonthViewCell::doHighLight( Incidence * inc )
{
MonthViewItem *mitem = (MonthViewItem*) firstItem ();
while ( mitem ) {
if ( mitem->incidence() == inc ) {
if ( mitem->setHighlighted( inc ) )
updateItem ( mitem );
return false;
}
mitem = (MonthViewItem *)mitem->next();
}
return true;
}
// *******************************************************************************
// *******************************************************************************
// *******************************************************************************
KOMonthView::KOMonthView(Calendar *calendar, QWidget *parent, const char *name)
: KOEventView( calendar, parent, name ),
mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ),
mWidthLongDayLabel( 0 ), mSelectedCell( 0 )
{
mFlagKeyPressed = false;
mShortDayLabelsM = false;
mShortDayLabelsW = false;
skipResize = false;
clPending = true;
mPopupCell = 0;
mNavigatorBar = new NavigatorBar( QDate::currentDate(), this, "useBigPixmaps" );
mWidStack = new QWidgetStack( this );
QVBoxLayout* hb = new QVBoxLayout( this );
mMonthView = new QWidget( mWidStack );
mWeekView = new QWidget( mWidStack );
#if QT_VERSION >= 0x030000
mWidStack->addWidget(mMonthView );
mWidStack->addWidget(mWeekView );
#else
mWidStack->addWidget( mMonthView, 1 );
mWidStack->addWidget( mWeekView , 1 );
#endif
hb->addWidget( mNavigatorBar );
hb->addWidget( mWidStack );
mShowWeekView = KOPrefs::instance()->mMonthViewWeek;
updatePossible = false;
//updatePossible = true;
mCells.setAutoDelete( true );
mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ;
mDayLabels.resize( mDaysPerWeek );
mDayLabelsW.resize( mDaysPerWeek );
QFont bfont = font();
if ( QApplication::desktop()->width() < 650 ) {
bfont.setPointSize( bfont.pointSize() - 2 );
}
bfont.setBold( true );
int i;
for( i = 0; i < mDaysPerWeek; i++ ) {
QLabel *label = new QLabel( mMonthView );
label->setFont(bfont);
label->setFrameStyle(QFrame::Panel|QFrame::Raised);
label->setLineWidth(1);
label->setAlignment(AlignCenter);
mDayLabels.insert( i, label );
label = new QLabel( mWeekView );
label->setFont(bfont);
label->setFrameStyle(QFrame::Panel|QFrame::Raised);
label->setLineWidth(1);
label->setAlignment(AlignCenter);
mDayLabelsW.insert( i, label );
}
bfont.setBold( false );
mWeekLabels.resize( mNumWeeks+1 );
mWeekLabelsW.resize( 2 );
for( i = 0; i < mNumWeeks+1; i++ ) {
KOWeekButton *label = new KOWeekButton( mMonthView );
label->setFocusPolicy(NoFocus);
label->setFont(bfont);
connect( label, SIGNAL( selectWeekNum ( int )),this, SLOT( selectInternalWeekNum ( int )) );
label->setFlat(true);
QWhatsThis::add(label,i18n("Click on the week number to\nshow week zoomed"));
//label->setFrameStyle(QFrame::Panel|QFrame::Raised);
//label->setLineWidth(1);
//label->setAlignment(AlignCenter);
mWeekLabels.insert( i, label );
}
mWeekLabels[mNumWeeks]->setText( i18n("W"));
mWeekLabels[mNumWeeks]->setFocusPolicy(WheelFocus);
QWhatsThis::add(mWeekLabels[mNumWeeks],i18n("Click on this to\nselect week number"));
for( i = 0; i < 1+1; i++ ) {
KOWeekButton *label = new KOWeekButton( mWeekView );
label->setFocusPolicy(NoFocus);
label->setFont(bfont);
connect( label, SIGNAL( selectWeekNum ( int )),this, SLOT( selectInternalWeekNum ( int )) );
label->setFlat(true);
QWhatsThis::add(label,i18n("Click on the week number to\nshow week zoomed"));
//label->setFrameStyle(QFrame::Panel|QFrame::Raised);
//label->setLineWidth(1);
//label->setAlignment(AlignCenter);
mWeekLabelsW.insert( i, label );
}
mWeekLabelsW[1]->setText( i18n("W"));
mWeekLabelsW[1]->setFocusPolicy(WheelFocus);
int row, col;
mCells.resize( mNumCells );
for( row = 0; row < mNumWeeks; ++row ) {
for( col = 0; col < mDaysPerWeek; ++col ) {
MonthViewCell *cell = new MonthViewCell( this, mMonthView );
mCells.insert( row * mDaysPerWeek + col, cell );
connect( cell, SIGNAL( defaultAction( Incidence * ) ),
SLOT( defaultAction( Incidence * ) ) );
connect( cell, SIGNAL( newEventSignal( QDateTime ) ),
SIGNAL( newEventSignal( QDateTime ) ) );
connect( cell, SIGNAL( showDaySignal( QDate ) ),
SIGNAL( showDaySignal( QDate ) ) );
connect( cell, SIGNAL( nextCell() ),
SLOT( nextCell() ) );
connect( cell, SIGNAL( prevCell() ),
SLOT( prevCell() ) );
connect( cell, SIGNAL( highlightIncidence( Incidence * , MonthViewCell *, int ) ),
SLOT( incidenceHighlighted( Incidence *, MonthViewCell *, int ) ));
}
}
mCellsW.resize( mDaysPerWeek );
for( col = 0; col < mDaysPerWeek; ++col ) {
MonthViewCell *cell = new MonthViewCell( this, mWeekView );
mCellsW.insert( col, cell );
connect( cell, SIGNAL( defaultAction( Incidence * ) ),
SLOT( defaultAction( Incidence * ) ) );
connect( cell, SIGNAL( newEventSignal( QDateTime ) ),
SIGNAL( newEventSignal( QDateTime ) ) );
connect( cell, SIGNAL( showDaySignal( QDate ) ),
SIGNAL( showDaySignal( QDate ) ) );
connect( cell, SIGNAL( nextCell() ),
SLOT( nextCell() ) );
connect( cell, SIGNAL( prevCell() ),
SLOT( prevCell() ) );
connect( cell, SIGNAL( highlightIncidence( Incidence * , MonthViewCell *, int ) ),
SLOT( incidenceHighlighted( Incidence *, MonthViewCell *, int ) ));
cell->updateConfig(KOPrefs::instance()->mMonthViewUsesBigFont );
}
//connect( mWeekLabels[mNumWeeks], SIGNAL( clicked() ), SLOT( switchView() ) );
mContextMenu = eventPopup();
mContextMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("New Event..."),this,
SLOT(slotNewEvent()),false);
mContextMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("New Todo..."),this,
SLOT(slotNewTodo()),false);
mContextMenu->addAdditionalItem(QIconSet(QPixmap()),
i18n("Journal"),this,
SLOT(slotEditJournal()),false);
connect (mContextMenu ,SIGNAL(categoryChanged( Incidence * )),this,
SLOT( catChanged( Incidence * ) ));
QString pathString = "";
if ( !KOPrefs::instance()->mToolBarMiniIcons ) {
if ( QApplication::desktop()->width() < 480 )
pathString += "icons16/";
} else
pathString += "iconsmini/";
mNewItemMenu = new QPopupMenu( this );
mNewItemMenu->insertItem( SmallIcon( pathString +"newevent" ), i18n("New Event..."),this, SLOT(slotNewEvent()));
mNewItemMenu->insertItem( SmallIcon( pathString +"newtodo" ),i18n("New Todo..."),this,SLOT(slotNewTodo()),false);
mNewItemMenu->insertItem( SmallIcon( pathString +"journal" ),i18n("Journal"),this,SLOT(slotEditJournal()),false);
// updateConfig(); //useless here...
// ... but we need mWidthLongDayLabel computed
QFontMetrics fontmetric(mDayLabels[0]->font());
mWidthLongDayLabel = 0;
for (int i = 0; i < 7; i++) {
int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1));
if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width;
}
//mWeekLabels[mNumWeeks]->setText( i18n("W"));
#if 0
if ( mShowWeekView )
mWidStack->raiseWidget( mWeekView );
else
mWidStack->raiseWidget( mMonthView );
#endif
emit incidenceSelected( 0 );
mComputeLayoutTimer = new QTimer( this );
connect (mComputeLayoutTimer ,SIGNAL(timeout()), this, SLOT ( slotComputeLayout()));
#ifndef DESKTOP_VERSION
resize( QApplication::desktop()->size() );
#else
resize(640, 480 );
updatePossible = true;
#endif
computeLayout();
if ( mShowWeekView )
mWidStack->raiseWidget( mWeekView );
else
mWidStack->raiseWidget( mMonthView );
}
KOMonthView::~KOMonthView()
{
delete mContextMenu;
}
void KOMonthView::catChanged( Incidence * )
{
updateView();
}
void KOMonthView::incidenceHighlighted( Incidence * inc , MonthViewCell* mc, int mday )
{
static Incidence * lastInc = 0;
static MonthViewCell * lastCell = 0;
if ( lastInc == inc && lastCell == mc )
return;
lastInc = inc;
lastCell = mc;
//qDebug("KOMonthView::incidenceHighlighted %d %d %d", inc, mc, mday );
bool weekview = false;
uint index = 0;
for (uint i = 0; i < mCellsW.count(); ++i) {
if ( mCellsW[i] == mc ) {
weekview = true;
index = i;
break;
}
}
QPtrVector<MonthViewCell> *cells;
if ( weekview )
cells = &mCellsW;
else {
for (uint i = 0; i < mCells.count(); ++i) {
if ( mCells[i] == mc ) {
index = i;
break;
}
}
cells = &mCells;
}
for (uint i = 0; i < (*cells).count(); ++i) {
(*cells)[i]->deHighLight();
}
if ( ! inc )
return;
uint count = (*cells).count();
bool goLeft = (mday > 1 && index > 0);
bool goRight = (mday < 3 && mday > 0 && index < count -1);
for (uint iii = 1; iii < count; ++iii) {
if ( goLeft ) {
int left = index - iii;
if ( left >= 0 ) {
if ( (*cells)[(uint)left]->doHighLight(inc) )
goLeft = false;
} else
goLeft = false;
}
if ( goRight ) {
uint right = index + iii;
if ( right < count ) {
if ( (*cells)[right]->doHighLight(inc) )
goRight = false;
} else
goRight = false;
}
}
#if 0
if ( mday > 1 && index > 0 )
for (int i = index-1; i >= 0; --i) {
//qDebug("index %d iii %d ", index, i);
if ( (*cells)[(uint)i]->doHighLight(inc) )
break;
}
if ( mday < 3 && mday > 0 && index < (*cells).count()-1)
for (uint i = index+1; i < (*cells).count(); ++i) {
if ( (*cells)[i]->doHighLight(inc) )
break;
}
#endif
}
void KOMonthView::selectInternalWeekNum ( int n )
{
switchView();
if ( !KOPrefs::instance()->mMonthViewWeek )
emit selectMonth ();
else
emit selectWeekNum ( n );
}
int KOMonthView::currentWeek()
{
if ( mShowWeekView )
return mWeekLabelsW[0]->getWeekNum();
return mWeekLabels[0]->getWeekNum();
}
void KOMonthView::switchView()
{
if ( selectedCell( ) )
selectedCell()->deselect();
mShowWeekView = !mShowWeekView;
KOPrefs::instance()->mMonthViewWeek = mShowWeekView;
if ( clPending ) {
computeLayout();
updateConfig();
}
if ( mShowWeekView )
mWidStack->raiseWidget( mWeekView );
else
mWidStack->raiseWidget( mMonthView );
clPending = false;
}
int KOMonthView::maxDatesHint()
{
return mNumCells;
}
int KOMonthView::currentDateCount()
{
return mNumCells;
}
QPtrList<Incidence> KOMonthView::selectedIncidences()
{
QPtrList<Incidence> selected;
if ( mSelectedCell ) {
Incidence *incidence = mSelectedCell->selectedIncidence();
if ( incidence ) selected.append( incidence );
}
return selected;
}
DateList KOMonthView::selectedDates()
{
DateList selected;
if ( mSelectedCell ) {
QDate qd = mSelectedCell->selectedIncidenceDate();
if ( qd.isValid() ) selected.append( qd );
}
return selected;
}
#if 0
void KOMonthView::printPreview(CalPrinter *calPrinter, const QDate &fd,
const QDate &td)
{
#ifndef KORG_NOPRINTER
calPrinter->preview(CalPrinter::Month, fd, td);
#endif
}
#endif
void KOMonthView::updateConfig()
{
int mWeekStartsMonday = KGlobal::locale()->weekStartsMonday();
if ( mShowWeekView || KOPrefs::instance()->mMonthViewSatSunTog ) {
mWeekStartsMonday = true;
}
QFontMetrics fontmetric(mDayLabels[0]->font());
mWidthLongDayLabel = 0;
for (int i = 0; i < 7; i++) {
int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1));
if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width;
}
bool temp = mShowSatSunComp ;
mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ;
if ( ! mShowWeekView ) {
if ( temp != KOPrefs::instance()->mMonthViewSatSunTog )
computeLayout();
} else
doComputeLayoutWeek();
updateDayLabels();
//qDebug("KOMonthView::updateConfig() %d %d %d ",height(), mDayLabels[0]->sizeHint().height() ,mNumWeeks);
//int cellHeight = (height() - mDayLabels[0]->sizeHint().height()) /mNumWeeks;
//resizeEvent( 0 );
for (uint i = 0; i < mCells.count(); ++i) {
mCells[i]->updateConfig();
}
for (uint i = 0; i < mCellsW.count(); ++i) {
mCellsW[i]->updateConfig(KOPrefs::instance()->mMonthViewUsesBigFont);
}
#ifdef DESKTOP_VERSION
MonthViewCell::toolTipGroup()->setEnabled(KOPrefs::instance()->mEnableToolTips);
#endif
updateView();
}
void KOMonthView::updateDayLabels()
{
QPtrVector<QLabel> *mDayLabelsT;
mDayLabelsT = &mDayLabelsW;
for (int i = 0; i < 7; i++) {
{
bool show = mShortDayLabelsW;
if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() )
show = true;
(*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show));
}
}
mDayLabelsT = &mDayLabels;
for (int i = 0; i < 7; i++) {
if (KGlobal::locale()->weekStartsMonday() || KOPrefs::instance()->mMonthViewSatSunTog ) {
bool show = mShortDayLabelsM;
if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() )
show = true;
(*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show));
} else {
if (i==0) (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabelsM));
else (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabelsM));
}
}
}
void KOMonthView::clearList()
{
unsigned int i;
for( i = 0; i < mCells.size(); ++i ) {
mCells[i]->clear();
}
for( i = 0; i < mCellsW.size(); ++i ) {
mCellsW[i]->clear();
}
}
void KOMonthView::showDates(const QDate &start, const QDate &)
{
// kdDebug() << "KOMonthView::showDates(): " << start.toString() << endl;
QPtrVector<MonthViewCell> *cells;
QPtrVector<QLabel> *dayLabels;
QPtrVector<KOWeekButton> *weekLabels;
uint weekNum = 6;
mStartDate = start;
if ( mShowWeekView ) {
weekNum = 1;
cells = &mCellsW;
dayLabels = &mDayLabelsW;
weekLabels = &mWeekLabelsW;
if ( !KGlobal::locale()->weekStartsMonday() ) {
mStartDate = mStartDate.addDays( 1 );
}
} else {
cells = &mCells;
dayLabels = &mDayLabels;
weekLabels = &mWeekLabels;
}
int mWeekStartsMonday = KGlobal::locale()->weekStartsMonday();
if ( mShowWeekView || KOPrefs::instance()->mMonthViewSatSunTog ) {
mWeekStartsMonday = true;
}
int startWeekDay = mWeekStartsMonday ? 1 : 7;
while( KOGlobals::self()->calendarSystem()->dayOfWeek(mStartDate) != startWeekDay ) {
mStartDate = mStartDate.addDays( -1 );
}
uint i;
for( i = 0; i < (*cells).size(); ++i ) {
QDate date = mStartDate.addDays( i );
(*cells)[i]->setDate( date );
#ifndef KORG_NOPLUGINS
// add holiday, if present
QString hstring(KOCore::self()->holiday(date));
(*cells)[i]->setHoliday( hstring );
#endif
}
QDate date = mStartDate.addDays( mWeekStartsMonday ? 3 : 4 );
for( i = 0; i < weekNum; ++i ) {
int wno;
// remember, according to ISO 8601, the first week of the year is the
// first week that contains a thursday. Thus we must subtract off 4,
// not just 1.
int dayOfYear = date.dayOfYear();
if (dayOfYear % 7 != 0)
wno = dayOfYear / 7 + 1;
else
wno =dayOfYear / 7;
(*weekLabels)[i]->setWeekNum( wno );
date = date.addDays( 7 );
}
updateView();
}
void KOMonthView::showEvents(QPtrList<Event>)
{
qDebug("KOMonthView::selectEvents is not implemented yet. ");
}
void KOMonthView::changeEventDisplay(Event *, int)
{
// this should be re-written to be much more efficient, but this
// quick-and-dirty-hack gets the job done for right now.
//qDebug("KOMonthView::changeEventDisplay ");
updateView();
}
void KOMonthView::updateView()
{
if ( !updatePossible )
return;
//qDebug("UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU ");
//QTime ti;
//ti.start();
clearSelection();
QPtrVector<MonthViewCell> *cells;
if ( mShowWeekView ) {
cells = &mCellsW;
} else {
cells = &mCells;
}
#if 1
int i;
int timeSpan = (*cells).size()-1;
if ( KOPrefs::instance()->mMonthViewWeek )
timeSpan = 6;
for( i = 0; i < timeSpan + 1; ++i ) {
(*cells)[i]->startUpdateCell();
}
QPtrList<Event> events = calendar()->events();
Event *event;
QDateTime dt;
QDate endDate = mStartDate.addDays( timeSpan );
for( event = events.first(); event; event = events.next() ) { // for event
if ( event->doesRecur() ) {
bool last;
QDateTime incidenceStart = event->recurrence()->getPreviousDateTime( QDateTime( mStartDate ) , &last );
QDateTime incidenceEnd;
int eventlen = event->dtStart().date().daysTo ( event->dtEnd().date() );
bool invalid = false;
while( true ) {
if ( incidenceStart.isValid() ) {
incidenceEnd = incidenceStart.addDays( eventlen );
int st = incidenceStart.date().daysTo( endDate );
if ( st >= 0 ) { // start before timeend
int end = mStartDate.daysTo( incidenceEnd.date() );
if ( end >= 0 ) { // end after timestart --- got one!
//normalize
st = timeSpan - st;
if ( st < 0 ) st = 0;
if ( end > timeSpan ) end = timeSpan;
int iii;
//qDebug("found %s %d %d ",event->summary().latin1(), st, end );
for ( iii = st;iii<= end;++iii)
(*cells)[iii]->insertEvent( event );
}
}
} else {
if ( invalid )
break;
invalid = true;
//qDebug("invalid %s", event->summary().latin1());
incidenceStart = QDateTime( mStartDate ).addSecs( -2 );;
}
if ( last )
break;
bool ok;
incidenceStart = event->getNextOccurence( incidenceStart.addSecs( 1 ) ,&ok );
if ( ! ok )
break;
if ( incidenceStart.date() > endDate )
break;
}
} else { // no recur
if ( !KOPrefs::instance()->mShowSyncEvents && event->uid().left(2) == QString("la") )
if ( event->uid().left(15) == QString("last-syncEvent-") )
continue;
int st = event->dtStart().date().daysTo( endDate );
if ( st >= 0 ) { // start before timeend
int end = mStartDate.daysTo( event->dtEnd().date() );
if ( end >= 0 ) { // end after timestart --- got one!
//normalize
st = timeSpan - st;
if ( st < 0 ) st = 0;
if ( end > timeSpan ) end = timeSpan;
int iii;
for ( iii = st;iii<= end;++iii)
(*cells)[iii]->insertEvent( event );
}
}
}
}
// insert due todos
QPtrList<Todo> todos = calendar()->todos( );
Todo *todo;
for(todo = todos.first(); todo; todo = todos.next()) {
//insertTodo( todo );
if ( todo->hasDueDate() ) {
int day = mStartDate.daysTo( todo->dtDue().date() );
if ( day >= 0 && day < timeSpan + 1) {
(*cells)[day]->insertTodo( todo );
}
}
}
for( i = 0; i < timeSpan+1; ++i ) {
(*cells)[i]->finishUpdateCell();
}
processSelectionChange();
//qApp->processEvents();
for( i = 0; i < timeSpan+1; ++i ) {
//(*cells)[i]->repaintfinishUpdateCell();
QTimer::singleShot( 0, (*cells)[i], SLOT ( repaintfinishUpdateCell() ) );
}
setKeyBFocus();
#else
// old code
//qDebug("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
int i;
for( i = 0; i < (*cells).count(); ++i ) {
(*cells)[i]->updateCell();
}
//qDebug("KOMonthView::updateView() ");
processSelectionChange();
// qDebug("---------------------------------------------------------------------+ ");
(*cells)[0]->setFocus();
#endif
//qDebug("update time %d ", ti.elapsed());
}
void KOMonthView::setKeyBoardFocus()
{
//qDebug("KOMonthView::setKeyBoardFocus() ");
bool shootAgain = false;
if ( mShowWeekView ) {
shootAgain = !mWeekLabelsW[1]->hasFocus();
mWeekLabelsW[1]->setFocus();
}
else {
shootAgain = !mWeekLabels[mNumWeeks]->hasFocus();
mWeekLabels[mNumWeeks]->setFocus();
}
--mKBFcounter;
if ( shootAgain && mKBFcounter > 0 ) {
QTimer::singleShot( 50, this, SLOT ( setKeyBoardFocus() ) );
}
}
void KOMonthView::setKeyBFocus()
{
//qDebug("KOMonthView::setKeyBFocus() ");
mKBFcounter = 10;
QTimer::singleShot( 0, this, SLOT ( setKeyBoardFocus() ) );
}
void KOMonthView::resizeEvent(QResizeEvent * e)
{
//qDebug("KOMonthView::resizeEvent %d %d -- %d %d ", e->size().width(), e->size().height(), e->oldSize().width(), e->oldSize().height());
if ( isVisible() ) {
//qDebug("KOMonthView::isVisible ");
slotComputeLayout();
} else
mComputeLayoutTimer->start( 100 );
if ( e )
KOEventView::resizeEvent( e );
}
void KOMonthView::slotComputeLayout()
{
mComputeLayoutTimer->stop();
//qDebug("KOMonthView::Post - resizeEvent %d %d ", width(), height() );
computeLayout();
clPending = true;
setKeyBFocus();
}
void KOMonthView::doComputeLayoutWeek()
{
int daysToShow;
bool combinedSatSun = false;
if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) {
daysToShow = 6;
combinedSatSun = true;
}
int wid = width();//e
int hei = height()-1-mNavigatorBar->height();
#ifdef DESKTOP_VERSION
if ( !KOPrefs::instance()->mMonthViewWeekRowlayout ) {
daysToShow = 2;
} else
#endif
{
if ( wid < hei + 40 )
daysToShow = 2;
else
daysToShow = 3;
}
bool landscape = (daysToShow == 3);
mShowSatSunComp = true;
combinedSatSun = true;
//qDebug("KOMonthView::computeLayout() WWW ------------------------------------ ");
QFontMetrics fm ( mWeekLabels[0]->font() );
int weeklabelwid = fm.width( "888" );
wid -= weeklabelwid;
int colWid = wid / daysToShow;
int dayLabelHei = mDayLabelsW[0]->sizeHint().height();
int cellHei = (hei - (5- daysToShow )*dayLabelHei) /(5- daysToShow );
int colModulo = wid % daysToShow;
int rowModulo = (hei- (5- daysToShow )*dayLabelHei) % daysToShow-1;
//qDebug("rowmod %d ", rowModulo);
int i;
int x,y,w,h;
x= 0;
y= 0;
w = colWid;
h = dayLabelHei ;
for ( i = 0; i < 7; i++) {
if ( i && !( i % daysToShow) && i < 6) {
y += hei/(5-daysToShow);
x = 0;
w = colWid;
}
if ( ((i) % daysToShow) >= daysToShow-colModulo ) {
++w;
}
int xC,yC,wC,hC;
if ( i >= 5 ) {
int wi = width() - x - weeklabelwid;
if ( i == 5 ) {
xC = x+weeklabelwid;
yC = y;
wC = wi/2+wi%2;
hC = h;
} else {
xC = x+weeklabelwid;
yC = y;
wC = wi;
hC = h;
}
x = x - w + wi - (wi/2 );
}
else {
int wi = w;
if ( !(( i+1) % daysToShow)) {
wi = width() - x - weeklabelwid;
}
xC = x+weeklabelwid;
yC = y;
wC = wi;
hC = h;
}
mDayLabelsW[mapWeekLayout(i,landscape)]->setGeometry( xC,yC,wC,hC);
x += w;
}
x= 0;
y= dayLabelHei;
w = colWid;
h = cellHei;
int max = 0;
int w_count = mCellsW.count();
for ( i = 0; i < w_count; ++i) {
if ( i > 6 ) {
mCellsW[i]->hide();
continue;
}
w = colWid;
if ( ((i) % daysToShow) >= daysToShow-colModulo ) {
++w;
}
if ( i == (daysToShow-1-rowModulo)*7)
++h;
int xC,yC,wC,hC;
if ( i >= 5 ) {
if ( i ==5 ) {
max = h/2;
xC = x+weeklabelwid;
yC = y;
wC = w;
hC = max;
x -= w ;y += h/2;
} else {
if ( ((i-1) % daysToShow) >= daysToShow-colModulo ) {
++w;
}
max = h-h/2;
xC = x+weeklabelwid;
yC = y;
wC = w;
hC = max;
y -= h/2;
}
} else {
max = h;
xC = x+weeklabelwid;
yC = y;
wC = w;
hC = h;
}
mCellsW[mapWeekLayout(i,landscape)]->setGeometry ( xC,yC,wC,hC );
x += w;
if ( x + w/2 > wid ) {
x = 0;
y += h+dayLabelHei ;
}
//mCellsW[i]->dateLabel()->setMaximumHeight( max - mCellsW[i]->lineWidth()*2 );
}
y= dayLabelHei;
h = cellHei ;
mWeekLabelsW[0]->setGeometry( 0,y,weeklabelwid,hei-dayLabelHei);
mWeekLabelsW[1]->setGeometry( 0,0,weeklabelwid,dayLabelHei);
// qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height());
//qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height());
mShortDayLabelsW = mDayLabelsW[0]->width()-2 < mWidthLongDayLabel ;
updateDayLabels();
//bool forceUpdate = !updatePossible;
updatePossible = true;
//mWeekLabels[mNumWeeks]->setText( i18n("M"));
//if ( forceUpdate )
// updateView();
}
void KOMonthView::computeLayoutWeek()
{
static int lastWid = 0;
static int lastHei = 0;
int tWid = topLevelWidget()->size().width();
int tHei = topLevelWidget()->size().height();
int wid = width();//e
int hei = height()-1-mNavigatorBar->height();
if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei )
return;
if ( lastWid == width() && lastHei == height() ) {
//qDebug("KOListWeekView::No compute layout needed ");
return;
}
lastWid = width();
lastHei = height();
doComputeLayoutWeek();
}
int KOMonthView::mapWeekLayout( int index, bool landscape )
{
if ( KOPrefs::instance()->mMonthViewWeekRowlayout )
return index;
int diff = 0;
if ( !landscape ) diff = 1;
switch( index ) {
case 0:
case 5:
case 6:
return index;
break;
case 1:
return 2+diff;
break;
case 2:
return 4-(3*diff);
break;
case 3:
return 1+(3*diff);
break;
case 4:
return 3-diff;
break;
default:
qDebug("KO: Error in mapping week layout ");
return index;
break;
}
return index;
}
void KOMonthView::computeLayout()
{
static int lastWid = 0;
static int lastHei = 0;
if ( mShowWeekView ){
computeLayoutWeek();
return;
}
int daysToShow = 7;
bool combinedSatSun = false;
if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) {
daysToShow = 6;
combinedSatSun = true;
}
int tWid = topLevelWidget()->size().width();
int tHei = topLevelWidget()->size().height();
int wid = width();//e
int hei = height()-1-mNavigatorBar->height();
if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei ) {
return;
}
if ( lastWid == width() && lastHei == height() ){
//qDebug("KOMonthview::No compute layout needed ");
return;
}
lastWid = width();
lastHei = height();
//qDebug("KOMonthView::computeLayout() MMM ------------------- ");
QFontMetrics fm ( mWeekLabels[0]->font() );
int weeklabelwid = fm.width( "888" );
wid -= weeklabelwid;
int colWid = wid / daysToShow;
int dayLabelHei = mDayLabels[0]->sizeHint().height();
int cellHei = (hei - dayLabelHei) /6;
int colModulo = wid % daysToShow;
int rowModulo = (hei- dayLabelHei) % 6;
//qDebug("rowmod %d ", rowModulo);
int i;
int x,y,w,h;
x= 0;
y= 0;
w = colWid;
h = dayLabelHei ;
for ( i = 0; i < 7; i++) {
if ( i == daysToShow-colModulo )
++w;
if ( combinedSatSun ) {
if ( i >= daysToShow-1 ) {
if ( i == 6 )
mDayLabels[i]->setGeometry( x+weeklabelwid,y,width()-x-weeklabelwid,h);
else
mDayLabels[i]->setGeometry( x+weeklabelwid,y,w/2,h);
x -= w/2 ;
}
else
mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h);
} else
mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h);
x += w;
}
x= 0;
y= dayLabelHei;
w = colWid;
h = cellHei ;
int max = 0;
int mc_count = mCells.count();
for ( i = 0; i < mc_count; ++i) {
//qDebug("iii %d ", i);
w = colWid;
if ( ((i) % 7) >= 7-colModulo ) {
++w;
}
if ( i == (6-rowModulo)*7)
++h;
if ( combinedSatSun ) {
if ( (i)%7 >= daysToShow-1 ) {
if ( (i)%7 == daysToShow-1 ) {
w = width()-x-weeklabelwid;
max = h/2;
mCells[i]->setGeometry ( x+weeklabelwid,y,w,max );
x -= w ;y += h/2;
} else {
w = width()-x-weeklabelwid;
max = h-h/2;
mCells[i]->setGeometry ( x+weeklabelwid,y,w,max );
y -= h/2;
}
} else {
max = h;
mCells[i]->setGeometry ( x+weeklabelwid,y,w,h );
}
}
else {
max = h;
mCells[i]->setGeometry ( x+weeklabelwid,y,w,h );
}
x += w;
if ( x + w/2 > wid ) {
x = 0;
y += h;
}
//mCells[i]->dateLabel()->setMaximumHeight( max- mCells[i]->lineWidth()*2 );
}
y= dayLabelHei;
h = cellHei ;
for ( i = 0; i < 6; i++) {
if ( i == (6-rowModulo))
++h;
mWeekLabels[i]->setGeometry( 0,y,weeklabelwid,h);
y += h;
}
mWeekLabels[6]->setGeometry( 0,0,weeklabelwid,dayLabelHei);
// qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height());
//qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height());
mShortDayLabelsM = mDayLabels[0]->width()-2 < mWidthLongDayLabel ;
updateDayLabels();
//bool forceUpdate = !updatePossible;
updatePossible = true;
//mWeekLabels[mNumWeeks]->setText( i18n("W"));
}
void KOMonthView::showContextMenu( Incidence *incidence )
{
if( incidence )
mContextMenu->showIncidencePopup(incidence);
else {
//qDebug("KOMonthView::showContextMenu ");
mNewItemMenu->popup(QCursor::pos());
}
/*
if( incidence && incidence->typeID() == eventID ) {
Event *event = static_cast<Event *>(incidence);
mContextMenu->showEventPopup(event);
} else {
kdDebug() << "MonthView::showContextMenu(): cast failed." << endl;
}
*/
}
MonthViewCell * KOMonthView::selectedCell( )
{
return mSelectedCell;
}
void KOMonthView::setSelectedCell( MonthViewCell *cell )
{
//qDebug("KOMonthView::setSelectedCell %d", cell);
if ( mSelectedCell && mSelectedCell != cell ) {
MonthViewCell * mvc = mSelectedCell;
mSelectedCell = cell;
mvc->deselect();
} else
mSelectedCell = cell;
// if ( mSelectedCell )
// mSelectedCell->select();
if ( !mSelectedCell )
emit incidenceSelected( 0 );
else
emit incidenceSelected( mSelectedCell->selectedIncidence() );
}
void KOMonthView::processSelectionChange()
{
QPtrList<Incidence> incidences = selectedIncidences();
if (incidences.count() > 0) {
emit incidenceSelected( incidences.first() );
} else {
emit incidenceSelected( 0 );
clearSelection();
}
}
void KOMonthView::clearSelection()
{
if ( mSelectedCell ) {
mSelectedCell->deselect();
mSelectedCell = 0;
}
}
void KOMonthView::keyReleaseEvent ( QKeyEvent * e)
{
if ( !e->isAutoRepeat() ) {
mFlagKeyPressed = false;
}
}
void KOMonthView::keyPressEvent ( QKeyEvent * e )
{
qApp->processEvents();
if ( e->isAutoRepeat() && !mFlagKeyPressed ) {
//e->ignore();
e->accept();
return;
}
if (! e->isAutoRepeat() )
mFlagKeyPressed = true;
switch(e->key()) {
case Key_Up:
{
if ( mShowWeekView ) {
emit selectWeekNum ( currentWeek() - 1 );
}
else {
emit prevMonth();
}
}
e->accept();
break;
case Key_Down:
{
if ( mShowWeekView ) {
emit selectWeekNum ( currentWeek() +1);
}
else {
emit nextMonth();
}
}
e->accept();
break;
case Key_Return:
case Key_Enter:
{
selectInternalWeekNum ( currentWeek() );
}
e->accept();
break;
case Key_D:
if ( mSelectedCell ) {
mSelectedCell->showDay();
e->accept();
} else {
e->ignore();
}
break;
default:
e->ignore();
break;
}
}
void KOMonthView::nextCell()
{
focusNextPrevChild ( true );
}
void KOMonthView::prevCell()
{
focusNextPrevChild ( false );
}
void KOMonthView::slotNewTodo()
{
//qDebug("KOMonthView::slotNewTodo() ");
if ( mPopupCell ){
QDateTime dt( mPopupCell->date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
emit newTodoSignal(dt,true);
}
mPopupCell = 0;
}
void KOMonthView::slotNewEvent()
{
if ( mPopupCell ) {
QDateTime dt( mPopupCell->date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
emit newEventSignal( dt );
}
//qDebug("KOMonthView::slotNewEvent() ");
mPopupCell = 0;
}
void KOMonthView::slotEditJournal()
{
if ( mPopupCell )
emit showJournalSignal( 7, mPopupCell->date() );
//qDebug("KOMonthView::slotEditJournal() ");
mPopupCell = 0;
}
void KOMonthView::setPopupCell( MonthViewCell * c)
{
mPopupCell = c;
}
diff --git a/korganizer/kotodoeditor.cpp b/korganizer/kotodoeditor.cpp
index 100a81b..682f83b 100644
--- a/korganizer/kotodoeditor.cpp
+++ b/korganizer/kotodoeditor.cpp
@@ -1,453 +1,454 @@
/*
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();
if ( QApplication::desktop()->height() <= 240 )
hideButtons();
}
KOTodoEditor::~KOTodoEditor()
{
emit dialogClose( mTodo );
}
void KOTodoEditor::init()
{
setupGeneral();
setupAttendeesTab();
setupRecurrence();
connect(mGeneral,SIGNAL(datesChecked()),this ,SLOT(checkRecurrence()));
mRecurrence->setDateTimeStr( i18n("<i>The recurrence is computed from the start datetime!</i>") );
connect(mGeneral,SIGNAL(dateTimesChanged(QDateTime,QDateTime)),
mRecurrence,SLOT(setDefaultsDates(QDateTime,QDateTime)));
}
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(marginHintSmall());
topLayout->setSpacing(spacingHintSmall());
} else {
topLayout->setMargin(marginHint());
topLayout->setSpacing(spacingHint());
}
topLayout->addStretch( 1 );
mGeneral->initHeader(topFrame,topLayout);
topLayout->addStretch( 1 );
mGeneral->initTime(topFrame,topLayout);
topLayout->addStretch( 1 );
mGeneral->initAlarm(topFrame,topLayout);
topLayout->addStretch( 1 );
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("fileimport16");
else
icon = SmallIcon("fileimport");
QPushButton * loadTemplate = new QPushButton( prioWidget);
loadTemplate->setIconSet (icon ) ;
int size = loadTemplate->sizeHint().height();
loadTemplate->setFixedSize( size, size );
if ( QApplication::desktop()->width() < 321 )
icon = SmallIcon("fileexport16");
else
icon = SmallIcon("fileexport");
QPushButton * saveTemplate = new QPushButton( prioWidget);
saveTemplate->setIconSet (icon ) ;
saveTemplate->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->fillCalCombo(mRelatedTodo->calID() );
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 ));
}
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) ) ;
}
if ( to < from )
to = from;
mRecurrence->setDefaults(from,to);
}
} else {
tabWidget()->setTabEnabled ( mRecurrence->parentWidget(), false );
mRecurrence->setDefaults(QDateTime::currentDateTime(),QDateTime::currentDateTime().addSecs( 3600 ));
}
}
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)
{
bool maybeComputeRecurrenceTime = false;
if( event->hasRecurrenceID() && event->percentComplete() < 100)
maybeComputeRecurrenceTime = true;
event->setHasRecurrenceID( false );
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);
if ( event->doesRecur() ) {
int addSec = -1 ;
if ( maybeComputeRecurrenceTime && event->percentComplete() == 100 )
addSec = 1;
event->setRecurrenceID( event->dtStart().addSecs( addSec ) );
event->setRecurDates();
} else {
event->setHasRecurrenceID( false );
}
} else {
event->setHasRecurrenceID( false );
- event->recurrence()->unsetRecurs();
+ if ( event->doesRecur() )
+ 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/kowhatsnextview.cpp b/korganizer/kowhatsnextview.cpp
index fafcb58..f88403c 100644
--- a/korganizer/kowhatsnextview.cpp
+++ b/korganizer/kowhatsnextview.cpp
@@ -1,803 +1,803 @@
/*
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.
*/
#include <qlayout.h>
#include <qtextbrowser.h>
#include <qtextcodec.h>
#include <qfileinfo.h>
#include <qlabel.h>
#include <qapplication.h>
#ifdef DESKTOP_VERSION
#include <qpaintdevicemetrics.h>
#endif
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <libkcal/calendar.h>
#ifndef KORG_NOPRINTER
#include "calprinter.h"
#endif
#include "koglobals.h"
#include "koprefs.h"
#include "koeventviewerdialog.h"
#include "koeventviewer.h"
#include <qstylesheet.h>
#include "kowhatsnextview.h"
using namespace KOrg;
void WhatsNextTextBrowser::setSource(const QString& n)
{
if (n.startsWith("event:")) {
emit showIncidence(n);
return;
} else if (n.startsWith("todo:")) {
emit showIncidence(n);
return;
} else {
QTextBrowser::setSource(n);
}
}
void WhatsNextTextBrowser::printMe()
{
#ifdef DESKTOP_VERSION
KOPrintPrefs pp ( this );
if (!pp.exec() )
return;
int scaleval = pp.printMode() ;
QPrinter printer;
if (!printer.setup() )
return;
QPainter p;
p.begin ( &printer );
QPaintDeviceMetrics m = QPaintDeviceMetrics ( &printer );
float dx, dy;
int wid = (m.width() * 9)/10;
dx = (float) wid/(float)contentsWidth ();
dy = (float)(m.height()) / (float)contentsHeight ();
float scale;
// scale to fit the width or height of the paper
if ( dx < dy )
scale = dx;
else
scale = dy;
p.translate( m.width()/10,0 );
if ( scaleval == 2 || scaleval == 1 && scale < 1.0 ) {
p.scale( scale, scale );
}
drawContents ( &p, 0,0, contentsWidth (), contentsHeight () );
p.end();
#endif
}
KOWhatsNextView::KOWhatsNextView(Calendar *calendar, QWidget *parent,
const char *name)
: KOrg::BaseView(calendar, parent, name)
{
// mDateLabel =
// new QLabel(KGlobal::locale()->formatDate(QDate::currentDate()),this);
// mDateLabel->setMargin(2);
// mDateLabel->setAlignment(AlignCenter);
setFont( KOPrefs::instance()->mWhatsNextFont );
mView = new WhatsNextTextBrowser(this);
connect(mView,SIGNAL(showIncidence(const QString &)),SLOT(showIncidence(const QString &)));
QStyleSheet* stsh = mView->styleSheet();
QStyleSheetItem * style ;
style = stsh->item ("h2" );
if ( style ) {
style->setMargin(QStyleSheetItem::MarginAll,0);
}
style = stsh->item ("h3" );
if ( style ) {
style->setMargin(QStyleSheetItem::MarginAll,0);
}
mEventViewer = 0;
QBoxLayout *topLayout = new QVBoxLayout(this);
// topLayout->addWidget(mDateLabel);
topLayout->addWidget(mView);
mTimer = new QTimer( this );
connect(mTimer,SIGNAL( timeout() ),this, SLOT(updateView()));
connect(mView->horizontalScrollBar (),SIGNAL( sliderReleased () ),this, SLOT(restartTimer()));
connect(mView->verticalScrollBar (),SIGNAL( sliderReleased () ),this, SLOT(restartTimer()));
}
KOWhatsNextView::~KOWhatsNextView()
{
}
int KOWhatsNextView::maxDatesHint()
{
return 0;
}
int KOWhatsNextView::currentDateCount()
{
return 0;
}
void KOWhatsNextView::clearList()
{
mTimer->stop();
mView->setText(" ");
}
QPtrList<Incidence> KOWhatsNextView::selectedIncidences()
{
QPtrList<Incidence> eventList;
return eventList;
}
void KOWhatsNextView::printMe()
{
#ifdef DESKTOP_VERSION
mView->printMe();
#endif
}
void KOWhatsNextView::printPreview(CalPrinter *calPrinter, const QDate &fd,
const QDate &td)
{
#ifndef KORG_NOPRINTER
calPrinter->preview(CalPrinter::Day, fd, td);
#endif
}
void KOWhatsNextView::updateConfig()
{
setFont( KOPrefs::instance()->mWhatsNextFont );
updateView();
}
void KOWhatsNextView::showEvent ( QShowEvent * e )
{
//qDebug("KOWhatsNextView::showEvent ");
restartTimer();
QWidget::showEvent ( e );
}
void KOWhatsNextView::hideEvent ( QHideEvent * e)
{
//qDebug(" KOWhatsNextView::hideEvent");
mTimer->stop();
QWidget::hideEvent ( e );
}
void KOWhatsNextView::restartTimer()
{
//qDebug("KOWhatsNextView::restartTimer() ");
mTimer->start( 300000 );
//mTimer->start( 5000 );
}
void KOWhatsNextView::updateView()
{
//qDebug("KOWhatsNextView::updateView() ");
if ( mTimer->isActive() )
restartTimer();
mCurrentMaxPrio = 5;
//qDebug("KOWhatsNextView::updateView() ");
// mDateLabel->setText(KGlobal::locale()->formatDate(QDate::currentDate()));
KIconLoader kil("korganizer");
QString ipath;// = new QString();
// kil.loadIcon("korganizer",KIcon::NoGroup,32,KIcon::DefaultState,&ipath);
//<big><big><strong>" + date + "</strong></big></big>\n";
mText = "<table width=\"100%\">\n";
//mText += "<tr bgcolor=\"#3679AD\"><td><h2>";
#ifdef DESKTOP_VERSION
mText += "<tr bgcolor=\"#5699CD\"><td align=\"center\"><h1>";
#else
mText += "<tr bgcolor=\"#5699CD\"><td align=\"center\"><h2>";
#endif
// mText += "<img src=\"";
// mText += ipath;
// mText += "\">";
mEventDate = QDate::currentDate();
#ifdef DESKTOP_VERSION
mText += "<font color=\"#FFFFFF\"> <em>" + KGlobal::locale()->formatDate( mEventDate , false )+"</em></font></h1>";
#else
mText += "<font color=\"#FFFFFF\"> <em>" + KGlobal::locale()->formatDate( mEventDate , false )+"</em></font></h2>";
#endif
mText += "</td></tr>\n<tr bgcolor=\"#EAF8FA\"><td>";
int iii;
mTodos.clear();
QPtrList<Event> events;
QPtrList<Todo> todos = calendar()->todos();
Todo * todo;
//mText += "<h2>" + i18n("Events: ") + "</h2>\n";
int daysToShow = KOPrefs::instance()->mWhatsNextDays ;
bool itemAdded = false;
for ( iii = 0; iii < daysToShow; ++iii ) {
QString date;
itemAdded = false;
events = calendar()->events( mEventDate, true );
if ( iii == 0 ) { // today !!!
todo = todos.first();
while(todo) {
if ( !todo->isCompleted() &&todo->hasDueDate() && todo->dtDue().date() < mEventDate ) {
if ( ! itemAdded ) {
appendDay ( iii, mEventDate );
//itemAdded = true;
} //bool reply=false, bool notRed = true, bool appendTable = false);
appendEvent(todo, false, false, !itemAdded );
itemAdded = true;
}
todo = todos.next();
}
}
if (events.count() > 0) {
// mText += "<p></p>";
// kil.loadIcon("month",KIcon::NoGroup,22,KIcon::DefaultState,&ipath);
// mText += "<h2>";
//mText += " <img src=\"";
//mText += ipath;
//mText += "\">";
if ( ! itemAdded ) {
appendDay ( iii, mEventDate );
}
// for first day (iii == 0)
// we may have syncevents, or events in the past, which maybe should not be diaplayed
// for that reason we cannot append <table> in appendDay () for iii == 0
// we must append it in the first successful call of appendEvent()
Event *ev = events.first();
while(ev) {
//qDebug("+++++event append %s", ev->summary().latin1());
if ( true /*!ev->recurrence()->doesRecur() || ev->recursOn( mEventDate)*/) {
if ( appendEvent(ev, false , iii!= 0,!itemAdded ) )
itemAdded = true;
}
ev = events.next();
}
//mText += "</table>\n";
}
todo = todos.first();
while(todo) {
if ( !todo->isCompleted() &&todo->hasDueDate() && todo->dtDue().date() == mEventDate ) {
if ( ! itemAdded ) {
appendDay ( iii, mEventDate );
//itemAdded = true;
}
appendEvent(todo, false , iii!= 0,!itemAdded);
itemAdded = true;
}
todo = todos.next();
}
if ( !itemAdded && iii == 0 ) {
// appendDay ( iii, mEventDate );
//mText += "<table>";
// mText += "<b><font color=\"#000080\"><em>"+i18n("No event, nothing to do.") +"</em></font></b>\n";
mText += "<h3 align=\"center\"><font color=\"#008000\"><em>"+i18n("No event, nothing to do.") +"</em></font></h3>\n";
//mText +="</table>";
}
if ( itemAdded )
mText += "</table>\n";
mEventDate = mEventDate.addDays( 1 );
}
int topmostPrios = KOPrefs::instance()->mWhatsNextPrios;
if (todos.count() > 0 && topmostPrios > 0 ) {
// kil.loadIcon("todo",KIcon::NoGroup,22,KIcon::DefaultState,&ipath);
// mText += "<h2>";
//<img src=\"";
// mText += ipath;
// mText += "\">";
// mText += i18n("Overdue To-Do:") + "</h2>\n";
//mText += "<ul>\n";
bool gotone = false;
int priority = 1;
int priosFound = 0;
#ifdef DESKTOP_VERSION
mText +="<p></p>";
#endif
mText +="<h2><em><font color=\"#000080\">" + i18n("Incomplete Todo:") + "</font></em></h2>\n";
mText += "<ul>\n";
while (!gotone && priority<6) {
todo = todos.first();
while(todo) {
if (!todo->isCompleted() && (todo->priority() == priority) ) {
mCurrentMaxPrio = priority - priosFound + topmostPrios -1;
if ( appendTodo(todo) )
gotone = true;
}
todo = todos.next();
}
if ( gotone ) {
gotone = false;
++priosFound;
if ( priosFound == topmostPrios )
break;
}
priority++;
// kdDebug() << "adding the todos..." << endl;
}
mText += "</ul>\n";
}
int replys = 0;
events = calendar()->events(QDate::currentDate(), QDate(2975,12,6));
if (events.count() > 0) {
Event *ev = events.first();
while(ev) {
Attendee *me = ev->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email());
if (me!=0) {
if (me->status()==Attendee::NeedsAction && me->RSVP()) {
if (replys == 0) {
mText += "<p></p>";
// kil.loadIcon("reply",KIcon::NoGroup,22,KIcon::DefaultState,&ipath);
//mText += "<h2>";
//<img src=\"";
// mText += ipath;
// mText += "\">";
//mText += i18n("Events and To-Dos that need a reply:") + "</h2>\n";
mText +="<h2><em><font color=\"#000080\">" + i18n("Events and To-Dos that need a reply:") + "</font></em></h2>\n";
mText += "<table>\n";
}
replys++;
appendEvent(ev,true);
}
}
ev = events.next();
}
}
todos = calendar()->todos();
if (todos.count() > 0) {
Todo *to = todos.first();
while(to) {
if ( !to->isCompleted() ){
Attendee *me = to->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email());
if (me!=0) {
if (me->status()==Attendee::NeedsAction && me->RSVP()) {
if (replys == 0) {
mText +="<h2><em><font color=\"#000080\">" + i18n("Events and To-Dos that need a reply:") + "</font></em></h2>\n";
mText += "<table>\n";
}
replys++;
appendEvent(to, true);
}
}
}
to = todos.next();
}
}
if (replys > 0 ) mText += "</table>\n";
mText += "</td></tr>\n</table>\n";
mView->setText(mText);
mView->setFocus();
// QPixmap bPix = SmallIcon( "back" );
// qDebug("xxxxxxxxxxxxxxxxxxxxx ");
// QWidget* test = new QWidget();
// test->setBackgroundMode(FixedPixmap );
// test->setBackgroundPixmap ( bPix );
// test->resize( 300, 400 );
// test->show();
// mView->setBackgroundMode(FixedPixmap );
// mView->setBackgroundPixmap ( bPix );
// qDebug("%s ",mText.latin1());
}
void KOWhatsNextView::appendDay( int i, QDate eventDate )
{
QString date;
QString day = KGlobal::locale()->formatDate( eventDate , KOPrefs::instance()->mShortDateInViewer);
if ( ! KOPrefs::instance()->mShortDateInViewer && QApplication::desktop()->width() < 320 ) {
if ( i == 0 ) {
//mText += "<table>\n";
return;//date = "<em><font color=\"#008000\"><em>" + day+"</font></em>";
}
else if ( i == 1 )
date = "<em><font color=\"#000080\">" + day + "</font></em>" ;
else date = "<em><font color=\"#000080\">" + day + "</font></em>";
mText += "<h2>" + date + "</h2>\n";
//mText += "<big><big><strong>" + date + "</strong></big></big>\n";
mText += "<table>\n";
} else {
if ( i == 0 ) {
//mText += "<table>\n";
return;// date = "<font color=\"#008000\"><em>" +i18n("Today: ") +"</em>" + day+"</font>";
}
#ifdef DESKTOP_VERSION
else if ( i == 1 ) {
date = "<h2><em><font color=\"#000080\">" + i18n("Tomorrow: ") + day +"</font></em></h2>" ;
}
else date = "<h2><em><font color=\"#000080\">" + i18n("In %1 days: ").arg( i ) +day + "</font></em></h2>";
#else
else if ( i == 1 ) {
date = "<em><font color=\"#000080\">" + i18n("Tomorrow: ") + day +"</font></em>" ;
}
else date = "<em><font color=\"#000080\">" + i18n("In %1 days: ").arg( i ) +day + "</font></em>";
#endif
mText += "<h2>" + date + "</h2>\n";
//mText += "<big><big><strong>" + date + "</strong></big></big>\n";
mText += "<table>\n";
}
}
void KOWhatsNextView::showDates(const QDate &, const QDate &)
{
updateView();
}
void KOWhatsNextView::showEvents(QPtrList<Event>)
{
}
void KOWhatsNextView::changeEventDisplay(Event *, int action)
{
switch(action) {
case KOGlobals::EVENTADDED:
updateView();
break;
case KOGlobals::EVENTEDITED:
updateView();
break;
case KOGlobals::EVENTDELETED:
updateView();
break;
default:
updateView();
kdDebug() << "KOWhatsNextView::changeEventDisplay(): Illegal action " << action << endl;
}
}
bool KOWhatsNextView::appendEvent(Incidence *ev, bool reply, bool notRed, bool appendTable )
{
if ( !KOPrefs::instance()->mShowSyncEvents && ev->uid().left(15) == QString("last-syncEvent-") )
return false;
QDateTime cdt = QDateTime::currentDateTime();
QDateTime noc;
QString tempText;
if ( appendTable && !notRed ) {
tempText = "<table>";
}
bool ok = true;
if ( reply ) {
noc = ev->getNextOccurence( cdt, &ok );
if (! ok && ev->typeID() == eventID)
return false;
}
bool bDay = false;
if ( ev->isBirthday() || ev->isAnniversary() )
bDay = true;
tempText += "<tr><td><b>";
if (ev->typeID() == eventID ) {
if (reply) {
if (!ev->doesFloat())
tempText += KGlobal::locale()->formatDateTime( noc , KOPrefs::instance()->mShortDateInViewer) +": ";
else
tempText += KGlobal::locale()->formatDate( noc.date() , KOPrefs::instance()->mShortDateInViewer) +": ";
} else {
if (!ev->doesFloat()) {
Event *event = static_cast<Event *>(ev);
QDateTime st,end;
- if ( event->recurrence()->doesRecur() ) {
+ if ( event->doesRecur() ) {
QDate recDate= mEventDate;
int days = event->dtStart().date().daysTo (event->dtEnd().date() );
while ( ! event->recursOn( recDate ) ) {
recDate = recDate.addDays( -1 );
}
st = QDateTime ( recDate, event->dtStart().time() );
end = QDateTime ( recDate.addDays( days ), event->dtEnd().time() );
}
else {
st = event->dtStart();
end = event->dtEnd();
}
QString dateText;
// qDebug("%s %s %s %s ", mEventDate.toString().latin1(),event->summary().latin1(), st .toString().latin1(),end.toString().latin1() );
if ( st.date() < mEventDate )
dateText = "++:++-";
else
dateText = event->dtStartTimeStr() + "-";
if ( KOPrefs::instance()->mWhatsNextTime2Lines )
dateText += " ";
if ( end.date() > mEventDate )
dateText += "++:++";
else
dateText += event->dtEndTimeStr();
if ( notRed )
tempText += dateText;
else {
if ( end < cdt ) {
if ( !KOPrefs::instance()->mWNViewShowsPast )
return false;
tempText += "<font color=\"#F00000\">" + dateText + "</font>";
}
else if ( st < cdt )
tempText += "<font color=\"#008000\">" + dateText + "</font>";
else
tempText += dateText;
}
} else {
if ( bDay ) {
if ( ev->isBirthday())
tempText += "<font color=\"#00B000\">" + i18n("Birthday") +":</font>";
else
tempText += "<font color=\"#00B0000\">" + i18n("Anniversary")+":</font>";
} else {
if ( ((Event*)ev)->isMultiDay() ) {
QString dfs = KGlobal::locale()->dateFormatShort();
KGlobal::locale()->setDateFormatShort("%d.%b");
tempText +=KGlobal::locale()->formatDate(((Event*)ev)->dtStart().date(), true, KLocale::Userdefined) + "-";
if ( KOPrefs::instance()->mWhatsNextTime2Lines )
tempText += " ";
tempText +=KGlobal::locale()->formatDate(((Event*)ev)->dtEnd().date(), true, KLocale::Userdefined);
KGlobal::locale()->setDateFormatShort(dfs);
} else {
tempText += " " ;//i18n("Allday:");
}
}
}
}
} else {
mTodos.append( ev );
tempText += i18n("ToDo:");
if ( KOPrefs::instance()->mWhatsNextTime2Lines )
tempText += " ";
if (reply) {
tempText += " ";
if ( noc != cdt ) {
tempText += KGlobal::locale()->formatDate( noc.date() , KOPrefs::instance()->mShortDateInViewer) +": ";
}
} else {
if ( ((Todo*)ev)->dtDue().date() < QDate::currentDate() ) {
// tempText +="<font color=\"#F00000\">" + i18n("O-due!") + "</font>";
QString dfs = KGlobal::locale()->dateFormatShort();
KGlobal::locale()->setDateFormatShort("%d.%b");
tempText +="<font color=\"#F00000\">" + KGlobal::locale()->formatDate(((Todo*)ev)->dtDue().date(), true, KLocale::Userdefined) + "</font>";
KGlobal::locale()->setDateFormatShort(dfs);
} else {
if (!ev->doesFloat() )
if( ( (Todo*)ev)->dtDue() < cdt ) {
tempText +="<font color=\"#F00000\">" + ((Todo*)ev)->dtDueTimeStr() + "</font>";
} else
tempText +=((Todo*)ev)->dtDueTimeStr();
mTodos.append( ev );
}
}
}
tempText += "</b></td><td>";
bool needClose = false;
if ( ev->cancelled() ) {
tempText += "<font color=\"#F00000\">[c";
needClose =true;
}
if ( ev->isAlarmEnabled() && ev->alarmEnabled()) {
if ( !needClose)
tempText +="[";
tempText += "a";
needClose =true;
}
if ( ev->description().length() > 0 ) {
if ( !needClose)
tempText +="[";
tempText += "i";
needClose =true;
}
- if ( ev->recurrence()->doesRecur() ) {
+ if ( ev->doesRecur() ) {
if ( !needClose)
tempText +="[";
tempText += "r";
needClose =true;
}
if ( needClose ) {
tempText += "] ";
}
if ( ev->cancelled() )
tempText += "</font>";
tempText += "<a ";
if (ev->typeID() == eventID ) tempText += "href=\"event:";
if (ev->typeID() == todoID ) tempText += "href=\"todo:";
tempText += ev->uid() + "\">";
if ( ev->summary().length() > 0 )
tempText += ev->summary();
else
tempText += i18n("-no summary-");
if ( bDay ) {
noc = ev->getNextOccurence( cdt.addDays(-1), &ok );
if ( ok ) {
int years = 0;
if ( ev->typeID() == todoID ) {
years = noc.date().year() -((Todo*)ev)->dtDue().date().year();
} else
years = noc.date().year() - ev->dtStart().date().year();
tempText += i18n(" (%1 y.)"). arg( years );
}
}
tempText += "</a>";
if ( KOPrefs::instance()->mWNViewShowLocation )
if ( !ev->location().isEmpty() )
tempText += " ("+ev->location() +")";
if ( ev->relatedTo() && KOPrefs::instance()->mWNViewShowsParents)
tempText += " ["+ev->relatedTo()->summary() +"]";
tempText += "</td></tr>\n";
mText += tempText;
return true;
}
bool KOWhatsNextView::appendTodo(Incidence *ev, QString ind , bool isSub )
{
if ( mTodos.find( ev ) != mTodos.end() ) return false;
mTodos.append( ev );
if ( !isSub )
mText += "<p>";
else
mText += "<li>";
mText += "[" +QString::number(ev->priority()) + "/" + QString::number(((Todo*)ev)->percentComplete())+"%] ";
mText += ind;
bool needClose = false;
if ( ev->cancelled() ) {
mText += "<font color=\"#F00000\">[c";
needClose =true;
}
if ( ev->isAlarmEnabled() && ev->alarmEnabled() ) {
if ( !needClose)
mText +="[";
mText += "a";
needClose =true;
}
if ( ev->description().length() > 0 ) {
if ( !needClose)
mText +="[";
mText += "i";
needClose =true;
}
if ( ev->doesRecur() ) {
if ( !needClose)
mText +="[";
mText += "r";
needClose =true;
}
// if ( ev->recurrence()->doesRecur() ) {
// if ( !needClose)
// mText +="(";
// mText += "r";
// needClose =true;
// }
if ( needClose )
mText += "] ";
if ( ev->cancelled() )
mText += "</font>";
mText += "<a href=\"todo:" + ev->uid() + "\">";
if ( ev->summary().length() > 0 )
mText += ev->summary();
else
mText += i18n("-no summary-");
mText += "</a>";
if ( ((Todo*)ev)->hasDueDate () ) {
QString year = "";
int ye = ((Todo*)ev)->dtDue().date().year();
if ( QDateTime::currentDateTime().date().year() != ye )
year = QString::number( ye );
QString dfs = KGlobal::locale()->dateFormatShort();
KGlobal::locale()->setDateFormatShort("%d.%b");
mText +="<font color=\"#00A000\"> [" + KGlobal::locale()->formatDate(((Todo*)ev)->dtDue().date(), true, KLocale::Userdefined) + "."+ year +"]</font>";
KGlobal::locale()->setDateFormatShort(dfs);
}
if ( KOPrefs::instance()->mWNViewShowLocation )
if ( !ev->location().isEmpty() )
mText += " ("+ev->location() +")";
if ( !isSub ) {
if ( ((Todo*)ev)->relatedTo()&& KOPrefs::instance()->mWNViewShowsParents)
mText += " ["+ev->relatedTo()->summary() +"]";
mText += "</p>\n";
}
else {
ind += "-";
mText += "</li>\n";
}
QPtrList<Incidence> Relations = ev->relations();
Incidence *to;
for (to=Relations.first();to;to=Relations.next()) {
if (!((Todo*)to)->isCompleted() && ((Todo*)to)->priority() <= mCurrentMaxPrio )
appendTodo( to, ind , true );
}
return true;
}
/*
void KOWhatsNextView::createEventViewer()
{
if (!mEventViewer) {
mEventViewer = new KOEventViewerDialog(this);
}
}
*/
void KOWhatsNextView::setEventViewer(KOEventViewerDialog* v )
{
mEventViewer = v;
}
// TODO: Create this function in CalendarView and remove it from here
void KOWhatsNextView::showIncidence(const QString &uid)
{
if ( !mEventViewer ) {
qDebug("KOWhatsNextView::showIncidence::sorry, no event viewer set ");
return;
}
//kdDebug() << "KOWhatsNextView::showIncidence(): " << uid << endl;
//qDebug("KOWhatsNextView::showIncidence %s ", uid.latin1());
if (uid.startsWith("event:")) {
#ifdef DESKTOP_VERSION
Event *event = calendar()->event(uid.mid(8));
#else
Event *event = calendar()->event(uid.mid(6));
#endif
//qDebug("event %d uid %s ", event, uid.mid(6).latin1());
if (!event) return;
//createEventViewer();
mEventViewer->setEvent(event);
} else if (uid.startsWith("todo:")) {
#ifdef DESKTOP_VERSION
Todo *todo = calendar()->todo(uid.mid(7));
#else
Todo *todo = calendar()->todo(uid.mid(5));
#endif
if (!todo) return;
//createEventViewer();
mEventViewer->setTodo(todo);
} else {
return;
}
mEventViewer->showMe();
mEventViewer->raise();
}
diff --git a/libkcal/event.cpp b/libkcal/event.cpp
index ad66639..0766fd9 100644
--- a/libkcal/event.cpp
+++ b/libkcal/event.cpp
@@ -1,415 +1,416 @@
/*
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 "event.h"
using namespace KCal;
Event::Event() :
mHasEndDate( false ), mTransparency( Opaque )
{
}
Event::Event(const Event &e) : Incidence(e)
{
mDtEnd = e.mDtEnd;
mHasEndDate = e.mHasEndDate;
mTransparency = e.mTransparency;
}
Event::~Event()
{
}
Incidence *Event::clone()
{
return new Event(*this);
}
bool KCal::operator==( const Event& e1, const Event& e2 )
{
return operator==( (const Incidence&)e1, (const Incidence&)e2 ) &&
e1.dtEnd() == e2.dtEnd() &&
e1.hasEndDate() == e2.hasEndDate() &&
e1.transparency() == e2.transparency();
}
bool Event::contains ( Event* from )
{
if ( !from->summary().isEmpty() )
if ( !summary().startsWith( from->summary() ))
return false;
if ( from->dtStart().isValid() )
if (dtStart() != from->dtStart() )
return false;
if ( from->dtEnd().isValid() )
if ( dtEnd() != from->dtEnd() )
return false;
if ( !from->location().isEmpty() )
if ( !location().startsWith( from->location() ) )
return false;
if ( !from->description().isEmpty() )
if ( !description().startsWith( from->description() ))
return false;
if ( from->alarms().count() ) {
Alarm *a = from->alarms().first();
if ( a->enabled() ){
if ( !alarms().count() )
return false;
Alarm *b = alarms().first();
if( ! b->enabled() )
return false;
if ( ! (a->offset() == b->offset() ))
return false;
}
}
QStringList cat = categories();
QStringList catFrom = from->categories();
QString nCat;
unsigned int iii;
for ( iii = 0; iii < catFrom.count();++iii ) {
nCat = catFrom[iii];
if ( !nCat.isEmpty() )
if ( !cat.contains( nCat )) {
return false;
}
}
if ( from->doesRecur() )
if ( from->doesRecur() != doesRecur() && ! (from->doesRecur()== Recurrence::rYearlyMonth && doesRecur()== Recurrence::rYearlyDay) )
return false;
return true;
}
void Event::setDtEnd(const QDateTime &dtEnd)
{
if (mReadOnly) return;
mDtEnd = getEvenTime( dtEnd );
setHasEndDate(true);
setHasDuration(false);
updated();
}
QDateTime Event::dtEnd() const
{
if (hasEndDate()) return mDtEnd;
if (hasDuration()) return dtStart().addSecs(duration());
return dtStart();
}
QString Event::dtEndTimeStr() const
{
return KGlobal::locale()->formatTime(mDtEnd.time());
}
QString Event::dtEndDateStr(bool shortfmt) const
{
return KGlobal::locale()->formatDate(mDtEnd.date(),shortfmt);
}
QString Event::dtEndStr(bool shortfmt) const
{
return KGlobal::locale()->formatDateTime(mDtEnd, shortfmt);
}
void Event::setHasEndDate(bool b)
{
mHasEndDate = b;
}
bool Event::hasEndDate() const
{
return mHasEndDate;
}
bool Event::isMultiDay() const
{
bool multi = !(dtStart().date() == dtEnd().date());
return multi;
}
void Event::setTransparency(Event::Transparency transparency)
{
if (mReadOnly) return;
mTransparency = transparency;
updated();
}
Event::Transparency Event::transparency() const
{
return mTransparency;
}
void Event::setDuration(int seconds)
{
setHasEndDate(false);
Incidence::setDuration(seconds);
}
bool Event::matchTime(QDateTime*startDT, QDateTime* endDT)
{
+ if ( cancelled() ) return false;
if ( ! doesRecur() ) {
if ( doesFloat() ) {
if ( mDtEnd.addDays( 1 ) < *startDT)
return false;
if ( endDT && mDtStart > * endDT)
return false;
} else {
if ( mDtEnd < *startDT )
return false;
if ( endDT && mDtStart > * endDT)
return false;
}
} else {
if ( endDT && mDtStart > * endDT)
return false;
}
return true;
}
bool Event::isOverlapping ( Event* testEvent, QDateTime* overlapDT, QDateTime* startDT )
{
if ( testEvent == this )
return false;
if ( ! doesRecur() && !testEvent->doesRecur() ) {
QDateTime te;
if ( testEvent->doesFloat() )
te = testEvent->mDtEnd.addDays( 1 );
else
te = testEvent->mDtEnd;
QDateTime e;
if ( doesFloat() )
e = mDtEnd.addDays( 1 );
else
e = mDtEnd;
if ( mDtStart < te && testEvent->mDtStart < e ) {
if ( mDtStart < testEvent->mDtStart )
*overlapDT = testEvent->mDtStart;
else
*overlapDT = mDtStart;
if ( startDT )
return (*overlapDT >= *startDT );
return true;
}
return false;
}
if ( !doesFloat() && !testEvent->doesFloat() && !isMultiDay() && !testEvent->isMultiDay() ) {
if ( mDtStart.time() >= testEvent->mDtEnd.time() || testEvent->mDtStart.time() >= mDtEnd.time() ) {
// no need to test. times mismatch
//fprintf(stderr,"timi ");
return false;
}
}
Event *nonRecur = 0;
Event *recurEvent = 0;
if ( ! doesRecur() ) {
nonRecur = this;
recurEvent = testEvent;
}
else if ( !testEvent->doesRecur() ) {
nonRecur = testEvent;
recurEvent = this;
}
if ( nonRecur ) {
QDateTime enr;
if ( nonRecur->doesFloat() )
enr = nonRecur->mDtEnd.addDays( 1 );
else
enr = nonRecur->mDtEnd;
if ( enr < recurEvent->mDtStart )
return false;
if ( startDT && enr < *startDT )
return false;
int recDuration = recurEvent->mDtStart.secsTo( recurEvent->mDtEnd );
if ( recurEvent->doesFloat() )
recDuration += 86400;
bool ok = false;
QDateTime recStart;
if ( startDT ) {
recStart = recurEvent->recurrence()->getPreviousDateTime( startDT->addSecs( 61 ), &ok );
}
if ( recStart.isValid() ) {
//qDebug("%s start at %s ", startDT-> toString().latin1(), recStart.toString().latin1());
recStart = recStart.addSecs( -300);
}
else
recStart = recurEvent->mDtStart.addSecs( -300);
ok = true;
while ( ok ) {
recStart = recurEvent->getNextOccurence( recStart.addSecs( 60 ), &ok );
if ( ok ) {
if ( recStart > enr )
return false;
QDateTime recEnd = recStart.addSecs( recDuration );
if ( nonRecur->mDtStart < recEnd && recStart < nonRecur->mDtEnd ) {
if ( nonRecur->mDtStart < recStart )
*overlapDT = recStart;
else
*overlapDT = nonRecur->mDtStart;
if ( startDT ) {
if ( *overlapDT >= *startDT )
return true;
} else
return true;
}
}
}
return false;
}
if ( !doesFloat() && !testEvent->doesFloat() && !isMultiDay() && !testEvent->isMultiDay() ) {
if ( recurrence()->doesRecur() == Recurrence::rWeekly && testEvent->recurrence()->doesRecur() == Recurrence::rWeekly ) {
bool found = false;
uint i;
for ( i=0; i< recurrence()->days().size();++i ) {
found = found || (recurrence()->days().testBit( i ) && testEvent->recurrence()->days().testBit( i ) );
}
if ( ! found ) {
//qDebug("recurring days mismatch %s -- %s", summary().latin1(),testEvent->summary().latin1());
return false;
}
}
}
bool ok = true;
QDateTime incidenceStart;// = mDtStart;
QDateTime testincidenceStart;// = testEvent->mDtStart;
if ( startDT ) {
incidenceStart = recurrence()->getPreviousDateTime( startDT->addSecs( 61 ), &ok );
testincidenceStart = testEvent->recurrence()->getPreviousDateTime( startDT->addSecs( 61 ), &ok );
}
if ( !testincidenceStart.isValid() )
testincidenceStart = testEvent->mDtStart;
if ( !incidenceStart.isValid() )
incidenceStart = mDtStart;
int duration = mDtStart.secsTo( mDtEnd );
if ( doesFloat() )
duration += 86400;
int testduration = testEvent->mDtStart.secsTo( testEvent->mDtEnd );
if ( testEvent->doesFloat() )
testduration += 86400;
bool computeThis = false;
if ( incidenceStart < testincidenceStart )
computeThis = true;
if ( computeThis )
incidenceStart = incidenceStart.addSecs( -300 );
else
testincidenceStart = testincidenceStart.addSecs( -300 );
int count = 0;
ok = true;
int countbreak = 2000;
QDateTime stopSearch;
bool testStop = false;
if ( startDT ) {
stopSearch = startDT->addDays( 365*3 );
testStop = true;
}
while ( ok ) {
++count;
if ( count > countbreak ) break;
if ( computeThis ) {
if ( testStop )
if ( testincidenceStart > stopSearch )
break;
incidenceStart = getNextOccurence( incidenceStart.addSecs( 60 ), &ok );
}
else {
if ( testStop )
if ( incidenceStart > stopSearch )
break;
testincidenceStart = testEvent->getNextOccurence( testincidenceStart.addSecs( 60 ), &ok );
}
if ( ok ) {
if ( incidenceStart < testincidenceStart.addSecs( testduration ) && testincidenceStart < incidenceStart.addSecs( duration ) ) {
if ( incidenceStart < testincidenceStart )
*overlapDT = testincidenceStart;
else
*overlapDT = incidenceStart;
if ( startDT ) {
if ( *overlapDT >= *startDT )
return true;
} else
return true;
}
computeThis = ( incidenceStart < testincidenceStart );
}
}
//qDebug("%d rec counter stopped at %d - %s %s", ok ,count, summary().latin1(),testEvent->summary().latin1() );
return false;
}
QDateTime Event::getNextAlarmDateTime( bool * ok, int * offset, QDateTime start_dt ) const
{
*ok = false;
if ( !alarmEnabled() )
return QDateTime ();
bool yes;
QDateTime incidenceStart = getNextOccurence( start_dt, &yes );
if ( ! yes || cancelled() ) {
*ok = false;
return QDateTime ();
}
bool enabled = false;
Alarm* alarm;
int off = 0;
QDateTime alarmStart = QDateTime::currentDateTime().addDays( 3650 );;
// if ( QDateTime::currentDateTime() > incidenceStart ){
// *ok = false;
// return incidenceStart;
// }
for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) {
if (alarm->enabled()) {
if ( alarm->hasTime () ) {
if ( alarm->time() < alarmStart ) {
alarmStart = alarm->time();
enabled = true;
off = alarmStart.secsTo( incidenceStart );
}
} else {
int secs = alarm->startOffset().asSeconds();
if ( incidenceStart.addSecs( secs ) < alarmStart ) {
alarmStart = incidenceStart.addSecs( secs );
enabled = true;
off = -secs;
}
}
}
}
if ( enabled ) {
if ( alarmStart > start_dt ) {
*ok = true;
* offset = off;
return alarmStart;
}
}
*ok = false;
return QDateTime ();
}
diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp
index 4794bc9..f349681 100644
--- a/libkcal/icalformatimpl.cpp
+++ b/libkcal/icalformatimpl.cpp
@@ -1,2175 +1,2173 @@
/*
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->relatedToUid().isEmpty()) {
icalcomponent_add_property(parent,icalproperty_new_relatedto(
incidence->relatedToUid().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)));
+ if (incidence->doesRecur()) {
+ icalcomponent_add_property(parent,writeRecurrenceRule(incidence->recurrence()));
+ // 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()));
}
icalattach_unref( attach );
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));
icalattach_unref( 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));
icalattach_unref( 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);
if ( !journal->dtStart().isValid() && journal->created().isValid() ) {
journal->setDtStart( journal->created() );
}
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();
+ if ( readrec )
+ 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;
}
t.year = datetime.date().year();
t.month = datetime.date().month();
t.day = datetime.date().day();
t.hour = datetime.time().hour();
t.minute = datetime.time().minute();
t.second = datetime.time().second();
//qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
// if ( mParent->utc() ) {
// datetime = KGlobal::locale()->localTime( dt );
// qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
// if (mParent->timeZoneId().isEmpty())
// t = icaltime_as_utc(t, 0);
// else
// t = icaltime_as_utc(t,mParent->timeZoneId().local8Bit());
// }
return t;
}
QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t)
{
QDateTime dt (QDate(t.year,t.month,t.day),
QTime(t.hour,t.minute,t.second) );
if (t.is_utc) {
int offset = KGlobal::locale()->localTimeOffset( dt );
dt = dt.addSecs ( offset*60);
}
return dt;
}
QDate ICalFormatImpl::readICalDate(icaltimetype t)
{
return QDate(t.year,t.month,t.day);
}
icaldurationtype ICalFormatImpl::writeICalDuration(int seconds)
{
icaldurationtype d;
d.is_neg = (seconds<0)?1:0;
if (seconds<0) seconds = -seconds;
d.weeks = seconds / gSecondsPerWeek;
seconds %= gSecondsPerWeek;
d.days = seconds / gSecondsPerDay;
seconds %= gSecondsPerDay;
d.hours = seconds / gSecondsPerHour;
seconds %= gSecondsPerHour;
d.minutes = seconds / gSecondsPerMinute;
seconds %= gSecondsPerMinute;
d.seconds = seconds;
return d;
}
int ICalFormatImpl::readICalDuration(icaldurationtype d)
{
int result = 0;
result += d.weeks * gSecondsPerWeek;
result += d.days * gSecondsPerDay;
result += d.hours * gSecondsPerHour;
result += d.minutes * gSecondsPerMinute;
result += d.seconds;
if (d.is_neg) result *= -1;
return result;
}
icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal)
{
icalcomponent *calendar;
// Root component
calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
icalproperty *p;
// Product Identifier
p = icalproperty_new_prodid(CalFormat::productId().utf8());
icalcomponent_add_property(calendar,p);
// TODO: Add time zone
// iCalendar version (2.0)
p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION));
icalcomponent_add_property(calendar,p);
// Custom properties
if( cal != 0 )
writeCustomProperties(calendar, cal);
return calendar;
}
// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
// and break it down from its tree-like format into the dictionary format
// that is used internally in the ICalFormatImpl.
bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar)
{
// this function will populate the caldict dictionary and other event
// lists. It turns vevents into Events and then inserts them.
if (!calendar) return false;
// TODO: check for METHOD
#if 0
if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) {
char *methodType = 0;
methodType = fakeCString(vObjectUStringZValue(curVO));
if (mEnableDialogs)
KMessageBox::information(mTopWidget,
i18n("This calendar is an iTIP transaction of type \"%1\".")
.arg(methodType),
i18n("%1: iTIP Transaction").arg(CalFormat::application()));
delete methodType;
}
#endif
icalproperty *p;
p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY);
if (!p) {
// TODO: does no PRODID really matter?
// mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
// return false;
mLoadedProductId = "";
mCalendarVersion = 0;
} else {
mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p));
mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId);
delete mCompat;
mCompat = CompatFactory::createCompat( mLoadedProductId );
}
// TODO: check for unknown PRODID
#if 0
if (!mCalendarVersion
&& CalFormat::productId() != mLoadedProductId) {
// warn the user that we might have trouble reading non-known calendar.
if (mEnableDialogs)
KMessageBox::information(mTopWidget,
i18n("This vCalendar file was not created by KOrganizer "
"or any other product we support. Loading anyway..."),
i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application()));
}
#endif
p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY);
if (!p) {
mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
return false;
} else {
const char *version = icalproperty_get_version(p);
if (strcmp(version,"1.0") == 0) {
mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1,
i18n("Expected iCalendar format")));
return false;
} else if (strcmp(version,"2.0") != 0) {
mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
return false;
}
}
// TODO: check for calendar format version
#if 0
// warn the user we might have trouble reading this unknown version.
if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVO));
if (strcmp(_VCAL_VERSION, s) != 0)
if (mEnableDialogs)
KMessageBox::sorry(mTopWidget,
i18n("This vCalendar file has version %1.\n"
"We only support %2.")
.arg(s).arg(_VCAL_VERSION),
i18n("%1: Unknown vCalendar Version").arg(CalFormat::application()));
deleteStr(s);
}
#endif
// custom properties
readCustomProperties(calendar, cal);
// TODO: set time zone
#if 0
// set the time zone
if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVO));
cal->setTimeZone(s);
deleteStr(s);
}
#endif
// Store all events with a relatedTo property in a list for post-processing
mEventsRelate.clear();
mTodosRelate.clear();
// TODO: make sure that only actually added ecvens go to this lists.
icalcomponent *c;
// Iterate through all todos
c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT);
while (c) {
// kdDebug(5800) << "----Todo found" << endl;
Todo *todo = readTodo(c);
if (!cal->todo(todo->uid())) cal->addTodo(todo);
c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT);
}
// Iterate through all events
c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT);
while (c) {
// kdDebug(5800) << "----Event found" << endl;
Event *event = readEvent(c);
if (!cal->event(event->uid())) cal->addEvent(event);
c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT);
}
// Iterate through all journals
c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT);
while (c) {
// kdDebug(5800) << "----Journal found" << endl;
Journal *journal = readJournal(c);
if (!cal->journal(journal->uid())) cal->addJournal(journal);
c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT);
}
#if 0
initPropIterator(&i, vcal);
// go through all the vobjects in the vcal
while (moreIteration(&i)) {
curVO = nextVObject(&i);
/************************************************************************/
// now, check to see that the object is an event or todo.
if (strcmp(vObjectName(curVO), VCEventProp) == 0) {
if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) {
char *s;
s = fakeCString(vObjectUStringZValue(curVOProp));
// check to see if event was deleted by the kpilot conduit
if (atoi(s) == Event::SYNCDEL) {
deleteStr(s);
goto SKIP;
}
deleteStr(s);
}
// this code checks to see if we are trying to read in an event
// that we already find to be in the calendar. If we find this
// to be the case, we skip the event.
if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVOProp));
QString tmpStr(s);
deleteStr(s);
if (cal->event(tmpStr)) {
goto SKIP;
}
if (cal->todo(tmpStr)) {
goto SKIP;
}
}
if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) &&
(!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) {
kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl;
goto SKIP;
}
anEvent = VEventToEvent(curVO);
// we now use addEvent instead of insertEvent so that the
// signal/slot get connected.
if (anEvent)
cal->addEvent(anEvent);
else {
// some sort of error must have occurred while in translation.
goto SKIP;
}
} else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) {
anEvent = VTodoToEvent(curVO);
cal->addTodo(anEvent);
} else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) ||
(strcmp(vObjectName(curVO), VCProdIdProp) == 0) ||
(strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) {
// do nothing, we know these properties and we want to skip them.
// we have either already processed them or are ignoring them.
;
} else {
;
}
SKIP:
;
} // while
#endif
// Post-Process list of events with relations, put Event objects in relation
Event *ev;
for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) {
Incidence * inc = cal->event(ev->relatedToUid());
if ( inc )
ev->setRelatedTo( inc );
}
Todo *todo;
for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) {
Incidence * inc = cal->todo(todo->relatedToUid());
if ( inc )
todo->setRelatedTo( inc );
}
return true;
}
QString ICalFormatImpl::extractErrorProperty(icalcomponent *c)
{
// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: "
// << icalcomponent_as_ical_string(c) << endl;
QString errorMessage;
icalproperty *error;
error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY);
while(error) {
errorMessage += icalproperty_get_xlicerror(error);
errorMessage += "\n";
error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY);
}
// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl;
return errorMessage;
}
void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r)
{
int i;
if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
int index = 0;
QString out = " By Day: ";
while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
out.append(QString::number(i) + " ");
}
}
if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
int index = 0;
QString out = " By Month Day: ";
while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
out.append(QString::number(i) + " ");
}
}
if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
int index = 0;
QString out = " By Year Day: ";
while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
out.append(QString::number(i) + " ");
}
}
if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
int index = 0;
QString out = " By Month: ";
while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
out.append(QString::number(i) + " ");
}
}
if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
int index = 0;
QString out = " By Set Pos: ";
while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
out.append(QString::number(i) + " ");
}
}
}
icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence,
Scheduler::Method method)
{
icalcomponent *message = createCalendarComponent();
icalproperty_method icalmethod = ICAL_METHOD_NONE;
switch (method) {
case Scheduler::Publish:
icalmethod = ICAL_METHOD_PUBLISH;
break;
case Scheduler::Request:
icalmethod = ICAL_METHOD_REQUEST;
break;
case Scheduler::Refresh:
icalmethod = ICAL_METHOD_REFRESH;
break;
case Scheduler::Cancel:
icalmethod = ICAL_METHOD_CANCEL;
break;
case Scheduler::Add:
icalmethod = ICAL_METHOD_ADD;
break;
case Scheduler::Reply:
icalmethod = ICAL_METHOD_REPLY;
break;
case Scheduler::Counter:
icalmethod = ICAL_METHOD_COUNTER;
break;
case Scheduler::Declinecounter:
icalmethod = ICAL_METHOD_DECLINECOUNTER;
break;
default:
return message;
}
icalcomponent_add_property(message,icalproperty_new_method(icalmethod));
// TODO: check, if dynamic cast is required
if(incidence->typeID() == todoID ) {
Todo *todo = static_cast<Todo *>(incidence);
icalcomponent_add_component(message,writeTodo(todo));
}
if(incidence->typeID() == eventID ) {
Event *event = static_cast<Event *>(incidence);
icalcomponent_add_component(message,writeEvent(event));
}
if(incidence->typeID() == freebusyID) {
FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
icalcomponent_add_component(message,writeFreeBusy(freebusy, method));
}
return message;
}
diff --git a/libkcal/incidence.cpp b/libkcal/incidence.cpp
index e4bcc5e..4643a3a 100644
--- a/libkcal/incidence.cpp
+++ b/libkcal/incidence.cpp
@@ -1,780 +1,811 @@
/*
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);
+ mRecurrence = 0;//new Recurrence(this);
mCancelled = false;
recreate();
mHasStartDate = true;
mAlarms.setAutoDelete(true);
mAttachments.setAutoDelete(true);
mHasRecurrenceID = false;
mHoliday = false;
mBirthday = false;
mAnniversary = 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 );
+ if ( i.mRecurrence )
+ mRecurrence = new Recurrence( *(i.mRecurrence), this );
+ else
+ mRecurrence = 0;
mHoliday = i.mHoliday ;
mBirthday = i.mBirthday;
mAnniversary = i.mAnniversary;
}
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;
+ if ( mRecurrence )
+ delete mRecurrence;
}
bool Incidence::isHoliday() const
{
return mHoliday;
}
bool Incidence::isBirthday() const
{
return mBirthday ;
}
bool Incidence::isAnniversary() const
{
return mAnniversary ;
}
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;
+ if ( i1.mRecurrence != 0 && i2.mRecurrence != 0 ) {
+ if (!( *i1.mRecurrence == *i2.mRecurrence) ) {
+ //qDebug("recurrence is NOT equal ");
+ return false;
+ }
+ } else {
+ // one ( or both ) recurrence is 0
+ if ( i1.mRecurrence == 0 ) {
+ if ( i2.mRecurrence != 0 && i2.mRecurrence->doesRecur() != Recurrence::rNone )
+ return false;
+ } else {
+ // i1.mRecurrence != 0
+ // i2.mRecurrence == 0
+ if ( i1.mRecurrence->doesRecur() != Recurrence::rNone )
+ 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();
if ( typeID() == eventID ) {
int len = dtStart().secsTo( ((Event*)this)->dtEnd());
QTime tim = dtStart().time();
newInc->setDtStart( QDateTime(d, tim) );
((Event*)newInc)->setDtEnd( newInc->dtStart().addSecs( len ) );
} else {
int len = dtStart().secsTo( ((Todo*)this)->dtDue());
QTime tim = ((Todo*)this)->dtDue().time();
((Todo*)newInc)->setDtDue( QDateTime(d, tim) );
((Todo*)newInc)->setDtStart( ((Todo*)newInc)->dtDue().addSecs( -len ) );
((Todo*)this)->setRecurDates();
}
newInc->setExDates( DateList () );
}
return newInc;
}
void Incidence::recreate()
{
setCreated(QDateTime::currentDateTime());
setUid(CalFormat::createUniqueId());
setRevision(0);
setIDStr( ":" );
setLastModified(QDateTime::currentDateTime());
}
void Incidence::cloneRelations( Incidence * newInc )
{
// newInc is already a clone of this incidence
Incidence * inc;
Incidence * cloneInc;
QPtrList<Incidence> Relations = relations();
for (inc=Relations.first();inc;inc=Relations.next()) {
cloneInc = inc->clone();
cloneInc->recreate();
cloneInc->setRelatedTo( newInc );
inc->cloneRelations( cloneInc );
}
}
void Incidence::setReadOnly( bool readOnly )
{
IncidenceBase::setReadOnly( readOnly );
- recurrence()->setRecurReadOnly( readOnly);
+ if ( mRecurrence )
+ mRecurrence->setRecurReadOnly( readOnly);
}
void Incidence::setLastModifiedSubInvalid()
{
mLastModifiedSub = QDateTime();
if ( mRelatedTo )
mRelatedTo->setLastModifiedSubInvalid();
}
QDateTime Incidence::lastModifiedSub()
{
if ( !mRelations.count() )
return lastModified();
if ( mLastModifiedSub.isValid() )
return mLastModifiedSub;
mLastModifiedSub = lastModified();
Incidence * inc;
QPtrList<Incidence> Relations = relations();
for (inc=Relations.first();inc;inc=Relations.next()) {
if ( inc->lastModifiedSub() > mLastModifiedSub )
mLastModifiedSub = inc->lastModifiedSub();
}
return mLastModifiedSub;
}
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);
+
+ if ( mRecurrence )
+ mRecurrence->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::checkCategories()
{
mHoliday = mCategories.contains("Holiday") || mCategories.contains(i18n("Holiday"));
mBirthday = mCategories.contains("Birthday") || mCategories.contains(i18n("Birthday"));
mAnniversary = mCategories.contains("Anniversary") || mCategories.contains(i18n("Anniversary"));
}
void Incidence::addCategories(const QStringList &categories, bool addToRelations ) //addToRelations = false
{
if (mReadOnly) return;
int i;
for( i = 0; i < categories.count(); ++i ) {
if ( !mCategories.contains (categories[i]))
mCategories.append( categories[i] );
}
checkCategories();
updated();
if ( addToRelations ) {
Incidence * inc;
QPtrList<Incidence> Relations = relations();
for (inc=Relations.first();inc;inc=Relations.next()) {
inc->addCategories( categories, true );
}
}
}
void Incidence::setCategories(const QStringList &categories, bool setForRelations ) //setForRelations = false
{
if (mReadOnly) return;
mCategories = categories;
checkCategories();
updated();
if ( setForRelations ) {
Incidence * inc;
QPtrList<Incidence> Relations = relations();
for (inc=Relations.first();inc;inc=Relations.next()) {
inc->setCategories( categories, true );
}
}
}
// 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();
}
checkCategories();
updated();
}
// using this makes filtering 3 times faster
QStringList* Incidence::categoriesP()
{
return &mCategories;
}
QStringList Incidence::categories() const
{
return mCategories;
}
QString Incidence::categoriesStr()
{
return mCategories.join(",");
}
QString Incidence::categoriesStrWithSpace()
{
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);
mRelatedToUid = mRelatedTo->uid();
} else {
mRelatedToUid = "";
}
}
Incidence *Incidence::relatedTo() const
{
return mRelatedTo;
}
QPtrList<Incidence> Incidence::relations() const
{
return mRelations;
}
void Incidence::addRelationsToList(QPtrList<Incidence> *rel)
{
Incidence* inc;
QPtrList<Incidence> Relations = relations();
for (inc=Relations.first();inc;inc=Relations.next()) {
inc->addRelationsToList( rel );
}
if ( rel->findRef( this ) == -1 )
rel->append( this );
}
void Incidence::addRelation(Incidence *event)
{
setLastModifiedSubInvalid();
if( mRelations.findRef( event ) == -1 ) {
mRelations.append(event);
//updated();
}
}
void Incidence::removeRelation(Incidence *event)
{
setLastModifiedSubInvalid();
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;
+ if (mRecurrence && mRecurrence->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
+#include <stdlib.h>
+Recurrence *Incidence::recurrence()
{
+ if ( ! mRecurrence ) {
+ mRecurrence = new Recurrence(this);
+ qDebug("creating new recurence ");
+ //abort();
+ }
return mRecurrence;
}
void Incidence::setRecurrence( Recurrence * r)
{
- delete mRecurrence;
- mRecurrence = r;
+ if ( mRecurrence )
+ delete mRecurrence;
+ mRecurrence = r;
}
void Incidence::setLocation(const QString &location)
{
if (mReadOnly) return;
mLocation = location;
updated();
}
QString Incidence::location() const
{
return mLocation;
}
+QString Incidence::recurrenceText() const
+{
+ if ( mRecurrence ) return mRecurrence->recurrenceText();
+ return i18n("No");
+}
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 );
+ mRecurrence->getPreviousDateTime( incidenceStart , &last );
int count = 0;
if ( !last ) {
while ( !last ) {
++count;
- incidenceStart = recurrence()->getNextDateTime( incidenceStart, &last );
+ incidenceStart = mRecurrence->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 ( typeID() == todoID ) {
if ( ((Todo*)this)->hasDueDate() )
incidenceStart = ((Todo*)this)->dtDue();
}
}
if ( incidenceStart > dt )
*ok = true;
return incidenceStart;
}
QDateTime Incidence::dtStart() const
{
if ( doesRecur() ) {
if ( typeID() == todoID ) {
((Todo*)this)->checkSetCompletedFalse();
}
}
return mDtStart;
}
diff --git a/libkcal/incidence.h b/libkcal/incidence.h
index d4af9f0..8519f01 100644
--- a/libkcal/incidence.h
+++ b/libkcal/incidence.h
@@ -1,321 +1,322 @@
/*
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 void cloneRelations( Incidence * );
void addRelationsToList(QPtrList<Incidence> *rel);
virtual QDateTime getNextAlarmDateTime( bool * ok, int * offset, QDateTime start_dt ) 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, bool setForRelations = false);
void addCategories(const QStringList &categories, bool addToRelations = false);
/** set event's categories based on a comma delimited string */
void setCategories(const QString &catStr);
/** return categories in a list */
QStringList categories() const;
QStringList* categoriesP();
/** return categories as a comma separated string */
QString categoriesStr();
QString categoriesStrWithSpace();
/** 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;
+ Recurrence *recurrence();
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;
QDateTime dtStart() const;
bool isHoliday() const;
bool isBirthday() const;
bool isAnniversary() const;
QDateTime lastModifiedSub();
+ QString recurrenceText() const;
void setLastModifiedSubInvalid();
+ Recurrence *mRecurrence;
protected:
QPtrList<Alarm> mAlarms;
QPtrList<Incidence> mRelations;
QDateTime mRecurrenceID;
bool mHasRecurrenceID;
private:
void checkCategories();
bool mHoliday, mBirthday, mAnniversary;
int mRevision;
bool mCancelled;
// base components of jounal, event and todo
QDateTime mCreated;
QDateTime mLastModifiedSub;
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/libkcal/kincidenceformatter.cpp b/libkcal/kincidenceformatter.cpp
index 9359fad..f8f40f1 100644
--- a/libkcal/kincidenceformatter.cpp
+++ b/libkcal/kincidenceformatter.cpp
@@ -1,425 +1,425 @@
#include "kincidenceformatter.h"
#include <kstaticdeleter.h>
#include <kglobal.h>
#include <klocale.h>
#ifdef DEKTOP_VERSION
#include <kabc/stdaddressbook.h>
#define size count
#endif
KIncidenceFormatter* KIncidenceFormatter::mInstance = 0;
static KStaticDeleter<KIncidenceFormatter> insd;
QString KIncidenceFormatter::getFormattedText( Incidence * inc, bool details, bool created , bool modified )
{
// #ifndef QT_NO_INPUTDIALOG
// return QInputDialog::getItem( caption, label, items, current, editable );
// #else
// return QString::null;
// #endif
mDetails = details;
mCreated = created ;
mModified = modified;
mText = "";
if ( inc->typeID() == eventID )
setEvent((Event *) inc );
else if ( inc->typeID() == todoID )
setTodo((Todo *) inc );
return mText;
}
KIncidenceFormatter* KIncidenceFormatter::instance()
{
if (!mInstance) {
mInstance = insd.setObject(new KIncidenceFormatter());
}
return mInstance;
}
KIncidenceFormatter::~KIncidenceFormatter()
{
if (mInstance == this)
mInstance = insd.setObject(0);
//qDebug("KIncidenceFormatter::~KIncidenceFormatter ");
}
KIncidenceFormatter::KIncidenceFormatter()
{
mColorMode = 0;
}
void KIncidenceFormatter::setEvent(Event *event)
{
int mode = 0;
mCurrentIncidence = event;
bool shortDate = true;
if ( mode == 0 ) {
addTag("h3",deTag(event->summary()));
formatReadOnly(event);
}
else {
if ( mColorMode == 1 ) {
mText +="<font color=\"#00A000\">";
}
if ( mColorMode == 2 ) {
mText +="<font color=\"#C00000\">";
}
// mText +="<font color=\"#F00000\">" + i18n("O-due!") + "</font>";
if ( mode == 1 ) {
addTag("h2",i18n( "Local: " ) +deTag(event->summary()));
} else {
addTag("h2",i18n( "Remote: " ) +deTag(event->summary()));
}
formatReadOnly(event);
addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) );
if ( mColorMode )
mText += "</font>";
}
if (event->cancelled ()) {
mText +="<font color=\"#B00000\">";
addTag("i",i18n("This event has been cancelled!"));
mText.append("<br>");
mText += "</font>";
}
if (event->doesFloat()) {
if (event->isMultiDay()) {
mText.append(i18n("<p><b>From:</b> %1 </p><p><b>To:</b> %2</p>")
.arg(event->dtStartDateStr(shortDate))
.arg(event->dtEndDateStr(shortDate)));
} else {
mText.append(i18n("<p><b>On:</b> %1</p>").arg(event->dtStartDateStr( shortDate )));
}
} else {
if (event->isMultiDay()) {
mText.append(i18n("<p><b>From:</b> %1</p> ")
.arg(event->dtStartStr( shortDate)));
mText.append(i18n("<p><b>To:</b> %1</p>")
.arg(event->dtEndStr(shortDate)));
} else {
mText.append(i18n("<p><b>From:</b> %1 <b>To:</b> %2</p>")
.arg(event->dtStartTimeStr())
.arg(event->dtEndTimeStr()));
mText.append(i18n("<p><b>On:</b> %1</p> ")
.arg(event->dtStartDateStr( shortDate )));
}
}
if (!event->location().isEmpty()) {
addTag("b",i18n("Location: "));
mText.append(deTag(event->location())+"<br>");
}
- if (event->recurrence()->doesRecur()) {
+ if (event->doesRecur()) {
QString recurText = event->recurrence()->recurrenceText();
addTag("p","<em>" + i18n("This is a %1 recurring event.").arg(recurText ) + "</em>");
bool ok;
QDate start = QDate::currentDate();
QDateTime next;
next = event->getNextOccurence( QDateTime::currentDateTime() , &ok );
if ( ok ) {
addTag("p",i18n("<b>Next recurrence is on:</b>") );
addTag("p", KGlobal::locale()->formatDate( next.date(), shortDate ));
} else {
bool last;
QDate nextd;
nextd = event->recurrence()->getPreviousDate( QDate::currentDate() , &last );
if ( last ) {
addTag("p",i18n("<b>Last recurrence was on:</b>") );
addTag("p", KGlobal::locale()->formatDate( nextd, shortDate ));
}
}
}
if (event->isAlarmEnabled()) {
Alarm *alarm =event->alarms().first() ;
QDateTime t = alarm->time();
QString s =i18n("( %1 before )").arg( alarm->offsetText() );
addTag("p",i18n("<b>Alarm on: </b>") + s + ": "+KGlobal::locale()->formatDateTime( t, shortDate ));
//addTag("p", KGlobal::locale()->formatDateTime( t, shortDate ));
//addTag("p",s);
}
addTag("p",i18n("<b>Access: </b>") +event->secrecyStr() );
// mText.append(event->secrecyStr()+"<br>");
formatCategories(event);
formatAttendees(event);
if ( mCreated ) {
#ifdef DESKTOP_VERSION
addTag("p",i18n("<b>Created: ") +" </b>"+KGlobal::locale()->formatDateTime( event->created(), shortDate ));
#else
addTag("p",i18n("<b>Created: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->created(), shortDate ));
#endif
}
if ( mModified ) {
#ifdef DESKTOP_VERSION
addTag("p",i18n("<b>Last modified: ") +" </b>"+KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ));
#else
addTag("p",i18n("<b>Last modified: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ));
#endif
}
if ( mDetails ) {
if (!event->description().isEmpty()) {
addTag("p",i18n("<b>Details: </b>"));
addTag("p",deTag(event->description()));
}
}
}
void KIncidenceFormatter::setTodo(Todo *event )
{
int mode = 0;
mCurrentIncidence = event;
bool shortDate = true;
if (mode == 0 ) {
addTag("h3",deTag(event->summary()));
formatReadOnly(event);
}
else {
if ( mColorMode == 1 ) {
mText +="<font color=\"#00A000\">";
}
if ( mColorMode == 2 ) {
mText +="<font color=\"#B00000\">";
}
if ( mode == 1 ) {
addTag("h2",i18n( "Local: " ) +deTag(event->summary()));
} else {
addTag("h2",i18n( "Remote: " ) +deTag(event->summary()));
}
formatReadOnly(event);
addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) );
if ( mColorMode )
mText += "</font>";
}
if ( event->percentComplete() == 100 && event->hasCompletedDate() ) {
mText +="<font color=\"#B00000\">";
addTag("i", i18n("<p><i>Completed on %1</i></p>").arg( event->completedStr(shortDate) ) );
mText += "</font>";
} else {
mText.append(i18n("<p><i>%1 % completed</i></p>")
.arg(event->percentComplete()));
}
if (event->cancelled ()) {
mText +="<font color=\"#B00000\">";
addTag("i",i18n("This todo has been cancelled!"));
mText.append("<br>");
mText += "</font>";
}
- if (event->recurrence()->doesRecur()) {
+ if (event->doesRecur()) {
QString recurText = event->recurrence()->recurrenceText();
addTag("p","<em>" + i18n("This is a %1 recurring todo.").arg(recurText ) + "</em>");
}
if (event->hasStartDate()) {
mText.append(i18n("<p><b>Start on:</b> %1</p>").arg(event->dtStartStr(shortDate)));
}
if (event->hasDueDate()) {
mText.append(i18n("<p><b>Due on:</b> %1</p>").arg(event->dtDueStr(shortDate)));
}
if (!event->location().isEmpty()) {
addTag("b",i18n("Location: "));
mText.append(deTag(event->location())+"<br>");
}
mText.append(i18n("<p><b>Priority:</b> %2</p>")
.arg(QString::number(event->priority())));
if (event->isAlarmEnabled()) {
Alarm *alarm =event->alarms().first() ;
QDateTime t = alarm->time();
QString s =i18n("( %1 before )").arg( alarm->offsetText() );
addTag("p",i18n("<b>Alarm on: ") + s +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( t, shortDate ));
//addTag("p",s);
}
addTag("p",i18n("<b>Access: </b>") +event->secrecyStr() );
formatCategories(event);
formatAttendees(event);
if ( mCreated ) {
#ifdef DESKTOP_VERSION
addTag("p",i18n("<b>Created: ") +" </b>"+KGlobal::locale()->formatDateTime( event->created(), shortDate ));
#else
addTag("p",i18n("<b>Created: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->created(), shortDate ));
#endif
}
if ( mModified ) {
#ifdef DESKTOP_VERSION
addTag("p",i18n("<b>Last modified: ") +" </b>"+KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ));
#else
addTag("p",i18n("<b>Last modified: ") +" </b>");
addTag("p", KGlobal::locale()->formatDateTime( event->lastModified(), shortDate ));
#endif
}
if ( mDetails ) {
if (!event->description().isEmpty()) {
addTag("p",i18n("<b>Details: </b>"));
addTag("p",deTag(event->description()));
}
}
}
void KIncidenceFormatter::setJournal(Journal* )
{
}
void KIncidenceFormatter::formatCategories(Incidence *event)
{
if (!event->categoriesStr().isEmpty()) {
addTag("p",i18n("<b>Categories: </b>")+event->categoriesStrWithSpace() );
//mText.append(event->categoriesStr());
}
}
void KIncidenceFormatter::addTag(const QString & tag,const QString & text)
{
int number=text.contains("\n");
QString str = "<" + tag + ">";
QString tmpText=text;
QString tmpStr=str;
if(number !=-1)
{
if (number > 0) {
int pos=0;
QString tmp;
for(int i=0;i<=number;i++) {
pos=tmpText.find("\n");
tmp=tmpText.left(pos);
tmpText=tmpText.right(tmpText.length()-pos-1);
tmpStr+=tmp+"<br>";
}
}
else tmpStr += tmpText;
tmpStr+="</" + tag + ">";
mText.append(tmpStr);
}
else
{
str += text + "</" + tag + ">";
mText.append(str);
}
}
void KIncidenceFormatter::formatAttendees(Incidence *event)
{
QPtrList<Attendee> attendees = event->attendees();
if (attendees.count()) {
QString iconPath = KGlobal::iconLoader()->iconPath("mailappt",KIcon::Small);
QString NOiconPath = KGlobal::iconLoader()->iconPath("nomailappt",KIcon::Small);
addTag("h3",i18n("Organizer"));
mText.append("<ul><li>");
#if 0
//ndef KORG_NOKABC
KABC::AddressBook *add_book = KABC::StdAddressBook::self();
KABC::Addressee::List addressList;
addressList = add_book->findByEmail(event->organizer());
KABC::Addressee o = addressList.first();
if (!o.isEmpty() && addressList.size()<2) {
mText += "<a href=\"uid:" + o.uid() + "\">";
mText += o.formattedName();
mText += "</a>\n";
} else {
mText.append(event->organizer());
}
#else
mText.append(event->organizer());
#endif
if (iconPath) {
mText += " <a href=\"mailto:" + event->organizer() + "\">";
mText += "<IMG src=\"" + iconPath + "\">";
mText += "</a>\n";
}
mText.append("</li></ul>");
addTag("h3",i18n("Attendees"));
Attendee *a;
mText.append("<ul>");
for(a=attendees.first();a;a=attendees.next()) {
#if 0
//ndef KORG_NOKABC
if (a->name().isEmpty()) {
addressList = add_book->findByEmail(a->email());
KABC::Addressee o = addressList.first();
if (!o.isEmpty() && addressList.size()<2) {
mText += "<a href=\"uid:" + o.uid() + "\">";
mText += o.formattedName();
mText += "</a>\n";
} else {
mText += "<li>";
mText.append(a->email());
mText += "\n";
}
} else {
mText += "<li><a href=\"uid:" + a->uid() + "\">";
if (!a->name().isEmpty()) mText += a->name();
else mText += a->email();
mText += "</a>\n";
}
#else
//qDebug("nokabc ");
mText += "<li><a href=\"uid:" + a->uid() + "\">";
if (!a->name().isEmpty()) mText += a->name();
else mText += a->email();
mText += "</a>\n";
#endif
if (!a->email().isEmpty()) {
if (iconPath) {
mText += "<a href=\"mailto:" + a->name() +" "+ "<" + a->email() + ">" + "\">";
if ( a->RSVP() )
mText += "<IMG src=\"" + iconPath + "\">";
else
mText += "<IMG src=\"" + NOiconPath + "\">";
mText += "</a>\n";
}
}
if (a->status() != Attendee::NeedsAction )
mText +="[" + a->statusStr() + "] ";
if (a->role() == Attendee::Chair )
mText +="(" + a->roleStr().left(1) + ".)";
}
mText.append("</li></ul>");
}
}
void KIncidenceFormatter::formatReadOnly(Incidence *event)
{
if (event->isReadOnly()) {
addTag("p","<em>(" + i18n("read-only") + ")</em>");
}
}
QString KIncidenceFormatter::deTag(QString text)
{
#if QT_VERSION >= 0x030000
text.replace( '<' , "&lt;" );
text.replace( '>' , "&gt;" );
#else
if ( text.find ('<') >= 0 ) {
text.replace( QRegExp("<") , "&lt;" );
}
if ( text.find ('>') >= 0 ) {
text.replace( QRegExp(">") , "&gt;" );
}
#endif
return text;
}
diff --git a/libkcal/vcalformat.cpp b/libkcal/vcalformat.cpp
index 8efc1ea..2e19740 100644
--- a/libkcal/vcalformat.cpp
+++ b/libkcal/vcalformat.cpp
@@ -1,1715 +1,1715 @@
/*
This file is part of libkcal.
Copyright (c) 1998 Preston Brwon
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 <qapplication.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qptrlist.h>
#include <qregexp.h>
#include <qclipboard.h>
#include <qdialog.h>
#include <qfile.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kmessagebox.h>
#include <kiconloader.h>
#include <klocale.h>
#include "vcc.h"
#include "vobject.h"
#include "vcaldrag.h"
#include "calendar.h"
#include "vcalformat.h"
using namespace KCal;
VCalFormat::VCalFormat()
{
mCalendar = 0;
useLocalTime = false;
}
VCalFormat::~VCalFormat()
{
}
void VCalFormat::setLocalTime ( bool b )
{
useLocalTime = b;
}
bool VCalFormat::load(Calendar *calendar, const QString &fileName)
{
mCalendar = calendar;
clearException();
if ( ! useLocalTime )
useLocalTime = mCalendar->isLocalTime();
VObject *vcal = 0;
// this is not necessarily only 1 vcal. Could be many vcals, or include
// a vcard...
vcal = Parse_MIME_FromFileName(const_cast<char *>(QFile::encodeName(fileName).data()));
if (!vcal) {
setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
return FALSE;
}
// any other top-level calendar stuff should be added/initialized here
// put all vobjects into their proper places
populate(vcal);
// clean up from vcal API stuff
cleanVObjects(vcal);
cleanStrTbl();
return true;
}
bool VCalFormat::save(Calendar *calendar, const QString &fileName)
{
mCalendar = calendar;
if ( ! useLocalTime )
useLocalTime = mCalendar->isLocalTime();
QString tmpStr;
VObject *vcal, *vo;
vcal = newVObject(VCCalProp);
// addPropValue(vcal,VCLocationProp, "0.0");
addPropValue(vcal,VCProdIdProp, productId());
tmpStr = mCalendar->getTimeZoneStr();
//qDebug("mCalendar->getTimeZoneStr() %s",tmpStr.latin1() );
addPropValue(vcal,VCTimeZoneProp, tmpStr.local8Bit());
addPropValue(vcal,VCVersionProp, _VCAL_VERSION);
// TODO STUFF
QPtrList<Todo> todoList = mCalendar->rawTodos();
QPtrListIterator<Todo> qlt(todoList);
for (; qlt.current(); ++qlt) {
vo = eventToVTodo(qlt.current());
addVObjectProp(vcal, vo);
}
// EVENT STUFF
QPtrList<Event> events = mCalendar->rawEvents();
Event *ev;
for(ev=events.first();ev;ev=events.next()) {
vo = eventToVEvent(ev);
addVObjectProp(vcal, vo);
}
writeVObjectToFile(QFile::encodeName(fileName).data() ,vcal);
cleanVObjects(vcal);
cleanStrTbl();
if (QFile::exists(fileName)) {
return true;
} else {
return false; // error
}
}
bool VCalFormat::fromString( Calendar *calendar, const QString &text )
{
// TODO: Factor out VCalFormat::fromString()
QCString data = text.utf8();
if ( !data.size() ) return false;
VObject *vcal = Parse_MIME( data.data(), data.size());
if ( !vcal ) return false;
VObjectIterator i;
VObject *curvo;
initPropIterator( &i, vcal );
// we only take the first object. TODO: parse all incidences.
do {
curvo = nextVObject( &i );
} while ( strcmp( vObjectName( curvo ), VCEventProp ) &&
strcmp( vObjectName( curvo ), VCTodoProp ) );
if ( strcmp( vObjectName( curvo ), VCEventProp ) == 0 ) {
Event *event = VEventToEvent( curvo );
calendar->addEvent( event );
} else {
qDebug("VCalFormat::fromString(): Unknown object type. ");
deleteVObject( vcal );
return false;
}
deleteVObject( vcal );
return true;
}
QString VCalFormat::eventToString( Event * event, Calendar *calendar, bool useLocal)
{
if ( !event ) return QString::null;
bool useL = useLocalTime;
useLocalTime = useLocal;
mCalendar = calendar;
VObject *vevent = eventToVEvent( event );
char *buf = writeMemVObject( 0, 0, vevent );
QString result( buf );
cleanVObject( vevent );
useLocalTime = useL;
return result;
}
QString VCalFormat::todoToString( Todo * todo, Calendar *calendar, bool useLocal )
{
if ( !todo ) return QString::null;
bool useL = useLocalTime;
useLocalTime = useLocal;
mCalendar = calendar;
VObject *vevent = eventToVTodo( todo );
char *buf = writeMemVObject( 0, 0, vevent );
QString result( buf );
cleanVObject( vevent );
useLocalTime = useL;
return result;
}
QString VCalFormat::toString( Calendar *calendar )
{
// TODO: Factor out VCalFormat::asString()
VObject *vcal = newVObject(VCCalProp);
addPropValue( vcal, VCProdIdProp, CalFormat::productId() );
QString tmpStr = mCalendar->getTimeZoneStr();
addPropValue( vcal, VCTimeZoneProp, tmpStr.local8Bit() );
addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
// TODO: Use all data.
QPtrList<Event> events = calendar->events();
Event *event = events.first();
if ( !event ) return QString::null;
VObject *vevent = eventToVEvent( event );
addVObjectProp( vcal, vevent );
char *buf = writeMemVObject( 0, 0, vcal );
QString result( buf );
cleanVObject( vcal );
return result;
}
VObject *VCalFormat::eventToVTodo(const Todo *anEvent)
{
VObject *vtodo;
QString tmpStr;
vtodo = newVObject(VCTodoProp);
// due date
if (anEvent->hasDueDate()) {
tmpStr = qDateTimeToISO(anEvent->dtDue(),
!anEvent->doesFloat());
addPropValue(vtodo, VCDueProp, tmpStr.local8Bit());
}
// start date
if (anEvent->hasStartDate()) {
tmpStr = qDateTimeToISO(anEvent->dtStart(),
!anEvent->doesFloat());
addPropValue(vtodo, VCDTstartProp, tmpStr.local8Bit());
}
// creation date
tmpStr = qDateTimeToISO(anEvent->created());
addPropValue(vtodo, VCDCreatedProp, tmpStr.local8Bit());
// unique id
addPropValue(vtodo, VCUniqueStringProp,
anEvent->uid().local8Bit());
// revision
tmpStr.sprintf("%i", anEvent->revision());
addPropValue(vtodo, VCSequenceProp, tmpStr.local8Bit());
// last modification date
tmpStr = qDateTimeToISO(anEvent->lastModified());
addPropValue(vtodo, VCLastModifiedProp, tmpStr.local8Bit());
// organizer stuff
tmpStr = "MAILTO:" + anEvent->organizer();
addPropValue(vtodo, ICOrganizerProp, tmpStr.local8Bit());
// attendees
if (anEvent->attendeeCount() != 0) {
QPtrList<Attendee> al = anEvent->attendees();
QPtrListIterator<Attendee> ai(al);
Attendee *curAttendee;
for (; ai.current(); ++ai) {
curAttendee = ai.current();
if (!curAttendee->email().isEmpty() &&
!curAttendee->name().isEmpty())
tmpStr = "MAILTO:" + curAttendee->name() + " <" +
curAttendee->email() + ">";
else if (curAttendee->name().isEmpty())
tmpStr = "MAILTO: " + curAttendee->email();
else if (curAttendee->email().isEmpty())
tmpStr = "MAILTO: " + curAttendee->name();
else if (curAttendee->name().isEmpty() &&
curAttendee->email().isEmpty())
kdDebug(5800) << "warning! this Event has an attendee w/o name or email!" << endl;
VObject *aProp = addPropValue(vtodo, VCAttendeeProp, tmpStr.local8Bit());
addPropValue(aProp, VCRoleProp, writeRole(curAttendee->role()));
addPropValue(aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE");
addPropValue(aProp, VCStatusProp, writeStatus(curAttendee->status()));
}
}
// description BL:
if (!anEvent->description().isEmpty()) {
VObject *d = addPropValue(vtodo, VCDescriptionProp,
anEvent->description().local8Bit());
if (anEvent->description().find('\n') != -1)
addProp(d, VCQuotedPrintableProp);
}
// summary
if (!anEvent->summary().isEmpty())
addPropValue(vtodo, VCSummaryProp, anEvent->summary().local8Bit());
if (!anEvent->location().isEmpty())
addPropValue(vtodo, VCLocationProp, anEvent->location().local8Bit());
// completed
// status
// backward compatibility, KOrganizer used to interpret only these two values
addPropValue(vtodo, VCStatusProp, anEvent->isCompleted() ? "COMPLETED" :
"NEEDS_ACTION");
// completion date
if (anEvent->hasCompletedDate()) {
tmpStr = qDateTimeToISO(anEvent->completed());
addPropValue(vtodo, VCCompletedProp, tmpStr.local8Bit());
}
// priority
tmpStr.sprintf("%i",anEvent->priority());
addPropValue(vtodo, VCPriorityProp, tmpStr.local8Bit());
// related event
if (anEvent->relatedToUid()) {
addPropValue(vtodo, VCRelatedToProp,
anEvent->relatedToUid().local8Bit());
}
// categories
QStringList tmpStrList = anEvent->categories();
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);
addPropValue(vtodo, VCCategoriesProp, tmpStr.local8Bit());
}
// alarm stuff
kdDebug(5800) << "vcalformat::eventToVTodo was called" << endl;
QPtrList<Alarm> alarms = anEvent->alarms();
Alarm* alarm;
for (alarm = alarms.first(); alarm; alarm = alarms.next()) {
if (alarm->enabled()) {
VObject *a;
tmpStr = qDateTimeToISO(alarm->time());
if (alarm->type() == Alarm::Audio) {
a = addProp(vtodo, VCAAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCAudioContentProp, QFile::encodeName(alarm->audioFile()));
}
else if (alarm->type() == Alarm::Procedure) {
a = addProp(vtodo, VCPAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCProcedureNameProp, QFile::encodeName(alarm->programFile()));
} else {
a = addProp(vtodo, VCDAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCDisplayStringProp, "beep!");
}
}
}
if (anEvent->pilotId()) {
// pilot sync stuff
tmpStr.sprintf("%i",anEvent->pilotId());
addPropValue(vtodo, XPilotIdProp, tmpStr.local8Bit());
tmpStr.sprintf("%i",anEvent->syncStatus());
addPropValue(vtodo, XPilotStatusProp, tmpStr.local8Bit());
}
return vtodo;
}
-VObject* VCalFormat::eventToVEvent(const Event *anEvent)
+VObject* VCalFormat::eventToVEvent(Event *anEvent)
{
VObject *vevent;
QString tmpStr;
vevent = newVObject(VCEventProp);
// start and end time
tmpStr = qDateTimeToISO(anEvent->dtStart(),
!anEvent->doesFloat());
addPropValue(vevent, VCDTstartProp, tmpStr.local8Bit());
// events that have time associated but take up no time should
// not have both DTSTART and DTEND.
if (anEvent->dtStart() != anEvent->dtEnd()) {
tmpStr = qDateTimeToISO(anEvent->dtEnd(),
!anEvent->doesFloat());
addPropValue(vevent, VCDTendProp, tmpStr.local8Bit());
}
// creation date
tmpStr = qDateTimeToISO(anEvent->created());
addPropValue(vevent, VCDCreatedProp, tmpStr.local8Bit());
// unique id
addPropValue(vevent, VCUniqueStringProp,
anEvent->uid().local8Bit());
// revision
tmpStr.sprintf("%i", anEvent->revision());
addPropValue(vevent, VCSequenceProp, tmpStr.local8Bit());
// last modification date
tmpStr = qDateTimeToISO(anEvent->lastModified());
addPropValue(vevent, VCLastModifiedProp, tmpStr.local8Bit());
// attendee and organizer stuff
tmpStr = "MAILTO:" + anEvent->organizer();
addPropValue(vevent, ICOrganizerProp, tmpStr.local8Bit());
if (anEvent->attendeeCount() != 0) {
QPtrList<Attendee> al = anEvent->attendees();
QPtrListIterator<Attendee> ai(al);
Attendee *curAttendee;
// TODO: Put this functionality into Attendee class
for (; ai.current(); ++ai) {
curAttendee = ai.current();
if (!curAttendee->email().isEmpty() &&
!curAttendee->name().isEmpty())
tmpStr = "MAILTO:" + curAttendee->name() + " <" +
curAttendee->email() + ">";
else if (curAttendee->name().isEmpty())
tmpStr = "MAILTO: " + curAttendee->email();
else if (curAttendee->email().isEmpty())
tmpStr = "MAILTO: " + curAttendee->name();
else if (curAttendee->name().isEmpty() &&
curAttendee->email().isEmpty())
kdDebug(5800) << "warning! this Event has an attendee w/o name or email!" << endl;
VObject *aProp = addPropValue(vevent, VCAttendeeProp, tmpStr.local8Bit());
addPropValue(aProp, VCRoleProp, writeRole(curAttendee->role()));
addPropValue(aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE");
addPropValue(aProp, VCStatusProp, writeStatus(curAttendee->status()));
}
}
// recurrence rule stuff
- if (anEvent->recurrence()->doesRecur()) {
+ if (anEvent->doesRecur()) {
// some more variables
QPtrList<Recurrence::rMonthPos> tmpPositions;
QPtrList<int> tmpDays;
int *tmpDay;
Recurrence::rMonthPos *tmpPos;
QString tmpStr2;
int i;
switch(anEvent->recurrence()->doesRecur()) {
case Recurrence::rDaily:
tmpStr.sprintf("D%i ",anEvent->recurrence()->frequency());
// if (anEvent->rDuration > 0)
// tmpStr += "#";
break;
case Recurrence::rWeekly:
tmpStr.sprintf("W%i ",anEvent->recurrence()->frequency());
for (i = 0; i < 7; i++) {
if (anEvent->recurrence()->days().testBit(i))
tmpStr += dayFromNum(i);
}
break;
case Recurrence::rMonthlyPos:
tmpStr.sprintf("MP%i ", anEvent->recurrence()->frequency());
// write out all rMonthPos's
tmpPositions = anEvent->recurrence()->monthPositions();
for (tmpPos = tmpPositions.first();
tmpPos;
tmpPos = tmpPositions.next()) {
tmpStr2.sprintf("%i", tmpPos->rPos);
if (tmpPos->negative)
tmpStr2 += "- ";
else
tmpStr2 += "+ ";
tmpStr += tmpStr2;
for (i = 0; i < 7; i++) {
if (tmpPos->rDays.testBit(i))
tmpStr += dayFromNum(i);
}
} // loop for all rMonthPos's
break;
case Recurrence::rMonthlyDay:
tmpStr.sprintf("MD%i ", anEvent->recurrence()->frequency());
// write out all rMonthDays;
tmpDays = anEvent->recurrence()->monthDays();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
tmpStr2.sprintf("%i ", *tmpDay);
tmpStr += tmpStr2;
}
break;
case Recurrence::rYearlyMonth:
tmpStr.sprintf("YM%i ", anEvent->recurrence()->frequency());
// write out all the rYearNums;
tmpDays = anEvent->recurrence()->yearNums();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
tmpStr2.sprintf("%i ", *tmpDay);
tmpStr += tmpStr2;
}
break;
case Recurrence::rYearlyDay:
tmpStr.sprintf("YD%i ", anEvent->recurrence()->frequency());
// write out all the rYearNums;
tmpDays = anEvent->recurrence()->yearNums();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
tmpStr2.sprintf("%i ", *tmpDay);
tmpStr += tmpStr2;
}
break;
default:
kdDebug(5800) << "ERROR, it should never get here in eventToVEvent!" << endl;
break;
} // switch
if (anEvent->recurrence()->duration() > 0) {
tmpStr2.sprintf("#%i",anEvent->recurrence()->duration());
tmpStr += tmpStr2;
} else if (anEvent->recurrence()->duration() == -1) {
tmpStr += "#0"; // defined as repeat forever
} else {
tmpStr += qDateTimeToISO(anEvent->recurrence()->endDate(), FALSE);
}
addPropValue(vevent,VCRRuleProp, tmpStr.local8Bit());
} // event repeats
// exceptions to recurrence
DateList dateList = anEvent->exDates();
DateList::ConstIterator it;
QString tmpStr2;
for (it = dateList.begin(); it != dateList.end(); ++it) {
tmpStr = qDateToISO(*it) + ";";
tmpStr2 += tmpStr;
}
if (!tmpStr2.isEmpty()) {
tmpStr2.truncate(tmpStr2.length()-1);
addPropValue(vevent, VCExpDateProp, tmpStr2.local8Bit());
}
// description
if (!anEvent->description().isEmpty()) {
VObject *d = addPropValue(vevent, VCDescriptionProp,
anEvent->description().local8Bit());
if (anEvent->description().find('\n') != -1)
addProp(d, VCQuotedPrintableProp);
}
// summary
if (!anEvent->summary().isEmpty())
addPropValue(vevent, VCSummaryProp, anEvent->summary().local8Bit());
if (!anEvent->location().isEmpty())
addPropValue(vevent, VCLocationProp, anEvent->location().local8Bit());
// status
// TODO: define Event status
// addPropValue(vevent, VCStatusProp, anEvent->statusStr().local8Bit());
// secrecy
const char *text = 0;
switch (anEvent->secrecy()) {
case Incidence::SecrecyPublic:
text = "PUBLIC";
break;
case Incidence::SecrecyPrivate:
text = "PRIVATE";
break;
case Incidence::SecrecyConfidential:
text = "CONFIDENTIAL";
break;
}
if (text) {
addPropValue(vevent, VCClassProp, text);
}
// categories
QStringList tmpStrList = anEvent->categories();
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);
addPropValue(vevent, VCCategoriesProp, tmpStr.local8Bit());
}
// attachments
// TODO: handle binary attachments!
QPtrList<Attachment> attachments = anEvent->attachments();
for ( Attachment *at = attachments.first(); at; at = attachments.next() )
addPropValue(vevent, VCAttachProp, at->uri().local8Bit());
// resources
tmpStrList = anEvent->resources();
tmpStr = tmpStrList.join(";");
if (!tmpStr.isEmpty())
addPropValue(vevent, VCResourcesProp, tmpStr.local8Bit());
// alarm stuff
QPtrList<Alarm> alarms = anEvent->alarms();
Alarm* alarm;
for (alarm = alarms.first(); alarm; alarm = alarms.next()) {
if (alarm->enabled()) {
VObject *a ;
tmpStr = qDateTimeToISO(alarm->time());
if (alarm->type() == Alarm::Audio) {
a = addProp(vevent, VCAAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCAudioContentProp, QFile::encodeName(alarm->audioFile()));
}
if (alarm->type() == Alarm::Procedure) {
a = addProp(vevent, VCPAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCProcedureNameProp, QFile::encodeName(alarm->programFile()));
} else {
a = addProp(vevent, VCDAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCDisplayStringProp, "beep!");
}
}
}
// priority
tmpStr.sprintf("%i",anEvent->priority());
addPropValue(vevent, VCPriorityProp, tmpStr.local8Bit());
// transparency
tmpStr.sprintf("%i",anEvent->transparency());
addPropValue(vevent, VCTranspProp, tmpStr.local8Bit());
// related event
if (anEvent->relatedToUid()) {
addPropValue(vevent, VCRelatedToProp,
anEvent->relatedToUid().local8Bit());
}
if (anEvent->pilotId()) {
// pilot sync stuff
tmpStr.sprintf("%i",anEvent->pilotId());
addPropValue(vevent, XPilotIdProp, tmpStr.local8Bit());
tmpStr.sprintf("%i",anEvent->syncStatus());
addPropValue(vevent, XPilotStatusProp, tmpStr.local8Bit());
}
return vevent;
}
Todo *VCalFormat::VTodoToEvent(VObject *vtodo)
{
VObject *vo;
VObjectIterator voi;
char *s;
Todo *anEvent = new Todo;
// creation date
if ((vo = isAPropertyOf(vtodo, VCDCreatedProp)) != 0) {
anEvent->setCreated(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// unique id
vo = isAPropertyOf(vtodo, VCUniqueStringProp);
// while the UID property is preferred, it is not required. We'll use the
// default Event UID if none is given.
if (vo) {
anEvent->setUid(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
// last modification date
if ((vo = isAPropertyOf(vtodo, VCLastModifiedProp)) != 0) {
anEvent->setLastModified(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setLastModified(QDateTime(QDate::currentDate(),
QTime::currentTime()));
// organizer
// if our extension property for the event's ORGANIZER exists, add it.
if ((vo = isAPropertyOf(vtodo, ICOrganizerProp)) != 0) {
anEvent->setOrganizer(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
} else {
anEvent->setOrganizer(mCalendar->getEmail());
}
// attendees.
initPropIterator(&voi, vtodo);
while (moreIteration(&voi)) {
vo = nextVObject(&voi);
if (strcmp(vObjectName(vo), VCAttendeeProp) == 0) {
Attendee *a;
VObject *vp;
s = fakeCString(vObjectUStringZValue(vo));
QString tmpStr = QString::fromLocal8Bit(s);
deleteStr(s);
tmpStr = tmpStr.simplifyWhiteSpace();
int emailPos1, emailPos2;
if ((emailPos1 = tmpStr.find('<')) > 0) {
// both email address and name
emailPos2 = tmpStr.findRev('>');
a = new Attendee(tmpStr.left(emailPos1 - 1),
tmpStr.mid(emailPos1 + 1,
emailPos2 - (emailPos1 + 1)));
} else if (tmpStr.find('@') > 0) {
// just an email address
a = new Attendee(0, tmpStr);
} else {
// just a name
// QString email = tmpStr.replace( QRegExp(" "), "." );
a = new Attendee(tmpStr,0);
}
// is there a Role property?
if ((vp = isAPropertyOf(vo, VCRoleProp)) != 0)
a->setRole(readRole(vObjectStringZValue(vp)));
// is there an RSVP property?
if ((vp = isAPropertyOf(vo, VCRSVPProp)) != 0)
a->setRSVP(vObjectStringZValue(vp));
// is there a status property?
if ((vp = isAPropertyOf(vo, VCStatusProp)) != 0)
a->setStatus(readStatus(vObjectStringZValue(vp)));
// add the attendee
anEvent->addAttendee(a);
}
}
// description for todo
if ((vo = isAPropertyOf(vtodo, VCDescriptionProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setDescription(QString::fromLocal8Bit(s));
deleteStr(s);
}
// summary
if ((vo = isAPropertyOf(vtodo, VCSummaryProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setSummary(QString::fromLocal8Bit(s));
deleteStr(s);
}
if ((vo = isAPropertyOf(vtodo, VCLocationProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setLocation(QString::fromLocal8Bit(s));
deleteStr(s);
}
// completed
// was: status
if ((vo = isAPropertyOf(vtodo, VCStatusProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
if (strcmp(s,"COMPLETED") == 0) {
anEvent->setCompleted(true);
} else {
anEvent->setCompleted(false);
}
deleteStr(s);
}
else
anEvent->setCompleted(false);
// completion date
if ((vo = isAPropertyOf(vtodo, VCCompletedProp)) != 0) {
anEvent->setCompleted(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// priority
if ((vo = isAPropertyOf(vtodo, VCPriorityProp))) {
anEvent->setPriority(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// due date
if ((vo = isAPropertyOf(vtodo, VCDueProp)) != 0) {
anEvent->setDtDue(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
anEvent->setHasDueDate(true);
} else {
anEvent->setHasDueDate(false);
}
// start time
if ((vo = isAPropertyOf(vtodo, VCDTstartProp)) != 0) {
anEvent->setDtStart(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
// kdDebug(5800) << "s is " << // s << ", ISO is " << ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))).toString() << endl;
deleteStr(s);
anEvent->setHasStartDate(true);
} else {
anEvent->setHasStartDate(false);
}
/* alarm stuff */
//kdDebug(5800) << "vcalformat::VTodoToEvent called" << endl;
if ((vo = isAPropertyOf(vtodo, VCDAlarmProp))) {
Alarm* alarm = anEvent->newAlarm();
VObject *a;
if ((a = isAPropertyOf(vo, VCRunTimeProp))) {
alarm->setTime(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(a))));
deleteStr(s);
}
alarm->setEnabled(true);
if ((vo = isAPropertyOf(vtodo, VCPAlarmProp))) {
if ((a = isAPropertyOf(vo, VCProcedureNameProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setProcedureAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
if ((vo = isAPropertyOf(vtodo, VCAAlarmProp))) {
if ((a = isAPropertyOf(vo, VCAudioContentProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setAudioAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
}
// related todo
if ((vo = isAPropertyOf(vtodo, VCRelatedToProp)) != 0) {
anEvent->setRelatedToUid(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
mTodosRelate.append(anEvent);
}
// categories
if ((vo = isAPropertyOf(vtodo, VCCategoriesProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
QString categories = QString::fromLocal8Bit(s);
deleteStr(s);
QStringList tmpStrList = QStringList::split( ';', categories );
anEvent->setCategories(tmpStrList);
}
/* PILOT SYNC STUFF */
if ((vo = isAPropertyOf(vtodo, XPilotIdProp))) {
anEvent->setPilotId(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setPilotId(0);
if ((vo = isAPropertyOf(vtodo, XPilotStatusProp))) {
anEvent->setSyncStatus(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setSyncStatus(Event::SYNCMOD);
return anEvent;
}
Event* VCalFormat::VEventToEvent(VObject *vevent)
{
VObject *vo;
VObjectIterator voi;
char *s;
Event *anEvent = new Event;
// creation date
if ((vo = isAPropertyOf(vevent, VCDCreatedProp)) != 0) {
anEvent->setCreated(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// unique id
vo = isAPropertyOf(vevent, VCUniqueStringProp);
// while the UID property is preferred, it is not required. We'll use the
// default Event UID if none is given.
if (vo) {
anEvent->setUid(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
// revision
// again NSCAL doesn't give us much to work with, so we improvise...
if ((vo = isAPropertyOf(vevent, VCSequenceProp)) != 0) {
anEvent->setRevision(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setRevision(0);
// last modification date
if ((vo = isAPropertyOf(vevent, VCLastModifiedProp)) != 0) {
anEvent->setLastModified(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setLastModified(QDateTime(QDate::currentDate(),
QTime::currentTime()));
// organizer
// if our extension property for the event's ORGANIZER exists, add it.
if ((vo = isAPropertyOf(vevent, ICOrganizerProp)) != 0) {
anEvent->setOrganizer(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
} else {
anEvent->setOrganizer(mCalendar->getEmail());
}
// deal with attendees.
initPropIterator(&voi, vevent);
while (moreIteration(&voi)) {
vo = nextVObject(&voi);
if (strcmp(vObjectName(vo), VCAttendeeProp) == 0) {
Attendee *a;
VObject *vp;
s = fakeCString(vObjectUStringZValue(vo));
QString tmpStr = QString::fromLocal8Bit(s);
deleteStr(s);
tmpStr = tmpStr.simplifyWhiteSpace();
int emailPos1, emailPos2;
if ((emailPos1 = tmpStr.find('<')) > 0) {
// both email address and name
emailPos2 = tmpStr.findRev('>');
a = new Attendee(tmpStr.left(emailPos1 - 1),
tmpStr.mid(emailPos1 + 1,
emailPos2 - (emailPos1 + 1)));
} else if (tmpStr.find('@') > 0) {
// just an email address
a = new Attendee(0, tmpStr);
} else {
// just a name
//QString email = tmpStr.replace( QRegExp(" "), "." );
a = new Attendee(tmpStr,0);
}
// is there a Role property?
if ((vp = isAPropertyOf(vo, VCRoleProp)) != 0)
a->setRole(readRole(vObjectStringZValue(vp)));
// is there an RSVP property?
if ((vp = isAPropertyOf(vo, VCRSVPProp)) != 0)
a->setRSVP(vObjectStringZValue(vp));
// is there a status property?
if ((vp = isAPropertyOf(vo, VCStatusProp)) != 0)
a->setStatus(readStatus(vObjectStringZValue(vp)));
// add the attendee
anEvent->addAttendee(a);
}
}
// This isn't strictly true. An event that doesn't have a start time
// or an end time doesn't "float", it has an anchor in time but it doesn't
// "take up" any time.
/*if ((isAPropertyOf(vevent, VCDTstartProp) == 0) ||
(isAPropertyOf(vevent, VCDTendProp) == 0)) {
anEvent->setFloats(TRUE);
} else {
}*/
anEvent->setFloats(FALSE);
// start time
if ((vo = isAPropertyOf(vevent, VCDTstartProp)) != 0) {
anEvent->setDtStart(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
// kdDebug(5800) << "s is " << // s << ", ISO is " << ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))).toString() << endl;
deleteStr(s);
if (anEvent->dtStart().time().isNull())
anEvent->setFloats(TRUE);
}
// stop time
if ((vo = isAPropertyOf(vevent, VCDTendProp)) != 0) {
anEvent->setDtEnd(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
if (anEvent->dtEnd().time().isNull())
anEvent->setFloats(TRUE);
}
// 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 (!(vo = isAPropertyOf(vevent, VCDTstartProp)))
anEvent->setDtStart(anEvent->dtEnd());
if (!(vo = isAPropertyOf(vevent, VCDTendProp)))
anEvent->setDtEnd(anEvent->dtStart());
///////////////////////////////////////////////////////////////////////////
// repeat stuff
if ((vo = isAPropertyOf(vevent, VCRRuleProp)) != 0) {
QString tmpStr = (s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
tmpStr.simplifyWhiteSpace();
tmpStr = tmpStr.upper();
/********************************* DAILY ******************************/
if (tmpStr.left(1) == "D") {
int index = tmpStr.find(' ');
int rFreq = tmpStr.mid(1, (index-1)).toInt();
index = tmpStr.findRev(' ') + 1; // advance to last field
if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setDaily(rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0) // VEvents set this to 0 forever, we use -1
anEvent->recurrence()->setDaily(rFreq, -1);
else
anEvent->recurrence()->setDaily(rFreq, rDuration);
}
}
/********************************* WEEKLY ******************************/
else if (tmpStr.left(1) == "W") {
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(1, (index-1)).toInt();
index += 1; // advance to beginning of stuff after freq
QBitArray qba(7);
QString dayStr;
if( index == last ) {
// e.g. W1 #0
qba.setBit(anEvent->dtStart().date().dayOfWeek() - 1);
}
else {
// e.g. W1 SU #0
while (index < last) {
dayStr = tmpStr.mid(index, 3);
int dayNum = numFromDay(dayStr);
qba.setBit(dayNum);
index += 3; // advance to next day, or possibly "#"
}
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setWeekly(rFreq, qba, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setWeekly(rFreq, qba, -1);
else
anEvent->recurrence()->setWeekly(rFreq, qba, rDuration);
}
}
/**************************** MONTHLY-BY-POS ***************************/
else if (tmpStr.left(2) == "MP") {
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(2, (index-1)).toInt();
index += 1; // advance to beginning of stuff after freq
QBitArray qba(7);
short tmpPos;
if( index == last ) {
// e.g. MP1 #0
tmpPos = anEvent->dtStart().date().day()/7 + 1;
if( tmpPos == 5 )
tmpPos = -1;
qba.setBit(anEvent->dtStart().date().dayOfWeek() - 1);
anEvent->recurrence()->addMonthlyPos(tmpPos, qba);
}
else {
// e.g. MP1 1+ SU #0
while (index < last) {
tmpPos = tmpStr.mid(index,1).toShort();
index += 1;
if (tmpStr.mid(index,1) == "-")
// convert tmpPos to negative
tmpPos = 0 - tmpPos;
index += 2; // advance to day(s)
while (numFromDay(tmpStr.mid(index,3)) >= 0) {
int dayNum = numFromDay(tmpStr.mid(index,3));
qba.setBit(dayNum);
index += 3; // advance to next day, or possibly pos or "#"
}
anEvent->recurrence()->addMonthlyPos(tmpPos, qba);
qba.detach();
qba.fill(FALSE); // clear out
} // while != "#"
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length() -
index))).date();
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, -1);
else
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, rDuration);
}
}
/**************************** MONTHLY-BY-DAY ***************************/
else if (tmpStr.left(2) == "MD") {
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(2, (index-1)).toInt();
index += 1;
short tmpDay;
if( index == last ) {
// e.g. MD1 #0
tmpDay = anEvent->dtStart().date().day();
anEvent->recurrence()->addMonthlyDay(tmpDay);
}
else {
// e.g. MD1 3 #0
while (index < last) {
int index2 = tmpStr.find(' ', index);
tmpDay = tmpStr.mid(index, (index2-index)).toShort();
index = index2-1;
if (tmpStr.mid(index, 1) == "-")
tmpDay = 0 - tmpDay;
index += 2; // advance the index;
anEvent->recurrence()->addMonthlyDay(tmpDay);
} // while != #
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, -1);
else
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, rDuration);
}
}
/*********************** YEARLY-BY-MONTH *******************************/
else if (tmpStr.left(2) == "YM") {
// we have to set this such that recurrence accepts addYearlyNum(tmpDay);
anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, 1, -1);
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(2, (index-1)).toInt();
index += 1;
short tmpMonth;
if( index == last ) {
// e.g. YM1 #0
tmpMonth = anEvent->dtStart().date().month();
anEvent->recurrence()->addYearlyNum(tmpMonth);
}
else {
// e.g. YM1 3 #0
while (index < last) {
int index2 = tmpStr.find(' ', index);
tmpMonth = tmpStr.mid(index, (index2-index)).toShort();
index = index2+1;
anEvent->recurrence()->addYearlyNum(tmpMonth);
} // while != #
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, -1);
else
anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rDuration);
}
}
/*********************** YEARLY-BY-DAY *********************************/
else if (tmpStr.left(2) == "YD") {
// we have to set this such that recurrence accepts addYearlyNum(tmpDay);
anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, 1, -1);
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(2, (index-1)).toInt();
index += 1;
short tmpDay;
if( index == last ) {
// e.g. YD1 #0
tmpDay = anEvent->dtStart().date().dayOfYear();
anEvent->recurrence()->addYearlyNum(tmpDay);
}
else {
// e.g. YD1 123 #0
while (index < last) {
int index2 = tmpStr.find(' ', index);
tmpDay = tmpStr.mid(index, (index2-index)).toShort();
index = index2+1;
anEvent->recurrence()->addYearlyNum(tmpDay);
} // while != #
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, -1);
else
anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rDuration);
}
} else {
kdDebug(5800) << "we don't understand this type of recurrence!" << endl;
} // if
} // repeats
// recurrence exceptions
if ((vo = isAPropertyOf(vevent, VCExpDateProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
QStringList exDates = QStringList::split(",",s);
QStringList::ConstIterator it;
for(it = exDates.begin(); it != exDates.end(); ++it ) {
anEvent->addExDate(ISOToQDate(*it));
}
deleteStr(s);
}
// summary
if ((vo = isAPropertyOf(vevent, VCSummaryProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setSummary(QString::fromLocal8Bit(s));
deleteStr(s);
}
if ((vo = isAPropertyOf(vevent, VCLocationProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setLocation(QString::fromLocal8Bit(s));
deleteStr(s);
}
// description
if ((vo = isAPropertyOf(vevent, VCDescriptionProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
if (!anEvent->description().isEmpty()) {
anEvent->setDescription(anEvent->description() + "\n" +
QString::fromLocal8Bit(s));
} else {
anEvent->setDescription(QString::fromLocal8Bit(s));
}
deleteStr(s);
}
// some stupid vCal exporters ignore the standard and use Description
// instead of Summary for the default field. Correct for this.
if (anEvent->summary().isEmpty() &&
!(anEvent->description().isEmpty())) {
QString tmpStr = anEvent->description().simplifyWhiteSpace();
anEvent->setDescription("");
anEvent->setSummary(tmpStr);
}
#if 0
// status
if ((vo = isAPropertyOf(vevent, VCStatusProp)) != 0) {
QString tmpStr(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
// TODO: Define Event status
// anEvent->setStatus(tmpStr);
}
else
// anEvent->setStatus("NEEDS ACTION");
#endif
// secrecy
int secrecy = Incidence::SecrecyPublic;
if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
if (strcmp(s,"PRIVATE") == 0) {
secrecy = Incidence::SecrecyPrivate;
} else if (strcmp(s,"CONFIDENTIAL") == 0) {
secrecy = Incidence::SecrecyConfidential;
}
deleteStr(s);
}
anEvent->setSecrecy(secrecy);
// categories
QStringList tmpStrList;
if ((vo = isAPropertyOf(vevent, VCCategoriesProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
QString categories = QString::fromLocal8Bit(s);
deleteStr(s);
tmpStrList = QStringList::split( ';', categories );
anEvent->setCategories(tmpStrList);
}
// attachments
initPropIterator(&voi, vevent);
while (moreIteration(&voi)) {
vo = nextVObject(&voi);
if (strcmp(vObjectName(vo), VCAttachProp) == 0) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->addAttachment(new Attachment(QString(s)));
deleteStr(s);
}
}
// resources
if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) {
QString resources = (s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
tmpStrList = QStringList::split( ';', resources );
anEvent->setResources(tmpStrList);
}
/* alarm stuff */
if ((vo = isAPropertyOf(vevent, VCDAlarmProp))) {
Alarm* alarm = anEvent->newAlarm();
VObject *a;
if ((a = isAPropertyOf(vo, VCRunTimeProp))) {
alarm->setTime(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(a))));
deleteStr(s);
}
alarm->setEnabled(true);
if ((vo = isAPropertyOf(vevent, VCPAlarmProp))) {
if ((a = isAPropertyOf(vo, VCProcedureNameProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setProcedureAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
if ((vo = isAPropertyOf(vevent, VCAAlarmProp))) {
if ((a = isAPropertyOf(vo, VCAudioContentProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setAudioAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
}
// priority
if ((vo = isAPropertyOf(vevent, VCPriorityProp))) {
anEvent->setPriority(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// transparency
if ((vo = isAPropertyOf(vevent, VCTranspProp)) != 0) {
int i = atoi(s = fakeCString(vObjectUStringZValue(vo)));
anEvent->setTransparency( i == 1 ? Event::Transparent : Event::Opaque );
deleteStr(s);
}
// related event
if ((vo = isAPropertyOf(vevent, VCRelatedToProp)) != 0) {
anEvent->setRelatedToUid(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
mEventsRelate.append(anEvent);
}
/* PILOT SYNC STUFF */
if ((vo = isAPropertyOf(vevent, XPilotIdProp))) {
anEvent->setPilotId(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setPilotId(0);
if ((vo = isAPropertyOf(vevent, XPilotStatusProp))) {
anEvent->setSyncStatus(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setSyncStatus(Event::SYNCMOD);
return anEvent;
}
QString VCalFormat::qDateToISO(const QDate &qd)
{
QString tmpStr;
ASSERT(qd.isValid());
tmpStr.sprintf("%.2d%.2d%.2d",
qd.year(), qd.month(), qd.day());
return tmpStr;
}
QString VCalFormat::qDateTimeToISO(const QDateTime &qdt, bool zulu)
{
QString tmpStr;
ASSERT(qdt.date().isValid());
ASSERT(qdt.time().isValid());
if (zulu && !useLocalTime ) {
QDateTime tmpDT = qdt.addSecs ( -KGlobal::locale()->localTimeOffset( qdt )*60);
tmpStr.sprintf("%.2d%.2d%.2dT%.2d%.2d%.2dZ",
tmpDT.date().year(), tmpDT.date().month(),
tmpDT.date().day(), tmpDT.time().hour(),
tmpDT.time().minute(), tmpDT.time().second());
} else {
tmpStr.sprintf("%.2d%.2d%.2dT%.2d%.2d%.2d",
qdt.date().year(), qdt.date().month(),
qdt.date().day(), qdt.time().hour(),
qdt.time().minute(), qdt.time().second());
}
return tmpStr;
}
QDateTime VCalFormat::ISOToQDateTime(const QString & dtStr)
{
QDate tmpDate;
QTime tmpTime;
QString tmpStr;
int year, month, day, hour, minute, second;
tmpStr = dtStr;
year = tmpStr.left(4).toInt();
month = tmpStr.mid(4,2).toInt();
day = tmpStr.mid(6,2).toInt();
hour = tmpStr.mid(9,2).toInt();
minute = tmpStr.mid(11,2).toInt();
second = tmpStr.mid(13,2).toInt();
tmpDate.setYMD(year, month, day);
tmpTime.setHMS(hour, minute, second);
ASSERT(tmpDate.isValid());
ASSERT(tmpTime.isValid());
QDateTime tmpDT(tmpDate, tmpTime);
// correct for GMT if string is in Zulu format
if (dtStr.at(dtStr.length()-1) == 'Z')
tmpDT = tmpDT.addSecs (KGlobal::locale()->localTimeOffset( tmpDT )*60);
return tmpDT;
}
QDate VCalFormat::ISOToQDate(const QString &dateStr)
{
int year, month, day;
year = dateStr.left(4).toInt();
month = dateStr.mid(4,2).toInt();
day = dateStr.mid(6,2).toInt();
return(QDate(year, month, day));
}
// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
// and break it down from it's tree-like format into the dictionary format
// that is used internally in the VCalFormat.
void VCalFormat::populate(VObject *vcal)
{
// this function will populate the caldict dictionary and other event
// lists. It turns vevents into Events and then inserts them.
VObjectIterator i;
VObject *curVO, *curVOProp;
Event *anEvent;
if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) {
char *methodType = 0;
methodType = fakeCString(vObjectUStringZValue(curVO));
kdDebug() << "This calendar is an iTIP transaction of type '"
<< methodType << "'" << endl;
delete methodType;
}
// warn the user that we might have trouble reading non-known calendar.
if ((curVO = isAPropertyOf(vcal, VCProdIdProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVO));
if (strcmp(productId().local8Bit(), s) != 0)
kdDebug() << "This vCalendar file was not created by KOrganizer "
"or any other product we support. Loading anyway..." << endl;
mLoadedProductId = s;
deleteStr(s);
}
// warn the user we might have trouble reading this unknown version.
if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVO));
if (strcmp(_VCAL_VERSION, s) != 0)
kdDebug() << "This vCalendar file has version " << s
<< "We only support " << _VCAL_VERSION << endl;
deleteStr(s);
}
// set the time zone
if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) {
if ( vObjectUStringZValue(curVO) != 0 ) {
char *s = fakeCString(vObjectUStringZValue(curVO));
mCalendar->setTimeZone(s);
deleteStr(s);
}
}
// Store all events with a relatedTo property in a list for post-processing
mEventsRelate.clear();
mTodosRelate.clear();
initPropIterator(&i, vcal);
// go through all the vobjects in the vcal
while (moreIteration(&i)) {
curVO = nextVObject(&i);
/************************************************************************/
// now, check to see that the object is an event or todo.
if (strcmp(vObjectName(curVO), VCEventProp) == 0) {
if ((curVOProp = isAPropertyOf(curVO, XPilotStatusProp)) != 0) {
char *s;
s = fakeCString(vObjectUStringZValue(curVOProp));
// check to see if event was deleted by the kpilot conduit
if (atoi(s) == Event::SYNCDEL) {
deleteStr(s);
kdDebug(5800) << "skipping pilot-deleted event" << endl;
goto SKIP;
}
deleteStr(s);
}
// this code checks to see if we are trying to read in an event
// that we already find to be in the calendar. If we find this
// to be the case, we skip the event.
if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVOProp));
QString tmpStr(s);
deleteStr(s);
if (mCalendar->event(tmpStr)) {
goto SKIP;
}
if (mCalendar->todo(tmpStr)) {
goto SKIP;
}
}
if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) &&
(!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) {
kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl;
goto SKIP;
}
anEvent = VEventToEvent(curVO);
// we now use addEvent instead of insertEvent so that the
// signal/slot get connected.
if (anEvent) {
if ( !anEvent->dtStart().isValid() || !anEvent->dtEnd().isValid() ) {
kdDebug() << "VCalFormat::populate(): Event has invalid dates."
<< endl;
} else {
mCalendar->addEvent(anEvent);
}
} else {
// some sort of error must have occurred while in translation.
goto SKIP;
}
} else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) {
Todo *aTodo = VTodoToEvent(curVO);
mCalendar->addTodo(aTodo);
} else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) ||
(strcmp(vObjectName(curVO), VCProdIdProp) == 0) ||
(strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) {
// do nothing, we know these properties and we want to skip them.
// we have either already processed them or are ignoring them.
;
} else {
kdDebug(5800) << "Ignoring unknown vObject \"" << vObjectName(curVO) << "\"" << endl;
}
SKIP:
;
} // while
// Post-Process list of events with relations, put Event objects in relation
Event *ev;
for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) {
Incidence * inc = mCalendar->event(ev->relatedToUid());
if ( inc )
ev->setRelatedTo( inc );
}
Todo *todo;
for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) {
Incidence * inc = mCalendar->todo(todo->relatedToUid());
if ( inc )
todo->setRelatedTo( inc );
}
}
const char *VCalFormat::dayFromNum(int day)
{
const char *days[7] = { "MO ", "TU ", "WE ", "TH ", "FR ", "SA ", "SU " };
return days[day];
}
int VCalFormat::numFromDay(const QString &day)
{
if (day == "MO ") return 0;
if (day == "TU ") return 1;
if (day == "WE ") return 2;
if (day == "TH ") return 3;
if (day == "FR ") return 4;
if (day == "SA ") return 5;
if (day == "SU ") return 6;
return -1; // something bad happened. :)
}
Attendee::Role VCalFormat::readRole(const char *s) const
{
QString statStr = s;
statStr = statStr.upper();
Attendee::Role role = Attendee::ReqParticipant;
if ( statStr == "OWNER")
role = Attendee::Chair;
// enum Role { ReqParticipant, OptParticipant, NonParticipant, Chair };
return role;
}
QCString VCalFormat::writeRole(Attendee::Role role) const
{
if ( role == Attendee::Chair )
return "OWNER";
return "ATTENDEE";
}
Attendee::PartStat VCalFormat::readStatus(const char *s) const
{
QString statStr = s;
statStr = statStr.upper();
Attendee::PartStat status;
if (statStr == "X-ACTION")
status = Attendee::NeedsAction;
else if (statStr == "NEEDS ACTION")
status = Attendee::NeedsAction;
else if (statStr== "ACCEPTED")
status = Attendee::Accepted;
else if (statStr== "SENT")
status = Attendee::NeedsAction;
else if (statStr== "TENTATIVE")
status = Attendee::Tentative;
else if (statStr== "CONFIRMED")
status = Attendee::Accepted;
else if (statStr== "DECLINED")
status = Attendee::Declined;
else if (statStr== "COMPLETED")
status = Attendee::Completed;
else if (statStr== "DELEGATED")
status = Attendee::Delegated;
else {
kdDebug(5800) << "error setting attendee mStatus, unknown mStatus!" << endl;
status = Attendee::NeedsAction;
}
return status;
}
QCString VCalFormat::writeStatus(Attendee::PartStat status) const
{
switch(status) {
default:
case Attendee::NeedsAction:
return "NEEDS ACTION";
break;
case Attendee::Accepted:
return "ACCEPTED";
break;
case Attendee::Declined:
return "DECLINED";
break;
case Attendee::Tentative:
return "TENTATIVE";
break;
case Attendee::Delegated:
return "DELEGATED";
break;
case Attendee::Completed:
return "COMPLETED";
break;
case Attendee::InProcess:
return "NEEDS ACTION";
break;
}
}
diff --git a/libkcal/vcalformat.h b/libkcal/vcalformat.h
index c7df017..6dae3d2 100644
--- a/libkcal/vcalformat.h
+++ b/libkcal/vcalformat.h
@@ -1,113 +1,113 @@
/*
This file is part of libkcal.
Copyright (c) 1998 Preston Brown
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 _VCALFORMAT_H
#define _VCALFORMAT_H
#include "calformat.h"
#define _VCAL_VERSION "1.0"
class VObject;
namespace KCal {
/**
This class implements the vCalendar format. It provides methods for
loading/saving/converting vCalendar format data into the internal KOrganizer
representation as Calendar and Events.
@short vCalendar format implementation
*/
class VCalFormat : public CalFormat {
public:
VCalFormat();
virtual ~VCalFormat();
/** loads a calendar on disk in vCalendar format into the current calendar.
* any information already present is lost. Returns TRUE if successful,
* else returns FALSE.
* @param fileName the name of the calendar on disk.
*/
bool load(Calendar *,const QString &fileName );
/** writes out the calendar to disk in vCalendar format. Returns true if
* successful and false on error.
* @param fileName the name of the file
*/
bool save(Calendar *,const QString &fileName );
/**
Parse string and populate calendar with that information.
*/
bool fromString( Calendar *, const QString & );
/**
Return calendar information as string.
*/
void setLocalTime ( bool );
QString toString( Calendar * );
QString eventToString( Event *, Calendar *calendar, bool useLocalTime = true );
QString todoToString( Todo * ,Calendar *calendar, bool useLocalTime = true );
protected:
/** translates a VObject of the TODO type into a Event */
Todo *VTodoToEvent(VObject *vtodo);
/** translates a VObject into a Event and returns a pointer to it. */
Event *VEventToEvent(VObject *vevent);
/** translate a Event into a VTodo-type VObject and return pointer */
VObject *eventToVTodo(const Todo *anEvent);
/** translate a Event into a VObject and returns a pointer to it. */
- VObject* eventToVEvent(const Event *anEvent);
+ VObject* eventToVEvent(Event *anEvent);
/** takes a QDate and returns a string in the format YYYYMMDDTHHMMSS */
QString qDateToISO(const QDate &);
/** takes a QDateTime and returns a string in format YYYYMMDDTHHMMSS */
QString qDateTimeToISO(const QDateTime &, bool zulu=TRUE);
/** takes a string in the format YYYYMMDDTHHMMSS and returns a
* valid QDateTime. */
QDateTime ISOToQDateTime(const QString & dtStr);
/** takes a string in the format YYYYMMDD and returns a
* valid QDate. */
QDate ISOToQDate(const QString & dtStr);
/** takes a vCalendar tree of VObjects, and puts all of them that have
* the "event" property into the dictionary, todos in the todo-list, etc. */
void populate(VObject *vcal);
/** takes a number 0 - 6 and returns the two letter string of that day,
* i.e. MO, TU, WE, etc. */
const char *dayFromNum(int day);
/** the reverse of the above function. */
int numFromDay(const QString &day);
Attendee::Role VCalFormat::readRole(const char *s) const;
QCString writeRole(Attendee::Role role) const;
Attendee::PartStat readStatus(const char *s) const;
QCString writeStatus(Attendee::PartStat status) const;
private:
Calendar *mCalendar;
bool useLocalTime;
QPtrList<Event> mEventsRelate; // events with relations
QPtrList<Todo> mTodosRelate; // todos with relations
};
}
#endif