File indexing completed on 2024-11-24 04:41:37
0001 /* 0002 SPDX-FileCopyrightText: 2007 Till Adam <adam@kde.org> 0003 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0004 SPDX-FileCopyrightText: 2010 Andras Mantia <andras@kdab.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0007 */ 0008 0009 #include "timelineview_p.h" 0010 #include "timelineitem.h" 0011 0012 #include <KGanttGraphicsView> 0013 0014 #include <Akonadi/CalendarUtils> 0015 #include <Akonadi/IncidenceChanger> 0016 #include <CalendarSupport/CollectionSelection> 0017 #include <KCalendarCore/OccurrenceIterator> 0018 0019 #include "calendarview_debug.h" 0020 0021 #include <QStandardItemModel> 0022 0023 using namespace KCalendarCore; 0024 using namespace EventViews; 0025 0026 TimelineViewPrivate::TimelineViewPrivate(TimelineView *parent) 0027 : q(parent) 0028 { 0029 } 0030 0031 TimelineViewPrivate::~TimelineViewPrivate() = default; 0032 0033 void TimelineViewPrivate::itemSelected(const QModelIndex &index) 0034 { 0035 auto tlitem = dynamic_cast<TimelineSubItem *>(static_cast<QStandardItemModel *>(mGantt->model())->item(index.row(), index.column())); 0036 if (tlitem) { 0037 Q_EMIT q->incidenceSelected(tlitem->incidence(), tlitem->originalStart().date()); 0038 } 0039 } 0040 0041 void TimelineViewPrivate::itemDoubleClicked(const QModelIndex &index) 0042 { 0043 auto tlitem = dynamic_cast<TimelineSubItem *>(static_cast<QStandardItemModel *>(mGantt->model())->item(index.row(), index.column())); 0044 if (tlitem) { 0045 Q_EMIT q->editIncidenceSignal(tlitem->incidence()); 0046 } 0047 } 0048 0049 void TimelineViewPrivate::contextMenuRequested(QPoint point) 0050 { 0051 QPersistentModelIndex index = mGantt->indexAt(point); 0052 // mHintDate = QDateTime( mGantt->getDateTimeForCoordX( QCursor::pos().x(), true ) ); 0053 auto tlitem = dynamic_cast<TimelineSubItem *>(static_cast<QStandardItemModel *>(mGantt->model())->item(index.row(), index.column())); 0054 if (!tlitem) { 0055 Q_EMIT q->showNewEventPopupSignal(); 0056 mSelectedItemList = Akonadi::Item::List(); 0057 } else { 0058 if (const auto calendar = tlitem->parent()->calendar(); calendar) { 0059 Q_EMIT q->showIncidencePopupSignal(calendar, tlitem->incidence(), Akonadi::CalendarUtils::incidence(tlitem->incidence())->dtStart().date()); 0060 } 0061 0062 mSelectedItemList << tlitem->incidence(); 0063 } 0064 } 0065 0066 // slot 0067 void TimelineViewPrivate::newEventWithHint(const QDateTime &dt) 0068 { 0069 mHintDate = dt; 0070 Q_EMIT q->newEventSignal(dt); 0071 } 0072 0073 TimelineItem *TimelineViewPrivate::calendarItemForIncidence(const Akonadi::Item &incidence) const 0074 { 0075 auto item = mCalendarItemMap.constFind(incidence.parentCollection().id()); 0076 if (item == mCalendarItemMap.cend()) { 0077 return mCalendarItemMap.value(-1); 0078 } 0079 0080 return *item; 0081 } 0082 0083 void TimelineViewPrivate::insertIncidence(const Akonadi::CollectionCalendar::Ptr &calendar, const Akonadi::Item &aitem, QDate day) 0084 { 0085 const Incidence::Ptr incidence = Akonadi::CalendarUtils::incidence(aitem); 0086 // qCDebug(CALENDARVIEW_LOG) << "Item " << aitem.id() << " parentcollection: " << aitem.parentCollection().id(); 0087 TimelineItem *item = calendarItemForIncidence(aitem); 0088 if (!item) { 0089 qCWarning(CALENDARVIEW_LOG) << "Help! Something is really wrong here!"; 0090 return; 0091 } 0092 0093 if (incidence->recurs()) { 0094 KCalendarCore::OccurrenceIterator occurIter(*calendar, incidence, QDateTime(day, QTime(0, 0, 0)), QDateTime(day, QTime(23, 59, 59))); 0095 while (occurIter.hasNext()) { 0096 occurIter.next(); 0097 const Akonadi::Item akonadiItem = calendar->item(occurIter.incidence()); 0098 const QDateTime startOfOccurrence = occurIter.occurrenceStartDate(); 0099 const QDateTime endOfOccurrence = occurIter.incidence()->endDateForStart(startOfOccurrence); 0100 item->insertIncidence(akonadiItem, startOfOccurrence.toLocalTime(), endOfOccurrence.toLocalTime()); 0101 } 0102 } else { 0103 if (incidence->dtStart().date() == day || incidence->dtStart().date() < mStartDate) { 0104 item->insertIncidence(aitem); 0105 } 0106 } 0107 } 0108 0109 void TimelineViewPrivate::insertIncidence(const Akonadi::CollectionCalendar::Ptr &calendar, const Akonadi::Item &incidence) 0110 { 0111 const Event::Ptr event = Akonadi::CalendarUtils::event(incidence); 0112 if (!event) { 0113 return; 0114 } 0115 0116 if (event->recurs()) { 0117 insertIncidence(calendar, incidence, QDate()); 0118 } 0119 0120 for (QDate day = mStartDate; day <= mEndDate; day = day.addDays(1)) { 0121 const auto events = calendar->events(day, QTimeZone::systemTimeZone(), KCalendarCore::EventSortStartDate, KCalendarCore::SortDirectionAscending); 0122 if (events.contains(event)) { 0123 // PENDING(AKONADI_PORT) check if correct. also check the original if, 0124 // was inside the for loop (unnecessarily) 0125 for (const KCalendarCore::Event::Ptr &i : events) { 0126 Akonadi::Item item = calendar->item(i); 0127 insertIncidence(calendar, item, day); 0128 } 0129 } 0130 } 0131 } 0132 0133 void TimelineViewPrivate::removeIncidence(const Akonadi::Item &incidence) 0134 { 0135 TimelineItem *item = calendarItemForIncidence(incidence); 0136 if (item) { 0137 item->removeIncidence(incidence); 0138 } else { 0139 #if 0 // AKONADI_PORT_DISABLED 0140 // try harder, the incidence might already be removed from the resource 0141 typedef QMap<QString, KOrg::TimelineItem *> M2_t; 0142 typedef QMap<KCalendarCore::ResourceCalendar *, M2_t> M1_t; 0143 for (M1_t::ConstIterator it1 = d->mCalendarItemMap.constBegin(); 0144 it1 != mCalendarItemMap.constEnd(); ++it1) { 0145 for (M2_t::ConstIterator it2 = it1.value().constBegin(); 0146 it2 != it1.value().constEnd(); ++it2) { 0147 if (it2.value()) { 0148 it2.value()->removeIncidence(incidence); 0149 } 0150 } 0151 } 0152 #endif 0153 } 0154 } 0155 0156 void TimelineViewPrivate::itemChanged(QStandardItem *item) 0157 { 0158 auto tlit = dynamic_cast<TimelineSubItem *>(item); 0159 if (!tlit) { 0160 return; 0161 } 0162 0163 const Akonadi::Item i = tlit->incidence(); 0164 const Incidence::Ptr inc = Akonadi::CalendarUtils::incidence(i); 0165 0166 QDateTime newStart(tlit->startTime()); 0167 if (inc->allDay()) { 0168 newStart = QDateTime(newStart.date().startOfDay()); 0169 } 0170 0171 int delta = tlit->originalStart().secsTo(newStart); 0172 inc->setDtStart(inc->dtStart().addSecs(delta)); 0173 int duration = tlit->startTime().secsTo(tlit->endTime()); 0174 int allDayOffset = 0; 0175 if (inc->allDay()) { 0176 int secsPerDay = 60 * 60 * 24; 0177 duration /= secsPerDay; 0178 duration *= secsPerDay; 0179 allDayOffset = secsPerDay; 0180 duration -= allDayOffset; 0181 if (duration < 0) { 0182 duration = 0; 0183 } 0184 } 0185 inc->setDuration(duration); 0186 TimelineItem *parent = tlit->parent(); 0187 parent->moveItems(i, tlit->originalStart().secsTo(newStart), duration + allDayOffset); 0188 } 0189 0190 #include "moc_timelineview_p.cpp"