File indexing completed on 2024-05-26 05:15:28

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 <Akonadi/Collection>
0010 #include <Akonadi/CollectionCalendar>
0011 #include <Akonadi/Item>
0012 
0013 #include <QBasicTimer>
0014 #include <QDate>
0015 #include <QGraphicsScene>
0016 #include <QGraphicsView>
0017 #include <QMap>
0018 
0019 namespace Akonadi
0020 {
0021 class IncidenceChanger;
0022 }
0023 
0024 namespace EventViews
0025 {
0026 class MonthCell;
0027 class MonthItem;
0028 class MonthView;
0029 class ScrollIndicator;
0030 
0031 class MonthScene : public QGraphicsScene
0032 {
0033     Q_OBJECT
0034 
0035     enum ActionType { None, Move, Resize };
0036 
0037 public:
0038     enum ResizeType { ResizeLeft, ResizeRight };
0039 
0040     explicit MonthScene(MonthView *parent);
0041     ~MonthScene() override;
0042 
0043     [[nodiscard]] int columnWidth() const;
0044     [[nodiscard]] int rowHeight() const;
0045 
0046     MonthCell *firstCellForMonthItem(MonthItem *manager);
0047     [[nodiscard]] int height(MonthItem *manager);
0048     [[nodiscard]] int itemHeight();
0049     [[nodiscard]] int itemHeightIncludingSpacing();
0050     QList<MonthItem *> mManagerList;
0051     MonthView *mMonthView = nullptr;
0052 
0053     MonthView *monthView() const
0054     {
0055         return mMonthView;
0056     }
0057 
0058     QMap<QDate, MonthCell *> mMonthCellMap;
0059 
0060     [[nodiscard]] bool initialized() const
0061     {
0062         return mInitialized;
0063     }
0064 
0065     void setInitialized(bool i)
0066     {
0067         mInitialized = i;
0068     }
0069 
0070     void resetAll();
0071     Akonadi::IncidenceChanger *incidenceChanger() const;
0072 
0073     int totalHeight();
0074 
0075     /**
0076      * Returns the vertical position where the top of the cell should be
0077      * painted taking in account margins, rowHeight
0078      */
0079     [[nodiscard]] int cellVerticalPos(const MonthCell *cell) const;
0080 
0081     /**
0082      * Idem, for the horizontal position
0083      */
0084     [[nodiscard]] int cellHorizontalPos(const MonthCell *cell) const;
0085 
0086     /**
0087       Select item. If the argument is 0, the currently selected item gets
0088       deselected. This function emits the itemSelected(bool) signal to inform
0089       about selection/deselection of events.
0090     */
0091     void selectItem(MonthItem *);
0092     [[nodiscard]] int maxRowCount();
0093 
0094     MonthCell *selectedCell() const;
0095     MonthCell *previousCell() const;
0096 
0097     /**
0098       Get the space on the right of the cell associated to the date @p date.
0099     */
0100     [[nodiscard]] int getRightSpan(QDate date) const;
0101 
0102     /**
0103       Get the space on the left of the cell associated to the date @p date.
0104     */
0105     [[nodiscard]] int getLeftSpan(QDate date) const;
0106 
0107     /**
0108       Returns the date in the first column of the row given by @p row.
0109     */
0110     [[nodiscard]] QDate firstDateOnRow(int row) const;
0111 
0112     /**
0113       Calls updateGeometry() on each MonthItem
0114     */
0115     void updateGeometry();
0116 
0117     /**
0118       Returns the first height. Used for scrolling
0119 
0120       @see MonthItem::height()
0121     */
0122     [[nodiscard]] int startHeight() const
0123     {
0124         return mStartHeight;
0125     }
0126 
0127     /**
0128       Set the current height using @p height.
0129       If height = 0, then the view is not scrolled. Else it will be scrolled
0130       by step of one item.
0131     */
0132     void setStartHeight(int height)
0133     {
0134         mStartHeight = height;
0135     }
0136 
0137     /**
0138       Returns the resize type.
0139     */
0140     [[nodiscard]] ResizeType resizeType() const
0141     {
0142         return mResizeType;
0143     }
0144 
0145     /**
0146       Returns the currently selected item.
0147     */
0148     MonthItem *selectedItem()
0149     {
0150         return mSelectedItem;
0151     }
0152 
0153     [[nodiscard]] QPixmap birthdayPixmap() const
0154     {
0155         return mBirthdayPixmap;
0156     }
0157 
0158     [[nodiscard]] QPixmap anniversaryPixmap() const
0159     {
0160         return mAnniversaryPixmap;
0161     }
0162 
0163     [[nodiscard]] QPixmap alarmPixmap() const
0164     {
0165         return mAlarmPixmap;
0166     }
0167 
0168     [[nodiscard]] QPixmap recurPixmap() const
0169     {
0170         return mRecurPixmap;
0171     }
0172 
0173     [[nodiscard]] QPixmap readonlyPixmap() const
0174     {
0175         return mReadonlyPixmap;
0176     }
0177 
0178     [[nodiscard]] QPixmap replyPixmap() const
0179     {
0180         return mReplyPixmap;
0181     }
0182 
0183     [[nodiscard]] QPixmap holidayPixmap() const
0184     {
0185         return mHolidayPixmap;
0186     }
0187 
0188     /**
0189        Removes an incidence from the scene
0190     */
0191     void removeIncidence(const QString &uid);
0192 
0193 Q_SIGNALS:
0194     void incidenceSelected(const Akonadi::Item &incidence, const QDate &);
0195     void showIncidencePopupSignal(const Akonadi::CollectionCalendar::Ptr &, const Akonadi::Item &, const QDate &);
0196     void newEventSignal();
0197     void showNewEventPopupSignal();
0198 
0199 protected:
0200     void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
0201     void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
0202     void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
0203     void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
0204     void wheelEvent(QGraphicsSceneWheelEvent *wheelEvent) override;
0205     void timerEvent(QTimerEvent *e) override;
0206     void helpEvent(QGraphicsSceneHelpEvent *helpEvent) override;
0207     /**
0208        Scrolls all incidences in cells up
0209      */
0210     virtual void scrollCellsUp();
0211 
0212     /**
0213        Scrolls all incidences in cells down
0214     */
0215     virtual void scrollCellsDown();
0216 
0217     /**
0218        A click on a scroll indicator has occurred
0219        TODO : move this handler to the scrollindicator
0220     */
0221     virtual void clickOnScrollIndicator(ScrollIndicator *scrollItem);
0222 
0223     /**
0224       Handles drag and drop events. Called from eventFilter.
0225     */
0226     //    virtual bool eventFilter_drag( QObject *, QDropEvent * );
0227 
0228     /**
0229       Returns true if the last item is visible in the given @p cell.
0230     */
0231     bool lastItemFit(MonthCell *cell);
0232 
0233 private:
0234     /**
0235      * Returns the height of the header of the view
0236      */
0237     int headerHeight() const;
0238 
0239     int availableWidth() const;
0240 
0241     /**
0242      * Height available to draw the cells. Doesn't include header.
0243      */
0244     int availableHeight() const;
0245 
0246     /**
0247      * Removes all the margins, frames, etc. to give the
0248      * X coordinate in the MonthGrid.
0249      */
0250     int sceneXToMonthGridX(int xScene);
0251 
0252     /**
0253      * Removes all the margins, frames, headers etc. to give the
0254      * Y coordinate in the MonthGrid.
0255      */
0256     int sceneYToMonthGridY(int yScene);
0257 
0258     /**
0259      * Given a pos in the scene coordinates,
0260      * returns the cell containing @p pos.
0261      */
0262     MonthCell *getCellFromPos(QPointF pos);
0263 
0264     /**
0265        Returns true if (x, y) is in the monthgrid, false else.
0266     */
0267     bool isInMonthGrid(int x, int y) const;
0268 
0269     bool mInitialized;
0270 
0271     // User interaction.
0272     MonthItem *mClickedItem = nullptr; // todo ini in ctor
0273     MonthItem *mActionItem = nullptr;
0274     bool mActionInitiated;
0275 
0276     MonthItem *mSelectedItem = nullptr;
0277     QDate mSelectedCellDate;
0278     MonthCell *mStartCell = nullptr; // start cell when dragging
0279     MonthCell *mPreviousCell = nullptr; // the cell before that one during dragging
0280 
0281     ActionType mActionType;
0282     ResizeType mResizeType;
0283 
0284     // The item height at the top of the cell. This is generally 0 unless
0285     // the user scroll the view when there are too many items.
0286     int mStartHeight;
0287 
0288     // icons to draw in front of the events
0289     QPixmap mEventPixmap;
0290     QPixmap mBirthdayPixmap;
0291     QPixmap mAnniversaryPixmap;
0292     QPixmap mTodoPixmap;
0293     QPixmap mTodoDonePixmap;
0294     QPixmap mJournalPixmap;
0295     QPixmap mAlarmPixmap;
0296     QPixmap mRecurPixmap;
0297     QPixmap mReadonlyPixmap;
0298     QPixmap mReplyPixmap;
0299     QPixmap mHolidayPixmap;
0300     QBasicTimer repeatTimer;
0301     ScrollIndicator *mCurrentIndicator = nullptr;
0302     friend class MonthGraphicsView;
0303 };
0304 
0305 /**
0306  * Renders a MonthScene
0307  */
0308 class MonthGraphicsView : public QGraphicsView
0309 {
0310     Q_OBJECT
0311 public:
0312     explicit MonthGraphicsView(MonthView *parent);
0313 
0314     /**
0315       Draws the cells.
0316     */
0317     void drawBackground(QPainter *painter, const QRectF &rect) override;
0318 
0319     void setScene(MonthScene *scene);
0320 
0321     /**
0322       Change the cursor according to @p actionType.
0323     */
0324     void setActionCursor(MonthScene::ActionType actionType);
0325 
0326 protected:
0327     void resizeEvent(QResizeEvent *) override;
0328 
0329 private:
0330     MonthScene *mScene = nullptr;
0331     MonthView *mMonthView = nullptr;
0332 };
0333 }