-rw-r--r-- | korganizer/koprefs.cpp | 10 | ||||
-rw-r--r-- | libkcal/phoneformat.cpp | 44 | ||||
-rw-r--r-- | libkcal/vcalformat.cpp | 19 | ||||
-rw-r--r-- | libkcal/vcalformat.h | 5 |
4 files changed, 61 insertions, 17 deletions
diff --git a/korganizer/koprefs.cpp b/korganizer/koprefs.cpp index 0db8e6d..dd978bf 100644 --- a/korganizer/koprefs.cpp +++ b/korganizer/koprefs.cpp @@ -204,363 +204,365 @@ KOPrefs::KOPrefs() : // addItemString("RemotePassWd",&mRemotePassWd, ""); // addItemString("RemoteFile", &mRemoteFile, hdp+"mycalendar.ics"); // addItemString("LocalTempFile",&mLocalTempFile, "/tmp/tempsyncfile.ics" ); KPrefs::setCurrentGroup("LoadSaveFileNames"); addItemString("LastImportFile", &mLastImportFile ,hdp +"import.ics" ); addItemString("LastVcalFile", &mLastVcalFile ,hdp +"export.vcs" ); addItemString("LastSaveFile", &mLastSaveFile ,hdp +"mybackup.ics" ); addItemString("LastLoadFile", &mLastLoadFile ,hdp +"mybackup.ics" ); addItemString("LastSyncedLocalFile", &mLastSyncedLocalFile ,hdp +"lastsync.ics" ); KPrefs::setCurrentGroup("Locale"); addItemInt("PreferredLanguage",&mPreferredLanguage,0); addItemInt("PreferredTime",&mPreferredTime,0); addItemInt("PreferredDate",&mPreferredDate,0); addItemBool("WeekStartsOnSunday",&mWeekStartsOnSunday,false); addItemBool("QuickSavingWOUnicode",&mUseQuicksave,false); addItemBool("ShortDateInViewer",&mShortDateInViewer,false); addItemString("UserDateFormatLong", &mUserDateFormatLong, "%A %d %b %y"); addItemString("UserDateFormatShort", &mUserDateFormatShort, "%aK %d.%m.%y"); KPrefs::setCurrentGroup("Colors"); addItemColor("Holiday Color",&mHolidayColor,defaultHolidayColor); addItemColor("Highlight Color",&mHighlightColor,defaultHighlightColor); addItemColor("Event Color",&mEventColor,mDefaultCategoryColor); addItemColor("Agenda Background Color",&mAgendaBgColor,defaultAgendaBgColor); addItemColor("WorkingHours Color",&mWorkingHoursColor,defaultWorkingHoursColor); addItemColor("Todo due today Color",&mTodoDueTodayColor,defaultTodoDueTodayColor); addItemColor("Todo overdue Color",&mTodoOverdueColor,defaultTodoOverdueColor); addItemColor("MonthViewEvenColor",&mMonthViewEvenColor,QColor( 160,160,255 )); addItemColor("MonthViewOddColor",&mMonthViewOddColor,QColor( 160,255,160 )); addItemColor("MonthViewHolidayColor",&mMonthViewHolidayColor,QColor( 255,160,160 )); addItemBool("MonthViewUsesDayColors",&mMonthViewUsesDayColors,true); addItemBool("MonthViewSatSunTog",&mMonthViewSatSunTog,true); addItemBool("HightlightDateTimeEdit",&mHightlightDateTimeEdit,false); addItemColor("AppColor1",&mAppColor1,QColor( 130,170,255 )); addItemColor("AppColor2",&mAppColor2,QColor( 174,216,255 )); addItemBool("UseAppColors",&mUseAppColors,false); KPrefs::setCurrentGroup("Views"); addItemInt("Hour Size",&mHourSize,8); addItemBool("Show Daily Recurrences",&mDailyRecur,true); addItemBool("Show Weekly Recurrences",&mWeeklyRecur,true); addItemBool("Show Month Daily Recurrences",&mMonthDailyRecur,true); addItemBool("Show Month Weekly Recurrences",&mMonthWeeklyRecur,true); addItemBool("ShowShortMonthName",&mMonthShowShort,false); addItemBool("ShowIconsInMonthCell",&mMonthShowIcons,true); addItemBool("Enable ToolTips",&mEnableToolTips,false); addItemBool("Enable MonthView ScrollBars",&mEnableMonthScroll,false); addItemBool("Marcus Bains shows seconds",&mMarcusBainsShowSeconds,false); addItemBool("Show Marcus Bains",&mMarcusBainsEnabled,true); addItemBool("EditOnDoubleClick",&mEditOnDoubleClick,true); addItemBool("ViewChangeHoldFullscreen",&mViewChangeHoldFullscreen,false); addItemBool("ViewChangeHoldNonFullscreen",&mViewChangeHoldNonFullscreen,false); addItemBool("CenterOnCurrentTime",&mCenterOnCurrentTime,false); addItemBool("SetTimeToDayStartAt",&mSetTimeToDayStartAt,true); addItemBool("HighlightCurrentDay",&mHighlightCurrentDay,true); addItemBool("WNViewShowsParents",&mWNViewShowsParents,true); addItemBool("WNViewShowLocation",&mWNViewShowLocation,false); addItemBool("UseHighlightLightColor",&mUseHighlightLightColor,false); addItemBool("ListViewMonthTimespan",&mListViewMonthTimespan,true); addItemBool("TodoViewUsesCatColors",&mTodoViewUsesCatColors,false); addItemBool("TodoViewShowsPercentage",&mTodoViewShowsPercentage,false); addItemBool("TodoViewUsesSmallFont",&mTodoViewUsesSmallFont,false); addItemBool("TodoViewUsesForegroundColor",&mTodoViewUsesForegroundColor,false); addItemBool("MonthViewUsesForegroundColor",&mMonthViewUsesForegroundColor,false); #ifdef DESKTOP_VERSION addItemBool("UseInternalAlarmNotification",&mUseInternalAlarmNotification,true); #else addItemBool("UseInternalAlarmNotification",&mUseInternalAlarmNotification,false); #endif addItemInt("Day Begins",&mDayBegins,7); addItemInt("Working Hours Start",&mWorkingHoursStart,8); addItemInt("Working Hours End",&mWorkingHoursEnd,17); addItemBool("Exclude Holidays",&mExcludeHolidays,true); addItemBool("Exclude Saturdays",&mExcludeSaturdays,true); addItemBool("Month View Uses Category Color",&mMonthViewUsesCategoryColor,false); addItemBool("Full View Month",&mFullViewMonth,true); addItemBool("Full View Todo",&mFullViewTodo,true); addItemBool("Quick Todo",&mEnableQuickTodo,false); addItemInt("Next X Days",&mNextXDays,3); KPrefs::setCurrentGroup("Printer"); KPrefs::setCurrentGroup("Layout"); addItemBool("CompactDialogs",&mCompactDialogs,false); addItemBool("VerticalScreen",&mVerticalScreen,true); KPrefs::setCurrentGroup("KOrganizer Plugins"); addItemStringList("SelectedPlugins",&mSelectedPlugins,"holidays"); KPrefs::setCurrentGroup("Group Scheduling"); addItemInt("IMIPScheduler",&mIMIPScheduler,IMIPKMail); addItemInt("IMIPSend",&mIMIPSend,IMIPdirectsend); addItemStringList("AdditionalMails",&mAdditionalMails,""); addItemInt("IMIP auto refresh",&mIMIPAutoRefresh,neverAuto); addItemInt("IMIP auto insert request",&mIMIPAutoInsertRequest,neverAuto); addItemInt("IMIP auto insert reply",&mIMIPAutoInsertReply,neverAuto); addItemInt("IMIP auto FreeBusy",&mIMIPAutoFreeBusy,neverAuto); addItemInt("IMIP auto save FreeBusy",&mIMIPAutoFreeBusyReply,neverAuto); KPrefs::setCurrentGroup( "Editors" ); addItemStringList( "EventTemplates", &mEventTemplates ); addItemStringList( "TodoTemplates", &mTodoTemplates ); addItemInt("DestinationPolicy",&mDestination,standardDestination); } KOPrefs::~KOPrefs() { if (mInstance == this) mInstance = insd.setObject(0); setLocaleDict( 0 ); if ( mLocaleDict ) delete mLocaleDict; //qDebug("KOPrefs::~KOPrefs() "); } KOPrefs *KOPrefs::instance() { if (!mInstance) { mInstance = insd.setObject(new KOPrefs()); mInstance->readConfig(); } return mInstance; } void KOPrefs::usrSetDefaults() { } void KOPrefs::fillMailDefaults() { if (mName.isEmpty()) mName = i18n("Anonymous"); if (mEmail.isEmpty()) mEmail = i18n("nobody@nowhere"); } void KOPrefs::setTimeZoneIdDefault() { mTimeZoneId = i18n("+01:00 Europe/Oslo(CET)"); } void KOPrefs::setCategoryDefaults() { mCustomCategories.clear(); mCustomCategories = getDefaultList(); QStringList::Iterator it; for (it = mCustomCategories.begin();it != mCustomCategories.end();++it ) { setCategoryColor(*it,mDefaultCategoryColor); } } QStringList KOPrefs::getDefaultList() { QStringList retval ; retval << i18n("Anniversary") << i18n("Appointment") << i18n("Birthday") << i18n("Business") << i18n("Business Travel") << i18n("Cinema") << i18n("Customer") << i18n("Break")<< i18n("Breakfast")<< i18n("Competition")<< i18n("Dinner") << i18n("Education")<< i18n("Family") << i18n("Favorites") << i18n("Festival")<< i18n("Fishing")<< i18n("Flight") << i18n("Gifts") << i18n("Holiday") << i18n("Holiday Cards")<< i18n("Hot Contacts") << i18n("Hiking") << i18n("Hunting") << i18n("Key Customer") << i18n("Kids") << i18n("Lunch") << i18n("Meeting") << i18n("Miscellaneous") << i18n("Partner")<< i18n("Party") << i18n("Personal") << i18n("Personal Travel") << i18n("PHB") << i18n("Phone Calls") << i18n("Projects") << i18n("Recurring") << i18n("School") << i18n("Shopping") << i18n("Speach") << i18n("Special Occasion") << i18n("Sports") << i18n("Talk") << i18n("Travel") << i18n("TV")<< i18n("University") << i18n("Vacation") << i18n("VIP") << i18n("SyncEvent") ; retval.sort(); return retval; } void KOPrefs::usrReadConfig() { mLocaleDict = 0; // pending LR fix translation // qDebug("KOPrefs::usrReadConfig() fix translation "); + if ( mPreferredLanguage > 0 && mPreferredLanguage < 4 ) { if ( mPreferredLanguage == 1 ) { mLocaleDict = new QDict<QString>; int i = 0; QString fw ( germanwords[i] [0]); while ( !fw.isEmpty() ) { mLocaleDict->insert( fw, new QString (germanwords[i] [1] )); ++i; fw = germanwords[i] [0]; } setLocaleDict( mLocaleDict ); } else { QString fileName ; if ( mPreferredLanguage == 3 ) fileName = MainWindow::resourcePath()+"usertranslation.txt"; else if ( mPreferredLanguage == 2 ) fileName = MainWindow::resourcePath()+"frenchtranslation.txt"; - else return; QFile file( fileName ); if (file.open( IO_ReadOnly ) ) { QTextStream ts( &file ); - ts.setCodec( QTextCodec::codecForLocale() ); + ts.setEncoding( QTextStream::Latin1 ); + //ts.setCodec( QTextCodec::latin1 ); QString text = ts.read(); file.close(); text.replace( QRegExp("\\\\n"), "\n" ); QString line; QString we; QString wt; int br = 0; int nbr; nbr = text.find ( "},", br ); line = text.mid( br, nbr - br ); br = nbr+1; int se, ee, st, et; mLocaleDict = new QDict<QString>; QString end = "{ \"\",\"\" }"; while ( (line != end) && (br > 1) ) { //qDebug("%d *%s* ", br, line.latin1()); se = line.find("\"")+1; et = line.findRev("\"",-1); ee = line.find("\",\""); st = ee+3; we = line.mid( se, ee-se ); wt = line.mid( st, et-st ); //qDebug("*%s* *%s* ", we.latin1(), wt.latin1()); mLocaleDict->insert( we, new QString (wt) ); nbr = text.find ( "}", br ); line = text.mid( br, nbr - br ); br = nbr+1; } //qDebug("end *%s* ", end.latin1()); setLocaleDict( mLocaleDict ); } else { qDebug("KO: Cannot find translation file %s",fileName.latin1() ); } } + } config()->setGroup("General"); mCustomCategories = config()->readListEntry("Custom Categories"); if ( KOPrefs::instance()->mLanguageChanged ) { mLocationDefaults.clear(); mEventSummaryUser.clear(); mTodoSummaryUser.clear(); } if (mLocationDefaults.isEmpty()) { - mLocationDefaults << i18n("Home") << i18n("Office") << i18n("Libary") << i18n("School") << i18n("Doctor") << i18n("Beach") - << i18n("University") << i18n("Restaurant") << i18n("Bar") << i18n("Conference room") << i18n("Cinema") << i18n("Lake") << i18n("Kindergarden") + mLocationDefaults << i18n("Home") << i18n("Office") << i18n("Library") << i18n("School") << i18n("Doctor") << i18n("Beach") + << i18n("University") << i18n("Restaurant") << i18n("Bar") << i18n("Conference room") << i18n("Cinema") << i18n("Lake") << i18n("Kindergarten") << i18n("Germany") << i18n("Sweden") << i18n("Forest") << i18n("Desert") << i18n("Kitchen") ; // << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") mLocationDefaults.sort(); } if (mEventSummaryUser.isEmpty()) { mEventSummaryUser = getDefaultList() ; } if (mTodoSummaryUser.isEmpty()) { mTodoSummaryUser = getDefaultList() ; } if (mCustomCategories.isEmpty()) setCategoryDefaults(); config()->setGroup("Personal Settings"); mName = config()->readEntry("user_name",""); mEmail = config()->readEntry("user_email",""); fillMailDefaults(); config()->setGroup("Category Colors"); QStringList::Iterator it; for (it = mCustomCategories.begin();it != mCustomCategories.end();++it ) { setCategoryColor(*it,config()->readColorEntry(*it,&mDefaultCategoryColor)); } if (mTimeZoneId.isEmpty()) { setTimeZoneIdDefault(); } KPimPrefs::usrReadConfig(); } void KOPrefs::usrWriteConfig() { config()->setGroup("General"); config()->writeEntry("Custom Categories",mCustomCategories); config()->setGroup("Personal Settings"); config()->writeEntry("user_name",mName); config()->writeEntry("user_email",mEmail); config()->setGroup("Category Colors"); QDictIterator<QColor> it(mCategoryColors); while (it.current()) { config()->writeEntry(it.currentKey(),*(it.current())); ++it; } KPimPrefs::usrWriteConfig(); } void KOPrefs::setCategoryColor(QString cat,const QColor & color) { mCategoryColors.replace(cat,new QColor(color)); } QColor *KOPrefs::categoryColor(QString cat) { QColor *color = 0; if (!cat.isEmpty()) color = mCategoryColors[cat]; if (color) return color; else return &mDefaultCategoryColor; } void KOPrefs::setFullName(const QString &name) { mName = name; } void KOPrefs::setEmail(const QString &email) { //qDebug(" KOPrefs::setEmai*********** %s",email.latin1() ); mEmail = email; } QString KOPrefs::fullName() { if (mEmailControlCenter) { KEMailSettings settings; return settings.getSetting(KEMailSettings::RealName); } else { return mName; } } QString KOPrefs::email() { if (mEmailControlCenter) { KEMailSettings settings; return settings.getSetting(KEMailSettings::EmailAddress); } else { return mEmail; } } KConfig* KOPrefs::getConfig() { return config(); } diff --git a/libkcal/phoneformat.cpp b/libkcal/phoneformat.cpp index 6276498..1769b37 100644 --- a/libkcal/phoneformat.cpp +++ b/libkcal/phoneformat.cpp @@ -257,471 +257,476 @@ public: break; case CAL_TEXT: //qDebug(" ev text %s", DecodeUnicodeConsole(Note->Entries[i].Text) ); event->setSummary( QString::fromUtf8 ( (const char*)DecodeUnicodeConsole( Note->Entries[i].Text ))); break; case CAL_LOCATION: event->setLocation(QString::fromUtf8 ((const char*) DecodeUnicodeConsole(Note->Entries[i].Text) )); break; case CAL_PHONE: //printmsg("Phone : \"%s\"\n",DecodeUnicodeConsole(Note->Entries[i].Text)); break; case CAL_PRIVATE: if ( Note->Entries[i].Number == 1 ) event->setSecrecy( Incidence::SecrecyPrivate ); else event->setSecrecy( Incidence::SecrecyPublic ); break; case CAL_CONTACTID: #if 0 entry.Location = Note->Entries[i].Number; entry.MemoryType = MEM_ME; error=Phone->GetMemory(&s, &entry); if (error == ERR_NONE) { name = GSM_PhonebookGetEntryName(&entry); if (name != NULL) { //printmsg("Contact ID : \"%s\" (%d)\n", DecodeUnicodeConsole(name), Note->Entries[i].Number); } else { //printmsg("Contact ID : %d\n",Note->Entries[i].Number); } } else { //printmsg("Contact ID : %d\n",Note->Entries[i].Number); } #endif break; case CAL_REPEAT_DAYOFWEEK: repeat_dayofweek = Note->Entries[i].Number; repeating = true; break; case CAL_REPEAT_DAY: repeat_day = Note->Entries[i].Number; repeating = true; break; case CAL_REPEAT_WEEKOFMONTH: repeat_weekofmonth = Note->Entries[i].Number; repeating = true; break; case CAL_REPEAT_MONTH: repeat_month = Note->Entries[i].Number; repeating = true; break; case CAL_REPEAT_FREQUENCY: repeat_frequency = Note->Entries[i].Number; repeating = true; break; case CAL_REPEAT_STARTDATE: repeat_startdate = Note->Entries[i].Date; repeating = true; break; case CAL_REPEAT_STOPDATE: repeat_stopdate = Note->Entries[i].Date; repeating = true; break; } } #if 0 event->setDescription( attList[4] ); bool repeating = false; int repeat_dayofweek = -1; int repeat_day = -1; int repeat_weekofmonth = -1; int repeat_month = -1; int repeat_frequency = -1; GSM_DateTime repeat_startdate = {0,0,0,0,0,0,0}; GSM_DateTime repeat_stopdate = {0,0,0,0,0,0,0}; #endif QString recurString = "no"; if ( repeating && repeat_frequency != -1) { recurString = "y"; if ( repeat_dayofweek >= 0 ) recurString += "dow" + QString::number (repeat_dayofweek); if ( repeat_day >= 0 ) recurString += "d" + QString::number (repeat_day); if ( repeat_weekofmonth >= 0 ) recurString += "w" + QString::number (repeat_weekofmonth); if ( repeat_month >= 0 ) recurString += "m" + QString::number ( repeat_month ); if ( repeat_frequency >= 0 ) recurString += "f" + QString::number (repeat_frequency ); int rtype = 0; // qDebug("recurs "); QDate startDate, endDate; if ( repeat_startdate.Day > 0 ) { startDate = datefromGSM ( &repeat_startdate ); event->setDtStart(QDateTime ( startDate, event->dtStart().time())); } else { startDate = event->dtStart().date(); } int freq = repeat_frequency; bool hasEndDate = false; if ( repeat_stopdate.Day > 0 ) { endDate = datefromGSM ( &repeat_stopdate ); hasEndDate = true; } uint weekDaysNum = repeat_dayofweek ; // 1 == monday, 7 == sunday QBitArray weekDays( 7 ); int i; int bb = 1; for( i = 1; i <= 7; ++i ) { weekDays.setBit( i - 1, ( bb & weekDaysNum )); bb = 2 << (i-1); //qDebug(" %d bit %d ",i-1,weekDays.at(i-1) ); } // qDebug("next "); int pos = 0; Recurrence *r = event->recurrence(); /* 0 daily; 1 weekly;x 2 monthpos;x 3 monthlyday; 4 rYearlyMont bool repeating = false; int repeat_dayofweek = -1; int repeat_day = -1; int repeat_weekofmonth = -1; int repeat_month = -1; int repeat_frequency = -1; */ int dayOfWeek = startDate.dayOfWeek(); if ( repeat_weekofmonth >= 0 ) { rtype = 2; // ************************ 2 MonthlyPos pos = repeat_weekofmonth; if ( repeat_dayofweek >= 0 ) dayOfWeek = repeat_dayofweek; if (repeat_month > 0) { if ( repeat_month != event->dtStart().date().month() ) { QDate date (event->dtStart().date().year(),repeat_month,event->dtStart().date().day() ); event->setDtStart(QDateTime ( date , event->dtStart().time()) ); } if ( freq == 1 ) freq = 12; } } else if ( repeat_dayofweek >= 0 ) { rtype = 1;// ************************ 1 Weekly } else if ( repeat_day >= 0 ) { if ( repeat_month > 0) { rtype = 4; } else { rtype = 3; } } else { rtype = 0 ; } if ( rtype == 0 ) { if ( hasEndDate ) r->setDaily( freq, endDate ); else r->setDaily( freq, -1 ); } else if ( rtype == 1 ) { if ( hasEndDate ) r->setWeekly( freq, weekDays, endDate ); else r->setWeekly( freq, weekDays, -1 ); } else if ( rtype == 3 ) { if ( hasEndDate ) r->setMonthly( Recurrence::rMonthlyDay, freq, endDate ); else r->setMonthly( Recurrence::rMonthlyDay, freq, -1 ); r->addMonthlyDay( startDate.day() ); } else if ( rtype == 2 ) { if ( hasEndDate ) r->setMonthly( Recurrence::rMonthlyPos, freq, endDate ); else r->setMonthly( Recurrence::rMonthlyPos, freq, -1 ); QBitArray days( 7 ); days.fill( false ); days.setBit( dayOfWeek - 1 ); r->addMonthlyPos( pos, days ); } else if ( rtype == 4 ) { if ( hasEndDate ) r->setYearly( Recurrence::rYearlyMonth, freq, endDate ); else r->setYearly( Recurrence::rYearlyMonth, freq, -1 ); r->addYearlyNum( startDate.month() ); } } else { event->recurrence()->unsetRecurs(); } - QStringList categoryList; - categoryList << getCategory( Note ); - event->setCategories( categoryList ); - // strange 0 semms to mean: alarm enabled + QStringList cat = event->categories(); + QString nCat = getCategory( Note ); + + if ( !nCat.isEmpty() ) + if ( !cat.contains( nCat )) { + cat << nCat; + event->setCategories( cat ); + } + if ( alarm ) { Alarm *alarm; if ( event->alarms().count() > 0 ) alarm = event->alarms().first(); else { alarm = new Alarm( event ); event->addAlarm( alarm ); } alarm->setType( Alarm::Audio ); alarm->setEnabled( true ); int alarmOffset = alarmDt.secsTo( event->dtStart() ); alarm->setStartOffset( -alarmOffset ); } else { Alarm *alarm; if ( event->alarms().count() > 0 ) { alarm = event->alarms().first(); alarm->setType( Alarm::Audio ); alarm->setStartOffset( -60*15 ); alarm->setEnabled( false ); } } // csum ***************************************** uint cSum; cSum = PhoneFormat::getCsumEvent( event ); event->setCsum( mProfileName, QString::number( cSum )); event->setTempSyncStat( SYNC_TEMPSTATE_NEW_EXTERNAL ); mCalendar->addEvent( event); return true; } QDateTime fromGSM ( GSM_DateTime* dtp, bool useTz = false ) { QDateTime dt; int y,m,t,h,min,sec; y = dtp->Year; m = dtp->Month; t = dtp->Day; h = dtp->Hour; min = dtp->Minute; sec = dtp->Second; dt = QDateTime(QDate(y,m,t), QTime(h,min,sec)); // dtp->Timezone: offset in hours int offset = KGlobal::locale()->localTimeOffset( dt ); if ( useTz ) dt = dt.addSecs ( offset*60); return dt; } static QString dtToString( const QDateTime& dti, bool useTZ = false ) { QString datestr; QString timestr; int offset = KGlobal::locale()->localTimeOffset( dti ); QDateTime dt; if (useTZ) dt = dti.addSecs ( -(offset*60)); else dt = dti; if(dt.date().isValid()){ const QDate& date = dt.date(); datestr.sprintf("%04d%02d%02d", date.year(), date.month(), date.day()); } if(dt.time().isValid()){ const QTime& time = dt.time(); timestr.sprintf("T%02d%02d%02d", time.hour(), time.minute(), time.second()); } return datestr + timestr; } QDate datefromGSM ( GSM_DateTime* dtp ) { return QDate ( dtp->Year, dtp->Month, dtp->Day ); } QString getCategory( GSM_CalendarEntry* Note) { QString CATEGORY; switch (Note->Type) { case GSM_CAL_REMINDER : CATEGORY = QString("Reminder"); break; case GSM_CAL_CALL : CATEGORY = QString("Call"); break; - case GSM_CAL_MEETING : CATEGORY = QString("Meeting"); break; + //case GSM_CAL_MEETING : CATEGORY = QString("Meeting"); break; case GSM_CAL_BIRTHDAY : CATEGORY = QString("Birthday"); break; case GSM_CAL_MEMO : CATEGORY = QString("Memo"); break; case GSM_CAL_TRAVEL : CATEGORY = QString("Travel"); break; case GSM_CAL_VACATION : CATEGORY = QString("Vacation"); break; case GSM_CAL_ALARM : CATEGORY = QString("Alarm"); break; case GSM_CAL_DAILY_ALARM : CATEGORY = QString("Daily alarm"); break; case GSM_CAL_T_ATHL : CATEGORY = QString("Training/Athletism"); break; case GSM_CAL_T_BALL : CATEGORY = QString("Training/Ball Games"); break; case GSM_CAL_T_CYCL : CATEGORY = QString("Training/Cycling"); break; case GSM_CAL_T_BUDO : CATEGORY = QString("Training/Budo"); break; case GSM_CAL_T_DANC : CATEGORY = QString("Training/Dance"); break; case GSM_CAL_T_EXTR : CATEGORY = QString("Training/Extreme Sports"); break; case GSM_CAL_T_FOOT : CATEGORY = QString("Training/Football"); break; case GSM_CAL_T_GOLF : CATEGORY = QString("Training/Golf"); break; case GSM_CAL_T_GYM : CATEGORY = QString("Training/Gym"); break; case GSM_CAL_T_HORS : CATEGORY = QString("Training/Horse Races"); break; case GSM_CAL_T_HOCK : CATEGORY = QString("Training/Hockey"); break; case GSM_CAL_T_RACE : CATEGORY = QString("Training/Races"); break; case GSM_CAL_T_RUGB : CATEGORY = QString("Training/Rugby"); break; case GSM_CAL_T_SAIL : CATEGORY = QString("Training/Sailing"); break; case GSM_CAL_T_STRE : CATEGORY = QString("Training/Street Games"); break; case GSM_CAL_T_SWIM : CATEGORY = QString("Training/Swimming"); break; case GSM_CAL_T_TENN : CATEGORY = QString("Training/Tennis"); break; case GSM_CAL_T_TRAV : CATEGORY = QString("Training/Travels"); break; case GSM_CAL_T_WINT : CATEGORY = QString("Training/Winter Games"); break; default : CATEGORY = QString(""); } return CATEGORY; } protected: private: Calendar *mCalendar; QString mProfileName ; }; PhoneFormat::PhoneFormat(QString profileName, QString device,QString connection, QString model ) { mProfileName = profileName; mDevice = device; mConnection = connection; mModel = model; } PhoneFormat::~PhoneFormat() { } int PhoneFormat::initDevice(GSM_StateMachine *s) { GSM_ReadConfig(NULL, &s->Config[0], 0); s->ConfigNum = 1; GSM_Config *cfg = &s->Config[0]; if ( ! mConnection.isEmpty() ) { cfg->Connection = strdup(mConnection.latin1()); cfg->DefaultConnection = false; qDebug("Connection set %s ", cfg->Connection ); } if ( ! mDevice.isEmpty() ) { cfg->Device = strdup(mDevice.latin1()); cfg->DefaultDevice = false; qDebug("Device set %s ", cfg->Device); } if ( ! mModel.isEmpty() ) { strcpy(cfg->Model,mModel.latin1() ); cfg->DefaultModel = false; qDebug("Model set %s ",cfg->Model ); } int error=GSM_InitConnection(s,3); return error; } ulong PhoneFormat::getCsumTodo( Todo* todo ) { QStringList attList; if ( todo->hasDueDate() ) attList << PhoneParser::dtToString ( todo->dtDue() ); attList << todo->summary(); QString completedString = "no"; if ( todo->isCompleted() ) completedString = "yes"; attList << completedString; attList << QString::number( todo->priority() ); QString alarmString = "na"; Alarm *alarm; if ( todo->alarms().count() > 0 ) { alarm = todo->alarms().first(); if ( alarm->enabled() ) { alarmString = QString::number(alarm->startOffset().asSeconds() ); } } attList << alarmString; attList << todo->categoriesStr(); attList << todo->secrecyStr(); return PhoneFormat::getCsum(attList ); } ulong PhoneFormat::getCsumEvent( Event* event ) { QStringList attList; attList << PhoneParser::dtToString ( event->dtStart() ); attList << PhoneParser::dtToString ( event->dtEnd() ); attList << event->summary(); attList << event->location(); QString alarmString = "na"; Alarm *alarm; if ( event->alarms().count() > 0 ) { alarm = event->alarms().first(); if ( alarm->enabled() ) { alarmString = QString::number( alarm->startOffset().asSeconds() ); } } attList << alarmString; Recurrence* rec = event->recurrence(); QStringList list; bool writeEndDate = false; switch ( rec->doesRecur() ) { case Recurrence::rDaily: // 0 list.append( "0" ); list.append( QString::number( rec->frequency() ));//12 list.append( "0" ); list.append( "0" ); writeEndDate = true; break; case Recurrence::rWeekly:// 1 list.append( "1" ); list.append( QString::number( rec->frequency()) );//12 list.append( "0" ); { int days = 0; QBitArray weekDays = rec->days(); int i; for( i = 1; i <= 7; ++i ) { if ( weekDays[i-1] ) { days += 1 << (i-1); } } list.append( QString::number( days ) ); } //pending weekdays writeEndDate = true; break; case Recurrence::rMonthlyPos:// 2 list.append( "2" ); list.append( QString::number( rec->frequency()) );//12 writeEndDate = true; { int count = 1; QPtrList<Recurrence::rMonthPos> rmp; rmp = rec->monthPositions(); if ( rmp.first()->negative ) count = 5 - rmp.first()->rPos - 1; else count = rmp.first()->rPos - 1; list.append( QString::number( count ) ); } list.append( "0" ); break; case Recurrence::rMonthlyDay:// 3 list.append( "3" ); list.append( QString::number( rec->frequency()) );//12 list.append( "0" ); list.append( "0" ); writeEndDate = true; break; case Recurrence::rYearlyMonth://4 list.append( "4" ); list.append( QString::number( rec->frequency()) );//12 list.append( "0" ); list.append( "0" ); writeEndDate = true; break; default: list.append( "255" ); list.append( QString() ); list.append( "0" ); list.append( QString() ); list.append( "0" ); list.append( "20991231T000000" ); break; } if ( writeEndDate ) { if ( rec->endDate().isValid() ) { // 15 + 16 @@ -881,391 +886,418 @@ void PhoneFormat::afterSave( Incidence* inc) } bool PhoneFormat::save( Calendar *calendar) { GSM_StateMachine s; qDebug(" save "); s.opened = false; s.msg = NULL; s.ConfigNum = 0; QLabel status ( i18n(" Opening device ..."), 0 ); int w = status.sizeHint().width()+20 ; if ( w < 200 ) w = 230; int h = status.sizeHint().height()+20 ; int dw = QApplication::desktop()->width(); int dh = QApplication::desktop()->height(); status.setCaption(i18n("Writing to phone...") ); status.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); status.show(); status.raise(); qApp->processEvents(); int error=initDevice(&s); qDebug("GSM Init %d (no error is %d)", error, ERR_NONE); if ( error != ERR_NONE ) return false; GSM_Phone_Functions *Phone; GSM_CalendarEntry Note; bool start = true; Phone=s.Phone.Functions; bool gshutdown = false; QPtrList<Event> er = calendar->rawEvents(); Event* ev = er.first(); QString message = i18n(" Deleting event # "); int procCount = 0; int diffProc = 0; bool setPossible = true; #ifdef _WIN32_ QString fileName = locateLocal("data", "korganizer") + "\\tempfile.vcs"; #else QString fileName = "/tmp/kdepimtemp.vcs"; #endif //algo 1 delete event while ( ev ) { if ( ev->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL ) { // event was changed during sync or is a new one status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); qDebug("del event1 %d ", procCount); //event2GSM( calendar, ev, &Note ); if ( ev->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete QString loc = ev->getID(mProfileName); if ( !loc.isEmpty() ){ Note.Location = loc.toInt(); } else { qDebug("error: loc is empty "); } error = Phone->DeleteCalendar(&s, &Note); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { qDebug(" e error delete1 planB %d ", error); break; } } else if ( ev->getID(mProfileName).isEmpty() ) { // add new // we have to do this later after deleting } else { // change existing QString loc = ev->getID(mProfileName); if ( !loc.isEmpty() ){ Note.Location = loc.toInt(); } else { qDebug("error3: loc is empty "); } error = Phone->DeleteCalendar(&s, &Note); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { qDebug(" e error delete2 planB %d ", error); break; } ev->removeID( mProfileName ); } } ev = er.next(); } //algo 1 delete todo GSM_ToDoEntry ToDoEntry; QPtrList<Todo> tl = calendar->rawTodos(); Todo* to = tl.first(); message = i18n(" Deleting todo # "); procCount = 0; while ( to ) { if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL ) { qDebug("todo3 %d ", procCount); status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); qDebug("todo5 %d ", procCount); // todo2GSM( calendar, to, &ToDoEntry ); QString loc = to->getID(mProfileName); if ( !loc.isEmpty() ){ ToDoEntry.Location = loc.toInt(); } else { qDebug("error2: loc is empty "); } if ( to->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete error=Phone->DeleteToDo(&s,&ToDoEntry); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { qDebug("delete planB %d ", error); } } else if ( to->getID(mProfileName).isEmpty() ) { // add new ; } else { // change existing error=Phone->DeleteToDo(&s,&ToDoEntry); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { qDebug("set planB %d ", error); } to->removeID( mProfileName ); } } to = tl.next(); } //algo 2 add event ev = er.first(); QString filec; message = i18n(" Preparing event # "); procCount = 0; while ( ev ) { if ( ev->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && ev->tempSyncStat() != SYNC_TEMPSTATE_DELETE) { if ( ev->getID(mProfileName).isEmpty() ) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); filec += vfconverter.eventToString( ev, calendar )+ "\n"; afterSave ( ev ); } } ev = er.next(); } //algo 2 add todo to = tl.first(); procCount = 0; message = i18n(" Preparing todo # "); while ( to ) { qDebug("todo2 %d ", procCount); if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && to->tempSyncStat() != SYNC_TEMPSTATE_DELETE) { qDebug("todo4 %d ", procCount); if ( to->getID(mProfileName).isEmpty() ) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); filec += vfconverter.todoToString( to, calendar )+ "\n"; afterSave ( to ); } } to = tl.next(); } if ( filec.isEmpty() ) { qDebug("Nothing to write back.Finished. "); error=GSM_TerminateConnection(&s); return true; } //algo 3 saving file message = i18n(" Saving temp file ... "); status.setText ( message ); qApp->processEvents(); QFile file( fileName ); if (!file.open( IO_WriteOnly ) ) { qDebug("error open file "); error=GSM_TerminateConnection(&s); return false; } QTextStream ts( &file ); ts.setCodec( QTextCodec::codecForName("utf8") ); ts << filec ; file.close(); message = i18n(" Parsing temp file ... "); status.setText ( message ); qApp->processEvents(); GSM_Backup Backup; error=GSM_ReadBackupFile( (char*) fileName.latin1() ,&Backup); qDebug("Read file result %d ",error ); //algo 4 writing event int max, i; procCount = 0; message = i18n(" Writing event # "); if (Backup.Calendar[0] != NULL) { max = 0; while (Backup.Calendar[max]!=NULL) max++; + + GSM_DateTime* dtp; + for (i=0;i<max;i++) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); Note = *Backup.Calendar[i]; + +#if 0 + int j; + for (j=0;j<Note.EntriesNum;j++) { + //qDebug(" for ev"); + switch (Note.Entries[j].EntryType) { + case CAL_START_DATETIME: + //Note->Entries[i].Date.Hour = 5; + dtp = &Note.Entries[j].Date; + qDebug("start event %d %d %d - %d %d %d", dtp->Year, dtp->Month, dtp->Day, dtp->Hour, dtp->Minute, dtp->Second ); + break; + case CAL_END_DATETIME: + dtp = &Note.Entries[j].Date; + qDebug("end event %d %d %d - %d %d %d", dtp->Year, dtp->Month, dtp->Day, dtp->Hour, dtp->Minute, dtp->Second ); + break; + } + } + int type = Note.Type; + qDebug(" event type %d - %d %d - %d %d %d",type, GSM_CAL_CALL , GSM_CAL_MEETING ,GSM_CAL_BIRTHDAY, GSM_CAL_MEMO ,GSM_CAL_ALARM ); +#endif + + Note.Type = GSM_CAL_MEETING; + // pending: fix in gammu GSM_ReadBackupFile the type settings + int loc = Note.Location; Note.Location = 0; error=Phone->AddCalendar(&s,&Note); - qDebug("add event %d %d", error, Note.Location ); + qDebug("add event %d %d %d", error, Note.Location, loc ); } } //algo 4 writing todo procCount = 0; message = i18n(" Writing todo # "); if (Backup.ToDo[0] != NULL) { max = 0; while (Backup.ToDo[max]!=NULL) max++; for (i=0;i<max;i++) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); ToDoEntry = *Backup.ToDo[i]; error = Phone->AddToDo(&s,&ToDoEntry); qDebug("add todo %d ", error); } } //algo 5 reread message = i18n(" Rereading all data ... "); status.setText ( message ); qApp->processEvents(); error=GSM_TerminateConnection(&s); CalendarLocal* calendarTemp = new CalendarLocal(); calendarTemp->setTimeZoneId( calendar->timeZoneId()); if ( ! load( calendarTemp,calendar) ){ qDebug("error reloading calendar "); delete calendarTemp; return false; } //algo 6 compare event ev = er.first(); message = i18n(" Comparing event # "); QPtrList<Event> er1 = calendarTemp->rawEvents(); Event* ev1; procCount = 0; while ( ev ) { if ( ev->tempSyncStat() == SYNC_TEMPSTATE_NEW_ID) { qDebug("event new ID "); status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); QString cSum = ev->getCsum(mProfileName); ev1 = er1.first(); while ( ev1 ) { if ( ev1->getCsum( mProfileName ) == cSum ) { er1.remove( ev1 ); ev->setID(mProfileName, ev1->getID(mProfileName) ); break; } ev1 = er1.next(); } if ( ! ev1 ) { ev->removeID(mProfileName); qDebug("ERROR: No event found on phone for %s ", ev->summary().latin1()); qDebug("Probably writing back of events not supported "); } } ev = er.next(); } //algo 6 compare todo to = tl.first(); procCount = 0; QPtrList<Todo> tl1 = calendarTemp->rawTodos(); Todo* to1 ; message = i18n(" Comparing todo # "); while ( to ) { qDebug("todo2 %d ", procCount); if ( to->tempSyncStat() == SYNC_TEMPSTATE_NEW_ID) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); QString cSum = to->getCsum(mProfileName); Todo* to1 = tl1.first(); while ( to1 ) { if ( to1->getCsum( mProfileName ) == cSum ) { tl1.remove( to1 ); to->setID(mProfileName, to1->getID(mProfileName) ); break; } to1 = tl1.next(); } if ( ! to1 ) { to->removeID(mProfileName); qDebug("ERROR: No todo found on phone for %s ", to->summary().latin1()); qDebug("Probably writing back of todos not supported "); } } to = tl.next(); } delete calendarTemp; return true; // ******************************************************************* // ******************************************************************* // ******************************************************************* #if 0 while ( ev && ! planB) { if ( ev->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL ) { // event was changed during sync or is a new one status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); qDebug("event1 %d ", procCount); event2GSM( calendar, ev, &Note ); if ( ev->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete error = Phone->DeleteCalendar(&s, &Note); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { planB = true; qDebug(" e delete1 planB %d ", error); break; } } else if ( ev->getID(mProfileName).isEmpty() ) { // add new // we have to do this later after deleting } else { // change existing if ( setPossible ) { error = Phone->SetCalendar(&s, &Note); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { setPossible = false; ++diffProc; qDebug("Set cal not supported %d ", error); break; } } if ( ! setPossible) { ++diffProc; error = Phone->DeleteCalendar(&s, &Note); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { planB = true; qDebug(" e delete2 planB %d ", error); break; } ev->removeID( mProfileName ); } qDebug("Change Calendar. Location %d status: %d",Note.Location, error ); } } ev = er.next(); } ev = er.first(); // pending get empty slots int loc = 0; procCount -= diffProc; while ( ev && ! planB) { if ( ev->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && ev->tempSyncStat() != SYNC_TEMPSTATE_DELETE) { qDebug("event2 %d ", procCount); if ( ev->getID(mProfileName).isEmpty() ) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); //int newID ;//= pending //ev->setID(mProfileName, QString::number( newID )); event2GSM( calendar, ev, &Note ); ++loc; Note.Location = loc; error = Phone->AddCalendar(&s, &Note); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { planB = true; qDebug(" e add planB %d ", error); break; } ev->setID( mProfileName, QString::number( Note.Location ) ); qDebug("New Calendar. Location %d stat %d %d",Note.Location ,error, ERR_UNKNOWN); afterSave( ev ); } else { afterSave( ev ); // setting temp sync stat for changed items } } ev = er.next(); } if ( planB ) { qDebug("delete all calendar..."); status.setText ( i18n("Deleting all calendar...")); qApp->processEvents(); error=Phone->DeleteAllCalendar(&s); if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { message = i18n(" Deleting event # "); procCount = 0; while (1) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); qDebug("deleting event ... %d", procCount); error = Phone->GetNextCalendar(&s,&Note,true); if (error != ERR_NONE) break; error = Phone->DeleteCalendar(&s,&Note); } qDebug("deleting calendar ... finished"); } else { status.setText ( i18n("All calendar deleted!")); qDebug("all cal deleted"); } diff --git a/libkcal/vcalformat.cpp b/libkcal/vcalformat.cpp index 9307f12..0ebd7d1 100644 --- a/libkcal/vcalformat.cpp +++ b/libkcal/vcalformat.cpp @@ -1,378 +1,388 @@ /* 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() { } bool VCalFormat::load(Calendar *calendar, const QString &fileName) { mCalendar = calendar; clearException(); kdDebug(5800) << "VCalFormat::load() " << fileName << endl; 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; QString tmpStr; VObject *vcal, *vo; kdDebug(5800) << "VCalFormat::save(): " << fileName << endl; 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)) { kdDebug(5800) << "No error" << endl; return true; } else { kdDebug(5800) << "Error" << endl; 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 { kdDebug(5800) << "VCalFormat::fromString(): Unknown object type." << endl; deleteVObject( vcal ); return false; } deleteVObject( vcal ); return true; } -QString VCalFormat::eventToString( Event * event, Calendar *calendar) +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 ) +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; QStringList tmpStrList; 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, 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->relatedTo()) { addPropValue(vtodo, VCRelatedToProp, anEvent->relatedTo()->uid().local8Bit()); } // categories 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()); } @@ -1245,387 +1255,386 @@ Event* VCalFormat::VEventToEvent(VObject *vevent) } // 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; int index1 = 0; int index2 = 0; if ((vo = isAPropertyOf(vevent, VCCategoriesProp)) != 0) { s = fakeCString(vObjectUStringZValue(vo)); QString categories = QString::fromLocal8Bit(s); deleteStr(s); //const char* category; QString category; while ((index2 = categories.find(',', index1)) != -1) { //category = (const char *) categories.mid(index1, (index2 - index1)); category = categories.mid(index1, (index2 - index1)); tmpStrList.append(category); index1 = index2+1; } // get last category category = categories.mid(index1, (categories.length()-index1)); tmpStrList.append(category); anEvent->setCategories(tmpStrList); } // attachments tmpStrList.clear(); 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.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); } /* 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) { - QDateTime tmpDT(qdt); - tmpDT = tmpDT.addSecs(60*(-mCalendar->getTimeZone())); // correct to GMT. + 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(60*mCalendar->getTimeZone()); 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) { 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() ) { ev->setRelatedTo(mCalendar->event(ev->relatedToUid())); } Todo *todo; for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) { todo->setRelatedTo(mCalendar->todo(todo->relatedToUid())); } } const char *VCalFormat::dayFromNum(int day) { const char *days[7] = { "MO ", "TU ", "WE ", "TH ", "FR ", "SA ", "SU " }; return days[day]; diff --git a/libkcal/vcalformat.h b/libkcal/vcalformat.h index 7b9ca26..848be78 100644 --- a/libkcal/vcalformat.h +++ b/libkcal/vcalformat.h @@ -1,110 +1,111 @@ /* 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. */ QString toString( Calendar * ); - QString eventToString( Event *, Calendar *calendar ); - QString todoToString( Todo * ,Calendar *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); /** 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::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 |