diff --git a/src/incidencedatetime.cpp b/src/incidencedatetime.cpp index fc94967..e2c1f80 100644 --- a/src/incidencedatetime.cpp +++ b/src/incidencedatetime.cpp @@ -1,996 +1,996 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencedatetime.h" #include "ui_dialogdesktop.h" #include "incidenceeditor_debug.h" #include #include #include using namespace IncidenceEditorNG; /** * Returns true if the incidence's dates are equal to the default ones specified in config. */ static bool incidenceHasDefaultTimes(const KCalCore::Incidence::Ptr &incidence) { if (!incidence || incidence->allDay()) { return false; } QTime defaultDuration = CalendarSupport::KCalPrefs::instance()->defaultDuration().time(); if (!defaultDuration.isValid()) { return false; } QTime defaultStart = CalendarSupport::KCalPrefs::instance()->mStartTime.time(); if (!defaultStart.isValid()) { return false; } if (incidence->dtStart().time() == defaultStart) { if (incidence->type() == KCalCore::Incidence::TypeJournal) { return true; // no duration to compare with } const QDateTime start = incidence->dtStart(); const QDateTime end = incidence->dateTime(KCalCore::Incidence::RoleEnd); if (!end.isValid() || !start.isValid()) { return false; } const int durationInSeconds = defaultDuration.hour() * 3600 + defaultDuration.minute() * 60; return start.secsTo(end) == durationInSeconds; } return false; } IncidenceDateTime::IncidenceDateTime(Ui::EventOrTodoDesktop *ui) : IncidenceEditor(nullptr) , mUi(ui) , mTimezoneCombosWereVisibile(false) { setTimeZonesVisibility(false); setObjectName(QStringLiteral("IncidenceDateTime")); mUi->mTimeZoneLabel->setVisible(!mUi->mWholeDayCheck->isChecked()); connect(mUi->mTimeZoneLabel, &QLabel::linkActivated, this, &IncidenceDateTime::toggleTimeZoneVisibility); mUi->mTimeZoneLabel->setContextMenuPolicy(Qt::NoContextMenu); const QList lineEdits { mUi->mStartDateEdit->lineEdit(), mUi->mEndDateEdit->lineEdit(), mUi->mStartTimeEdit->lineEdit(), mUi->mEndTimeEdit->lineEdit()}; for (QLineEdit *lineEdit : lineEdits) { if (lineEdit) { lineEdit->setClearButtonEnabled(false); } } connect(mUi->mFreeBusyCheck, &QCheckBox::toggled, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::enableTimeEdits); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::checkDirtyStatus); connect(this, &IncidenceDateTime::startDateChanged, this, &IncidenceDateTime::updateStartToolTips); connect(this, &IncidenceDateTime::startTimeChanged, this, &IncidenceDateTime::updateStartToolTips); connect(this, &IncidenceDateTime::endDateChanged, this, &IncidenceDateTime::updateEndToolTips); connect(this, &IncidenceDateTime::endTimeChanged, this, &IncidenceDateTime::updateEndToolTips); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateStartToolTips); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateEndToolTips); connect(mUi->mStartCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateStartToolTips); connect(mUi->mEndCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateEndToolTips); } IncidenceDateTime::~IncidenceDateTime() { } bool IncidenceDateTime::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::FocusIn) { if (obj == mUi->mStartDateEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emiting startDateTime: " << mUi->mStartDateEdit; Q_EMIT startDateFocus(obj); } else if (obj == mUi->mEndDateEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emiting endDateTime: " << mUi->mEndDateEdit; Q_EMIT endDateFocus(obj); } else if (obj == mUi->mStartTimeEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emiting startTimeTime: " << mUi->mStartTimeEdit; Q_EMIT startTimeFocus(obj); } else if (obj == mUi->mEndTimeEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emiting endTimeTime: " << mUi->mEndTimeEdit; Q_EMIT endTimeFocus(obj); } return true; } else { // standard event processing return QObject::eventFilter(obj, event); } } void IncidenceDateTime::load(const KCalCore::Incidence::Ptr &incidence) { if (mLoadedIncidence && *mLoadedIncidence == *incidence) { return; } const bool isTemplate = incidence->customProperty("kdepim", "isTemplate") == QLatin1String( "true"); const bool templateOverridesTimes = incidenceHasDefaultTimes(mLoadedIncidence); mLoadedIncidence = incidence; mLoadingIncidence = true; // We can only handle events or todos. if (KCalCore::Todo::Ptr todo = IncidenceDateTime::incidence()) { load(todo, isTemplate, templateOverridesTimes); } else if (KCalCore::Event::Ptr event = IncidenceDateTime::incidence()) { load(event, isTemplate, templateOverridesTimes); } else if (KCalCore::Journal::Ptr journal = IncidenceDateTime::incidence()) { load(journal, isTemplate, templateOverridesTimes); } else { qCDebug(INCIDENCEEDITOR_LOG) << "Not an Incidence."; } // Set the initial times before calling enableTimeEdits, as enableTimeEdits // assumes that the initial times are initialized. mInitialStartDT = currentStartDateTime(); mInitialEndDT = currentEndDateTime(); enableTimeEdits(); if (mUi->mTimeZoneComboStart->currentIndex() == 0) { // Floating mInitialStartDT.setTimeZone(QTimeZone::systemTimeZone()); } if (mUi->mTimeZoneComboEnd->currentIndex() == 0) { // Floating mInitialEndDT.setTimeZone(QTimeZone::systemTimeZone()); } mWasDirty = false; mLoadingIncidence = false; } void IncidenceDateTime::save(const KCalCore::Incidence::Ptr &incidence) { if (KCalCore::Todo::Ptr todo = IncidenceDateTime::incidence(incidence)) { save(todo); } else if (KCalCore::Event::Ptr event = IncidenceDateTime::incidence(incidence)) { save(event); } else if (KCalCore::Journal::Ptr journal = IncidenceDateTime::incidence(incidence)) { save(journal); } else { Q_ASSERT_X(false, "IncidenceDateTimeEditor::save", "Only implemented for todos, events and journals"); } } bool IncidenceDateTime::isDirty() const { if (KCalCore::Todo::Ptr todo = IncidenceDateTime::incidence()) { return isDirty(todo); } else if (KCalCore::Event::Ptr event = IncidenceDateTime::incidence()) { return isDirty(event); } else if (KCalCore::Journal::Ptr journal = IncidenceDateTime::incidence()) { return isDirty(journal); } else { Q_ASSERT_X(false, "IncidenceDateTimeEditor::isDirty", "Only implemented for todos and events"); return false; } } void IncidenceDateTime::setActiveDate(const QDate &activeDate) { mActiveDate = activeDate; } QDate IncidenceDateTime::startDate() const { return currentStartDateTime().date(); } QDate IncidenceDateTime::endDate() const { return currentEndDateTime().date(); } QTime IncidenceDateTime::startTime() const { return currentStartDateTime().time(); } QTime IncidenceDateTime::endTime() const { return currentEndDateTime().time(); } /// private slots for General void IncidenceDateTime::setTimeZonesVisibility(bool visible) { static const QString tz(i18nc("@action show or hide the time zone widgets", "Time zones")); - QString placeholder(QStringLiteral("<< %1")); + QString placeholder(QStringLiteral("<< %1")); if (visible) { placeholder = placeholder.arg(tz); } else { - placeholder = QStringLiteral("%1 >>"); + placeholder = QStringLiteral("%1 >>"); placeholder = placeholder.arg(tz); } mUi->mTimeZoneLabel->setText(placeholder); mUi->mTimeZoneComboStart->setVisible(visible); mUi->mTimeZoneComboEnd->setVisible(visible && type() != KCalCore::Incidence::TypeJournal); } void IncidenceDateTime::toggleTimeZoneVisibility() { setTimeZonesVisibility(!mUi->mTimeZoneComboStart->isVisible()); } void IncidenceDateTime::updateStartTime(const QTime &newTime) { if (!newTime.isValid()) { return; } QDateTime endDateTime = currentEndDateTime(); const int secsep = mCurrentStartDateTime.secsTo(endDateTime); mCurrentStartDateTime.setTime(newTime); if (mUi->mEndCheck->isChecked()) { // Only update the end time when it is actually enabled, adjust end time so // that the event/todo has the same duration as before. endDateTime = mCurrentStartDateTime.addSecs(secsep); mUi->mEndTimeEdit->setTime(endDateTime.time()); mUi->mEndDateEdit->setDate(endDateTime.date()); } Q_EMIT startTimeChanged(mCurrentStartDateTime.time()); checkDirtyStatus(); } void IncidenceDateTime::updateStartDate(const QDate &newDate) { if (!newDate.isValid()) { return; } const bool dateChanged = mCurrentStartDateTime.date().day() != newDate.day() || mCurrentStartDateTime.date().month() != newDate.month(); QDateTime endDateTime = currentEndDateTime(); int daysep = mCurrentStartDateTime.daysTo(endDateTime); mCurrentStartDateTime.setDate(newDate); if (mUi->mEndCheck->isChecked()) { // Only update the end time when it is actually enabled, adjust end time so // that the event/todo has the same duration as before. endDateTime.setDate(mCurrentStartDateTime.date().addDays(daysep)); mUi->mEndDateEdit->setDate(endDateTime.date()); } checkDirtyStatus(); if (dateChanged) { Q_EMIT startDateChanged(mCurrentStartDateTime.date()); } } void IncidenceDateTime::updateStartSpec() { const QDate prevDate = mCurrentStartDateTime.date(); if (mUi->mEndCheck->isChecked() && currentEndDateTime().timeZone() == mCurrentStartDateTime.timeZone()) { mUi->mTimeZoneComboEnd->selectTimeZone(mUi->mTimeZoneComboStart->selectedTimeZone()); } mCurrentStartDateTime.setTimeZone(mUi->mTimeZoneComboStart->selectedTimeZone()); const bool dateChanged = mCurrentStartDateTime.date().day() != prevDate.day() || mCurrentStartDateTime.date().month() != prevDate.month(); if (dateChanged) { Q_EMIT startDateChanged(mCurrentStartDateTime.date()); } if (type() == KCalCore::Incidence::TypeJournal) { checkDirtyStatus(); } } /// private slots for Todo void IncidenceDateTime::enableStartEdit(bool enable) { mUi->mStartDateEdit->setEnabled(enable); if (mUi->mEndCheck->isChecked() || mUi->mStartCheck->isChecked()) { mUi->mWholeDayCheck->setEnabled(true); setTimeZoneLabelEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mWholeDayCheck->setEnabled(false); mUi->mWholeDayCheck->setChecked(false); setTimeZoneLabelEnabled(false); } if (enable) { mUi->mStartTimeEdit->setEnabled(!mUi->mWholeDayCheck->isChecked()); mUi->mTimeZoneComboStart->setEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mStartTimeEdit->setEnabled(false); mUi->mTimeZoneComboStart->setEnabled(false); } mUi->mTimeZoneComboStart->setFloating(!mUi->mTimeZoneComboStart->isEnabled()); checkDirtyStatus(); } void IncidenceDateTime::enableEndEdit(bool enable) { mUi->mEndDateEdit->setEnabled(enable); if (mUi->mEndCheck->isChecked() || mUi->mStartCheck->isChecked()) { mUi->mWholeDayCheck->setEnabled(true); setTimeZoneLabelEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mWholeDayCheck->setEnabled(false); mUi->mWholeDayCheck->setChecked(false); setTimeZoneLabelEnabled(false); } if (enable) { mUi->mEndTimeEdit->setEnabled(!mUi->mWholeDayCheck->isChecked()); mUi->mTimeZoneComboEnd->setEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mEndTimeEdit->setEnabled(false); mUi->mTimeZoneComboEnd->setEnabled(false); } mUi->mTimeZoneComboEnd->setFloating(!mUi->mTimeZoneComboEnd->isEnabled()); checkDirtyStatus(); } bool IncidenceDateTime::timeZonesAreLocal(const QDateTime &start, const QDateTime &end) { // Returns false if the incidence start or end timezone is not the local zone. if ((start.isValid() && start.timeZone() != QTimeZone::systemTimeZone()) || (end.isValid() && end.timeZone() != QTimeZone::systemTimeZone())) { return false; } else { return true; } } void IncidenceDateTime::enableTimeEdits() { // NOTE: assumes that the initial times are initialized. const bool wholeDayChecked = mUi->mWholeDayCheck->isChecked(); setTimeZoneLabelEnabled(!wholeDayChecked); if (mUi->mStartCheck->isChecked()) { mUi->mStartTimeEdit->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboStart->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboStart->setFloating(wholeDayChecked, mInitialStartDT.timeZone()); } if (mUi->mEndCheck->isChecked()) { mUi->mEndTimeEdit->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboEnd->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboEnd->setFloating(wholeDayChecked, mInitialEndDT.timeZone()); } /** When editing a whole-day event, unchecking mWholeDayCheck shouldn't set both times to 00:00. DTSTART must always be smaller than DTEND */ if (sender() == mUi->mWholeDayCheck && !wholeDayChecked // Somebody unchecked it, the incidence will now have time. && mUi->mStartCheck->isChecked() && mUi->mEndCheck->isChecked() // The incidence has both start and end/due dates && currentStartDateTime() == currentEndDateTime()) { // DTSTART == DTEND. This is illegal, lets correct it. // Not sure about the best time here... doesn't really matter, when someone unchecks mWholeDayCheck, she will // always want to set a time. mUi->mStartTimeEdit->setTime(QTime(0, 0)); mUi->mEndTimeEdit->setTime(QTime(1, 0)); } const bool currentlyVisible = mUi->mTimeZoneLabel->text().contains(QStringLiteral("<<")); setTimeZonesVisibility(!wholeDayChecked && mTimezoneCombosWereVisibile); mTimezoneCombosWereVisibile = currentlyVisible; if (!wholeDayChecked && !timeZonesAreLocal(currentStartDateTime(), currentEndDateTime())) { setTimeZonesVisibility(true); mTimezoneCombosWereVisibile = true; } } bool IncidenceDateTime::isDirty(const KCalCore::Todo::Ptr &todo) const { Q_ASSERT(todo); const bool hasDateTimes = mUi->mStartCheck->isChecked() || mUi->mEndCheck->isChecked(); // First check the start time/date of the todo if (todo->hasStartDate() != mUi->mStartCheck->isChecked()) { return true; } if ((hasDateTimes && todo->allDay()) != mUi->mWholeDayCheck->isChecked()) { return true; } if (todo->hasDueDate() != mUi->mEndCheck->isChecked()) { return true; } if (mUi->mStartCheck->isChecked()) { // Use mActiveStartTime. This is the QTimeZone selected on load coming from // the combobox. We use this one as it can slightly differ (e.g. missing // country code in the incidence time spec) from the incidence. if (currentStartDateTime() != mInitialStartDT) { return true; } } if (mUi->mEndCheck->isChecked() && currentEndDateTime() != mInitialEndDT) { return true; } return false; } /// Event specific methods bool IncidenceDateTime::isDirty(const KCalCore::Event::Ptr &event) const { if (event->allDay() != mUi->mWholeDayCheck->isChecked()) { return true; } if (mUi->mFreeBusyCheck->isChecked() && event->transparency() != KCalCore::Event::Opaque) { return true; } if (!mUi->mFreeBusyCheck->isChecked() && event->transparency() != KCalCore::Event::Transparent) { return true; } if (event->allDay()) { if (mUi->mStartDateEdit->date() != mInitialStartDT.date() || mUi->mEndDateEdit->date() != mInitialEndDT.date()) { return true; } } else { if (currentStartDateTime() != mInitialStartDT || currentEndDateTime() != mInitialEndDT || currentStartDateTime().timeZone() != mInitialStartDT.timeZone() || currentEndDateTime().timeZone() != mInitialEndDT.timeZone()) { return true; } } return false; } bool IncidenceDateTime::isDirty(const KCalCore::Journal::Ptr &journal) const { if (journal->allDay() != mUi->mWholeDayCheck->isChecked()) { return true; } if (journal->allDay()) { if (mUi->mStartDateEdit->date() != mInitialStartDT.date()) { return true; } } else { if (currentStartDateTime() != mInitialStartDT) { return true; } } return false; } /// Private methods QDateTime IncidenceDateTime::currentStartDateTime() const { return QDateTime( mUi->mStartDateEdit->date(), mUi->mStartTimeEdit->time(), mUi->mTimeZoneComboStart->selectedTimeZone()); } QDateTime IncidenceDateTime::currentEndDateTime() const { return QDateTime( mUi->mEndDateEdit->date(), mUi->mEndTimeEdit->time(), mUi->mTimeZoneComboEnd->selectedTimeZone()); } void IncidenceDateTime::load(const KCalCore::Event::Ptr &event, bool isTemplate, bool templateOverridesTimes) { // First en/disable the necessary ui bits and pieces mUi->mStartCheck->setVisible(false); mUi->mStartCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. mUi->mEndCheck->setVisible(false); mUi->mEndCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. // Start time connect(mUi->mStartTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::updateStartTime); // when editing with mouse, or up/down arrows connect(mUi->mStartTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::updateStartTime); // When editing with any key except up/down connect(mUi->mStartDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::updateStartDate); connect(mUi->mTimeZoneComboStart, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::updateStartSpec); // End time connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::endTimeChanged); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::endTimeChanged); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::endDateChanged); connect(mUi->mTimeZoneComboEnd, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::checkDirtyStatus); mUi->mWholeDayCheck->setChecked(event->allDay()); enableTimeEdits(); if (isTemplate) { if (templateOverridesTimes) { // We only use the template times if the user didn't override them. setTimes(event->dtStart(), event->dtEnd()); } } else { QDateTime startDT = event->dtStart(); QDateTime endDT = event->dtEnd(); setDateTimes(startDT, endDT); } switch (event->transparency()) { case KCalCore::Event::Transparent: mUi->mFreeBusyCheck->setChecked(false); break; case KCalCore::Event::Opaque: mUi->mFreeBusyCheck->setChecked(true); break; } } void IncidenceDateTime::load(const KCalCore::Journal::Ptr &journal, bool isTemplate, bool templateOverridesTimes) { // First en/disable the necessary ui bits and pieces mUi->mStartCheck->setVisible(false); mUi->mStartCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. mUi->mEndCheck->setVisible(false); mUi->mEndCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. mUi->mEndDateEdit->setVisible(false); mUi->mEndTimeEdit->setVisible(false); mUi->mTimeZoneComboEnd->setVisible(false); mUi->mEndLabel->setVisible(false); mUi->mFreeBusyCheck->setVisible(false); // Start time connect(mUi->mStartTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::updateStartTime); connect(mUi->mStartDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::updateStartDate); connect(mUi->mTimeZoneComboStart, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::updateStartSpec); mUi->mWholeDayCheck->setChecked(journal->allDay()); enableTimeEdits(); if (isTemplate) { if (templateOverridesTimes) { // We only use the template times if the user didn't override them. setTimes(journal->dtStart(), QDateTime()); } } else { QDateTime startDT = journal->dtStart(); // Convert UTC to local timezone, if needed (i.e. for kolab #204059) if (startDT.timeZone() == QTimeZone::utc()) { startDT = startDT.toLocalTime(); } setDateTimes(startDT, QDateTime()); } } void IncidenceDateTime::load(const KCalCore::Todo::Ptr &todo, bool isTemplate, bool templateOverridesTimes) { // First en/disable the necessary ui bits and pieces mUi->mStartCheck->setVisible(true); mUi->mStartCheck->setChecked(todo->hasStartDate()); mUi->mStartDateEdit->setEnabled(todo->hasStartDate()); mUi->mStartTimeEdit->setEnabled(todo->hasStartDate()); mUi->mTimeZoneComboStart->setEnabled(todo->hasStartDate()); mUi->mEndLabel->setText(i18nc("@label The due date/time of a to-do", "Due:")); mUi->mEndCheck->setVisible(true); mUi->mEndCheck->setChecked(todo->hasDueDate()); mUi->mEndDateEdit->setEnabled(todo->hasDueDate()); mUi->mEndTimeEdit->setEnabled(todo->hasDueDate()); mUi->mTimeZoneComboEnd->setEnabled(todo->hasDueDate()); // These fields where not enabled in the old code either: mUi->mFreeBusyCheck->setVisible(false); const bool hasDateTimes = mUi->mEndCheck->isChecked() || mUi->mStartCheck->isChecked(); mUi->mWholeDayCheck->setChecked(hasDateTimes && todo->allDay()); mUi->mWholeDayCheck->setEnabled(hasDateTimes); // Connect to the right logic connect(mUi->mStartCheck, &QCheckBox::toggled, this, &IncidenceDateTime::enableStartEdit); connect(mUi->mStartCheck, &QCheckBox::toggled, this, &IncidenceDateTime::startDateTimeToggled); connect(mUi->mStartDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mStartTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::updateStartTime); connect(mUi->mTimeZoneComboStart, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndCheck, &QCheckBox::toggled, this, &IncidenceDateTime::enableEndEdit); connect(mUi->mEndCheck, &QCheckBox::toggled, this, &IncidenceDateTime::endDateTimeToggled); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::endDateChanged); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::endTimeChanged); connect(mUi->mTimeZoneComboEnd, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::checkDirtyStatus); const QDateTime rightNow = QDateTime::currentDateTime(); if (isTemplate) { if (templateOverridesTimes) { // We only use the template times if the user didn't override them. setTimes(todo->dtStart(), todo->dateTime(KCalCore::Incidence::RoleEnd)); } } else { const QDateTime endDT = todo->hasDueDate() ? todo->dtDue(true /** first */) : rightNow; const QDateTime startDT = todo->hasStartDate() ? todo->dtStart(true /** first */) : rightNow; setDateTimes(startDT, endDT); } } void IncidenceDateTime::save(const KCalCore::Event::Ptr &event) { if (mUi->mWholeDayCheck->isChecked()) { // All day event event->setAllDay(true); // TODO: need to change this. QDateTime eventDTStart = currentStartDateTime(); event->setAllDay(true); event->setDtStart(eventDTStart); QDateTime eventDTEnd = currentEndDateTime(); event->setDtEnd(eventDTEnd); } else { // Timed Event event->setAllDay(false); // set date/time end event->setDtStart(currentStartDateTime()); event->setDtEnd(currentEndDateTime()); } // Free == Event::Transparent // Busy == Event::Opaque event->setTransparency(mUi->mFreeBusyCheck->isChecked() ? KCalCore::Event::Opaque : KCalCore::Event::Transparent); } void IncidenceDateTime::save(const KCalCore::Todo::Ptr &todo) { if (mUi->mStartCheck->isChecked()) { todo->setDtStart(currentStartDateTime()); // Set allday must be executed after setDtStart todo->setAllDay(mUi->mWholeDayCheck->isChecked()); if (currentStartDateTime() != mInitialStartDT) { // We don't offer any way to edit the current completed occurrence. // So, if the start date changes, reset the dtRecurrence todo->setDtRecurrence(currentStartDateTime()); } } else { todo->setDtStart(QDateTime()); } if (mUi->mEndCheck->isChecked()) { todo->setDtDue(currentEndDateTime(), true /** first */); // Set allday must be executed after setDtDue todo->setAllDay(mUi->mWholeDayCheck->isChecked()); } else { todo->setDtDue(QDateTime()); } } void IncidenceDateTime::save(const KCalCore::Journal::Ptr &journal) { journal->setAllDay(mUi->mWholeDayCheck->isChecked()); if (mUi->mWholeDayCheck->isChecked()) { // All day journal QDateTime journalDTStart = currentStartDateTime(); journal->setAllDay(true); journal->setDtStart(journalDTStart); } else { // Timed Journal // set date/time end journal->setDtStart(currentStartDateTime()); } } void IncidenceDateTime::setDateTimes(const QDateTime &start, const QDateTime &end) { if (start.isValid()) { mUi->mStartDateEdit->setDate(start.date()); mUi->mStartTimeEdit->setTime(start.time()); mUi->mTimeZoneComboStart->selectTimeZone(start.timeZone()); } else { QDateTime dt = QDateTime::currentDateTime(); mUi->mStartDateEdit->setDate(dt.date()); mUi->mStartTimeEdit->setTime(dt.time()); mUi->mTimeZoneComboStart->selectTimeZone(dt.timeZone()); } if (end.isValid()) { mUi->mEndDateEdit->setDate(end.date()); mUi->mEndTimeEdit->setTime(end.time()); mUi->mTimeZoneComboEnd->selectTimeZone(end.timeZone()); } else { QDateTime dt(QDate::currentDate(), QTime::currentTime().addSecs(60 * 60)); mUi->mEndDateEdit->setDate(dt.date()); mUi->mEndTimeEdit->setTime(dt.time()); mUi->mTimeZoneComboEnd->selectTimeZone(dt.timeZone()); } mCurrentStartDateTime = currentStartDateTime(); Q_EMIT startDateChanged(start.date()); Q_EMIT startTimeChanged(start.time()); Q_EMIT endDateChanged(end.date()); Q_EMIT endTimeChanged(end.time()); updateStartToolTips(); updateEndToolTips(); } void IncidenceDateTime::updateStartToolTips() { if (mUi->mStartCheck->isChecked()) { QString datetimeStr = KCalUtils::IncidenceFormatter::dateTimeToString( currentStartDateTime(), mUi->mWholeDayCheck->isChecked(), false); mUi->mStartDateEdit->setToolTip(i18n("Starts: %1", datetimeStr)); mUi->mStartTimeEdit->setToolTip(i18n("Starts: %1", datetimeStr)); } else { mUi->mStartDateEdit->setToolTip(i18n("Starting Date")); mUi->mStartTimeEdit->setToolTip(i18n("Starting Time")); } } void IncidenceDateTime::updateEndToolTips() { if (mUi->mStartCheck->isChecked()) { QString datetimeStr = KCalUtils::IncidenceFormatter::dateTimeToString( currentEndDateTime(), mUi->mWholeDayCheck->isChecked(), false); if (mLoadedIncidence->type() == KCalCore::Incidence::TypeTodo) { mUi->mEndDateEdit->setToolTip(i18n("Due on: %1", datetimeStr)); mUi->mEndTimeEdit->setToolTip(i18n("Due on: %1", datetimeStr)); } else { mUi->mEndDateEdit->setToolTip(i18n("Ends: %1", datetimeStr)); mUi->mEndTimeEdit->setToolTip(i18n("Ends: %1", datetimeStr)); } } else { if (mLoadedIncidence->type() == KCalCore::Incidence::TypeTodo) { mUi->mEndDateEdit->setToolTip(i18n("Due Date")); mUi->mEndTimeEdit->setToolTip(i18n("Due Time")); } else { mUi->mEndDateEdit->setToolTip(i18n("Ending Date")); mUi->mEndTimeEdit->setToolTip(i18n("Ending Time")); } } } void IncidenceDateTime::setTimes(const QDateTime &start, const QDateTime &end) { // like setDateTimes(), but it set only the start/end time, not the date // it is used while applying a template to an event. mUi->mStartTimeEdit->blockSignals(true); mUi->mStartTimeEdit->setTime(start.time()); mUi->mStartTimeEdit->blockSignals(false); mUi->mEndTimeEdit->setTime(end.time()); mUi->mTimeZoneComboStart->selectTimeZone(start.timeZone()); mUi->mTimeZoneComboEnd->selectTimeZone(end.timeZone()); // emitDateTimeStr(); } void IncidenceDateTime::setStartDate(const QDate &newDate) { mUi->mStartDateEdit->setDate(newDate); updateStartDate(newDate); } void IncidenceDateTime::setStartTime(const QTime &newTime) { mUi->mStartTimeEdit->setTime(newTime); updateStartTime(newTime); } bool IncidenceDateTime::startDateTimeEnabled() const { return mUi->mStartCheck->isChecked(); } bool IncidenceDateTime::endDateTimeEnabled() const { return mUi->mEndCheck->isChecked(); } bool IncidenceDateTime::isValid() const { if (startDateTimeEnabled() && !currentStartDateTime().isValid()) { mLastErrorString = i18nc("@info", "Invalid start date and time."); qCWarning(INCIDENCEEDITOR_LOG) << "Start date is invalid"; return false; } if (endDateTimeEnabled() && !currentEndDateTime().isValid()) { mLastErrorString = i18nc("@info", "Invalid end date and time."); qCWarning(INCIDENCEEDITOR_LOG) << "End date is invalid"; return false; } if (startDateTimeEnabled() && endDateTimeEnabled() && currentStartDateTime() > currentEndDateTime()) { if (mLoadedIncidence->type() == KCalCore::Incidence::TypeEvent) { mLastErrorString = i18nc("@info", "The event ends before it starts.\n" "Please correct dates and times."); } else if (mLoadedIncidence->type() == KCalCore::Incidence::TypeTodo) { mLastErrorString = i18nc("@info", "The to-do is due before it starts.\n" "Please correct dates and times."); } else if (mLoadedIncidence->type() == KCalCore::Incidence::TypeJournal) { return true; } qCDebug(INCIDENCEEDITOR_LOG) << mLastErrorString; return false; } else { mLastErrorString.clear(); return true; } } void IncidenceDateTime::printDebugInfo() const { qCDebug(INCIDENCEEDITOR_LOG) << "startDateTimeEnabled() : " << startDateTimeEnabled(); qCDebug(INCIDENCEEDITOR_LOG) << "endDateTimeEnabled() : " << endDateTimeEnabled(); qCDebug(INCIDENCEEDITOR_LOG) << "currentStartDateTime().isValid(): " << currentStartDateTime().isValid(); qCDebug(INCIDENCEEDITOR_LOG) << "currentEndDateTime().isValid() : " << currentEndDateTime().isValid(); qCDebug(INCIDENCEEDITOR_LOG) << "currentStartDateTime() : " << currentStartDateTime().toString(); qCDebug(INCIDENCEEDITOR_LOG) << "currentEndDateTime() : " << currentEndDateTime().toString(); qCDebug(INCIDENCEEDITOR_LOG) << "Incidence type : " << mLoadedIncidence->type(); qCDebug(INCIDENCEEDITOR_LOG) << "allday : " << mLoadedIncidence->allDay(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialStartDT : " << mInitialStartDT.toString(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialEndDT : " << mInitialEndDT.toString(); qCDebug(INCIDENCEEDITOR_LOG) << "currentStartDateTime().timeZone(): " << currentStartDateTime().timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "currentEndDateTime().timeZone() : " << currentEndDateTime().timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialStartDT.timeZone() : " << mInitialStartDT.timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialEndDT.timeZone() : " << mInitialEndDT.timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test1: " << (mLoadedIncidence->allDay() != mUi->mWholeDayCheck->isChecked()); if (mLoadedIncidence->type() == KCalCore::Incidence::TypeEvent) { KCalCore::Event::Ptr event = mLoadedIncidence.staticCast(); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test2: " << (mUi->mFreeBusyCheck->isChecked() && event->transparency() != KCalCore::Event::Opaque); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test3: " << (!mUi->mFreeBusyCheck->isChecked() && event->transparency() != KCalCore::Event::Transparent); } if (mLoadedIncidence->allDay()) { qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4: " << (mUi->mStartDateEdit->date() != mInitialStartDT.date() || mUi->mEndDateEdit->date() != mInitialEndDT.date()); } else { qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.1: " << (currentStartDateTime() != mInitialStartDT); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.2: " << (currentEndDateTime() != mInitialEndDT); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.3: " << (currentStartDateTime().timeZone() != mInitialStartDT.timeZone()); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.4: " << (currentEndDateTime().timeZone() != mInitialEndDT.timeZone()); } } void IncidenceDateTime::setTimeZoneLabelEnabled(bool enable) { mUi->mTimeZoneLabel->setVisible(enable); } diff --git a/src/incidencedescription.cpp b/src/incidencedescription.cpp index 39a2068..5591276 100644 --- a/src/incidencedescription.cpp +++ b/src/incidencedescription.cpp @@ -1,230 +1,230 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencedescription.h" #include "ui_dialogdesktop.h" #include #include "incidenceeditor_debug.h" #include #include #include using namespace IncidenceEditorNG; namespace IncidenceEditorNG { class IncidenceDescriptionPrivate { public: IncidenceDescriptionPrivate() : mRichTextEnabled(false) { } QString mRealOriginalDescriptionEditContents; bool mRichTextEnabled; }; } IncidenceDescription::IncidenceDescription(Ui::EventOrTodoDesktop *ui) : IncidenceEditor(nullptr) , mUi(ui) , d(new IncidenceDescriptionPrivate()) { setObjectName(QStringLiteral("IncidenceDescription")); mUi->mRichTextLabel->setContextMenuPolicy(Qt::NoContextMenu); setupToolBar(); connect(mUi->mRichTextLabel, &QLabel::linkActivated, this, &IncidenceDescription::toggleRichTextDescription); connect( mUi->mDescriptionEdit->richTextComposer(), &KPIMTextEdit::RichTextComposer::textChanged, this, &IncidenceDescription::checkDirtyStatus); } IncidenceDescription::~IncidenceDescription() { delete d; } void IncidenceDescription::load(const KCalCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; d->mRealOriginalDescriptionEditContents.clear(); if (incidence) { enableRichTextDescription(incidence->descriptionIsRich()); if (incidence->descriptionIsRich()) { mUi->mDescriptionEdit->richTextComposer()->setHtml(incidence->richDescription()); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toHtml(); } else { mUi->mDescriptionEdit->richTextComposer()->setPlainText(incidence->description()); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toPlainText(); } } else { enableRichTextDescription(false); mUi->mDescriptionEdit->richTextComposer()->clear(); } mWasDirty = false; } void IncidenceDescription::save(const KCalCore::Incidence::Ptr &incidence) { if (d->mRichTextEnabled) { incidence->setDescription(mUi->mDescriptionEdit->richTextComposer()->toHtml(), true); } else { incidence->setDescription(mUi->mDescriptionEdit->richTextComposer()->toPlainText(), false); } } bool IncidenceDescription::isDirty() const { /* Sometimes, what you put in a KRichTextWidget isn't the same as what you get out. Line terminators (cr,lf) for example can be converted. So, to see if the user changed something, we can't compare the original incidence with the new editor content. Instead we compare the new editor content, with the original editor content, this way any tranformation regarding non-printable chars will be irrelevant. */ if (d->mRichTextEnabled) { return !mLoadedIncidence->descriptionIsRich() || d->mRealOriginalDescriptionEditContents != mUi->mDescriptionEdit->richTextComposer()->toHtml(); } else { return mLoadedIncidence->descriptionIsRich() || d->mRealOriginalDescriptionEditContents != mUi->mDescriptionEdit->richTextComposer()->toPlainText(); } } void IncidenceDescription::enableRichTextDescription(bool enable) { d->mRichTextEnabled = enable; QString rt(i18nc("@action Enable or disable rich text editting", "Enable rich text")); - QString placeholder(QStringLiteral("%1 >>")); + QString placeholder(QStringLiteral("%1 >>")); if (enable) { rt = i18nc("@action Enable or disable rich text editting", "Disable rich text"); - placeholder = QStringLiteral("<< %1"); + placeholder = QStringLiteral("<< %1"); mUi->mDescriptionEdit->richTextComposer()->activateRichText(); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toHtml(); } else { mUi->mDescriptionEdit->richTextComposer()->switchToPlainText(); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toPlainText(); } placeholder = placeholder.arg(rt); mUi->mRichTextLabel->setText(placeholder); mUi->mDescriptionEdit->richTextComposer()->setEnableActions(enable); mUi->mEditToolBarPlaceHolder->setVisible(enable); checkDirtyStatus(); } void IncidenceDescription::toggleRichTextDescription() { enableRichTextDescription(!d->mRichTextEnabled); } void IncidenceDescription::setupToolBar() { #ifndef QT_NO_TOOLBAR KActionCollection *collection = new KActionCollection(this); mUi->mDescriptionEdit->richTextComposer()->createActions(collection); KToolBar *mEditToolBar = new KToolBar(mUi->mEditToolBarPlaceHolder); mEditToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_bold"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_italic"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_underline"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_strikeout"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_font_family"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_font_size"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_foreground_color"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_background_color"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_list_style"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_left"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_center"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_right"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_justify"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_painter"))); mUi->mDescriptionEdit->richTextComposer()->setEnableActions(false); QGridLayout *layout = new QGridLayout(mUi->mEditToolBarPlaceHolder); layout->addWidget(mEditToolBar); #endif // By default we don't show the rich text toolbar. mUi->mEditToolBarPlaceHolder->setVisible(false); d->mRichTextEnabled = false; } void IncidenceDescription::printDebugInfo() const { // We're going to crash qCDebug(INCIDENCEEDITOR_LOG) << "RichText enabled " << d->mRichTextEnabled; if (mLoadedIncidence) { qCDebug(INCIDENCEEDITOR_LOG) << "Incidence description is rich " << mLoadedIncidence->descriptionIsRich(); if (mLoadedIncidence->descriptionIsRich()) { qCDebug(INCIDENCEEDITOR_LOG) << "desc is rich, and it is " << mLoadedIncidence->richDescription() << "; " << "widget has " << mUi->mDescriptionEdit->richTextComposer()->toHtml() << "; " << "expr mLoadedIncidence->richDescription() != mUi->mDescriptionEdit->toHtml() is " << (mLoadedIncidence->richDescription() != mUi->mDescriptionEdit->richTextComposer()->toHtml()); } else { qCDebug(INCIDENCEEDITOR_LOG) << "desc is not rich, and it is " << mLoadedIncidence->description() << "; " << "widget has " << mUi->mDescriptionEdit->richTextComposer()->toPlainText() << "; " << "expr mLoadedIncidence->description() != mUi->mDescriptionEdit->toPlainText() is " << (mLoadedIncidence->description() != mUi->mDescriptionEdit->richTextComposer()->toPlainText()); } } else { qCDebug(INCIDENCEEDITOR_LOG) << "Incidence is invalid"; } } diff --git a/src/ui/dialogdesktop.ui b/src/ui/dialogdesktop.ui index a349112..fc0f668 100644 --- a/src/ui/dialogdesktop.ui +++ b/src/ui/dialogdesktop.ui @@ -1,1849 +1,1849 @@ EventOrTodoDesktop 0 0 661 660 false 0 0 0 0 0 0 Qt::LeftToRight Calen&dar: Qt::PlainText Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse 0 0 0 0 You are Invited, what do you want to do? Accept the invitation Click this button to accept the invitation. Accept Decline Qt::Horizontal 40 20 0 0 75 true Set the title Sets the Title of this event or to-do. Qt::LeftToRight &Title: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter mSummaryEdit 0 0 Set the title Sets the Title of this event or to-do. 0 0 Qt::LeftToRight &Location: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter mLocationEdit 0 0 Set the location Sets where the event or to-do will take place. Qt::Horizontal Completion: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 0 100 10 true Qt::Horizontal QSlider::TicksBelow 10 0 0 completed Priority: 5 unspecified 1 (highest) 2 3 4 5 (medium) 6 7 8 9 (lowest) 0 0 Set if this to-do's start and due dates have times associated with them. All Day true Qt::Horizontal QSizePolicy::Fixed 40 20 Blocks me for other events Qt::Horizontal 40 20 0 0 Qt::LeftToRight S&tart: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter mStartDateEdit 0 0 Set the start date Sets the start date for this to-do false 0 0 Sets the start time for this to-do. false 0 0 Select the timezone for this event. It will also affect recurrences 0 0 false - <a href="hide"><font color='blue'>&lt;&lt; Time zones</font></a> + <a href="hide"><< Time zones</a> Qt::RichText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Horizontal 40 20 0 0 Qt::LeftToRight E&nd: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter mEndDateEdit 0 0 Sets the due date for this to-do. false 0 0 Sets the due time for this to-do. false 0 0 Select the timezone for this event. It will also affect recurrences Qt::Horizontal 40 0 Qt::Horizontal 0 General 0 0 Set the secrecy level Sets whether the access to this event or to-do is restricted. Please note that KOrganizer currently does not use this setting, so the implementation of the restrictions will depend on the groupware server. This means that events or to-dos marked as private or confidential may be visible to others. Access: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 - <a href=\"hide\"><font color='blue'>Rich text &gt;&gt;</font></a> + <a href=\"hide\">Rich text &gt;&gt;</a> Qt::RichText Qt::Horizontal 40 20 0 0 Categories: Set the secrecy level Sets whether the access to this event or to-do is restricted. Please note that KOrganizer currently does not use this setting, so the implementation of the restrictions will depend on the groupware server. This means that events or to-dos marked as private or confidential may be visible to others. Attendees QAbstractItemView::AllEditTriggers false Meeting organizer: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Participants: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Schedule the meeting with your attendees. Opens the scheduling dialog, which will assist in picking a time slot that works for all attendees. Schedule... Qt::Horizontal 258 24 false Substitute with group members Select attendees from your address book. Opens your address book, allowing you to select new attendees from it. Select Attendees... 0 0 1 0 0 0 0 0 0 Set the organizer identity Sets the identity corresponding to the organizer of this to-do or event. Identities can be set in the 'Personal' section of the KOrganizer configuration. In addition, identities are gathered from your KMail settings and from your address book. 0 0 0 0 0 0 TextLabel Resources QAbstractItemView::AllEditTriggers true Qt::SolidLine false false false true true Book resource false false Qt::Horizontal QSizePolicy::Preferred 40 0 Find Resources... Reminder 0 0 Add default reminder: 0 0 0 0 Add Qt::Horizontal 141 22 QAbstractItemView::NoEditTriggers New Modify Disable Remove Qt::Vertical 88 126 Recurrence 0 0 Repeats: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Never Daily Weekly Monthly Yearly 0 0 every 0 0 1 999 1 0 0 day(s) This and future occurrences. Qt::Horizontal 40 20 0 0 2 0 0 0 0 0 0 0 0 0 0 QComboBox::AdjustToContentsOnFirstShow 0 0 0 0 0 0 QComboBox::AdjustToContents Qt::Horizontal 40 20 0 0 0 0 0 0 QComboBox::AdjustToContents Qt::Horizontal 40 20 0 0 Ends: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 never on after 0 0 2 0 0 0 0 0 0 0 0 0 0 Date after which the event or to-do should stop recurring Qt::Horizontal 276 18 0 0 0 0 0 1 9999 0 0 occurrence(s) 0 0 Exceptions: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 false Add Qt::Horizontal 40 20 0 0 QAbstractItemView::ExtendedSelection on: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Remove Qt::Vertical 20 40 Attachments 0 0 0 0 Add an attachment Shows a dialog used to select an attachment to add to this event or to-do as link or as inline data. Add false 0 0 Remove the selected attachment Removes the attachment selected in the list above from this event or to-do. Remove Qt::Vertical 20 210 QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults KPIM::KCheckComboBox KComboBox
Libkdepim/KCheckComboBox
KLineEdit QLineEdit
klineedit.h
KTimeComboBox QComboBox
ktimecombobox.h
KDateComboBox QComboBox
kdatecombobox.h
KSeparator QFrame
kseparator.h
1
KComboBox QComboBox
kcombobox.h
KPIMTextEdit::RichTextComposerWidget QWidget
kpimtextedit/richtextcomposerwidget.h
KPIM::KWeekdayCheckCombo KPIM::KCheckComboBox
Libkdepim/KWeekdayCheckCombo
IncidenceEditorNG::KTimeZoneComboBox KComboBox
ktimezonecombobox.h
CalendarSupport::MessageWidget QWidget
CalendarSupport/MessageWidget
Akonadi::TagWidget QWidget
AkonadiWidgets/TagWidget
1
mCalSelectorPlaceHolder mAcceptInvitationButton mDeclineInvitationButton mSummaryEdit mLocationEdit mCompletionSlider mPriorityCombo mWholeDayCheck mFreeBusyCheck mStartCheck mStartDateEdit mStartTimeEdit mTimeZoneComboStart mEndCheck mEndDateEdit mEndTimeEdit mTimeZoneComboEnd mTabWidget mTagWidget mSecrecyCombo mSolveButton mSelectButton mOrganizerCombo mAlarmPresetCombo mAlarmAddPresetButton mAlarmList mAlarmNewButton mAlarmConfigureButton mAlarmToggleButton mAlarmRemoveButton mRecurrenceTypeCombo mFrequencyEdit mThisAndFutureCheck mWeekDayCombo mMonthlyCombo mYearlyCombo mRecurrenceEndCombo mRecurrenceEndDate mEndDurationEdit mExceptionDateEdit mExceptionAddButton mExceptionList mExceptionRemoveButton mAddButton mRemoveButton mRecurrenceEndCombo activated(int) mRecurrenceEndStack setCurrentIndex(int) 144 314 144 314 mRecurrenceTypeCombo activated(int) mRepeatStack setCurrentIndex(int) 142 304 104 280 mNewResource returnPressed() mBookResourceButton click() 271 805 402 808