1 /* 2 SPDX-FileCopyrightText: 2000, 2001, 2003 Cornelius Schumacher <schumacher@kde.org> 3 SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 4 5 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 6 */ 7 #pragma once 8 9 #include "viewcalendar.h" 10 11 #include <CalendarSupport/CellItem> 12 13 #include <Akonadi/Calendar/ETMCalendar> 14 #include <Akonadi/Item> 15 16 #include <QDateTime> 17 #include <QPointer> 18 #include <QWidget> 19 20 namespace EventViews 21 { 22 class AgendaItem; 23 class EventView; 24 25 struct MultiItemInfo { 26 int mStartCellXLeft, mStartCellXRight; 27 int mStartCellYTop, mStartCellYBottom; 28 QPointer<AgendaItem> mFirstMultiItem; 29 QPointer<AgendaItem> mPrevMultiItem; 30 QPointer<AgendaItem> mNextMultiItem; 31 QPointer<AgendaItem> mLastMultiItem; 32 }; 33 34 /** 35 @class AgendaItem 36 37 @brief This class describes the widgets that represent the various calendar 38 items in the agenda view 39 40 The AgendaItem has to make sure that it receives all mouse events, which 41 are to be used for dragging and resizing. That means it has to be installed 42 as event filter for its children, if it has children, and it has to pass 43 mouse events from the children to itself. See eventFilter(). 44 45 Some comments on the movement of multi-day items: 46 Basically, the agenda items are arranged in two implicit double-linked lists. 47 The mMultiItemInfo works like before to describe the currently viewed 48 multi-item. 49 When moving, new events might need to be added to the beginning or the end of 50 the multi-item sequence, or events might need to be hidden. I cannot just 51 delete this items, since I have to restore/show them if the move is reset 52 (i.e. if a drag started). So internally, I keep another doubly-linked list 53 which is longer than the one defined by mMultiItemInfo, but includes the 54 multi-item sequence, too. 55 56 The mStartMoveInfo stores the first and last item of the multi-item sequence 57 when the move started. The prev and next members of mStartMoveInfo are used 58 for that longer sequence including all (shown and hidden) items. 59 */ 60 61 class AgendaItem : public QWidget, public CalendarSupport::CellItem 62 { 63 Q_OBJECT 64 public: 65 using QPtr = QPointer<AgendaItem>; 66 using List = QList<QPtr>; 67 68 AgendaItem(EventView *eventView, 69 const MultiViewCalendar::Ptr &calendar, 70 const KCalendarCore::Incidence::Ptr &incidence, 71 int itemPos, 72 int itemCount, 73 const QDateTime &qd, 74 bool isSelected, 75 QWidget *parent); 76 ~AgendaItem() override; 77 cellXLeft()78 Q_REQUIRED_RESULT int cellXLeft() const 79 { 80 return mCellXLeft; 81 } 82 cellXRight()83 Q_REQUIRED_RESULT int cellXRight() const 84 { 85 return mCellXRight; 86 } 87 cellYTop()88 Q_REQUIRED_RESULT int cellYTop() const 89 { 90 return mCellYTop; 91 } 92 cellYBottom()93 Q_REQUIRED_RESULT int cellYBottom() const 94 { 95 return mCellYBottom; 96 } 97 98 Q_REQUIRED_RESULT int cellHeight() const; 99 Q_REQUIRED_RESULT int cellWidth() const; 100 itemPos()101 Q_REQUIRED_RESULT int itemPos() const 102 { 103 return mItemPos; 104 } 105 itemCount()106 Q_REQUIRED_RESULT int itemCount() const 107 { 108 return mItemCount; 109 } 110 111 void setCellXY(int X, int YTop, int YBottom); 112 void setCellY(int YTop, int YBottom); 113 void setCellX(int XLeft, int XRight); 114 void setCellXRight(int XRight); 115 116 /** Start movement */ 117 void startMove(); 118 119 /** Reset to original values */ 120 void resetMove(); 121 122 /** End the movement (i.e. clean up) */ 123 void endMove(); 124 125 void moveRelative(int dx, int dy); 126 127 /** 128 * Expands the item's top. 129 * 130 * @param dy delta y, number of units to be added to mCellYTop 131 * @param allowOverLimit If false, the new mCellYTop can't be bigger than 132 * mCellYBottom, instead, it gets mCellYBottom's value. 133 * If true, @p dy is always added, regardless if mCellYTop 134 * becomes bigger than mCellYBottom, this is useful when 135 * moving items because it guarantees expandTop and the 136 * following expandBottom call add the same value. 137 */ 138 void expandTop(int dy, const bool allowOverLimit = false); 139 void expandBottom(int dy); 140 void expandLeft(int dx); 141 void expandRight(int dx); 142 143 Q_REQUIRED_RESULT bool isMultiItem() const; 144 prevMoveItem()145 AgendaItem::QPtr prevMoveItem() const 146 { 147 return (mStartMoveInfo) ? (mStartMoveInfo->mPrevMultiItem) : nullptr; 148 } 149 nextMoveItem()150 AgendaItem::QPtr nextMoveItem() const 151 { 152 return (mStartMoveInfo) ? (mStartMoveInfo->mNextMultiItem) : nullptr; 153 } 154 moveInfo()155 MultiItemInfo *moveInfo() const 156 { 157 return mStartMoveInfo; 158 } 159 160 void setMultiItem(const AgendaItem::QPtr &first, const AgendaItem::QPtr &prev, const AgendaItem::QPtr &next, const AgendaItem::QPtr &last); 161 162 AgendaItem::QPtr prependMoveItem(const AgendaItem::QPtr &); 163 164 AgendaItem::QPtr appendMoveItem(const AgendaItem::QPtr &); 165 166 AgendaItem::QPtr removeMoveItem(const AgendaItem::QPtr &); 167 firstMultiItem()168 AgendaItem::QPtr firstMultiItem() const 169 { 170 return (mMultiItemInfo) ? (mMultiItemInfo->mFirstMultiItem) : nullptr; 171 } 172 prevMultiItem()173 AgendaItem::QPtr prevMultiItem() const 174 { 175 return (mMultiItemInfo) ? (mMultiItemInfo->mPrevMultiItem) : nullptr; 176 } 177 nextMultiItem()178 AgendaItem::QPtr nextMultiItem() const 179 { 180 return (mMultiItemInfo) ? (mMultiItemInfo->mNextMultiItem) : nullptr; 181 } 182 lastMultiItem()183 AgendaItem::QPtr lastMultiItem() const 184 { 185 return (mMultiItemInfo) ? (mMultiItemInfo->mLastMultiItem) : nullptr; 186 } 187 188 Q_REQUIRED_RESULT bool dissociateFromMultiItem(); 189 190 void setIncidence(const KCalendarCore::Incidence::Ptr &incidence); 191 incidence()192 const KCalendarCore::Incidence::Ptr &incidence() const 193 { 194 return mIncidence; 195 } 196 occurrenceDateTime()197 Q_REQUIRED_RESULT QDateTime occurrenceDateTime() const 198 { 199 return mOccurrenceDateTime; 200 } 201 202 Q_REQUIRED_RESULT QDate occurrenceDate() const; 203 204 // /** Update the date of this item's occurrence (not in the event) */ 205 void setOccurrenceDateTime(const QDateTime &qd); 206 setText(const QString & text)207 void setText(const QString &text) 208 { 209 mLabelText = text; 210 } 211 text()212 Q_REQUIRED_RESULT QString text() const 213 { 214 return mLabelText; 215 } 216 217 QList<AgendaItem::QPtr> &conflictItems(); 218 void setConflictItems(const QList<AgendaItem::QPtr> &); 219 void addConflictItem(const AgendaItem::QPtr &ci); 220 221 QString label() const override; 222 223 /** Tells whether this item overlaps item @p o */ 224 bool overlaps(CellItem *o) const override; 225 setResourceColor(const QColor & color)226 void setResourceColor(const QColor &color) 227 { 228 mResourceColor = color; 229 } 230 resourceColor()231 Q_REQUIRED_RESULT QColor resourceColor() const 232 { 233 return mResourceColor; 234 } 235 236 Q_SIGNALS: 237 void removeAgendaItem(const AgendaItem::QPtr &); 238 void showAgendaItem(const AgendaItem::QPtr &); 239 240 public Q_SLOTS: 241 void updateIcons(); 242 void select(bool selected = true); 243 void addAttendee(const QString &); 244 245 protected: 246 bool eventFilter(QObject *obj, QEvent *event) override; 247 bool event(QEvent *event) override; 248 void dragEnterEvent(QDragEnterEvent *e) override; 249 void dropEvent(QDropEvent *e) override; 250 void paintEvent(QPaintEvent *e) override; 251 252 /** private movement functions. startMove needs to be called of only one of 253 * the multitems. it will then loop through the whole series using 254 * startMovePrivate. Same for resetMove and endMove */ 255 void startMovePrivate(); 256 void resetMovePrivate(); 257 void endMovePrivate(); 258 259 // Variables to remember start position 260 MultiItemInfo *mStartMoveInfo = nullptr; 261 // Color of the resource 262 QColor mResourceColor; 263 264 private: 265 void paintIcon(QPainter *p, int &x, int y, int ft); 266 267 // paint all visible icons 268 void paintIcons(QPainter *p, int &x, int y, int ft); 269 270 void drawRoundedRect(QPainter *p, QRect rect, bool selected, const QColor &bgColor, const QColor &frameColor, bool frame, int ft, bool roundTop, bool roundBottom); 271 272 Q_REQUIRED_RESULT QColor getCategoryColor() const; 273 Q_REQUIRED_RESULT QColor getFrameColor(const QColor &resourceColor, const QColor &categoryColor) const; 274 Q_REQUIRED_RESULT QColor getBackgroundColor(const QColor &resourceColor, const QColor &categoryColor) const; 275 276 int mCellXLeft, mCellXRight; 277 int mCellYTop, mCellYBottom; 278 279 EventView *const mEventView; 280 MultiViewCalendar::Ptr mCalendar; 281 KCalendarCore::Incidence::Ptr mIncidence; 282 QDateTime mOccurrenceDateTime; 283 bool mValid = true; 284 bool mCloned = false; 285 QString mLabelText; 286 bool mSelected; 287 bool mIconAlarm; 288 bool mIconRecur; 289 bool mIconReadonly; 290 bool mIconReply; 291 bool mIconGroup; 292 bool mIconGroupTent; 293 bool mIconOrganizer; 294 bool mSpecialEvent; 295 296 // For incidences that expand through more than 1 day 297 // Will be 1 for single day incidences 298 int mItemPos; 299 int mItemCount; 300 301 // Multi item pointers 302 MultiItemInfo *mMultiItemInfo = nullptr; 303 304 QList<AgendaItem::QPtr> mConflictItems; 305 306 static QPixmap *alarmPxmp; 307 static QPixmap *recurPxmp; 308 static QPixmap *readonlyPxmp; 309 static QPixmap *replyPxmp; 310 static QPixmap *groupPxmp; 311 static QPixmap *groupPxmpTent; 312 static QPixmap *organizerPxmp; 313 static QPixmap *eventPxmp; 314 static QPixmap *todoPxmp; 315 static QPixmap *completedPxmp; 316 }; 317 } 318 319