File indexing completed on 2024-04-28 16:13:35

0001 /*
0002  * This file is part of the KDE project
0003  *
0004  * Copyright (C) 2013 Arjen Hiemstra <ahiemstra@heimr.nl>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Library General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2 of the License, or (at your option) any later version.
0010  *
0011  * This library 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 GNU
0014  * Library General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Library General Public License
0017  * along with this library; see the file COPYING.LIB.  If not, write to
0018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020  *
0021  */
0022 
0023 #ifndef CALLIGRA_COMPONENTS_VIEWCONTROLLER_H
0024 #define CALLIGRA_COMPONENTS_VIEWCONTROLLER_H
0025 
0026 #include <QQuickItem>
0027 
0028 namespace Calligra {
0029 namespace Components {
0030 
0031 class View;
0032 
0033 /**
0034  * \brief Provides an object to control the document transformation within a View.
0035  *
0036  * Due to API restrictions it is not easily possible to inherit Flickable's behaviour
0037  * in custom QtQuick items. This object works around that by providing an item that
0038  * can be put inside a Flickable and will scroll a View object based on the Flickable's
0039  * scrolling.
0040  *
0041  * In addition, this object controls the zoom level of a view. It can clamps zoom to a
0042  * minimum and maximum value and can optionally use an image during zoom operations to
0043  * accelerate the zoom operation, since zooming an actual document can be an expensive
0044  * operation.
0045  *
0046  * \note This object will control its own width and height as well as the contentWidth
0047  * and contentHeight of #flickable. While it is possible to put this item outside of a
0048  * flickable this is not recommended.
0049  */
0050 
0051 class ViewController : public QQuickItem
0052 {
0053     Q_OBJECT
0054     /**
0055      * \property view
0056      * \brief The view to control.
0057      *
0058      * \default null
0059      * \get view() const
0060      * \set setView()
0061      * \notify viewChanged()
0062      */
0063     Q_PROPERTY(Calligra::Components::View* view READ view WRITE setView NOTIFY viewChanged)
0064     /**
0065      * \property flickable
0066      * \brief The flickable that is used to control scrolling.
0067      *
0068      * \default null
0069      * \get flickable() const
0070      * \set setFlickable()
0071      * \notify flickableChanged()
0072      */
0073     Q_PROPERTY(QQuickItem* flickable READ flickable WRITE setFlickable NOTIFY flickableChanged)
0074     /**
0075      * \property minimumZoom
0076      * \brief The minimum zoom level.
0077      *
0078      * \default 0.5
0079      * \get minimumZoom() const
0080      * \set setMinimumZoom()
0081      * \notify minimumZoomChanged()
0082      */
0083     Q_PROPERTY(float minimumZoom READ minimumZoom WRITE setMinimumZoom NOTIFY minimumZoomChanged)
0084     /**
0085      * \property minimumZoomFitsWidth
0086      * \brief Should the ViewController determine minimum zoom level automatically?
0087      *
0088      * When true, the minimum zoom level will be determined automatically  based on the width of
0089      * the item assigned to this controller's #flickable property.
0090      *
0091      * \default false
0092      * \get minimumZoomFitsWidth() const
0093      * \set setMinimumZoomFitsWidth()
0094      * \notify minimumZoomFitsWidthChanged()
0095      */
0096     Q_PROPERTY(bool minimumZoomFitsWidth READ minimumZoomFitsWidth WRITE setMinimumZoomFitsWidth NOTIFY minimumZoomFitsWidthChanged)
0097     /**
0098      * \property zoom
0099      * \brief The zoom amount of the view.
0100      *
0101      * \default 1.0
0102      * \get zoom() const
0103      * \set setZoom()
0104      * \notify zoomChanged()
0105      */
0106     Q_PROPERTY(float zoom READ zoom WRITE setZoom NOTIFY zoomChanged)
0107     /**
0108      * \property maximumZoom
0109      * \brief The maximum zoom amount.
0110      *
0111      * \default 2.0
0112      * \get maximumZoom() const
0113      * \set setMaximumZoom()
0114      * \notify maximumZoomChanged()
0115      */
0116     Q_PROPERTY(float maximumZoom READ maximumZoom WRITE setMaximumZoom NOTIFY maximumZoomChanged)
0117     /**
0118      * \property useZoomProxy
0119      * \brief Should the ViewController use a proxy image when zooming?
0120      *
0121      * When true, during zooming, apply the zoom to a proxy image that is scaled and shown for a
0122      * short duration before applying it to the view. This makes continuous zooming operations
0123      * far smoother.
0124      *
0125      * \default true
0126      * \get useZoomProxy() const
0127      * \set setUseZoomProxy()
0128      * \notify useZoomProxyChanged()
0129      */
0130     Q_PROPERTY(bool useZoomProxy READ useZoomProxy WRITE setUseZoomProxy NOTIFY useZoomProxyChanged)
0131 
0132 public:
0133     /**
0134      * Constructor.
0135      *
0136      * \param parent The parent item.
0137      */
0138     explicit ViewController(QQuickItem* parent = 0);
0139     /**
0140      * Destructor.
0141      */
0142     ~ViewController() override;
0143 
0144     /**
0145      * Getter for property #view
0146      */
0147     View* view() const;
0148     /**
0149      * Setter for property #view
0150      */
0151     void setView(View* newView);
0152     /**
0153      * Getter for property #flickable
0154      */
0155     QQuickItem* flickable() const;
0156     /**
0157      * Setter for property #flickable
0158      */
0159     void setFlickable(QQuickItem* item);
0160     /**
0161      * Getter for property #minimumZoom
0162      */
0163     float minimumZoom() const;
0164     /**
0165      * Setter for property #minimumZoom
0166      */
0167     void setMinimumZoom(float newValue);
0168     /**
0169      * Getter for property #minimumZoomFitsWidth
0170      */
0171     bool minimumZoomFitsWidth() const;
0172     /**
0173      * Setter for property #minimumZoomFitsWidth
0174      */
0175     void setMinimumZoomFitsWidth(bool newValue);
0176     /**
0177      * Getter for property #zoom
0178      */
0179     float zoom() const;
0180     /**
0181      * Setter for property #zoom
0182      */
0183     void setZoom(float newZoom);
0184     /**
0185      * Getter for property #maximumZoom
0186      */
0187     float maximumZoom() const;
0188     /**
0189      * Setter for property #maximumZoom
0190      */
0191     void setMaximumZoom(float newValue);
0192     /**
0193      * Getter for property #useZoomProxy
0194      */
0195     bool useZoomProxy() const;
0196     /**
0197      * Setter for property #useZoomProxy
0198      */
0199     void setUseZoomProxy(bool proxy);
0200 
0201     /**
0202      * Reimlemented from superclass
0203      */
0204     bool event(QEvent* event) override;
0205 public Q_SLOTS:
0206     /**
0207      * \brief Zoom by a specific amount around a centre point.
0208      *
0209      * \note The centre point should be relative to this item. The easiest way
0210      * to achieve this in QML is to use the following:
0211      *
0212      * \code
0213      * var newCenter = mapToItem(controller, center.x, center.y);
0214      * controller.zoomAroundPoint(amount, newCenter.x, newCenter.y);
0215      * \endcode
0216      *
0217      * \param amount The amount to zoom by, relative to the current zoom level.
0218      * \param x The horizontal coordinate of the centre point.
0219      * \param y The vertical coordinate of the centre point.
0220      */
0221     void zoomAroundPoint(float amount, float x, float y);
0222     /**
0223      * \brief Zoom the item such that it will fit a certain width.
0224      *
0225      * This will zoom the view to make sure that the document fits the specified
0226      * width, as long as the resulting zoom level is not less than #minimumZoom or
0227      * more than #maximumZoom.
0228      *
0229      * \param width The width to fit to.
0230      */
0231     void zoomToFitWidth(float width);
0232 
0233 Q_SIGNALS:
0234     /**
0235      * Notify signal for property #view.
0236      */
0237     void viewChanged();
0238     /**
0239      * Notify signal for property #flickable.
0240      */
0241     void flickableChanged();
0242     /**
0243      * Notify signal for property #minimumZoom.
0244      */
0245     void minimumZoomChanged();
0246     /**
0247      * Notify signal for property #minimumZoomFitsWidth.
0248      */
0249     void minimumZoomFitsWidthChanged();
0250     /**
0251      * Notify signal for property #zoom.
0252      */
0253     void zoomChanged();
0254     /**
0255      * Notify signal for property #maximumZoom.
0256      */
0257     void maximumZoomChanged();
0258     /**
0259      * Notify signal for property #useZoomProxy.
0260      */
0261     void useZoomProxyChanged();
0262 
0263 protected:
0264     QSGNode* updatePaintNode(QSGNode* node, QQuickItem::UpdatePaintNodeData* ) override;
0265 
0266 private Q_SLOTS:
0267     void documentChanged();
0268     void contentPositionChanged();
0269     void documentSizeChanged();
0270     void documentStatusChanged();
0271     void documentOffsetChanged(const QPoint& offset);
0272     void zoomTimeout();
0273     void flickableWidthChanged();
0274 
0275 private:
0276     class Private;
0277     Private* const d;
0278 };
0279 
0280 } // Namespace Components
0281 } // Namepsace Calligra
0282 
0283 #endif // CALLIGRA_COMPONENTS_VIEWCONTROLLER_H