File indexing completed on 2024-05-12 15:54:24

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