File indexing completed on 2024-06-16 04:51:13

0001 /*
0002   SPDX-FileCopyrightText: 2008 Bruno Virlet <bruno.virlet@gmail.com>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0005 */
0006 
0007 #pragma once
0008 
0009 #include "eventviews_export.h"
0010 
0011 #include <Akonadi/CollectionCalendar>
0012 #include <Akonadi/Item>
0013 #include <KCalendarCore/Incidence>
0014 
0015 #include <QDate>
0016 #include <QObject>
0017 
0018 namespace EventViews
0019 {
0020 class MonthGraphicsItem;
0021 class MonthScene;
0022 
0023 /**
0024  * A month item manages different MonthGraphicsItems.
0025  */
0026 class EVENTVIEWS_EXPORT MonthItem : public QObject
0027 {
0028     Q_OBJECT
0029 
0030 public:
0031     explicit MonthItem(MonthScene *monthWidget);
0032     ~MonthItem() override;
0033 
0034     QWidget *parentWidget() const;
0035 
0036     /**
0037       Compares two items to decide which to place in the view first.
0038 
0039       The month view displays a list of items. When loading (which occurs each
0040       time there is a change), the items are sorted in an order intended to
0041       avoid unsightly gaps:
0042       - biggest durations first
0043       - earliest date
0044       - finally, time in the day
0045       Holidays are sorted before events with the same start date and length,
0046       so they appear at the top of the day's box.
0047     */
0048     static bool greaterThan(const MonthItem *e1, const MonthItem *e2);
0049 
0050     /**
0051       Compare this event with a second one, if the former function is not
0052       able to sort them.
0053     */
0054     virtual bool greaterThanFallback(const MonthItem *other) const;
0055 
0056     /**
0057       The start date of the incidence, generally realStartDate. But it
0058       reflect changes, even during move.
0059     */
0060     [[nodiscard]] QDate startDate() const;
0061 
0062     /**
0063       The end date of the incidence, generally realEndDate. But it
0064       reflect changes, even during move.
0065      */
0066     [[nodiscard]] QDate endDate() const;
0067 
0068     /**
0069       The number of days this item spans.
0070     */
0071     [[nodiscard]] int daySpan() const;
0072 
0073     /**
0074       This is the real start date, usually the start date of the incidence.
0075     */
0076     virtual QDate realStartDate() const = 0;
0077 
0078     /**
0079       This is the real end date, usually the end date of the incidence.
0080     */
0081     virtual QDate realEndDate() const = 0;
0082 
0083     /**
0084       True if this item last all the day.
0085     */
0086     virtual bool allDay() const = 0;
0087 
0088     /**
0089       Updates geometry of all MonthGraphicsItems.
0090     */
0091     void updateGeometry();
0092 
0093     /**
0094       Find the lowest possible position for this item.
0095 
0096       The position of an item in a cell is it's vertical position. This is used
0097       to avoid overlapping of items. An item keeps the same position in every
0098       cell it crosses. The position is measured from top to bottom.
0099     */
0100     void updatePosition();
0101 
0102     /**
0103       Returns true if this item is selected.
0104     */
0105     [[nodiscard]] bool selected() const
0106     {
0107         return mSelected;
0108     }
0109 
0110     /**
0111       Returns the position of the item ( > 0 ).
0112     */
0113     [[nodiscard]] int position() const
0114     {
0115         return mPosition;
0116     }
0117 
0118     /**
0119       Returns the associated month scene to this item.
0120     */
0121     MonthScene *monthScene() const
0122     {
0123         return mMonthScene;
0124     }
0125 
0126     /**
0127       Begin a move.
0128     */
0129     void beginMove();
0130 
0131     /**
0132       End a move.
0133     */
0134     void endMove();
0135 
0136     /**
0137       Begin a resize.
0138     */
0139     void beginResize();
0140 
0141     /**
0142       End a resize.
0143     */
0144     void endResize();
0145 
0146     /**
0147       Called during move to move the item a bit, relative to the previous
0148       move step.
0149     */
0150     void moveBy(int offsetFromPreviousDate);
0151 
0152     /**
0153      * Called during a drag to move the item to a particular date.
0154      * An invalid date indicates a drag outside the month grid.
0155      */
0156     void moveTo(QDate date);
0157 
0158     /**
0159       Called during resize to resize the item a bit, relative to the previous
0160       resize step.
0161     */
0162     bool resizeBy(int offsetFromPreviousDate);
0163 
0164     /**
0165       Returns true if the item is being moved.
0166     */
0167     [[nodiscard]] bool isMoving() const
0168     {
0169         return mMoving;
0170     }
0171 
0172     /**
0173       Returns true if the item is being resized.
0174     */
0175     [[nodiscard]] bool isResizing() const
0176     {
0177         return mResizing;
0178     }
0179 
0180     /**
0181       Returns true if the item can be moved.
0182     */
0183     virtual bool isMoveable() const = 0;
0184 
0185     /**
0186       Returns true if the item can be resized.
0187     */
0188     virtual bool isResizable() const = 0;
0189 
0190     /**
0191       Deletes all MonthGraphicsItem this item handles. Clear the list.
0192     */
0193     void deleteAll();
0194 
0195     /**
0196       Update the monthgraphicsitems
0197 
0198       This basically deletes and rebuild all the MonthGraphicsItems but tries
0199         to do it wisely:
0200       - If there is a moving item, it won't be deleted because then the
0201         new item won't receive anymore the MouseMove events.
0202       - If there is an item on a line where the new state needs an item,
0203         it is used and not deleted. This will avoid flickers.
0204     */
0205     void updateMonthGraphicsItems();
0206 
0207     /**
0208       Sets the selection state of this item.
0209     */
0210     void setSelected(bool selected)
0211     {
0212         mSelected = selected;
0213     }
0214 
0215     // METHODS NEEDED TO PAINT ITEMS
0216 
0217     /**
0218       Returns the text to draw in an item.
0219 
0220      @param end True if the text at the end of an item should be returned.
0221     */
0222     virtual QString text(bool end) const = 0;
0223 
0224     /**
0225        Returns the text for the tooltip of the item
0226      */
0227     virtual QString toolTipText(const QDate &date) const = 0;
0228 
0229     /**
0230       Returns the background color of the item.
0231     */
0232     [[nodiscard]] virtual QColor bgColor() const = 0;
0233 
0234     /**
0235       Returns the frame color of the item.
0236     */
0237     [[nodiscard]] virtual QColor frameColor() const = 0;
0238 
0239     /**
0240       Returns a list of pixmaps to draw next to the items.
0241     */
0242     virtual QList<QPixmap> icons() const = 0;
0243 
0244     QList<MonthGraphicsItem *> monthGraphicsItems() const;
0245 
0246 protected:
0247     /**
0248       Called after a move operation.
0249     */
0250     virtual void finalizeMove(const QDate &newStartDate) = 0;
0251 
0252     /**
0253       Called after a resize operation.
0254     */
0255     virtual void finalizeResize(const QDate &newStartDate, const QDate &newEndDate) = 0;
0256 
0257 private:
0258     /**
0259       Sets the value of all MonthGraphicsItem to @param z.
0260     */
0261     EVENTVIEWS_NO_EXPORT void setZValue(qreal z);
0262 
0263     QList<MonthGraphicsItem *> mMonthGraphicsItemList;
0264 
0265     MonthScene *mMonthScene = nullptr;
0266 
0267     bool mSelected = false;
0268     bool mMoving = false; // during move
0269     bool mResizing = false; // during resize
0270     QDate mOverrideStartDate;
0271     int mOverrideDaySpan;
0272 
0273     int mPosition;
0274 };
0275 
0276 class EVENTVIEWS_EXPORT IncidenceMonthItem : public MonthItem
0277 {
0278     Q_OBJECT
0279 
0280 public:
0281     IncidenceMonthItem(MonthScene *monthScene,
0282                        const Akonadi::CollectionCalendar::Ptr &calendar,
0283                        const Akonadi::Item &item,
0284                        const KCalendarCore::Incidence::Ptr &incidence,
0285                        QDate recurStartDate = QDate());
0286 
0287     ~IncidenceMonthItem() override;
0288 
0289     KCalendarCore::Incidence::Ptr incidence() const;
0290     Akonadi::Item akonadiItem() const;
0291     Akonadi::Item::Id akonadiItemId() const;
0292     Akonadi::CollectionCalendar::Ptr calendar() const;
0293 
0294     bool greaterThanFallback(const MonthItem *other) const override;
0295 
0296     QDate realStartDate() const override;
0297     QDate realEndDate() const override;
0298     bool allDay() const override;
0299 
0300     bool isMoveable() const override;
0301     bool isResizable() const override;
0302 
0303     QString text(bool end) const override;
0304     QString toolTipText(const QDate &date) const override;
0305 
0306     QColor bgColor() const override;
0307     QColor frameColor() const override;
0308 
0309     QList<QPixmap> icons() const override;
0310 
0311 protected:
0312     void finalizeMove(const QDate &newStartDate) override;
0313     void finalizeResize(const QDate &newStartDate, const QDate &newEndDate) override;
0314 
0315 protected Q_SLOTS:
0316     /**
0317       Update the selected state of this item.
0318       If will be selected if incidence is the incidence managed by this item.
0319       Else it will be deselected.
0320     */
0321     void updateSelection(const Akonadi::Item &incidence, QDate date);
0322 
0323 private:
0324     EVENTVIEWS_NO_EXPORT void updateDates(int startOffset, int endOffset);
0325 
0326     EVENTVIEWS_NO_EXPORT void setNewDates(const KCalendarCore::Incidence::Ptr &incidence, int startOffset, int endOffset);
0327 
0328     /**
0329       Returns the category color for this incidence.
0330     */
0331     QColor catColor() const;
0332 
0333     Akonadi::CollectionCalendar::Ptr mCalendar;
0334     KCalendarCore::Incidence::Ptr mIncidence;
0335     Akonadi::Item::Id mAkonadiItemId;
0336     int mRecurDayOffset;
0337     bool mIsEvent, mIsTodo, mIsJournal;
0338 };
0339 
0340 class EVENTVIEWS_EXPORT HolidayMonthItem : public MonthItem
0341 {
0342     Q_OBJECT
0343 
0344 public:
0345     HolidayMonthItem(MonthScene *monthScene, QDate date, const QString &name);
0346     HolidayMonthItem(MonthScene *monthScene, QDate startDate, QDate endDate, const QString &name);
0347     ~HolidayMonthItem() override;
0348 
0349     bool greaterThanFallback(const MonthItem *other) const override;
0350 
0351     QDate realStartDate() const override
0352     {
0353         return mStartDate;
0354     }
0355 
0356     QDate realEndDate() const override
0357     {
0358         return mEndDate;
0359     }
0360 
0361     bool allDay() const override
0362     {
0363         return true;
0364     }
0365 
0366     bool isMoveable() const override
0367     {
0368         return false;
0369     }
0370 
0371     bool isResizable() const override
0372     {
0373         return false;
0374     }
0375 
0376     QString text(bool end) const override
0377     {
0378         Q_UNUSED(end)
0379         return mName;
0380     }
0381 
0382     QString toolTipText(const QDate &) const override
0383     {
0384         return mName;
0385     }
0386 
0387     QColor bgColor() const override;
0388     QColor frameColor() const override;
0389 
0390     QList<QPixmap> icons() const override;
0391 
0392 protected:
0393     void finalizeMove(const QDate &newStartDate) override;
0394     void finalizeResize(const QDate &newStartDate, const QDate &newEndDate) override;
0395 
0396 private:
0397     QDate mStartDate;
0398     QDate mEndDate;
0399     QString mName;
0400 };
0401 }