void AlarmDialog::save( const KCalCore::Alarm::Ptr &alarm ) const
{
  // Offsets
  int offset = mUi->mAlarmOffset->value() * 60; // minutes
  int offsetunit = mUi->mOffsetUnit->currentIndex();
  if ( offsetunit >= 1 ) {
    offset *= 60; // hours
  }
  if ( offsetunit >= 2 ) {
    offset *= 24; // days
  }
  if ( offsetunit >= 3 ) {
    offset *= 7; // weeks
  }

  const int beforeafterpos = mUi->mBeforeAfter->currentIndex();
  if ( beforeafterpos % 2 == 0 ) { // before -> negative
    offset = -offset;
  }

  // Note: if this triggers, fix the logic at the place causing it. It really makes
  // no sense to have both disabled.
  Q_ASSERT( mAllowBeginReminders || mAllowEndReminders );

  // TODO: Add possibility to specify a given time for the reminder
  if ( mAllowBeginReminders && beforeafterpos == 0 ) { // before start
    alarm->setStartOffset( KCalCore::Duration( offset ) );
  } else if ( mAllowBeginReminders && beforeafterpos == 1 ) { // after start
    alarm->setStartOffset( KCalCore::Duration( offset ) );
  }

  // We assume that if mAllowBeginReminders is not set, that mAllowBeginReminders
  // is set.
  if ( !mAllowBeginReminders && beforeafterpos == 0 ) { // before end
    alarm->setStartOffset( KCalCore::Duration( offset ) );
  } else if ( !mAllowBeginReminders && beforeafterpos == 1 ) { // after end
    alarm->setStartOffset( KCalCore::Duration( offset ) );
  } else if ( beforeafterpos == 2 ) { // before end
    alarm->setStartOffset( KCalCore::Duration( offset ) );
  } else if ( beforeafterpos == 3 ) { // after end
    alarm->setStartOffset( KCalCore::Duration( offset ) );
  }

  if ( beforeafterpos / 2 == 0 ) { // start offset
    alarm->setStartOffset( KCalCore::Duration( offset ) );
  } else {
    alarm->setEndOffset( KCalCore::Duration( offset ) );
  }

  // Repeating
  if ( mUi->mRepeats->isChecked() ) {
    alarm->setRepeatCount( mUi->mRepeatCount->value() );
    alarm->setSnoozeTime( mUi->mRepeatInterval->value() * 60 ); // convert back to seconds
  } else {
    alarm->setRepeatCount( 0 );
  }

  if ( mUi->mTypeCombo->currentIndex() == 1 ) { // Audio
    alarm->setAudioAlarm( mUi->mSoundFile->url().toLocalFile() );
  } else if ( mUi->mTypeCombo->currentIndex() == 2 ) { // Application / script
    alarm->setProcedureAlarm( mUi->mApplication->url().toLocalFile(),
                              mUi->mAppArguments->text() );
  } else if ( mUi->mTypeCombo->currentIndex() == 3 ) { // Email
    QStringList addresses = KPIMUtils::splitAddressList( mUi->mEmailAddress->text() );
    KCalCore::Person::List add;
    for ( QStringList::Iterator it = addresses.begin(); it != addresses.end(); ++it ) {
      add << KCalCore::Person::fromFullName( *it );
    }
    // TODO: Add a subject line and possibilities for attachments
    alarm->setEmailAlarm( QString(), mUi->mEmailText->toPlainText(), add );
  } else { // Display
    alarm->setDisplayAlarm( mUi->mDisplayText->toPlainText() );
  }
}
void AlarmDialog::load( const KCalCore::Alarm::Ptr &alarm )
{
  if ( !alarm ) {
    return;
  }

  setWindowTitle( i18n( "Edit existing reminder" ) );

  // Offsets
  int offset;
  int beforeafterpos = 0;

  if ( alarm->hasEndOffset() ) {
    beforeafterpos = 2;
    offset = alarm->endOffset().asSeconds();
  } else {
    // TODO: Also allow alarms at fixed times, not relative to start/end
    offset = alarm->startOffset().asSeconds();
  }
  // Negative offset means before the start/end...
  if ( offset < 0 ) {
    offset = -offset;
  } else {
    ++beforeafterpos;
  }
  mUi->mBeforeAfter->setCurrentIndex( beforeafterpos );

  offset = offset / 60; // make minutes
  int useoffset = offset;

  if ( offset % ( 24 * 60 ) == 0 && offset > 0 ) { // divides evenly into days?
    useoffset = offset / ( 24 * 60 );
    mUi->mOffsetUnit->setCurrentIndex( 2 );
  } else if ( offset % 60 == 0 && offset > 0 ) { // divides evenly into hours?
    useoffset = offset / 60;
    mUi->mOffsetUnit->setCurrentIndex( 1 );
  } else {
    useoffset = offset;
    mUi->mOffsetUnit->setCurrentIndex( 0 );
  }
  mUi->mAlarmOffset->setValue( useoffset );

  // Repeating
  mUi->mRepeats->setChecked( alarm->repeatCount() > 0 );
  if ( alarm->repeatCount() > 0 ) {
    mUi->mRepeatCount->setValue( alarm->repeatCount() );
    mUi->mRepeatInterval->setValue( alarm->snoozeTime().asSeconds() / 60 ); // show as minutes
  }
  int id = 0;

  switch ( alarm->type() ) {
  case KCalCore::Alarm::Audio:
    mUi->mTypeCombo->setCurrentIndex( 1 );
    mUi->mSoundFile->setUrl( alarm->audioFile() );
    id = 1;
    break;
  case KCalCore::Alarm::Procedure:
    mUi->mTypeCombo->setCurrentIndex( 2 );
    mUi->mApplication->setUrl( alarm->programFile() );
    mUi->mAppArguments->setText( alarm->programArguments() );
    id = 2;
    break;
  case KCalCore::Alarm::Email:
  {
    mUi->mTypeCombo->setCurrentIndex( 3 );
    KCalCore::Person::List addresses = alarm->mailAddresses();
    QStringList add;
    for ( KCalCore::Person::List::ConstIterator it = addresses.constBegin();
          it != addresses.constEnd(); ++it ) {
      add << (*it)->fullName();
    }
    mUi->mEmailAddress->setText( add.join( ", " ) );
    mUi->mEmailText->setPlainText( alarm->mailText() );
    id = 3;
    break;
  }
  case KCalCore::Alarm::Display:
  case KCalCore::Alarm::Invalid:
  default:
    mUi->mTypeCombo->setCurrentIndex( 0 );
    mUi->mDisplayText->setPlainText( alarm->text() );
    break;
  }

  mUi->mTypeStack->setCurrentIndex( id );
  if ( alarm->audioFile().isEmpty() &&
       IncidenceEditorNG::EditorConfig::instance()->defaultAudioFileReminders() ) {
    mUi->mSoundFile->setUrl( IncidenceEditorNG::EditorConfig::instance()->audioFilePath() );
  }
}
void KCalConversionTest::testConversion_data()
{
    QTest::addColumn<KCalCore::Event>( "kcal" );
    QTest::addColumn<Kolab::Event>( "kolab" );
    
    Kolab::cDateTime date(2011,2,2,12,11,10,true);
    Kolab::cDateTime date2(2011,2,2,12,12,10,true);
    Kolab::cDateTime date3(2012,2,2,12,12,10,true);
    std::vector<int> intVector;
    intVector.push_back(1);
    intVector.push_back(-3);
    intVector.push_back(2);
    std::vector<std::string> stringVector;
    stringVector.push_back("cat1");
    stringVector.push_back("cat2");
    stringVector.push_back("parent/child");
    
    {
        KCalCore::Event kcal;
        kcal.setUid("uid");
        kcal.setCreated(toDate(date));
        kcal.setLastModified(toDate(date));
        kcal.setRevision(3);
        kcal.setSecrecy(KCalCore::Incidence::SecrecyConfidential);
        kcal.setCategories(toStringList(stringVector));
        kcal.setDtStart(toDate(date));
        kcal.setDtEnd(toDate(date2));
        kcal.setTransparency(KCalCore::Event::Transparent);
        
        kcal.setRecurrenceId(toDate(date2)); //TODO THISANDFUTURE
        kcal.recurrence()->setDaily(3);
        kcal.recurrence()->setDuration(5);
        kcal.recurrence()->addRDateTime(toDate(date2));
        kcal.recurrence()->addRDate(toDate(date2).date());
        kcal.recurrence()->addExDateTime(toDate(date3));
        kcal.recurrence()->addExDate(toDate(date3).date());
        
        KCalCore::RecurrenceRule *rr = kcal.recurrence()->defaultRRule(true);
        QList<int> intList = QVector<int>::fromStdVector(intVector).toList();
        rr->setBySeconds(intList);
        rr->setByMinutes(intList);
        rr->setByHours(intList);
        rr->setByDays(QList<KCalCore::RecurrenceRule::WDayPos>() << KCalCore::RecurrenceRule::WDayPos(3,1) << KCalCore::RecurrenceRule::WDayPos(5,4));
        rr->setByMonthDays(intList);
        rr->setByYearDays(intList);
        rr->setByMonths(intList);
        rr->setByWeekNumbers(intList);
        
        kcal.setSummary("summary");
        kcal.setDescription("description");
        kcal.setPriority(3);
        kcal.setStatus(KCalCore::Incidence::StatusConfirmed);
        kcal.setLocation("location");
        kcal.setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person("organizer", "organizer@email")));
        //Url
        kcal.setNonKDECustomProperty("X-KOLAB-URL", "http://test.org");
        KCalCore::Attendee::Ptr att(new KCalCore::Attendee("attendee", "attendee@email", false, KCalCore::Attendee::NeedsAction, KCalCore::Attendee::ReqParticipant));
        att->setDelegate("mailto:delegatee<delegatee@email>");
        att->setDelegator("mailto:delegator<delegator@email>");
        kcal.addAttendee(att);
        kcal.addAttachment(KCalCore::Attachment::Ptr(new KCalCore::Attachment(QString("uri"), "mimetype/mime")));
        KCalCore::Alarm::Ptr alarm = KCalCore::Alarm::Ptr(new KCalCore::Alarm(&kcal));    
        KCalCore::Person::List addressees;
        addressees.append(KCalCore::Person::Ptr(new KCalCore::Person("name", "email@email")));
        alarm->setEmailAlarm("subject", "text", addressees, QStringList()); //No support for attachments
        kcal.addAlarm(alarm);
        //TODO alarms

        kcal.setNonKDECustomProperty("X-KOLAB-key1", "value1");
        kcal.setNonKDECustomProperty("X-KOLAB-key2", "value2");
        kcal.setCustomProperty("SOMEOTHERAPP", "key2", "value2");
        Q_ASSERT(kcal.nonKDECustomProperty("X-KOLAB-key1") == "value1");
        
        Kolab::Event kolab;
        kolab.setUid("uid");
        kolab.setCreated(date);
        kolab.setLastModified(date);
        kolab.setSequence(3);
        kolab.setClassification(Kolab::ClassConfidential);
        kolab.setCategories(stringVector);
        kolab.setStart(date);
        kolab.setEnd(date2);
        kolab.setTransparency(true);
        
        Kolab::RecurrenceRule rrule;
        rrule.setInterval(3);
        rrule.setFrequency(Kolab::RecurrenceRule::Daily);
        rrule.setCount(5);
        rrule.setBysecond(intVector);
        rrule.setByminute(intVector);
        rrule.setByhour(intVector);
        rrule.setByday(std::vector<Kolab::DayPos>() << Kolab::DayPos(3, Kolab::Monday) << Kolab::DayPos(5, Kolab::Thursday));
        rrule.setBymonthday(intVector);
        rrule.setByyearday(intVector);
        rrule.setByweekno(intVector);
        rrule.setBymonth(intVector);
        
        kolab.setRecurrenceRule(rrule);
        kolab.setRecurrenceID(date2, true);
        kolab.setRecurrenceDates(std::vector<Kolab::cDateTime>() << date2 << Kolab::cDateTime(date2.year(), date2.month(), date2.day()));
        kolab.setExceptionDates(std::vector<Kolab::cDateTime>() << date3 << Kolab::cDateTime(date3.year(), date3.month(), date3.day()));
        
        kolab.setSummary("summary");
        kolab.setDescription("description");
        kolab.setPriority(3);
        kolab.setStatus(Kolab::StatusConfirmed);
        kolab.setLocation("location");
        kolab.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"organizer@email", "organizer")); //TODO uid
        kolab.setUrl("http://test.org");
        
        Kolab::Attendee a(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"attendee@email", "attendee"));//TODO uid
        a.setDelegatedTo(std::vector<Kolab::ContactReference>() << Kolab::ContactReference(Kolab::ContactReference::EmailReference,"delegatee@email", "delegatee"));
        a.setDelegatedFrom(std::vector<Kolab::ContactReference>() << Kolab::ContactReference(Kolab::ContactReference::EmailReference,"delegator@email", "delegator"));
        a.setCutype(Kolab::CutypeIndividual);
        kolab.setAttendees(std::vector<Kolab::Attendee>() << a);
        
        Kolab::Attachment attach;
        attach.setUri("uri", "mimetype/mime");
        kolab.setAttachments(std::vector<Kolab::Attachment>() << attach);
        
    //     std::vector<std::string> receipents;
    //     receipents.push_back("email@email");
    //     Kolab::Alarm alarm2("summary", "description", receipents);
    //     kolab.setAlarms(std::vector<Kolab::Alarm>() << alarm2);

        //The sorting is random, just sort them here how we think they should arrive so we don't have to sort during compare (due to lazyness).
        std::vector<Kolab::CustomProperty> customproperties;
        customproperties.push_back(Kolab::CustomProperty("X-KDE-SOMEOTHERAPP-key2", "value2"));
        customproperties.push_back(Kolab::CustomProperty("key1", "value1"));
        customproperties.push_back(Kolab::CustomProperty("key2", "value2"));
        
        kolab.setCustomProperties(customproperties);

        QTest::newRow( "with endDate and recurrence duration" ) << kcal << kolab;
    }
    {
        KCalCore::Event kcal;
        kcal.setUid("uid");
        kcal.setCreated(toDate(date));
        kcal.setLastModified(toDate(date));
        kcal.setRevision(3);
        kcal.setDtStart(toDate(date));
        kcal.setDuration(KCalCore::Duration(toDate(date), toDate(date2)));
        kcal.recurrence()->setDaily(3);
        kcal.recurrence()->setEndDateTime(toDate(date3));
        
        Kolab::Event kolab;
        kolab.setUid("uid");
        kolab.setCreated(date);
        kolab.setLastModified(date);
        kolab.setSequence(3);
        kolab.setStart(date);
        kolab.setDuration(Kolab::Duration(0, 0, 1, 0));
        Kolab::RecurrenceRule rrule;
        rrule.setInterval(3);
        rrule.setFrequency(Kolab::RecurrenceRule::Daily);
        rrule.setEnd(date3);
        kolab.setRecurrenceRule(rrule);
        
        QTest::newRow("with duration and recurrence endDate") << kcal << kolab;
    }
    {
        Kolab::cDateTime start(2011,1,1);
        Kolab::cDateTime end(2011,1,3);
        
        KCalCore::Event kcal;
        kcal.setUid("uid");
        kcal.setCreated(toDate(date));
        kcal.setLastModified(toDate(date));
        kcal.setDtStart(toDate(start));
        kcal.setDtEnd(toDate(end));
        kcal.recurrence()->setDaily(3);
        kcal.recurrence()->setEndDateTime(toDate(end));
        
        Kolab::Event kolab;
        kolab.setUid("uid");
        kolab.setCreated(date);
        kolab.setLastModified(date);
        kolab.setStart(start);
        kolab.setEnd(end);
        Kolab::RecurrenceRule rrule;
        rrule.setInterval(3);
        rrule.setFrequency(Kolab::RecurrenceRule::Daily);
        rrule.setEnd(end);
        kolab.setRecurrenceRule(rrule);
        
        QTest::newRow("date only dates") << kcal << kolab;
    }
    {
        KCalCore::Event kcal;
        kcal.setUid("uid");
        kcal.setCreated(toDate(date));
        kcal.setLastModified(toDate(date));
        kcal.setDtStart(toDate(date));
        kcal.setSummary("äöü%@$£é¤¼²°€Š�");
        
        Kolab::Event kolab;
        kolab.setUid("uid");
        kolab.setCreated(date);
        kolab.setLastModified(date);
        kolab.setStart(date);
        kolab.setSummary(std::string(QString("äöü%@$£é¤¼²°€Š�").toUtf8().constData()));
        
        QTest::newRow("latin1+Unicode") << kcal << kolab;

    }
}