File indexing completed on 2024-05-12 04:20:40

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KGantt library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef KGANTTDATETIMEGRID_H
0010 #define KGANTTDATETIMEGRID_H
0011 
0012 #include "kganttabstractgrid.h"
0013 
0014 #include <QDateTime>
0015 #include <QSet>
0016 #include <QPair>
0017 
0018 namespace KGantt {
0019 
0020     class DateTimeScaleFormatter;
0021     class DateTimeTimeLine;
0022 
0023 
0024     /*!\class KGantt::DateTimeGrid
0025      * \ingroup KGantt
0026      *
0027      * This implementation of AbstractGrid works with QDateTime
0028      * and shows days and week numbers in the header
0029      */
0030     class KGANTT_EXPORT DateTimeGrid : public AbstractGrid
0031     {
0032         Q_OBJECT
0033         KGANTT_DECLARE_PRIVATE_DERIVED( DateTimeGrid )
0034     public:
0035         enum Scale {
0036             ScaleAuto, 
0037             ScaleHour,
0038             ScaleDay,
0039             ScaleWeek,
0040             ScaleMonth,
0041             ScaleUserDefined
0042         };
0043         enum HeaderType {
0044             NoHeader,
0045             UpperHeader,
0046             LowerHeader
0047         };
0048 
0049         DateTimeGrid();
0050         ~DateTimeGrid() override;
0051 
0052         /*! \returns The QDateTime used as start date for the grid.
0053          *
0054          * The default is three days before the current date.
0055          */
0056         QDateTime startDateTime() const;
0057 
0058         /*! \param dt The start date of the grid. It is used as the beginning of the
0059          * horizontal scrollbar in the view.
0060          *
0061          * Emits gridChanged() after the start date has changed.
0062          */
0063         void setStartDateTime( const QDateTime& dt );
0064 
0065         /*! \returns The width in pixels for each day in the grid.
0066          *
0067          * The default is 100 pixels.
0068          */
0069         qreal dayWidth() const;
0070 
0071         /*! \param w The width in pixels for each day in the grid.
0072          *
0073          * The signal gridChanged() is emitted after the day width is changed.
0074          */
0075         void setDayWidth( qreal );
0076 
0077         /*! Maps a given point in time \a dt to an X value in the scene.
0078          */
0079         qreal mapFromDateTime( const QDateTime& dt) const;
0080 
0081         /*! Maps a given X value \a x in scene coordinates to a point in time.
0082          */
0083         QDateTime mapToDateTime( qreal x ) const;
0084 
0085         /*! \param ws The start day of the week.
0086          *
0087          * A solid line is drawn on the grid to mark the beginning of a new week.
0088          * Emits gridChanged() after the start day has changed.
0089          */
0090         void setWeekStart( Qt::DayOfWeek );
0091 
0092         /*! \returns The start day of the week */
0093         Qt::DayOfWeek weekStart() const;
0094 
0095         /*! \param fd A set of days to mark as free in the grid.
0096          *
0097          * Free days are filled with the alternate base brush of the
0098          * palette used by the view.
0099          * The signal gridChanged() is emitted after the free days are changed.
0100          */
0101         void setFreeDays( const QSet<Qt::DayOfWeek>& fd );
0102 
0103         /*! \returns The days marked as free in the grid. */
0104         QSet<Qt::DayOfWeek> freeDays() const;
0105 
0106         /*! Sets the brush to use to paint free days.
0107         */
0108         void setFreeDaysBrush(const QBrush brush);
0109 
0110         /*!
0111           \returns The brush used to paint free days.
0112         */
0113         QBrush freeDaysBrush() const;
0114 
0115         /*! \param s The scale to be used to paint the grid.
0116          *
0117          * The signal gridChanged() is emitted after the scale has changed.
0118          * \sa Scale
0119          *
0120          * Following example demonstrates how to change the format of the header to use
0121          * a date-scaling with the header-label displayed with the ISO date-notation.
0122          * \code
0123          * DateTimeScaleFormatter* formatter = new DateTimeScaleFormatter(DateTimeScaleFormatter::Day, QString::fromLatin1("yyyy-MMMM-dddd"));
0124          * grid->setUserDefinedUpperScale( formatter );
0125          * grid->setUserDefinedLowerScale( formatter );
0126          * grid->setScale( DateTimeGrid::ScaleUserDefined );
0127          * \endcode
0128          */
0129         void setScale( Scale s );
0130 
0131         /*! \returns The scale used to paint the grid.
0132          *
0133          * The default is ScaleAuto, which means the day scale will be used
0134          * as long as the day width is less or equal to 500.
0135          * \sa Scale
0136          */
0137         Scale scale() const;
0138 
0139         /*! Sets the scale formatter for the lower part of the header to the
0140          *  user defined formatter to \a lower. The DateTimeGrid object takes
0141          *  ownership of the formatter, which has to be allocated with new.
0142          *
0143          * You have to set the scale to ScaleUserDefined for this setting to take effect.
0144          * \sa DateTimeScaleFormatter
0145          */
0146         void setUserDefinedLowerScale( DateTimeScaleFormatter* lower );
0147 
0148         /*! Sets the scale formatter for the upper part of the header to the
0149          *  user defined formatter to \a upper. The DateTimeGrid object takes
0150          *  ownership of the formatter, which has to be allocated with new.
0151          *
0152          * You have to set the scale to ScaleUserDefined for this setting to take effect.
0153          * \sa DateTimeScaleFormatter
0154          */
0155         void setUserDefinedUpperScale( DateTimeScaleFormatter* upper );
0156 
0157         /*! \return The DateTimeScaleFormatter being used to render the lower scale.
0158          */
0159         DateTimeScaleFormatter* userDefinedLowerScale() const;
0160 
0161 
0162         /*! \return The DateTimeScaleFormatter being used to render the upper scale.
0163          */
0164         DateTimeScaleFormatter* userDefinedUpperScale() const;
0165 
0166         /*! \returns true if row separators are used. */
0167         bool rowSeparators() const;
0168 
0169         /*! \param enable Whether to use row separators or not. */
0170         void setRowSeparators( bool enable );
0171 
0172         /*! Sets the brush used to display rows where no data is found.
0173          * Default is a red pattern. If set to QBrush() rows with no
0174          * information will not be marked.
0175          */
0176         void setNoInformationBrush( const QBrush& brush );
0177 
0178         /*! \returns the brush used to mark rows with no information.
0179          */
0180         QBrush noInformationBrush() const;
0181 
0182         /*! \param idx The index to get the Span for.
0183          * \returns The start and end pixels, in a Span, of the specified index.
0184          */
0185         /*reimp*/ Span mapToChart( const QModelIndex& idx ) const override;
0186 
0187         /*! Maps the supplied Span to QDateTimes, and puts them as start time and
0188          * end time for the supplied index.
0189          *
0190          * \param span The span used to map from.
0191          * \param idx The index used for setting the start time and end time in the model.
0192          * \param constraints A list of hard constraints to match against the start time and
0193          * end time mapped from the span.
0194          *
0195          * \returns true if the start time and time was successfully added to the model, or false
0196          * if unsuccessful.
0197          * Also returns false if any of the constraints isn't satisfied. That is, if the start time of
0198          * the constrained index is before the end time of the dependency index, or the end time of the
0199          * constrained index is before the start time of the dependency index.
0200          */
0201         /*reimp*/ bool mapFromChart( const Span& span, const QModelIndex& idx,
0202                                      const QList<Constraint>& constraints=QList<Constraint>() ) const override;
0203 
0204         /*!
0205         * \param value The datetime to get the x value for.
0206         * \returns The x value corresponding to \a value or -1.0 if \a value is not a datetime variant.
0207         */
0208         /*reimp*/ qreal mapToChart( const QVariant& value ) const override;
0209 
0210         /*!
0211          * \param x The x value to get the datetime for.
0212          * \returns The datetime corresponding to \a x or an invalid datetime if x cannot be mapped.
0213          */
0214         /*reimp*/ QVariant mapFromChart( qreal x ) const override;
0215         /*reimp*/ void paintGrid( QPainter* painter, 
0216                                   const QRectF& sceneRect, const QRectF& exposedRect,
0217                                   AbstractRowController* rowController = nullptr,
0218                                   QWidget* widget = nullptr ) override;
0219         /*reimp*/ void paintHeader( QPainter* painter, 
0220                                     const QRectF& headerRect, const QRectF& exposedRect,
0221                                     qreal offset, QWidget* widget = nullptr ) override;
0222 
0223         /**
0224          * @return the timeline control object
0225          */
0226         DateTimeTimeLine *timeLine() const;
0227 
0228         HeaderType sectionHandleAtPos(int x, int y, const QRect &headerRect) const;
0229 
0230     protected:
0231         /*! Paints the hour scale header.
0232          * \sa paintHeader()
0233          */
0234         virtual void paintHourScaleHeader( QPainter* painter, 
0235                            const QRectF& headerRect, const QRectF& exposedRect,
0236                            qreal offset, QWidget* widget = nullptr );
0237 
0238         /*! Paints the day scale header.
0239          * \sa paintHeader()
0240          */
0241         virtual void paintDayScaleHeader( QPainter* painter, 
0242                           const QRectF& headerRect, const QRectF& exposedRect,
0243                           qreal offset, QWidget* widget = nullptr );
0244 
0245         /*! Paints the week scale header.
0246          * \sa paintHeader()
0247          */
0248         virtual void paintWeekScaleHeader( QPainter* painter,
0249                                            const QRectF& headerRect, const QRectF& exposedRect,
0250                                            qreal offset, QWidget* widget = nullptr );
0251 
0252         /*! Paints the week scale header.
0253          * \sa paintHeader()
0254          */
0255         virtual void paintMonthScaleHeader( QPainter* painter,
0256                                             const QRectF& headerRect, const QRectF& exposedRect,
0257                                             qreal offset, QWidget* widget = nullptr );
0258 
0259         virtual void paintUserDefinedHeader( QPainter* painter, 
0260                                      const QRectF& headerRect, const QRectF& exposedRect, 
0261                                      qreal offset, const DateTimeScaleFormatter* formatter, 
0262                                      QWidget* widget = nullptr );
0263 
0264 
0265         /*! Draw the background for a day.
0266         */
0267         virtual void drawDayBackground(QPainter* painter, const QRectF& rect, const QDate& date);
0268 
0269         /*! Draw the foreground for a day.
0270         */
0271         virtual void drawDayForeground(QPainter* painter, const QRectF& rect, const QDate& date);
0272 
0273         /** Return the rectangle that represents the date-range.
0274         */
0275         QRectF computeRect(const QDateTime& from, const QDateTime& to, const QRectF& rect) const;
0276 
0277 
0278         /** Return a date-range represented by the rectangle.
0279         */
0280         QPair<QDateTime, QDateTime> dateTimeRange(const QRectF& rect) const;
0281 
0282         /* reimp */ void drawBackground(QPainter* paint, const QRectF& rect) override;
0283         /* reimp */ void drawForeground(QPainter* paint, const QRectF& rect) override;
0284     };
0285 
0286     /*!\class KGantt::DateTimeScaleFormatter
0287      * \ingroup KGantt
0288      *
0289      * This class formats dates and times used in DateTimeGrid follawing a given format.
0290      *
0291      * The format follows the format of QDateTime::toString(), with one addition:
0292      * "w" is replaced with the week number of the date as number without a leading zero (1-53)
0293      * "ww" is replaced with the week number of the date as number with a leading zero (01-53)
0294      *
0295      * For example:
0296      *
0297      * \code
0298      *  // formatter to print the complete date over the current week
0299      *  // This leads to the first day of the week being printed
0300      *  DateTimeScaleFormatter formatter = DateTimeScaleFormatter( DateTimeScaleFormatter::Week, "yyyy-MM-dd" );
0301      * \endcode
0302      *
0303      * Optionally, you can set an user defined text alignment flag. The default value is Qt::AlignCenter.
0304      * \sa DateTimeScaleFormatter::DateTimeScaleFormatter
0305      *
0306      * This class even controls the range of the grid sections.
0307      * \sa KGanttDateTimeScaleFormatter::Range
0308      */
0309     class KGANTT_EXPORT DateTimeScaleFormatter
0310     {
0311         KGANTT_DECLARE_PRIVATE_BASE_POLYMORPHIC( DateTimeScaleFormatter )
0312     public:
0313         enum Range {
0314             Second,
0315             Minute,
0316             Hour,
0317             Day,
0318             Week,
0319             Month,
0320             Year
0321         };
0322 
0323         /*! Creates a DateTimeScaleFormatter using \a range and \a format.
0324          *  The text on the header is aligned following \a alignment.
0325          */
0326         DateTimeScaleFormatter( Range range, const QString& formatString,
0327                                 Qt::Alignment alignment = Qt::AlignCenter );
0328         DateTimeScaleFormatter( Range range, const QString& formatString,
0329                                 const QString& templ, Qt::Alignment alignment = Qt::AlignCenter );
0330 
0331         /*! \returns The format being used for formatting dates and times.
0332          */
0333         DateTimeScaleFormatter( const DateTimeScaleFormatter& other );
0334         virtual ~DateTimeScaleFormatter();
0335 
0336         DateTimeScaleFormatter& operator=( const DateTimeScaleFormatter& other );
0337 
0338         /*! \returns The format string
0339          */
0340         QString format() const;
0341 
0342         /*! \returns The range of each item on a DateTimeGrid header.
0343          * \sa DateTimeScaleFormatter::Range */
0344         Range range() const;
0345         Qt::Alignment alignment() const;
0346 
0347         /*! \returns the QDateTime being the begin of the range after the one containing \a datetime
0348          *  \sa currentRangeBegin
0349          */
0350         virtual QDateTime nextRangeBegin( const QDateTime& datetime ) const;
0351 
0352         /*! \returns the QDateTime being the begin of the range containing \a datetime
0353          *  \sa nextRangeBegin
0354          */
0355         virtual QDateTime currentRangeBegin( const QDateTime& datetime ) const;
0356 
0357         /*! \returns The \a datetime as string respecting the format.
0358          */
0359         QString format( const QDateTime& datetime ) const;
0360         virtual QString text( const QDateTime& datetime ) const;
0361     };
0362 }
0363 
0364 
0365 
0366 #ifndef QT_NO_DEBUG_STREAM
0367 QDebug KGANTT_EXPORT operator<<( QDebug dbg, KGantt::DateTimeScaleFormatter::Range );
0368 #endif
0369 
0370 #endif /* KGANTTDATETIMEGRID_H */
0371