diff --git a/libksieve/ksieveui/vacation/tests/data/vacation-complex-time.siv b/libksieve/ksieveui/vacation/tests/data/vacation-complex-time.siv new file mode 100644 --- /dev/null +++ b/libksieve/ksieveui/vacation/tests/data/vacation-complex-time.siv @@ -0,0 +1,8 @@ +require ["date","relational","vacation"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if allof (currentdate :value "ge" "iso8601" "2015-01-02T02:00:00+00:00", currentdate :value "le" "date" "2015-03-04", not header :contains "X-Spam-Flag" "YES") +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; +} \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/tests/vacationutilstest.h b/libksieve/ksieveui/vacation/tests/vacationutilstest.h --- a/libksieve/ksieveui/vacation/tests/vacationutilstest.h +++ b/libksieve/ksieveui/vacation/tests/vacationutilstest.h @@ -32,6 +32,7 @@ void testParseScript_data(); void testParseScript(); void testParseScriptComplex(); + void testParseScriptComplexTime(); void testWriteScript(); void testWriteSimpleScript(); void testUpdateVacationBlock(); diff --git a/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp b/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp --- a/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp +++ b/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp @@ -121,6 +121,8 @@ QCOMPARE(vacationD.excludeDomain, vacationA.excludeDomain); QCOMPARE(vacationD.startDate, vacationA.startDate); QCOMPARE(vacationD.endDate, vacationA.endDate); + QCOMPARE(vacationD.startTime, QTime()); + QCOMPARE(vacationD.endTime, QTime()); } void VacationUtilsTest::testParseScriptComplex() @@ -139,6 +141,33 @@ QCOMPARE(vacation.excludeDomain, QString()); QCOMPARE(vacation.startDate, QDate(2015, 01, 02)); QCOMPARE(vacation.endDate, QDate(2015, 03, 04)); + QCOMPARE(vacation.startTime, QTime()); + QCOMPARE(vacation.endTime, QTime()); +} + +void VacationUtilsTest::testParseScriptComplexTime() +{ + QFile file(QLatin1String(VACATIONTESTDATADIR "vacation-complex-time.siv")); + QVERIFY(file.open(QIODevice::ReadOnly)); + QString script = QString::fromUtf8(file.readAll()); + + VacationUtils::Vacation vacation = VacationUtils::parseScript(script); + QCOMPARE(vacation.active, true); + QCOMPARE(vacation.messageText, QLatin1String("dsfgsdfgsdfg")); + QCOMPARE(vacation.subject, QLatin1String("XXX")); + QCOMPARE(vacation.notificationInterval, 7); + testAliases(vacation.aliases, QStringList() << QLatin1String("test@test.de")); + QCOMPARE(vacation.sendForSpam, false); + QCOMPARE(vacation.excludeDomain, QString()); + QCOMPARE(vacation.startDate, QDate(2015, 01, 02)); + QCOMPARE(vacation.endDate, QDate(2015, 03, 04)); + QCOMPARE(vacation.startTime, QTime(2,0)); + QCOMPARE(vacation.endTime, QTime()); + + QString composedScript = VacationUtils::composeScript(vacation); + vacation = VacationUtils::parseScript(composedScript); + QCOMPARE(vacation.startTime, QTime(2,0)); + QCOMPARE(vacation.endTime, QTime()); } void VacationUtilsTest::testWriteScript() @@ -175,6 +204,8 @@ QCOMPARE(vacationA.excludeDomain, vacation.excludeDomain); QCOMPARE(vacationA.startDate, vacation.startDate); QCOMPARE(vacationA.endDate, vacation.endDate); + QCOMPARE(vacationA.startTime, QTime()); + QCOMPARE(vacationA.endTime, QTime()); vacation.active = false; script = VacationUtils::composeScript(vacation); @@ -189,6 +220,8 @@ QCOMPARE(vacationA.excludeDomain, vacation.excludeDomain); QCOMPARE(vacationA.startDate, vacation.startDate); QCOMPARE(vacationA.endDate, vacation.endDate); + QCOMPARE(vacationA.startTime, QTime()); + QCOMPARE(vacationA.endTime, QTime()); } diff --git a/libksieve/ksieveui/vacation/vacation.cpp b/libksieve/ksieveui/vacation/vacation.cpp --- a/libksieve/ksieveui/vacation/vacation.cpp +++ b/libksieve/ksieveui/vacation/vacation.cpp @@ -134,7 +134,9 @@ if (supportsDate) { mDialog->enableDates( supportsDate ); mDialog->setStartDate( vacation.startDate ); + mDialog->setEndTime(vacation.endTime); mDialog->setEndDate( vacation.endDate ); + mDialog->setEndTime(vacation.endTime); } connect( mDialog, SIGNAL(okClicked()), SLOT(slotDialogOk()) ); @@ -168,7 +170,9 @@ vacation.sendForSpam = mDialog->sendForSpam(); vacation.excludeDomain = mDialog->domainName(); vacation.startDate = mDialog->startDate(); + vacation.startTime = mDialog->startTime(); vacation.endDate = mDialog->endDate(); + vacation.endTime = mDialog->endTime(); const QString script = VacationUtils::composeScript(vacation); emit scriptActive( active, mServerName); diff --git a/libksieve/ksieveui/vacation/vacationdialog.h b/libksieve/ksieveui/vacation/vacationdialog.h --- a/libksieve/ksieveui/vacation/vacationdialog.h +++ b/libksieve/ksieveui/vacation/vacationdialog.h @@ -70,9 +70,14 @@ QDate startDate() const; void setStartDate( const QDate &startDate ); + QTime startTime() const; + void setStartTime( const QTime &startTime ); + QDate endDate() const; void setEndDate( const QDate &endDate ); + QTime endTime() const; + void setEndTime( const QTime &endTime ); private slots: void slotDialogDefaults(); diff --git a/libksieve/ksieveui/vacation/vacationdialog.cpp b/libksieve/ksieveui/vacation/vacationdialog.cpp --- a/libksieve/ksieveui/vacation/vacationdialog.cpp +++ b/libksieve/ksieveui/vacation/vacationdialog.cpp @@ -189,6 +189,16 @@ mVacationEditWidget->setEndDate( endDate ); } +QTime VacationDialog::endTime() const +{ + return mVacationEditWidget->endTime(); +} + +void VacationDialog::setEndTime(const QTime &endTime) +{ + mVacationEditWidget->setEndTime(endTime); +} + QDate VacationDialog::startDate() const { return mVacationEditWidget->startDate(); @@ -198,3 +208,13 @@ { mVacationEditWidget->setStartDate( startDate ); } + +QTime VacationDialog::startTime() const +{ + return mVacationEditWidget->startTime(); +} + +void VacationDialog::setStartTime(const QTime &startTime) +{ + mVacationEditWidget->setStartTime(startTime); +} diff --git a/libksieve/ksieveui/vacation/vacationeditwidget.h b/libksieve/ksieveui/vacation/vacationeditwidget.h --- a/libksieve/ksieveui/vacation/vacationeditwidget.h +++ b/libksieve/ksieveui/vacation/vacationeditwidget.h @@ -22,8 +22,10 @@ class KIntSpinBox; class KLineEdit; class KDateComboBox; +class KTimeComboBox; class QDate; +class QTime; namespace PimCommon { class RichTextEditorWidget; @@ -79,9 +81,15 @@ QDate startDate() const; void setStartDate( const QDate &startDate ); - QDate endDate(); + QTime startTime() const; + void setStartTime( const QTime &startTime ); + + QDate endDate() const; void setEndDate( const QDate &endDate ); + QTime endTime() const; + void setEndTime( const QTime &endTime ); + void setDefault(); private Q_SLOTS: @@ -97,7 +105,11 @@ KLineEdit *mDomainEdit; KLineEdit *mSubject; KDateComboBox *mStartDate; + KTimeComboBox *mStartTime; + QCheckBox *mStartTimeActive; KDateComboBox *mEndDate; + KTimeComboBox *mEndTime; + QCheckBox *mEndTimeActive; }; } diff --git a/libksieve/ksieveui/vacation/vacationeditwidget.cpp b/libksieve/ksieveui/vacation/vacationeditwidget.cpp --- a/libksieve/ksieveui/vacation/vacationeditwidget.cpp +++ b/libksieve/ksieveui/vacation/vacationeditwidget.cpp @@ -33,7 +33,9 @@ #include #include #include +#include #include +#include #include using KMime::Types::AddrSpecList; @@ -83,26 +85,57 @@ glay->addWidget(mSubject, row, 1); // From date - ++row; + + QHBoxLayout *timeLayout = new QHBoxLayout(this); + mStartDate = new KDateComboBox( this ); mStartDate->setObjectName( QLatin1String( "mStartDate" ) ); mStartDate->setOptions( KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords | KDateComboBox::WarnOnInvalid ); mStartDate->setEnabled( false ); // Disable by default - we need an extension to support this + + mStartTime = new KTimeComboBox( this ); + mStartTime->setObjectName( QLatin1String( "mStartTime" ) ); + mStartTime->setOptions( KTimeComboBox::EditTime | KTimeComboBox::SelectTime | KTimeComboBox::EditTime | KTimeComboBox::WarnOnInvalid ); + mStartTime->setEnabled( false ); // Disable by default - we need an extension to support this + + mStartTimeActive = new QCheckBox(this); + connect(mStartTimeActive,SIGNAL(toggled(bool)), mStartTime, SLOT(setEnabled(bool))); + + timeLayout->addWidget(mStartDate); + timeLayout->addWidget(mStartTimeActive); + timeLayout->addWidget(mStartTime); + + ++row; QLabel *label = new QLabel( i18n("&Start:"), this ); label->setBuddy( mStartDate ); glay->addWidget( label, row, 0 ); - glay->addWidget( mStartDate, row, 1 ); + glay->addLayout(timeLayout, row, 1); // End date - ++row; + timeLayout = new QHBoxLayout(this); + mEndDate = new KDateComboBox( this ); mEndDate->setObjectName( QLatin1String( "mEndDate" ) ); mEndDate->setOptions( KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords | KDateComboBox::WarnOnInvalid ); mEndDate->setEnabled( false ); // Disable by default - we need an extension to support this + + mEndTime = new KTimeComboBox( this ); + mEndTime->setObjectName( QLatin1String( "mEndTime" ) ); + mEndTime->setOptions( KTimeComboBox::EditTime | KTimeComboBox::SelectTime | KTimeComboBox::EditTime | KTimeComboBox::WarnOnInvalid ); + mEndTime->setEnabled( false ); // Disable by default - we need an extension to support this + + mEndTimeActive = new QCheckBox(this); + connect(mEndTimeActive,SIGNAL(toggled(bool)), mEndTime, SLOT(setEnabled(bool))); + + timeLayout->addWidget(mEndDate); + timeLayout->addWidget(mEndTimeActive); + timeLayout->addWidget(mEndTime); + + ++row; label = new QLabel( i18n("&End:"), this ); label->setBuddy( mEndDate ); glay->addWidget( label, row, 0 ); - glay->addWidget( mEndDate, row, 1 ); + glay->addLayout(timeLayout, row, 1); // "Resent only after" spinbox and label: ++row; @@ -255,7 +288,7 @@ mSpamCheck->setChecked( !enable ); } -QDate VacationEditWidget::endDate() +QDate VacationEditWidget::endDate() const { if ( mEndDate->isEnabled() ) { return mEndDate->date(); @@ -269,6 +302,22 @@ mEndDate->setDate( endDate ); } +QTime VacationEditWidget::endTime() const +{ + if ( mEndTime->isEnabled() ) { + return mEndTime->time(); + } else { + return QTime(); + } +} + +void VacationEditWidget::setEndTime( const QTime &endTime ) +{ + mEndTimeActive->setChecked(endTime.isValid()); + mEndTime->setEnabled(endTime.isValid()); + mEndTime->setTime( endTime ); +} + QDate VacationEditWidget::startDate() const { if ( mStartDate->isEnabled() ) { @@ -283,6 +332,22 @@ mStartDate->setDate( startDate ); } +QTime VacationEditWidget::startTime() const +{ + if ( mStartTime->isEnabled() ) { + return mStartTime->time(); + } else { + return QTime(); + } +} + +void VacationEditWidget::setStartTime( const QTime &startTime ) +{ + mStartTimeActive->setChecked(startTime.isValid()); + mStartTime->setEnabled(startTime.isValid()); + mStartTime->setTime( startTime ); +} + void VacationEditWidget::setSubject(const QString &subject) { mSubject->setText(subject); diff --git a/libksieve/ksieveui/vacation/vacationpagewidget.cpp b/libksieve/ksieveui/vacation/vacationpagewidget.cpp --- a/libksieve/ksieveui/vacation/vacationpagewidget.cpp +++ b/libksieve/ksieveui/vacation/vacationpagewidget.cpp @@ -143,7 +143,9 @@ mVacationEditWidget->enableDates( supportsSieveDate ); if ( supportsSieveDate ) { mVacationEditWidget->setStartDate( vacation.startDate ); + mVacationEditWidget->setStartTime(vacation.startTime); mVacationEditWidget->setEndDate( vacation.endDate ); + mVacationEditWidget->setEndTime(vacation.endTime); } //emit scriptActive( mWasActive, mServerName ); @@ -168,7 +170,9 @@ vacation.sendForSpam = mVacationEditWidget->sendForSpam(); vacation.excludeDomain = mVacationEditWidget->domainName(); vacation.startDate = mVacationEditWidget->startDate(); + vacation.startTime = mVacationEditWidget->startTime(); vacation.endDate = mVacationEditWidget->endDate(); + vacation.endTime = mVacationEditWidget->endTime(); const QString script = VacationUtils::composeScript(vacation); createJob->setStatus(active, mWasActive); //Q_EMIT scriptActive( active, mServerName); diff --git a/libksieve/ksieveui/vacation/vacationscriptextractor.h b/libksieve/ksieveui/vacation/vacationscriptextractor.h --- a/libksieve/ksieveui/vacation/vacationscriptextractor.h +++ b/libksieve/ksieveui/vacation/vacationscriptextractor.h @@ -325,40 +325,48 @@ // handle startDate and endDate in arbitrary order { 0, GIE::TestListStart, 0, 3, 0, 0 }, // 2 - { 0, GIE::TestStart, "currentdate", 4, 3, 0 }, // 3 - { 0, GIE::TaggedArgument, "value", 5, 4, 0 }, // 4 - { 0, GIE::StringArgument, "ge", 6, 8, 0 }, // 5 - { 0, GIE::StringArgument, "date", 7, 0, 0 }, // 6 - { 0, GIE::StringArgument, 0, 11, 0, "startDate" }, // 7 - { 0, GIE::StringArgument, "le", 9, 0, 0 }, // 8 - { 0, GIE::StringArgument, "date", 10, 0, 0 }, // 9 - { 0, GIE::StringArgument, 0, 11, 0, "endDate" }, // 10 - { 0, GIE::TestEnd, 0, 12, 0, 0 }, // 11 - - { 0, GIE::TestStart, "currentdate", 13, 12, 0 }, // 12 - { 0, GIE::TaggedArgument, "value", 14, 13, 0 }, // 13 - { 0, GIE::StringArgument, "le", 15, 17, 0 }, // 14 - { 0, GIE::StringArgument, "date", 16, 0, 0 }, // 15 - { 0, GIE::StringArgument, 0, 20, 0, "endDate" }, // 16 - { 0, GIE::StringArgument, "ge", 18, 0, 0 }, // 17 - { 0, GIE::StringArgument, "date", 19, 0, 0 }, // 18 - { 0, GIE::StringArgument, 0, 20, 0, "startDate" }, // 19 - { 0, GIE::TestEnd, 0, 24, 0, 0 }, // 20 - { 0, GIE::TestStart, 0, 23, 22, 0 }, // 21 - { -1, GIE::Any, 0, 24, 0, 0 }, // 22 - { 0, GIE::TestEnd, 0, 24, 22, 0 }, // 23 - { 0, GIE::TestListEnd, 0, 25, 21, 0 }, // 24 - - { 0, GIE::TestEnd, 0, 26, 0, 0 }, // 25 + { 0, GIE::TestStart, "currentdate", 4, 3, 0 }, // 3 + { 0, GIE::TaggedArgument, "value", 5, 4, 0 }, // 4 + { 0, GIE::StringArgument, "ge", 6, 10, 0 }, // 5 + { 0, GIE::StringArgument, "date", 7, 8, 0 }, // 6 + { 0, GIE::StringArgument, 0, 15, 0, "startDate" }, // 7 + { 0, GIE::StringArgument, "iso8601", 9, 0, 0 }, // 8 + { 0, GIE::StringArgument, 0, 15, 0, "startDateTime" },// 9 + { 0, GIE::StringArgument, "le", 11, 0, 0 }, // 10 + { 0, GIE::StringArgument, "date", 12, 13, 0 }, // 11 + { 0, GIE::StringArgument, 0, 15, 0, "endDate" }, // 12 + { 0, GIE::StringArgument, "iso8601", 14, 0, 0 }, // 13 + { 0, GIE::StringArgument, 0, 15, 0, "endDateTime" }, // 14 + { 0, GIE::TestEnd, 0, 16, 0, 0 }, // 15 + + { 0, GIE::TestStart, "currentdate", 17, 16, 0 }, // 16 + { 0, GIE::TaggedArgument, "value", 18, 17, 0 }, // 17 + { 0, GIE::StringArgument, "le", 19, 23, 0 }, // 18 + { 0, GIE::StringArgument, "date", 20, 21, 0 }, // 19 + { 0, GIE::StringArgument, 0, 28, 0, "endDate" }, // 20 + { 0, GIE::StringArgument, "iso8601", 22, 0, 0 }, // 21 + { 0, GIE::StringArgument, 0, 28, 0, "endDateTime" }, // 22 + { 0, GIE::StringArgument, "ge", 24, 0, 0 }, // 23 + { 0, GIE::StringArgument, "date", 25, 26, 0 }, // 24 + { 0, GIE::StringArgument, 0, 28, 0, "startDate" }, // 25 + { 0, GIE::StringArgument, "iso8601", 27, 0, 0 }, // 26 + { 0, GIE::StringArgument, 0, 28, 0, "startDateTime" }, // 27 + { 0, GIE::TestEnd, 0, 32, 0, 0 }, // 28 + { 0, GIE::TestStart, 0, 31, 30, 0 }, // 29 + { -1, GIE::Any, 0, 32, 0, 0 }, // 30 + { 0, GIE::TestEnd, 0, 32, 30, 0 }, // 31 + { 0, GIE::TestListEnd, 0, 33, 29, 0 }, // 32 + + { 0, GIE::TestEnd, 0, 34, 0, 0 }, // 33 // block of commands, find "stop", take nested if's into account: - { 0, GIE::BlockStart, 0, 28, 25, 0 }, // 26 - { -1, GIE::Any, 0, 28, 0, 0 }, // 27 - { 1, GIE::CommandStart, "vacation", 30, 27, "vacation" }, // 28 - { -1, GIE::Any, 0, 30, 0, 0 }, // 29 - { 0, GIE::BlockEnd, 0, 31, 29, 0 }, // 30 + { 0, GIE::BlockStart, 0, 36, 33, 0 }, // 34 + { -1, GIE::Any, 0, 36, 0, 0 }, // 35 + { 1, GIE::CommandStart, "vacation", 38, 35, "vacation" }, // 36 + { -1, GIE::Any, 0, 38, 0, 0 }, // 37 + { 0, GIE::BlockEnd, 0, 39, 37, 0 }, // 38 - { -1, GIE::Any, 0, 31, 31, 0 } // 31 end state + { -1, GIE::Any, 0, 39, 39, 0 } // 39 end state }; static const unsigned int numDatesNodes = sizeof datesNodes / sizeof *datesNodes; @@ -372,12 +380,30 @@ QDate endDate() { - return date( QLatin1String( "endDate" ) ); + if (mResults.count(QLatin1String("endDateTime")) == 1) { + return datetime(QLatin1String("endDateTime")).date(); + } else { + return date(QLatin1String("endDate")); + } } QDate startDate() { - return date( QLatin1String( "startDate" ) ); + if (mResults.count(QLatin1String("startDateTime")) == 1) { + return datetime(QLatin1String("startDateTime")).date(); + } else { + return date(QLatin1String("startDate")); + } + } + + QTime endTime() + { + return datetime(QLatin1String("endDateTime")).time(); + } + + QTime startTime() + { + return datetime(QLatin1String("startDateTime")).time(); } private: @@ -388,6 +414,14 @@ return QDate::fromString( mResults[name], Qt::ISODate ); } } + + QDateTime datetime(const QString &name ) { + if (mResults.count(name) == 0) { + return QDateTime(); + } else { + return QDateTime::fromString( mResults[name], Qt::ISODate ); + } + } }; diff --git a/libksieve/ksieveui/vacation/vacationutils.h b/libksieve/ksieveui/vacation/vacationutils.h --- a/libksieve/ksieveui/vacation/vacationutils.h +++ b/libksieve/ksieveui/vacation/vacationutils.h @@ -46,7 +46,9 @@ bool sendForSpam; QString excludeDomain; QDate startDate; + QTime startTime; QDate endDate; + QTime endTime; }; QString composeScript(const Vacation &vacation); diff --git a/libksieve/ksieveui/vacation/vacationutils.cpp b/libksieve/ksieveui/vacation/vacationutils.cpp --- a/libksieve/ksieveui/vacation/vacationutils.cpp +++ b/libksieve/ksieveui/vacation/vacationutils.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include using KMime::Types::AddrSpecList; @@ -168,7 +168,9 @@ vacation.sendForSpam = !sdx.found(); vacation.excludeDomain = drdx.domainName(); vacation.startDate = dx.startDate(); + vacation.startTime = dx.startTime(); vacation.endDate = dx.endDate(); + vacation.endTime = dx.endTime(); return vacation; } @@ -232,13 +234,25 @@ QStringList condition; if (vacation.startDate.isValid()) { - condition.append(QString::fromLatin1("currentdate :value \"ge\" \"date\" \"%1\"") - .arg(vacation.startDate.toString(Qt::ISODate))); + if (vacation.startTime.isValid()) { + KDateTime start(vacation.startDate, vacation.startTime); + condition.append(QString::fromLatin1("currentdate :value \"ge\" \"iso8601\" \"%1\"") + .arg(start.toString(KDateTime::ISODate))); + } else { + condition.append(QString::fromLatin1("currentdate :value \"ge\" \"date\" \"%1\"") + .arg(vacation.startDate.toString(Qt::ISODate))); + } } if (vacation.endDate.isValid()) { - condition.append(QString::fromLatin1("currentdate :value \"le\" \"date\" \"%1\"") - .arg(vacation.endDate.toString(Qt::ISODate))); + if (vacation.endTime.isValid()) { + KDateTime end(vacation.endDate, vacation.endTime); + condition.append(QString::fromLatin1("currentdate :value \"le\" \"iso8601\" \"%1\"") + .arg(end.toString(KDateTime::ISODate))); + } else { + condition.append(QString::fromLatin1("currentdate :value \"le\" \"date\" \"%1\"") + .arg(vacation.endDate.toString(Qt::ISODate))); + } } if (!vacation.sendForSpam) {