4#include <KLocalizedString>
7#include <incidencewrapper.h>
10IncidenceWrapper::IncidenceWrapper(
QObject *parent)
34 connect(CalendarManager::instance(), &CalendarManager::calendarChanged,
this, &IncidenceWrapper::resetChildIncidences);
45IncidenceWrapper::~IncidenceWrapper()
47 cleanupChildIncidences();
50void IncidenceWrapper::notifyDataChanged()
52 Q_EMIT incidenceTypeChanged();
53 Q_EMIT incidenceTypeStrChanged();
54 Q_EMIT incidenceIconNameChanged();
55 Q_EMIT collectionIdChanged();
57 Q_EMIT parentIncidenceChanged();
58 Q_EMIT childIncidencesChanged();
60 Q_EMIT categoriesChanged();
61 Q_EMIT descriptionChanged();
63 Q_EMIT incidenceStartChanged();
64 Q_EMIT incidenceStartDateDisplayChanged();
65 Q_EMIT incidenceStartTimeDisplayChanged();
66 Q_EMIT incidenceEndChanged();
67 Q_EMIT incidenceEndDateDisplayChanged();
68 Q_EMIT incidenceEndTimeDisplayChanged();
70 Q_EMIT startTimeZoneUTCOffsetMinsChanged();
71 Q_EMIT endTimeZoneUTCOffsetMinsChanged();
73 Q_EMIT durationDisplayStringChanged();
78 Q_EMIT recurrenceDataChanged();
81 Q_EMIT todoCompletedChanged();
82 Q_EMIT todoCompletionDtChanged();
83 Q_EMIT todoPercentCompleteChanged();
84 Q_EMIT googleConferenceUrlChanged();
92void IncidenceWrapper::setIncidenceItem(
const Akonadi::Item &incidenceItem)
98 Q_EMIT incidenceItemChanged();
99 Q_EMIT collectionIdChanged();
101 qWarning() <<
"This is not an incidence item.";
112 m_incidence = incidencePtr;
115 m_originalIncidence = originalIncidence;
117 Q_EMIT incidencePtrChanged(incidencePtr);
118 Q_EMIT originalIncidencePtrChanged();
124 return m_originalIncidence;
127int IncidenceWrapper::incidenceType()
const
129 return m_incidence->type();
132QString IncidenceWrapper::incidenceTypeStr()
const
137QString IncidenceWrapper::incidenceIconName()
const
139 return m_incidence->iconName();
142QString IncidenceWrapper::uid()
const
144 return m_incidence->uid();
147qint64 IncidenceWrapper::collectionId()
const
152void IncidenceWrapper::setCollectionId(qint64 collectionId)
154 m_collectionId = collectionId;
155 Q_EMIT collectionIdChanged();
158QString IncidenceWrapper::parent()
const
160 return m_incidence->relatedTo();
163void IncidenceWrapper::setParent(
QString parent)
165 m_incidence->setRelatedTo(parent);
166 updateParentIncidence();
172 updateParentIncidence();
173 return m_parentIncidence.
data();
176QVariantList IncidenceWrapper::childIncidences()
178 resetChildIncidences();
179 return m_childIncidences;
182QString IncidenceWrapper::summary()
const
184 return m_incidence->summary();
187void IncidenceWrapper::setSummary(
const QString &summary)
189 m_incidence->setSummary(summary);
195 return m_incidence->categories();
198void IncidenceWrapper::setCategories(
QStringList categories)
200 m_incidence->setCategories(categories);
201 Q_EMIT categoriesChanged();
204QString IncidenceWrapper::description()
const
206 return m_incidence->description();
209void IncidenceWrapper::setDescription(
const QString &description)
211 if (m_incidence->description() == description) {
214 m_incidence->setDescription(description);
215 Q_EMIT descriptionChanged();
218QString IncidenceWrapper::location()
const
220 return m_incidence->location();
223void IncidenceWrapper::setLocation(
const QString &location)
225 m_incidence->setLocation(location);
229bool IncidenceWrapper::hasGeo()
const
231 return m_incidence->hasGeo();
234float IncidenceWrapper::geoLatitude()
const
236 return m_incidence->geoLatitude();
239float IncidenceWrapper::geoLongitude()
const
241 return m_incidence->geoLongitude();
244QDateTime IncidenceWrapper::incidenceStart()
const
246 return m_incidence->dtStart();
249void IncidenceWrapper::setIncidenceStart(
const QDateTime &incidenceStart,
bool respectTimeZone)
257 auto oldStart = this->incidenceStart();
259 if (respectTimeZone) {
260 m_incidence->setDtStart(incidenceStart);
261 auto newTzEnd = incidenceEnd();
262 newTzEnd.setTimeZone(incidenceStart.
timeZone());
263 setIncidenceEnd(newTzEnd,
true);
265 const auto date = incidenceStart.
date();
266 const auto time = incidenceStart.
time();
271 m_incidence->setDtStart(
start);
274 auto oldStartEndDifference = oldStart.secsTo(incidenceEnd());
275 auto newEnd = this->incidenceStart().
addSecs(oldStartEndDifference);
276 setIncidenceEnd(newEnd);
278 Q_EMIT incidenceStartChanged();
279 Q_EMIT incidenceStartDateDisplayChanged();
280 Q_EMIT incidenceStartTimeDisplayChanged();
282 Q_EMIT durationDisplayStringChanged();
285void IncidenceWrapper::setIncidenceStartDate(
int day,
int month,
int year)
288 date.
setDate(year, month, day);
290 auto newStart = incidenceStart();
291 newStart.setDate(date);
293 setIncidenceStart(newStart,
true);
296void IncidenceWrapper::setIncidenceStartTime(
int hours,
int minutes)
299 time.
setHMS(hours, minutes, 0);
301 auto newStart = incidenceStart();
302 newStart.setTime(time);
304 setIncidenceStart(newStart,
true);
307QString IncidenceWrapper::incidenceStartDateDisplay()
const
312QString IncidenceWrapper::incidenceStartTimeDisplay()
const
317QDateTime IncidenceWrapper::incidenceEnd()
const
319 if (m_incidence->type() == KCalendarCore::Incidence::IncidenceType::TypeEvent) {
321 return event->
dtEnd();
322 }
else if (m_incidence->type() == KCalendarCore::Incidence::IncidenceType::TypeTodo) {
324 return todo->dtDue();
329void IncidenceWrapper::setIncidenceEnd(
const QDateTime &incidenceEnd,
bool respectTimeZone)
332 if (respectTimeZone) {
335 const auto date = incidenceEnd.
date();
336 const auto time = incidenceEnd.
time();
342 if (m_incidence->type() == KCalendarCore::Incidence::IncidenceType::TypeEvent) {
345 }
else if (m_incidence->type() == KCalendarCore::Incidence::IncidenceType::TypeTodo) {
349 qWarning() <<
"Unknown incidence type";
351 Q_EMIT incidenceEndChanged();
352 Q_EMIT incidenceEndDateDisplayChanged();
353 Q_EMIT incidenceEndTimeDisplayChanged();
355 Q_EMIT durationDisplayStringChanged();
358void IncidenceWrapper::setIncidenceEndDate(
int day,
int month,
int year)
361 date.
setDate(year, month, day);
363 auto newEnd = incidenceEnd();
364 newEnd.setDate(date);
366 setIncidenceEnd(newEnd,
true);
369void IncidenceWrapper::setIncidenceEndTime(
int hours,
int minutes)
372 time.
setHMS(hours, minutes, 0);
374 auto newEnd = incidenceEnd();
375 newEnd.setTime(time);
377 setIncidenceEnd(newEnd,
true);
380QString IncidenceWrapper::incidenceEndDateDisplay()
const
385QString IncidenceWrapper::incidenceEndTimeDisplay()
const
390void IncidenceWrapper::setIncidenceTimeToNearestQuarterHour(
bool setStartTime,
bool setEndTime)
393 const int quarterHourInSecs = 15 * 60;
394 const int secsToSet = now + (quarterHourInSecs - now % quarterHourInSecs);
396 startTime.setSecsSinceEpoch(secsToSet);
398 setIncidenceStart(startTime,
true);
401 setIncidenceEnd(startTime.addSecs(3600),
true);
410void IncidenceWrapper::setTimeZone(
const QByteArray &timeZone)
413 if (
start.isValid()) {
415 setIncidenceStart(
start,
true);
421 setIncidenceEnd(end,
true);
425 Q_EMIT startTimeZoneUTCOffsetMinsChanged();
426 Q_EMIT endTimeZoneUTCOffsetMinsChanged();
429int IncidenceWrapper::startTimeZoneUTCOffsetMins()
434int IncidenceWrapper::endTimeZoneUTCOffsetMins()
441 return m_incidence->duration();
457QString IncidenceWrapper::durationDisplayString()
const
459 return formatSpelloutDuration(duration(), m_format, allDay());
462bool IncidenceWrapper::allDay()
const
464 return m_incidence->allDay();
467void IncidenceWrapper::setAllDay(
bool allDay)
469 m_incidence->setAllDay(allDay);
473int IncidenceWrapper::priority()
const
475 return m_incidence->priority();
478void IncidenceWrapper::setPriority(
int priority)
480 m_incidence->setPriority(priority);
490QVariantMap IncidenceWrapper::recurrenceData()
492 QBitArray weekDaysBits = m_incidence->recurrence()->days();
495 for (
int i = 0; i < weekDaysBits.
size(); i++) {
496 weekDaysBools[i] = weekDaysBits[i];
499 QVariantList monthPositions;
500 const auto monthPositionsToConvert = m_incidence->recurrence()->monthPositions();
501 for (
const auto &pos : monthPositionsToConvert) {
502 QVariantMap positionToAdd;
503 positionToAdd[QStringLiteral(
"day")] = pos.day();
504 positionToAdd[QStringLiteral(
"pos")] = pos.pos();
505 monthPositions.append(positionToAdd);
511 {QStringLiteral(
"duration"), m_incidence->recurrence()->duration()},
512 {QStringLiteral(
"frequency"), m_incidence->recurrence()->frequency()},
513 {QStringLiteral(
"startDateTime"), m_incidence->recurrence()->startDateTime()},
515 {QStringLiteral(
"endDateTime"), m_incidence->recurrence()->endDateTime()},
517 {QStringLiteral(
"allDay"), m_incidence->recurrence()->allDay()},
518 {QStringLiteral(
"type"), m_incidence->recurrence()->recurrenceType()},
519 {QStringLiteral(
"monthDays"),
QVariant::fromValue(m_incidence->recurrence()->monthDays())},
520 {QStringLiteral(
"monthPositions"), monthPositions},
522 {QStringLiteral(
"yearDates"),
QVariant::fromValue(m_incidence->recurrence()->yearDates())},
523 {QStringLiteral(
"yearMonths"),
QVariant::fromValue(m_incidence->recurrence()->yearMonths())},
527void IncidenceWrapper::setRecurrenceDataItem(
const QString &key,
const QVariant &value)
529 QVariantMap
map = recurrenceData();
530 if (
map.contains(key)) {
534 if (!jsval.isArray()) {
541 for (
int i = 0; i < vlist.size(); i++) {
542 days[i] = vlist[i].toBool();
548 for (
int i = 0; i < 7; ++i) {
549 if (days.testBit(i)) {
555 rrule->setByDays(positions);
556 m_incidence->recurrence()->updated();
558 }
else if (key == QStringLiteral(
"duration")) {
559 m_incidence->recurrence()->setDuration(value.
toInt());
561 }
else if (key == QStringLiteral(
"frequency")) {
562 m_incidence->recurrence()->setFrequency(value.
toInt());
564 }
else if ((key == QStringLiteral(
"startDateTime") || key == QStringLiteral(
"endDateTime")) && value.
toDateTime().
isValid()) {
571 if (key == QStringLiteral(
"startDateTime")) {
572 m_incidence->recurrence()->setStartDateTime(adjustedDt,
false);
574 }
else if (key == QStringLiteral(
"endDateTime")) {
575 m_incidence->recurrence()->setEndDateTime(adjustedDt);
578 }
else if (key == QStringLiteral(
"allDay")) {
579 m_incidence->recurrence()->setAllDay(value.
toBool());
596 for (
const auto &pos : values) {
598 newPos.setDay(pos[QStringLiteral(
"day")].toInt());
599 newPos.setPos(pos[QStringLiteral(
"pos")].toInt());
600 newMonthPositions.
append(newPos);
603 m_incidence->recurrence()->setMonthlyPos(newMonthPositions);
606 Q_EMIT recurrenceDataChanged();
609QString IncidenceWrapper::googleConferenceUrl()
611 return m_incidence->customProperty(
"LIBKGAPI",
"EventHangoutLink");
614QVariantMap IncidenceWrapper::organizer()
616 auto organizerPerson = m_incidence->organizer();
617 return QVariantMap{{QStringLiteral(
"name"), organizerPerson.name()},
618 {QStringLiteral(
"email"), organizerPerson.email()},
619 {QStringLiteral(
"fullName"), organizerPerson.fullName()}};
642bool IncidenceWrapper::todoCompleted()
649 return todo->isCompleted();
652void IncidenceWrapper::setTodoCompleted(
bool completed)
659 todo->setCompleted(completed);
661 Q_EMIT todoCompletionDtChanged();
662 Q_EMIT todoPercentCompleteChanged();
663 Q_EMIT incidenceIconNameChanged();
664 Q_EMIT todoCompletedChanged();
667QDateTime IncidenceWrapper::todoCompletionDt()
674 return todo->completed();
677int IncidenceWrapper::todoPercentComplete()
684 return todo->percentComplete();
687void IncidenceWrapper::setTodoPercentComplete(
int todoPercentComplete)
694 todo->setPercentComplete(todoPercentComplete);
696 Q_EMIT todoPercentCompleteChanged();
698 if (todoPercentComplete < 100 && todoCompleted()) {
699 setTodoCompleted(
false);
702 Q_EMIT todoCompletedChanged();
705void IncidenceWrapper::triggerEditMode()
707 auto itemToEdit =
item();
710 setIncidenceItem(itemToEdit);
713static int nearestQuarterHour(
int secsSinceEpoch)
715 const int quarterHourInSecs = 60 * 15;
716 return secsSinceEpoch + (quarterHourInSecs - secsSinceEpoch % quarterHourInSecs);
719void IncidenceWrapper::setNewEvent()
724 event->setDtStart(
start);
725 event->setDtEnd(
start.addSecs(60 * 60));
728 alarm->setEnabled(
true);
730 alarm->setStartOffset(-1 * 15 * 60);
732 event->addAlarm(alarm);
734 setNewIncidence(
event);
737void IncidenceWrapper::setNewTodo()
740 setNewIncidence(todo);
747 setIncidenceItem(incidenceItem);
759void IncidenceWrapper::updateParentIncidence()
765 if (!parent().isEmpty() && (!m_parentIncidence || m_parentIncidence->uid() != parent())) {
767 m_parentIncidence->setIncidenceItem(CalendarManager::instance()->incidenceItem(parent()));
768 Q_EMIT parentIncidenceChanged();
772void IncidenceWrapper::resetChildIncidences()
774 cleanupChildIncidences();
780 const auto incidences = CalendarManager::instance()->childIncidences(uid());
781 QVariantList wrappedIncidences;
783 for (
const auto &incidence : incidences) {
785 wrappedIncidence->setIncidenceItem(CalendarManager::instance()->incidenceItem(incidence));
789 m_childIncidences = wrappedIncidences;
790 Q_EMIT childIncidencesChanged();
793void IncidenceWrapper::cleanupChildIncidences()
795 while (!m_childIncidences.isEmpty()) {
796 const auto incidence = m_childIncidences.takeFirst();
805 for (
int i = 0; i < alarms.
size(); i++) {
806 m_incidence->addAlarm(alarms[i]);
810void IncidenceWrapper::setRegularRecurrence(IncidenceWrapper::RecurrenceIntervals interval,
int freq)
814 m_incidence->recurrence()->setDaily(freq);
815 Q_EMIT recurrenceDataChanged();
818 m_incidence->recurrence()->setWeekly(freq);
819 Q_EMIT recurrenceDataChanged();
822 m_incidence->recurrence()->setMonthly(freq);
823 Q_EMIT recurrenceDataChanged();
826 m_incidence->recurrence()->setYearly(freq);
827 Q_EMIT recurrenceDataChanged();
830 qWarning() <<
"Unknown interval for recurrence" << interval;
835void IncidenceWrapper::setMonthlyPosRecurrence(
short pos,
int day)
838 daysBitArray[day] = 1;
839 m_incidence->recurrence()->addMonthlyPos(pos, daysBitArray);
842void IncidenceWrapper::setRecurrenceOccurrences(
int occurrences)
844 m_incidence->recurrence()->setDuration(occurrences);
845 Q_EMIT recurrenceDataChanged();
848void IncidenceWrapper::clearRecurrences()
850 m_incidence->recurrence()->clear();
851 Q_EMIT recurrenceDataChanged();
858 setIncidenceItem(
item);
865 setCollectionId(collection.
id());
868#ifndef UNITY_CMAKE_SUPPORT
void setAncestorRetrieval(AncestorRetrieval ancestorDepth)
void fetchAllAttributes(bool fetch=true)
void fetchFullPayload(bool fetch=true)
void setItem(const Item &item)
Collection & parentCollection()
void setPayload(const T &p)
This class is a wrapper for a KCalendarCore::Incidence::Ptr object.
void setDtEnd(const QDateTime &dtEnd)
QSharedPointer< Event > Ptr
virtual QDateTime dtEnd() const
QSharedPointer< Todo > Ptr
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Incidence::Ptr incidence(const Akonadi::Item &item)
AKONADI_CALENDAR_EXPORT KCalendarCore::Todo::Ptr todo(const Akonadi::Item &item)
const QList< QKeySequence > & end()
qsizetype size() const const
bool setDate(int year, int month, int day)
QDateTime addSecs(qint64 s) const const
QDateTime currentDateTime()
qint64 currentSecsSinceEpoch()
bool isValid() const const
void setSecsSinceEpoch(qint64 secs)
void setTimeZone(const QTimeZone &toZone)
QTimeZone timeZone() const const
QVariant toVariant() const const
void append(QList< T > &&value)
qsizetype size() const const
QString toString(QDate date, FormatType format) const const
virtual bool event(QEvent *e)
QSharedPointer< X > staticCast() const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool setHMS(int h, int m, int s, int ms)
QByteArray id() const const
int offsetFromUtc(const QDateTime &atDateTime) const const
bool canConvert() const const
QVariant fromValue(T &&value)
bool toBool() const const
QDateTime toDateTime() const const
int toInt(bool *ok) const const