File indexing completed on 2024-05-12 05:21:23
0001 /* 0002 This file is part of KOrganizer. 0003 0004 SPDX-FileCopyrightText: 2001 Eitzenberger Thomas <thomas.eitzenberger@siemens.at> 0005 SPDX-FileCopyrightText: 2003 Cornelius Schumacher <schumacher@kde.org> 0006 SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0009 */ 0010 0011 #pragma once 0012 0013 #include <Akonadi/CollectionCalendar> 0014 0015 #include <KCalendarCore/IncidenceBase> //for KCalendarCore::DateList typedef 0016 0017 #include <QDate> 0018 #include <QFrame> 0019 0020 /** 0021 * Replacement for kdpdatebuton.cpp that used 42 widgets for the day 0022 * matrix to be displayed. Cornelius thought this was a waste of memory 0023 * and a lot of overhead. In addition the selection was not very intuitive 0024 * so I decided to rewrite it using a QFrame that draws the labels and 0025 * allows for dragging selection while maintaining nearly full compatibility 0026 * in behavior with its predecessor. 0027 * 0028 * The following functionality has been changed: 0029 * 0030 * o when shifting events in the agenda view from one day to another 0031 * the day matrix is updated now 0032 * 0033 * o dragging an event to the matrix will MOVE not COPY the event to the 0034 * new date. 0035 * 0036 * o no support for Ctrl+click to create groups of dates 0037 * (This has not really been supported in the predecessor. 0038 * It was not very intuitive nor was it user friendly.) 0039 * This feature has been replaced with dragging a selection on the matrix. 0040 * The matrix will automatically choose the appropriate selection (e.g. you 0041 * are not any longer able to select two distinct groups of date selections 0042 * as in the old class) 0043 * 0044 * o now that you can select more than a week it can happen that not all 0045 * selected days are displayed in the matrix. However this is preferred 0046 * to the alternative which would mean to adjust the selection and leave 0047 * some days undisplayed while scrolling through the months 0048 * 0049 * @short day matrix widget of the KDateNavigator 0050 * 0051 * @author Eitzenberger Thomas 0052 */ 0053 class KODayMatrix : public QFrame, public KCalendarCore::Calendar::CalendarObserver 0054 { 0055 Q_OBJECT 0056 public: 0057 /** constructor to create a day matrix widget. 0058 * 0059 * @param parent widget that is the parent of the day matrix. 0060 * Normally this should be a KDateNavigator 0061 */ 0062 explicit KODayMatrix(QWidget *parent); 0063 0064 /** destructor that deallocates all dynamically allocated private members. 0065 */ 0066 ~KODayMatrix() override; 0067 0068 /** returns the first and last date of the 6*7 matrix that displays @p month 0069 * @param month The month we want to get matrix boundaries 0070 */ 0071 [[nodiscard]] static QPair<QDate, QDate> matrixLimits(QDate month); 0072 0073 /** 0074 Associate a calendar with this day matrix. If there is a calendar, the 0075 day matrix will accept drops and days with events will be highlighted. 0076 */ 0077 void addCalendar(const Akonadi::CollectionCalendar::Ptr &calendar); 0078 void removeCalendar(const Akonadi::CollectionCalendar::Ptr &calendar); 0079 0080 /** updates the day matrix to start with the given date. Does all the 0081 * necessary checks for holidays or events on a day and stores them 0082 * for display later on. 0083 * Does NOT update the view visually. Call repaint() for this. 0084 * 0085 * @param actdate recalculates the day matrix to show NUMDAYS starting 0086 * from this date. 0087 */ 0088 void updateView(QDate actdate); 0089 0090 /** 0091 Update incidence states of dates. Depending of the preferences days with 0092 incidences are highlighted in some way. 0093 */ 0094 void updateIncidences(); 0095 0096 /** 0097 * Returns the QDate object associated with day indexed by the supplied 0098 * offset. 0099 */ 0100 const QDate &getDate(int offset) const; 0101 0102 /** 0103 * Returns the official name of this holy day or 0 if there is no label 0104 * for this day. 0105 */ 0106 QString getHolidayLabel(int offset) const; 0107 0108 /** 0109 * Adds all actual selected days from mSelStart to mSelEnd to the supplied 0110 * DateList. 0111 */ 0112 void addSelectedDaysTo(KCalendarCore::DateList &); 0113 0114 /** 0115 * Sets the actual to be displayed selection in the day matrix starting 0116 * from start and ending with end. Theview must be manually updated by 0117 * calling repaint. (?) 0118 * @param start start of the new selection 0119 * @param end end date of the new selection 0120 */ 0121 void setSelectedDaysFrom(QDate start, QDate end); 0122 0123 /** 0124 Clear all selections. 0125 */ 0126 void clearSelection(); 0127 0128 /** Is today visible in the view? Keep this in sync with 0129 * the values today (below) can take. 0130 */ 0131 [[nodiscard]] bool isTodayVisible() const 0132 { 0133 return mToday >= 0; 0134 } 0135 0136 /** 0137 * If today is visible, then we can find out if today is 0138 * near the beginning or the end of the month. 0139 * This is dependent on today remaining the index 0140 * in the array of visible dates and going from 0141 * top left (0) to bottom right (41). 0142 */ 0143 [[nodiscard]] bool isBeginningOfMonth() const 0144 { 0145 return mToday <= 8; 0146 } 0147 0148 [[nodiscard]] bool isEndOfMonth() const 0149 { 0150 return mToday >= 27; 0151 } 0152 0153 /** 0154 * Reimplemented from Akonadi::ETMCalendar 0155 * They set mPendingChanges to true 0156 */ 0157 void calendarIncidenceAdded(const KCalendarCore::Incidence::Ptr &incidence) override; 0158 void calendarIncidenceChanged(const KCalendarCore::Incidence::Ptr &incidence) override; 0159 void calendarIncidenceDeleted(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Calendar *calendar) override; 0160 0161 /** Sets which incidences should be highlighted */ 0162 void setHighlightMode(bool highlightEvents, bool highlightTodos, bool highlightJournals); 0163 void setUpdateNeeded(); 0164 public Q_SLOTS: 0165 /** 0166 * Recalculates all the flags of the days in the matrix like holidays or 0167 * events on a day (Actually calls above method with the actual startdate). 0168 */ 0169 void updateView(); 0170 0171 /** 0172 * Calculates which square in the matrix should be highlighted to indicate 0173 * the square is on "today". 0174 */ 0175 void recalculateToday(); 0176 0177 /** 0178 * Handle resource changes. 0179 */ 0180 void resourcesChanged(); 0181 0182 Q_SIGNALS: 0183 /** 0184 * Emitted if the user selects a block of days with the mouse by dragging 0185 * a rectangle inside the matrix 0186 * 0187 * @param daylist list of days that have been selected by the user 0188 */ 0189 void selected(const KCalendarCore::DateList &daylist); 0190 0191 void newEventSignal(const QDate &date, const QDate &Date); 0192 void newTodoSignal(const QDate &date); 0193 void newJournalSignal(const QDate &date); 0194 0195 /** 0196 * Emitted if the user has dropped an incidence (event or todo) inside 0197 * the matrix. 0198 * 0199 * @param incidence the dropped calendar incidence 0200 * @param dt QDate that has been selected 0201 */ 0202 void incidenceDropped(const Akonadi::Item &item, const QDate &dt); 0203 0204 /** 0205 * Emitted if the user has dropped an event inside the matrix and chose 0206 * to move it instead of copy 0207 * 0208 * @param oldincidence the new calendar incidence 0209 * @param dt QDate that has been selected 0210 */ 0211 void incidenceDroppedMove(const Akonadi::Item &item, const QDate &dt); 0212 0213 protected: 0214 bool event(QEvent *e) override; 0215 0216 void paintEvent(QPaintEvent *ev) override; 0217 0218 void mousePressEvent(QMouseEvent *e) override; 0219 0220 void mouseReleaseEvent(QMouseEvent *e) override; 0221 0222 void mouseMoveEvent(QMouseEvent *e) override; 0223 0224 void resizeEvent(QResizeEvent *) override; 0225 0226 void dragEnterEvent(QDragEnterEvent *e) override; 0227 0228 void dragMoveEvent(QDragMoveEvent *e) override; 0229 0230 void dragLeaveEvent(QDragLeaveEvent *e) override; 0231 0232 void dropEvent(QDropEvent *e) override; 0233 0234 private: 0235 /** 0236 * Pop-up a context menu for creating a new Event, To-do, or Journal. 0237 */ 0238 void popupMenu(const QDate &date, const QDate &date2); 0239 0240 /** returns the index of the day located at the matrix's widget (x,y) position. 0241 * 0242 * @param x horizontal coordinate 0243 * @param y vertical coordinate 0244 */ 0245 int getDayIndexFrom(int x, int y) const; 0246 0247 /** calculates a "shaded" color from the supplied color object. 0248 * (Copied from Cornelius's kdpdatebutton.cpp) 0249 * 0250 * @param color source based on which a shaded color should be calculated. 0251 */ 0252 QColor getShadedColor(const QColor &color) const; 0253 0254 /** updates mEvent list with all days that have events */ 0255 void updateEvents(); 0256 0257 /** updates mEvent list with all days that have to-dos with due date */ 0258 void updateTodos(); 0259 0260 /** updates mEvent list with all days that have journals */ 0261 void updateJournals(); 0262 0263 /** number of days to be displayed. For now there is no support for any 0264 other number than 42. so change it at your own risk :o) */ 0265 static const int NUMDAYS; 0266 0267 /** calendar instance to be queried for holidays, events, ... */ 0268 QList<Akonadi::CollectionCalendar::Ptr> mCalendars; 0269 0270 /** starting date of the matrix */ 0271 QDate mStartDate; 0272 0273 /** array of day labels to optimeize drawing performance. */ 0274 QString *mDayLabels = nullptr; 0275 0276 /** array of days displayed to reduce memory consumption by 0277 subsequently calling QDate::addDays(). */ 0278 QDate *mDays = nullptr; 0279 0280 /** List for storing days which should be drawn using bold font. */ 0281 QList<QDate> mEvents; 0282 0283 /** stores holiday names of the days shown in the matrix. */ 0284 QMap<int, QString> mHolidays; 0285 0286 /** index of today or -1 if today is not visible in the matrix. */ 0287 int mToday; 0288 0289 /** index of day where dragged selection was initiated. 0290 used to detect "negative" timely selections */ 0291 int mSelInit; 0292 0293 /** if mSelStart has this value it indicates that there is no 0294 actual selection in the matrix. */ 0295 static const int NOSELECTION; 0296 0297 /** index of first selected day. */ 0298 int mSelStart; 0299 0300 /** index of last selected day. */ 0301 int mSelEnd; 0302 0303 /** default width of the frame drawn around today if it is visible 0304 in the matrix. */ 0305 int mTodayMarginWidth; 0306 0307 /** stores actual size of each day in the widget so we don't need to 0308 * ask on every repaint. 0309 */ 0310 QRect mDaySize; 0311 0312 /** 0313 * Indicate pending calendar changes. 0314 */ 0315 bool mPendingChanges = false; 0316 0317 /** Whether days with events are highlighted */ 0318 bool mHighlightEvents = false; 0319 0320 /** Whether days with to-dos (with due date) are highlighted */ 0321 bool mHighlightTodos = false; 0322 0323 /** Whether days with journals are highlighted */ 0324 bool mHighlightJournals = false; 0325 };