File indexing completed on 2024-04-28 04:20:56

0001 // SPDX-FileCopyrightText: 2004 - 2010 Jesper K. Pedersen <jesper.pedersen@kdab.com>
0002 // SPDX-FileCopyrightText: 2005, 2007 Dirk Mueller <mueller@kde.org>
0003 // SPDX-FileCopyrightText: 2012 Miika Turkia <miika.turkia@gmail.com>
0004 // SPDX-FileCopyrightText: 2013 Dominik Broj <broj.dominik@gmail.com>
0005 // SPDX-FileCopyrightText: 2018 - 2020 Robert Krawitz <rlk@alum.mit.edu>
0006 // SPDX-FileCopyrightText: 2019, 2022 Tobias Leupold <tl@stonemx.de>
0007 // SPDX-FileCopyrightText: 2013 - 2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0008 //
0009 // SPDX-License-Identifier: GPL-2.0-or-later
0010 
0011 #ifndef DATEBAR_H
0012 #define DATEBAR_H
0013 #include "ViewHandler.h"
0014 
0015 #include <Utilities/FastDateTime.h>
0016 #include <QExplicitlySharedDataPointer>
0017 #include <QPixmap>
0018 #include <QWidget>
0019 
0020 class KActionCollection;
0021 class QMenu;
0022 class QKeyEvent;
0023 class QMouseEvent;
0024 class QFocusEvent;
0025 class QResizeEvent;
0026 class QPaintEvent;
0027 class QWheelEvent;
0028 class QContextMenuEvent;
0029 class QToolButton;
0030 class QFontMetrics;
0031 
0032 namespace DB
0033 {
0034 
0035 class ImageInfoList;
0036 class ImageDateCollection;
0037 class ImageDate;
0038 }
0039 
0040 namespace DateBar
0041 {
0042 class MouseHandler;
0043 class FocusItemDragHandler;
0044 class BarDragHandler;
0045 class SelectionHandler;
0046 
0047 /**
0048  * @brief The DateBarWidget class provides a histogram-like depiction of the image distribution over time.
0049  * If \ref includeFuzzyCounts() is \c true,
0050  * then both exact and fuzzy dates are taken into account and shown in different style (currently yellow and green).
0051  * If enough space is available, the number of images within each time period is printed inside each box.
0052  *
0053  * ## "unit" concept
0054  * A central concept in the widget design is that of a time \c unit.
0055  * Units are an integer offset into the number of available "boxes".
0056  * The number of units (or boxes) is calculated according to the available space (see \ref numberOfUnits()).
0057  * Each unit corresponds to a time period at the current resolution and offset.
0058  *
0059  * The time resulution is represented by the \c ViewHandler, and the offset is stored in \c m_currentDate.
0060  *
0061  * ## UI Description
0062  *
0063  * The area below the histogram bars can be used to select a date range using mouse click or drag.
0064  * Clicking outside the selected range clears the selection (as does pressing the "Clear date selection" button).
0065  *
0066  * Clicking within the histogram bar area changes the focus item. The focus item of the DateBar can be used by other
0067  * components (e.g. the ThumbnailViewer) to jump to an item at or close to the date unit represented by the focus item.
0068  *
0069  */
0070 class DateBarWidget : public QWidget
0071 {
0072     Q_OBJECT
0073 
0074 public:
0075     explicit DateBarWidget(QWidget *parent);
0076     enum ViewType { DecadeView,
0077                     YearView,
0078                     MonthView,
0079                     WeekView,
0080                     DayView,
0081                     HourView,
0082                     TenMinuteView,
0083                     MinuteView };
0084     /**
0085      * @brief includeFuzzyCounts
0086      * @return \c true if date ranges are shown, \c false otherwise.
0087      * @see setIncludeFuzzyCounts
0088      */
0089     bool includeFuzzyCounts() const;
0090     KActionCollection *actions();
0091 
0092     bool canZoomIn() const;
0093     bool canZoomOut() const;
0094 
0095 public Q_SLOTS:
0096     /**
0097      * @brief centerDateRange centers the view on the given range.
0098      * If the date range does not fit withing the current view range,
0099      * the view is instead anchored to the \c range.start() date.
0100      * @param range
0101      */
0102     void centerDateRange(const DB::ImageDate &range);
0103     /**
0104      * @brief centerDateRange centers the view on the given range.
0105      * If the date range does not fit withing the current view range,
0106      * the view is instead anchored to the \c min date.
0107      * @param min
0108      * @param max
0109      */
0110     void centerDateRange(const Utilities::FastDateTime &min, const Utilities::FastDateTime &max);
0111     void clearSelection();
0112     void setViewType(ViewType tp, bool redrawNow = true);
0113     void setDate(const Utilities::FastDateTime &date);
0114     /**
0115      * @brief setImageCollection sets the list of images that are counted for the histogram graph.
0116      * @param images
0117      */
0118     void setImageCollection(const DB::ImageInfoList &images);
0119     void scrollLeft();
0120     void scrollRight();
0121     void scroll(int units);
0122     void zoomIn();
0123     void zoomOut();
0124     void setHistogramBarSize(const QSize &size);
0125     void setIncludeFuzzyCounts(bool);
0126     /**
0127      * @brief setShowResolutionIndicator
0128      * If set to \c true, an indicator is shown to indicate the current ViewType.
0129      * The indicator indicates the size of one unit / histogram box alongside a text
0130      * indicating the respective temporal resolution (e.g. "10 minutes").
0131      */
0132     void setShowResolutionIndicator(bool);
0133     /**
0134      * @brief setAutomaticRangeAdjustment
0135      * If set to \c true, the ViewType and range is adjusted automatically to best
0136      * match the current set of images.
0137      */
0138     void setAutomaticRangeAdjustment(bool);
0139 
0140 Q_SIGNALS:
0141     void zoomInEnabled(bool);
0142     void zoomOutEnabled(bool);
0143     void dateSelected(const DB::ImageDate &, bool includeRanges);
0144     void toolTipInfo(const QString &);
0145     void dateRangeChange(const DB::ImageDate &);
0146     void dateRangeCleared();
0147     void dateRangeSelected(bool);
0148 
0149 public:
0150     // Overridden methods for internal purpose
0151     QSize sizeHint() const override;
0152     QSize minimumSizeHint() const override;
0153 
0154 protected:
0155     bool event(QEvent *event) override;
0156     void paintEvent(QPaintEvent *event) override;
0157     void resizeEvent(QResizeEvent *event) override;
0158     void mousePressEvent(QMouseEvent *event) override;
0159     void mouseMoveEvent(QMouseEvent *event) override;
0160     void mouseReleaseEvent(QMouseEvent *event) override;
0161     void contextMenuEvent(QContextMenuEvent *) override;
0162     void keyPressEvent(QKeyEvent *event) override;
0163     void focusInEvent(QFocusEvent *) override;
0164     void focusOutEvent(QFocusEvent *) override;
0165     void wheelEvent(QWheelEvent *e) override;
0166 
0167     /**
0168      * @brief redraw the widget
0169      * This method creates a QPainter and then uses the draw* methods to draw the different parts of the widget.
0170      * \see drawTickMarks
0171      * \see drawHistograms
0172      * \see drawFocusRectangle
0173      * \see drawResolutionIndicator
0174      */
0175     void redraw();
0176     void drawTickMarks(QPainter &p, const QRect &textRect);
0177     void drawHistograms(QPainter &p);
0178     void drawFocusRectangle(QPainter &p);
0179     void drawResolutionIndicator(QPainter &p, int *leftEdge);
0180     /**
0181      * @brief zoom in or out by a number of steps.
0182      * One steps corresponds to one step in the ViewType.
0183      * @param steps positive steps to increase temporal resolution, negative to decrease.
0184      */
0185     void zoom(int steps);
0186     QRect barAreaGeometry() const;
0187     QRect tickMarkGeometry() const;
0188     QRect dateAreaGeometry() const;
0189     int numberOfUnits() const;
0190     void drawArrow(QPainter &, const QPoint &start, const QPoint &end);
0191     void updateArrowState();
0192     DB::ImageDate currentDateRange() const;
0193     void showStatusBarTip(const QPoint &pos);
0194     DB::ImageDate rangeAt(const QPoint &);
0195     DB::ImageDate rangeForUnit(int unit);
0196     void placeAndSizeButtons();
0197     /**
0198      * @brief unitAtPos maps horizontal screen coordinates to units.
0199      * @param x a valid pixel offset in the histogram area
0200      * @return a unit index between 0 and numberOfUnits, or -1 if the pixel offset is not valid
0201      */
0202     int unitAtPos(int x) const;
0203     Utilities::FastDateTime dateForUnit(int unit, const Utilities::FastDateTime &offset = Utilities::FastDateTime()) const;
0204     /**
0205      * @brief unitForDate return the unit index corresponding to the date/time.
0206      * @param date a valid Utilities::FastDateTime.
0207      * @return An integer greater or equal to 0 if \p date is in view, -1 otherwise.
0208      */
0209     int unitForDate(const Utilities::FastDateTime &date) const;
0210     bool isUnitSelected(int unit) const;
0211     bool hasSelection() const;
0212     DB::ImageDate currentSelection() const;
0213     void emitDateSelected();
0214     void emitRangeSelection(const DB::ImageDate &);
0215     void setImageDateCollection(const QExplicitlySharedDataPointer<DB::ImageDateCollection> &);
0216 
0217 private:
0218     void setViewHandlerForType(ViewType tp);
0219     int stringWidth(const QFontMetrics &fontMetrics, const QString &text) const;
0220     QPixmap m_buffer;
0221     friend class DateBarTip;
0222 
0223     QExplicitlySharedDataPointer<DB::ImageDateCollection> m_dates;
0224     DecadeViewHandler m_decadeViewHandler;
0225     YearViewHandler m_yearViewHandler;
0226     MonthViewHandler m_monthViewHandler;
0227     WeekViewHandler m_weekViewHandler;
0228     DayViewHandler m_dayViewHandler;
0229     HourViewHandler m_hourViewHandler;
0230     TenMinuteViewHandler m_tenMinuteViewHandler;
0231     MinuteViewHandler m_minuteViewHandler;
0232     ViewHandler *m_currentHandler;
0233     ViewType m_tp;
0234 
0235     MouseHandler *m_currentMouseHandler;
0236     FocusItemDragHandler *m_focusItemDragHandler;
0237     BarDragHandler *m_barDragHandler;
0238     SelectionHandler *m_selectionHandler;
0239     friend class Handler;
0240     friend class FocusItemDragHandler;
0241     friend class BarDragHandler;
0242     friend class SelectionHandler;
0243 
0244     QToolButton *m_rightArrow;
0245     QToolButton *m_leftArrow;
0246     QToolButton *m_zoomIn;
0247     QToolButton *m_zoomOut;
0248     QToolButton *m_cancelSelection;
0249 
0250     int m_currentUnit; ///< focus unit; also offset for drawing.
0251     Utilities::FastDateTime m_currentDate; ///< reference frame for date bar. Equals unit 0.
0252     int m_barWidth; ///< width of a single unit in pixel
0253     int m_barHeight;
0254     bool m_includeFuzzyCounts;
0255     QMenu *m_contextMenu;
0256     bool m_showResolutionIndicator;
0257     bool m_doAutomaticRangeAdjustment;
0258     KActionCollection *m_actionCollection;
0259 };
0260 }
0261 
0262 #endif /* DATEBAR_H */
0263 
0264 // vi:expandtab:tabstop=4 shiftwidth=4: