File indexing completed on 2024-05-12 05:13:27

0001 /*
0002   SPDX-FileCopyrightText: 1999 Preston Brown <pbrown@kde.org>
0003   SPDX-FileCopyrightText: 2000, 2001 Cornelius Schumacher <schumacher@kde.org>
0004   SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
0005   SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
0006   SPDX-FileContributor: Kevin Krammer <krake@kdab.com>
0007 
0008   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0009 */
0010 #pragma once
0011 
0012 #include "eventviews_export.h"
0013 
0014 #include <Akonadi/Collection>
0015 #include <Akonadi/CollectionCalendar>
0016 #include <Akonadi/Item>
0017 
0018 #include <KCalendarCore/Incidence>
0019 #include <KCalendarCore/Todo>
0020 
0021 #include <QByteArray>
0022 #include <QDate>
0023 #include <QSet>
0024 #include <QWidget>
0025 
0026 #include <memory>
0027 
0028 class QAbstractItemModel;
0029 
0030 namespace CalendarSupport
0031 {
0032 class CollectionSelection;
0033 class KCalPrefs;
0034 }
0035 
0036 namespace Akonadi
0037 {
0038 class IncidenceChanger;
0039 }
0040 
0041 class KCheckableProxyModel;
0042 class KConfigGroup;
0043 
0044 namespace EventViews
0045 {
0046 enum { BUSY_BACKGROUND_ALPHA = 70 };
0047 
0048 class EventViewPrivate;
0049 class Prefs;
0050 using PrefsPtr = QSharedPointer<Prefs>;
0051 using KCalPrefsPtr = QSharedPointer<CalendarSupport::KCalPrefs>;
0052 
0053 /**
0054   EventView is the abstract base class from which all other calendar views
0055   for event data are derived.  It provides methods for displaying
0056   appointments and events on one or more days.  The actual number of
0057   days that a view actually supports is not defined by this abstract class;
0058   that is up to the classes that inherit from it.  It also provides
0059   methods for updating the display, retrieving the currently selected
0060   event (or events), and the like.
0061 
0062   @short Abstract class from which all event views are derived.
0063   @author Preston Brown <pbrown@kde.org>
0064   @see KOListView, AgendaView, KOMonthView
0065 */
0066 class EVENTVIEWS_EXPORT EventView : public QWidget
0067 {
0068     Q_OBJECT
0069 public:
0070     enum {
0071         // This value is passed to QColor's lighter(int factor) for selected events
0072         BRIGHTNESS_FACTOR = 110
0073     };
0074 
0075     enum ItemIcon {
0076         CalendarCustomIcon = 0,
0077         TaskIcon,
0078         JournalIcon,
0079         RecurringIcon,
0080         ReminderIcon,
0081         ReadOnlyIcon,
0082         ReplyIcon,
0083         AttendingIcon,
0084         TentativeIcon,
0085         OrganizerIcon,
0086         IconCount = 10 // Always keep at the end
0087     };
0088 
0089     enum Change {
0090         NothingChanged = 0,
0091         IncidencesAdded = 1,
0092         IncidencesEdited = 2,
0093         IncidencesDeleted = 4,
0094         DatesChanged = 8,
0095         FilterChanged = 16,
0096         ResourcesChanged = 32,
0097         ZoomChanged = 64,
0098         ConfigChanged = 128
0099     };
0100     Q_DECLARE_FLAGS(Changes, Change)
0101 
0102     /**
0103      * Constructs a view.
0104      * @param cal is a pointer to the calendar object from which events
0105      *        will be retrieved for display.
0106      * @param parent is the parent QWidget.
0107      */
0108     explicit EventView(QWidget *parent = nullptr);
0109 
0110     /**
0111      * Destructor. Views will do view-specific cleanups here.
0112      */
0113     ~EventView() override;
0114 
0115     virtual void addCalendar(const Akonadi::CollectionCalendar::Ptr &calendar);
0116     virtual void removeCalendar(const Akonadi::CollectionCalendar::Ptr &calendar);
0117 
0118     virtual void setModel(QAbstractItemModel *model);
0119     QAbstractItemModel *model() const;
0120     Akonadi::EntityTreeModel *entityTreeModel() const;
0121 
0122     /*
0123       update config is called after prefs are set.
0124     */
0125     virtual void setPreferences(const PrefsPtr &preferences);
0126     [[nodiscard]] PrefsPtr preferences() const;
0127 
0128     virtual void setKCalPreferences(const KCalPrefsPtr &preferences);
0129     [[nodiscard]] KCalPrefsPtr kcalPreferences() const;
0130 
0131     /**
0132       @return a list of selected events. Most views can probably only
0133       select a single event at a time, but some may be able to select
0134       more than one.
0135     */
0136     virtual Akonadi::Item::List selectedIncidences() const = 0;
0137 
0138     /**
0139       Returns a list of the dates of selected events. Most views can
0140       probably only select a single event at a time, but some may be able
0141       to select more than one.
0142     */
0143     virtual KCalendarCore::DateList selectedIncidenceDates() const = 0;
0144 
0145     /**
0146        Returns the start of the selection, or an invalid QDateTime if there is no selection
0147        or the view doesn't support selecting cells.
0148      */
0149     virtual QDateTime selectionStart() const;
0150 
0151     /**
0152       Returns the end of the selection, or an invalid QDateTime if there is no selection
0153       or the view doesn't support selecting cells.
0154      */
0155     virtual QDateTime selectionEnd() const;
0156 
0157     /**
0158       Sets the default start/end date/time for new events.
0159       Return true if anything was changed
0160     */
0161     virtual bool eventDurationHint(QDateTime &startDt, QDateTime &endDt, bool &allDay) const;
0162 
0163     /**
0164       Returns whether or not date range selection is enabled. This setting only
0165       applies to views that actually supports selecting cells.
0166       @see selectionStart()
0167       @see selectionEnd()
0168      */
0169     [[nodiscard]] bool dateRangeSelectionEnabled() const;
0170 
0171     /**
0172       Enable or disable date range selection.
0173       @see dateRangeSelectionEnabled()
0174      */
0175     void setDateRangeSelectionEnabled(bool enable);
0176 
0177     /**
0178       Returns the number of currently shown dates.
0179       A return value of 0 means no idea.
0180     */
0181     virtual int currentDateCount() const = 0;
0182 
0183     /**
0184      * returns whether this view supports zoom.
0185      * Base implementation returns false.
0186      */
0187     virtual bool supportsZoom() const;
0188 
0189     virtual bool hasConfigurationDialog() const;
0190 
0191     virtual void showConfigurationDialog(QWidget *parent);
0192 
0193     [[nodiscard]] QByteArray identifier() const;
0194     void setIdentifier(const QByteArray &identifier);
0195 
0196     /**
0197      * reads the view configuration. View-specific configuration can be
0198      * restored via doRestoreConfig()
0199      *
0200      * @param configGroup the group to read settings from
0201      * @see doRestoreConfig()
0202      */
0203     void restoreConfig(const KConfigGroup &configGroup);
0204 
0205     /**
0206      * writes out the view configuration. View-specific configuration can be
0207      * saved via doSaveConfig()
0208      *
0209      * @param configGroup the group to store settings in
0210      * @see doSaveConfig()
0211      */
0212     void saveConfig(KConfigGroup &configGroup);
0213 
0214     //----------------------------------------------------------------------------
0215     KCheckableProxyModel *takeCustomCollectionSelectionProxyModel();
0216     KCheckableProxyModel *customCollectionSelectionProxyModel() const;
0217     void setCustomCollectionSelectionProxyModel(KCheckableProxyModel *model);
0218 
0219     CalendarSupport::CollectionSelection *customCollectionSelection() const;
0220 
0221     static CalendarSupport::CollectionSelection *globalCollectionSelection();
0222     static void setGlobalCollectionSelection(CalendarSupport::CollectionSelection *selection);
0223     //----------------------------------------------------------------------------
0224 
0225     /**
0226      * returns the view at the given widget coordinate. This is usually the view
0227      * itself, except for composite views, where a subview will be returned.
0228      * The default implementation returns @p this .
0229      */
0230     virtual EventView *viewAt(const QPoint &p);
0231 
0232     /**
0233      * @param preferredMonth Used by month orientated views.  Contains the
0234      * month to show when the week crosses months.  It's a QDate instead
0235      * of uint so it can be easily fed to KCalendarSystem's functions.
0236      */
0237     virtual void setDateRange(const QDateTime &start, const QDateTime &end, const QDate &preferredMonth = QDate());
0238 
0239     [[nodiscard]] QDateTime startDateTime() const;
0240     [[nodiscard]] QDateTime endDateTime() const;
0241 
0242     [[nodiscard]] QDateTime actualStartDateTime() const;
0243     [[nodiscard]] QDateTime actualEndDateTime() const;
0244 
0245     [[nodiscard]] int showMoveRecurDialog(const KCalendarCore::Incidence::Ptr &incidence, QDate date);
0246 
0247     /**
0248       Handles key events, opens the new event dialog when enter is pressed, activates type ahead.
0249     */
0250     [[nodiscard]] bool processKeyEvent(QKeyEvent *);
0251 
0252     /*
0253      * Sets the QObject that will receive key events that were made
0254      * while the new event dialog was still being created.
0255      */
0256     void setTypeAheadReceiver(QObject *o);
0257 
0258     /**
0259       Returns the selection of collection to be used by this view
0260       (custom if set, or global otherwise).
0261     */
0262     CalendarSupport::CollectionSelection *collectionSelection() const;
0263 
0264     /**
0265       Notifies the view that there are pending changes so a redraw is needed.
0266       @param needed if the update is needed or not.
0267     */
0268     virtual void setChanges(Changes changes);
0269 
0270     /**
0271       Returns if there are pending changes and a redraw is needed.
0272     */
0273     [[nodiscard]] Changes changes() const;
0274 
0275     /**
0276      * Returns a variation of @p color that will be used for the border
0277      * of an agenda or month item.
0278      */
0279     [[nodiscard]] static QColor itemFrameColor(const QColor &color, bool selected);
0280 
0281     [[nodiscard]] QString iconForItem(const Akonadi::Item &);
0282 
0283     [[nodiscard]] Akonadi::CollectionCalendar::Ptr calendarForCollection(const Akonadi::Collection &collection) const;
0284     [[nodiscard]] Akonadi::CollectionCalendar::Ptr calendarForCollection(Akonadi::Collection::Id collectionId) const;
0285 
0286 public Q_SLOTS:
0287     /**
0288       Shows given incidences. Depending on the actual view it might not
0289       be possible to show all given events.
0290 
0291       @param incidenceList a list of incidences to show.
0292       @param date is the QDate on which the incidences are being shown.
0293     */
0294     virtual void showIncidences(const Akonadi::Item::List &incidenceList, const QDate &date) = 0;
0295 
0296     /**
0297       Updates the current display to reflect changes that may have happened
0298       in the calendar since the last display refresh.
0299     */
0300     virtual void updateView() = 0;
0301     virtual void dayPassed(const QDate &);
0302 
0303     /**
0304       Assign a new incidence change helper object.
0305      */
0306     virtual void setIncidenceChanger(Akonadi::IncidenceChanger *changer);
0307 
0308     /**
0309       Write all unsaved data back to calendar store.
0310     */
0311     virtual void flushView();
0312 
0313     /**
0314       Re-reads the configuration and picks up relevant
0315       changes which are applicable to the view.
0316     */
0317     virtual void updateConfig();
0318 
0319     /**
0320       Clear selection. The incidenceSelected signal is not emitted.
0321     */
0322     virtual void clearSelection();
0323 
0324     void focusChanged(QWidget *, QWidget *);
0325 
0326     /**
0327      Perform the default action for an incidence, e.g. open the event editor,
0328      when double-clicking an event in the agenda view.
0329     */
0330     void defaultAction(const Akonadi::Item &incidence);
0331 
0332     /**
0333        Set which holiday regions the user wants to use.
0334        @param regions a list of Holiday Regions strings.
0335     */
0336     void setHolidayRegions(const QStringList &regions);
0337 
0338 Q_SIGNALS:
0339     /**
0340      * when the view changes the dates that are selected in one way or
0341      * another, this signal is emitted.  It should be connected back to
0342      * the KDateNavigator object so that it changes appropriately,
0343      * and any other objects that need to be aware that the list of
0344      * selected dates has changed.
0345      *   @param datelist the new list of selected dates
0346      */
0347     void datesSelected(const KCalendarCore::DateList &datelist);
0348 
0349     /**
0350      * Emitted when an event is moved using the mouse in an agenda
0351      * view (week / month).
0352      */
0353     void shiftedEvent(const QDate &olddate, const QDate &newdate);
0354 
0355     void incidenceSelected(const Akonadi::Item &, const QDate);
0356 
0357     /**
0358      * instructs the receiver to show the incidence in read-only mode.
0359      */
0360     void showIncidenceSignal(const Akonadi::Item &);
0361 
0362     /**
0363      * instructs the receiver to begin editing the incidence specified in
0364      * some manner.  Doesn't make sense to connect to more than one
0365      * receiver.
0366      */
0367     void editIncidenceSignal(const Akonadi::Item &);
0368 
0369     /**
0370      * instructs the receiver to delete the Incidence in some manner; some
0371      * possibilities include automatically, with a confirmation dialog
0372      * box, etc.  Doesn't make sense to connect to more than one receiver.
0373      */
0374     void deleteIncidenceSignal(const Akonadi::Item &);
0375 
0376     /**
0377      * instructs the receiver to cut the Incidence
0378      */
0379     void cutIncidenceSignal(const Akonadi::Item &);
0380 
0381     /**
0382      * instructs the receiver to copy the incidence
0383      */
0384     void copyIncidenceSignal(const Akonadi::Item &);
0385 
0386     /**
0387      * instructs the receiver to paste the incidence
0388      */
0389     void pasteIncidenceSignal();
0390 
0391     /**
0392      * instructs the receiver to toggle the alarms of the Incidence.
0393      */
0394     void toggleAlarmSignal(const Akonadi::Item &);
0395 
0396     /**
0397      * instructs the receiver to toggle the completion state of the Incidence
0398      * (which must be a Todo type).
0399      */
0400     void toggleTodoCompletedSignal(const Akonadi::Item &);
0401 
0402     /**
0403      * Copy the incidence to the specified resource.
0404      */
0405     void copyIncidenceToResourceSignal(const Akonadi::Item &, const Akonadi::Collection &);
0406 
0407     /**
0408      * Move the incidence to the specified resource.
0409      */
0410     void moveIncidenceToResourceSignal(const Akonadi::Item &, const Akonadi::Collection &);
0411 
0412     /** Dissociate from a recurring incidence the occurrence on the given
0413      *  date to a new incidence or dissociate all occurrences from the
0414      *  given date onwards.
0415      */
0416     void dissociateOccurrencesSignal(const Akonadi::Item &, const QDate &);
0417 
0418     /**
0419      * instructs the receiver to create a new event in given collection. Doesn't make
0420      * sense to connect to more than one receiver.
0421      */
0422     void newEventSignal();
0423     /**
0424      * instructs the receiver to create a new event with the specified beginning
0425      * time. Doesn't make sense to connect to more than one receiver.
0426      */
0427     void newEventSignal(const QDate &);
0428     /**
0429      * instructs the receiver to create a new event with the specified beginning
0430      * time. Doesn't make sense to connect to more than one receiver.
0431      */
0432     void newEventSignal(const QDateTime &);
0433     /**
0434      * instructs the receiver to create a new event, with the specified
0435      * beginning end ending times.  Doesn't make sense to connect to more
0436      * than one receiver.
0437      */
0438     void newEventSignal(const QDateTime &, const QDateTime &);
0439 
0440     void newTodoSignal(const QDate &);
0441     void newSubTodoSignal(const Akonadi::Item &);
0442 
0443     void newJournalSignal(const QDate &);
0444 
0445 protected Q_SLOTS:
0446     virtual void calendarReset();
0447 
0448 private:
0449     EVENTVIEWS_NO_EXPORT void onCollectionChanged(const Akonadi::Collection &, const QSet<QByteArray> &);
0450 
0451 protected:
0452     QList<Akonadi::CollectionCalendar::Ptr> calendars() const;
0453     Akonadi::CollectionCalendar::Ptr calendar3(const Akonadi::Item &item) const;
0454     Akonadi::CollectionCalendar::Ptr calendar3(const KCalendarCore::Incidence::Ptr &incidence) const;
0455 
0456     bool makesWholeDayBusy(const KCalendarCore::Incidence::Ptr &incidence) const;
0457     Akonadi::IncidenceChanger *changer() const;
0458 
0459     /**
0460      * reimplement to read view-specific settings.
0461      */
0462     virtual void doRestoreConfig(const KConfigGroup &configGroup);
0463 
0464     /**
0465      * reimplement to write view-specific settings.
0466      */
0467     virtual void doSaveConfig(KConfigGroup &configGroup);
0468 
0469     /**
0470       @deprecated
0471      */
0472     virtual void showDates(const QDate &start, const QDate &end, const QDate &preferredMonth = QDate()) = 0;
0473 
0474     /**
0475      * from the requested date range (passed via setDateRange()), calculates the
0476      * adjusted date range actually displayed by the view, depending on the
0477      * view's supported range (e.g., a month view always displays one month)
0478      * The default implementation returns the range unmodified
0479      *
0480      * @param preferredMonth Used by month orientated views. Contains the
0481      * month to show when the week crosses months.  It's a QDate instead of
0482      * uint so it can be easily fed to KCalendarSystem's functions.
0483      */
0484     virtual QPair<QDateTime, QDateTime> actualDateRange(const QDateTime &start, const QDateTime &end, const QDate &preferredMonth = QDate()) const;
0485     /*
0486     virtual void incidencesAdded( const Akonadi::Item::List &incidences );
0487     virtual void incidencesAboutToBeRemoved( const Akonadi::Item::List &incidences );
0488     virtual void incidencesChanged( const Akonadi::Item::List &incidences );
0489     */
0490     virtual void handleBackendError(const QString &error);
0491 
0492 private:
0493     std::unique_ptr<EventViewPrivate> const d_ptr;
0494     Q_DECLARE_PRIVATE(EventView)
0495 };
0496 }