File indexing completed on 2024-11-17 04:42:35

0001 /*
0002   SPDX-FileCopyrightText: 2000, 2001, 2003 Cornelius Schumacher <schumacher@kde.org>
0003   SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
0004 
0005   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0006 */
0007 #pragma once
0008 
0009 #include "viewcalendar.h"
0010 
0011 #include <CalendarSupport/CellItem>
0012 
0013 #include <Akonadi/Item>
0014 
0015 #include <QDateTime>
0016 #include <QPointer>
0017 #include <QWidget>
0018 
0019 namespace EventViews
0020 {
0021 class AgendaItem;
0022 class EventView;
0023 
0024 struct MultiItemInfo {
0025     int mStartCellXLeft, mStartCellXRight;
0026     int mStartCellYTop, mStartCellYBottom;
0027     QPointer<AgendaItem> mFirstMultiItem;
0028     QPointer<AgendaItem> mPrevMultiItem;
0029     QPointer<AgendaItem> mNextMultiItem;
0030     QPointer<AgendaItem> mLastMultiItem;
0031 };
0032 
0033 /**
0034   @class AgendaItem
0035 
0036   @brief This class describes the widgets that represent the various calendar
0037          items in the agenda view
0038 
0039   The AgendaItem has to make sure that it receives all mouse events, which
0040   are to be used for dragging and resizing. That means it has to be installed
0041   as event filter for its children, if it has children, and it has to pass
0042   mouse events from the children to itself. See eventFilter().
0043 
0044   Some comments on the movement of multi-day items:
0045   Basically, the agenda items are arranged in two implicit double-linked lists.
0046   The mMultiItemInfo works like before to describe the currently viewed
0047   multi-item.
0048   When moving, new events might need to be added to the beginning or the end of
0049   the multi-item sequence, or events might need to be hidden. I cannot just
0050   delete this items, since I have to restore/show them if the move is reset
0051   (i.e. if a drag started). So internally, I keep another doubly-linked list
0052   which is longer than the one defined by mMultiItemInfo, but includes the
0053   multi-item sequence, too.
0054 
0055   The mStartMoveInfo stores the first and last item of the multi-item sequence
0056   when the move started. The prev and next members of mStartMoveInfo are used
0057   for that longer sequence including all (shown and hidden) items.
0058 */
0059 
0060 class AgendaItem : public QWidget, public CalendarSupport::CellItem
0061 {
0062     Q_OBJECT
0063 public:
0064     using QPtr = QPointer<AgendaItem>;
0065     using List = QList<QPtr>;
0066 
0067     AgendaItem(EventView *eventView,
0068                const MultiViewCalendar::Ptr &calendar,
0069                const KCalendarCore::Incidence::Ptr &incidence,
0070                int itemPos,
0071                int itemCount,
0072                const QDateTime &qd,
0073                bool isSelected,
0074                QWidget *parent);
0075     ~AgendaItem() override;
0076 
0077     [[nodiscard]] int cellXLeft() const
0078     {
0079         return mCellXLeft;
0080     }
0081 
0082     [[nodiscard]] int cellXRight() const
0083     {
0084         return mCellXRight;
0085     }
0086 
0087     [[nodiscard]] int cellYTop() const
0088     {
0089         return mCellYTop;
0090     }
0091 
0092     [[nodiscard]] int cellYBottom() const
0093     {
0094         return mCellYBottom;
0095     }
0096 
0097     [[nodiscard]] int cellHeight() const;
0098     [[nodiscard]] int cellWidth() const;
0099 
0100     [[nodiscard]] int itemPos() const
0101     {
0102         return mItemPos;
0103     }
0104 
0105     [[nodiscard]] int itemCount() const
0106     {
0107         return mItemCount;
0108     }
0109 
0110     void setCellXY(int X, int YTop, int YBottom);
0111     void setCellY(int YTop, int YBottom);
0112     void setCellX(int XLeft, int XRight);
0113     void setCellXRight(int XRight);
0114 
0115     /** Start movement */
0116     void startMove();
0117 
0118     /** Reset to original values */
0119     void resetMove();
0120 
0121     /** End the movement (i.e. clean up) */
0122     void endMove();
0123 
0124     void moveRelative(int dx, int dy);
0125 
0126     /**
0127      * Expands the item's top.
0128      *
0129      * @param dy             delta y, number of units to be added to mCellYTop
0130      * @param allowOverLimit If false, the new mCellYTop can't be bigger than
0131      *                       mCellYBottom, instead, it gets mCellYBottom's value.
0132      *                       If true, @p dy is always added, regardless if mCellYTop
0133      *                       becomes bigger than mCellYBottom, this is useful when
0134      *                       moving items because it guarantees expandTop and the
0135      *                       following expandBottom call add the same value.
0136      */
0137     void expandTop(int dy, const bool allowOverLimit = false);
0138     void expandBottom(int dy);
0139     void expandLeft(int dx);
0140     void expandRight(int dx);
0141 
0142     [[nodiscard]] bool isMultiItem() const;
0143 
0144     AgendaItem::QPtr prevMoveItem() const
0145     {
0146         return (mStartMoveInfo) ? (mStartMoveInfo->mPrevMultiItem) : nullptr;
0147     }
0148 
0149     AgendaItem::QPtr nextMoveItem() const
0150     {
0151         return (mStartMoveInfo) ? (mStartMoveInfo->mNextMultiItem) : nullptr;
0152     }
0153 
0154     MultiItemInfo *moveInfo() const
0155     {
0156         return mStartMoveInfo;
0157     }
0158 
0159     void setMultiItem(const AgendaItem::QPtr &first, const AgendaItem::QPtr &prev, const AgendaItem::QPtr &next, const AgendaItem::QPtr &last);
0160 
0161     AgendaItem::QPtr prependMoveItem(const AgendaItem::QPtr &);
0162 
0163     AgendaItem::QPtr appendMoveItem(const AgendaItem::QPtr &);
0164 
0165     AgendaItem::QPtr removeMoveItem(const AgendaItem::QPtr &);
0166 
0167     AgendaItem::QPtr firstMultiItem() const
0168     {
0169         return (mMultiItemInfo) ? (mMultiItemInfo->mFirstMultiItem) : nullptr;
0170     }
0171 
0172     AgendaItem::QPtr prevMultiItem() const
0173     {
0174         return (mMultiItemInfo) ? (mMultiItemInfo->mPrevMultiItem) : nullptr;
0175     }
0176 
0177     AgendaItem::QPtr nextMultiItem() const
0178     {
0179         return (mMultiItemInfo) ? (mMultiItemInfo->mNextMultiItem) : nullptr;
0180     }
0181 
0182     AgendaItem::QPtr lastMultiItem() const
0183     {
0184         return (mMultiItemInfo) ? (mMultiItemInfo->mLastMultiItem) : nullptr;
0185     }
0186 
0187     [[nodiscard]] bool dissociateFromMultiItem();
0188 
0189     void setIncidence(const KCalendarCore::Incidence::Ptr &incidence);
0190 
0191     const KCalendarCore::Incidence::Ptr &incidence() const
0192     {
0193         return mIncidence;
0194     }
0195 
0196     [[nodiscard]] QDateTime occurrenceDateTime() const
0197     {
0198         return mOccurrenceDateTime;
0199     }
0200 
0201     [[nodiscard]] QDate occurrenceDate() const;
0202 
0203     // /** Update the date of this item's occurrence (not in the event) */
0204     void setOccurrenceDateTime(const QDateTime &qd);
0205 
0206     void setText(const QString &text)
0207     {
0208         mLabelText = text;
0209     }
0210 
0211     [[nodiscard]] QString text() const
0212     {
0213         return mLabelText;
0214     }
0215 
0216     QList<AgendaItem::QPtr> &conflictItems();
0217     void setConflictItems(const QList<AgendaItem::QPtr> &);
0218     void addConflictItem(const AgendaItem::QPtr &ci);
0219 
0220     QString label() const override;
0221 
0222     /** Tells whether this item overlaps item @p o */
0223     bool overlaps(CellItem *o) const override;
0224 
0225     void setResourceColor(const QColor &color)
0226     {
0227         mResourceColor = color;
0228     }
0229 
0230     [[nodiscard]] QColor resourceColor() const
0231     {
0232         return mResourceColor;
0233     }
0234 
0235 Q_SIGNALS:
0236     void removeAgendaItem(const AgendaItem::QPtr &);
0237     void showAgendaItem(const AgendaItem::QPtr &);
0238 
0239 public Q_SLOTS:
0240     void updateIcons();
0241     void select(bool selected = true);
0242     void addAttendee(const QString &);
0243 
0244 protected:
0245     bool eventFilter(QObject *obj, QEvent *event) override;
0246     bool event(QEvent *event) override;
0247     void dragEnterEvent(QDragEnterEvent *e) override;
0248     void dropEvent(QDropEvent *e) override;
0249     void paintEvent(QPaintEvent *e) override;
0250 
0251     /** private movement functions. startMove needs to be called of only one of
0252      *  the multitems. it will then loop through the whole series using
0253      *  startMovePrivate. Same for resetMove and endMove */
0254     void startMovePrivate();
0255     void resetMovePrivate();
0256     void endMovePrivate();
0257 
0258     // Variables to remember start position
0259     MultiItemInfo *mStartMoveInfo = nullptr;
0260     // Color of the resource
0261     QColor mResourceColor;
0262 
0263 private:
0264     void paintIcon(QPainter *p, int &x, int y, int ft);
0265 
0266     // paint all visible icons
0267     void paintIcons(QPainter *p, int &x, int y, int ft);
0268 
0269     void drawRoundedRect(QPainter *p,
0270                          QRect rect,
0271                          bool selected,
0272                          const QColor &bgColor,
0273                          const QColor &frameColor,
0274                          bool frame,
0275                          int ft,
0276                          bool roundTop,
0277                          bool roundBottom);
0278 
0279     [[nodiscard]] QColor getCategoryColor() const;
0280     [[nodiscard]] QColor getFrameColor(const QColor &resourceColor, const QColor &categoryColor) const;
0281     [[nodiscard]] QColor getBackgroundColor(const QColor &resourceColor, const QColor &categoryColor) const;
0282 
0283     int mCellXLeft, mCellXRight;
0284     int mCellYTop, mCellYBottom;
0285 
0286     EventView *const mEventView;
0287     MultiViewCalendar::Ptr mCalendar;
0288     KCalendarCore::Incidence::Ptr mIncidence;
0289     QDateTime mOccurrenceDateTime;
0290     bool mValid = true;
0291     bool mCloned = false;
0292     QString mLabelText;
0293     bool mSelected;
0294     bool mIconAlarm;
0295     bool mIconRecur;
0296     bool mIconReadonly;
0297     bool mIconReply;
0298     bool mIconGroup;
0299     bool mIconGroupTent;
0300     bool mIconOrganizer;
0301     bool mSpecialEvent;
0302 
0303     // For incidences that expand through more than 1 day
0304     // Will be 1 for single day incidences
0305     int mItemPos;
0306     int mItemCount;
0307 
0308     // Multi item pointers
0309     MultiItemInfo *mMultiItemInfo = nullptr;
0310 
0311     QList<AgendaItem::QPtr> mConflictItems;
0312 
0313     static QPixmap *alarmPxmp;
0314     static QPixmap *recurPxmp;
0315     static QPixmap *readonlyPxmp;
0316     static QPixmap *replyPxmp;
0317     static QPixmap *groupPxmp;
0318     static QPixmap *groupPxmpTent;
0319     static QPixmap *organizerPxmp;
0320     static QPixmap *eventPxmp;
0321     static QPixmap *todoPxmp;
0322     static QPixmap *completedPxmp;
0323 };
0324 }