1 /*
2     KmPlot - a math. function plotter for the KDE-Desktop
3 
4     SPDX-FileCopyrightText: 1998, 1999, 2000, 2002 Klaus-Dieter Möller <kd.moeller@t-online.de>
5     SPDX-FileCopyrightText: 2006 David Saxton <david@bluehaze.org>
6 
7     This file is part of the KDE Project.
8     KmPlot is part of the KDE-EDU Project.
9 
10     SPDX-License-Identifier: GPL-2.0-or-later
11 
12 */
13 
14 #ifndef View_included
15 #define View_included
16 
17 #include "function.h"
18 
19 // Qt includes
20 #include <QDebug>
21 #include <QEasingCurve>
22 #include <QEvent>
23 #include <QKeyEvent>
24 #include <QMouseEvent>
25 #include <QPixmap>
26 #include <QPointer>
27 #include <QPropertyAnimation>
28 #include <QResizeEvent>
29 
30 // KDE includes
31 #include <KToggleAction>
32 #include <KTextEdit>
33 
34 class KSliderWindow;
35 class MainDlg;
36 class QPaintEvent;
37 class QTextDocument;
38 class QMenu;
39 class QElapsedTimer;
40 
41 //@{
42 /// Some abbreviations for horizontal and vertical lines.
43 #define Line drawLine
44 #define Lineh(x1, y, x2) drawLine( QPointF(x1, y), QPointF(x2, y) )
45 #define Linev(x, y1, y2) drawLine( QPointF(x, y1), QPointF(x, y2) )
46 //@}
47 
48 
49 /**
50  * For drawing the area of a (Cartesian) plot.
51  */
52  class IntegralDrawSettings
53 {
54 	public:
55 		IntegralDrawSettings();
56 
57 		Plot plot;
58 		double dmin, dmax;
59 		/// Set to true when calculating the area under the graph
60 		bool draw;
61 };
62 
63 
64 /**
65  * @short This class contains the plots.
66  *
67  * It is the central widget of MainDlg.
68  * @see MainDlg, MainDlg::view
69  */
70 class View : public QWidget
71 {
72 	Q_OBJECT
73 	Q_PROPERTY( QRectF viewport READ getViewport WRITE setViewport )
74 	public:
75 		/// Constructor
76 		View( bool readOnly, QMenu * functionPopup, QWidget* parent );
77 		virtual ~View();
78 
79 		/// There is only one view.
self()80 		static View * self() { return m_self; }
81 
82 		enum PlotMedium
83 		{
84 			Screen,
85 			Printer,
86 			SVG,
87 			Pixmap
88 		};
89 		/**
90 		 * Draw the plot to \p dev, which is of the given \p medium.
91 		 */
92 		void draw( QPaintDevice * dev, PlotMedium medium );
93 
94 		enum ExtremaType { Minimum, Maximum };
95 		/**
96 		* Finding the minimum or maximum value.
97 		* \return The (x,y) coordinates of the extrema point.
98 		*/
99 		QPointF findMinMaxValue( const Plot & plot, ExtremaType type, double dmin, double dmax );
100 		/**
101 		* Calculates the area between the given plot and the x-axis
102 		* (from x = \p dmin to x = \p dmax). The area will also be colored in.
103 		* \return the area.
104 		*/
105 		double areaUnderGraph( IntegralDrawSettings settings );
106 		/**
107 		 * \return if the calculation was cancelled by the user.
108 		 */
109 		bool isCalculationStopped();
110 		/**
111 		 * Used in posToString for requesting how the position string is to be
112 		 * created.
113 		 */
114 		enum PositionFormatting
115 		{
116 			DecimalFormat,		///< Plain text, using no scientific notation; just decimal expansion.
117 			ScientificFormat	///< Rich text possibly using scientific notation (mult x 10 ^ exp).
118 		};
119 		/**
120 		 * @return a string for displaying the x or y coordinate in the statusbar.
121 		 * \param x The number to convert to a string.
122 		 * \param delta is the amount by which the value varies over one pixel in
123 		 * the view. This is for choosing an appropriate number of decimals so that
124 		 * moving the cursor shows a nice change in the string.
125 		 * \param format How the number should be represented as a string.
126 		 * \param color If using scientific mode, the color to format the text.
127 		 */
128 		QString posToString( double x, double delta, PositionFormatting format, const QColor &color = Qt::black ) const;
129 
130 		/// Slider controlling parameter values
131 		QPointer<KSliderWindow> m_sliderWindow;
132 		/// Menu actions for the sliders
133 		KToggleAction * m_menuSliderAction;
134 		void updateSliders(); /// show only needed sliders
135 
136 		/**
137 		 * Convert \p width_mm (millimeters) to the equivalent length when
138 		 * drawing using \p painter.
139 		 */
140 		double millimetersToPixels( double width_mm, QPaintDevice * device ) const;
141 		/**
142 		 * The inverse of millimetersToPixels().
143 		 */
144 		double pixelsToMillimeters( double width_pixels, QPaintDevice * device ) const;
145 
146 		/** Current plot x-range. */
147 		double m_xmin;
148 		double m_xmax;
149 		/** Current plot y-range. */
150 		double m_ymin;
151 		double m_ymax;
152 
153 		/// trace mode stuff, must be accessible in FunctionTools
154 		Plot m_currentPlot;
155 		/**
156 		 * Convenience function for calculating the value of \p eq using the
157 		 * given \p mode
158 		 */
159 		double value( const Plot & plot, int eq, double x, bool updateFunction );
160 		/**
161 		 * \return the real position of the function (similar to calling
162 		 * value(), but returns both coordinates).
163 		 */
164 		QPointF realValue( const Plot & plot, double x, bool updateFunction );
165 		/**
166 		 * \return the (signed) curvature (in screen coordinates) of the plot
167 		 * at \p x (and \p y for implicit functions).
168 		 */
169 		double pixelCurvature( const Plot & plot, double x, double y = 0 );
170 		/**
171 		 * \return the angle of the normal (in radians) of the plot when viewed
172 		 * on the screen.
173 		 */
174 		double pixelNormal( const Plot & plot, double x, double y = 0 );
175 		/**
176 		 * Animates zooming from the current zoom rect to the one given (in real
177 		 * coordinates)
178 		 */
179 		void animateZoom( const QRectF & newCoords );
180 
181 		///Methods for the Print Dialog to set options for drawing
182 		void setPrintHeaderTable( bool status );
183 		void setPrintBackground( bool status );
184 		void setPrintWidth( double width );
185 		void setPrintHeight( double height );
186 
187 		/**
188 		 * Which part of the status bar.
189 		 */
190 		enum StatusBarSection
191 		{
192 			XSection		= 0,
193 			YSection		= 1,
194 			RootSection		= 2,
195 			FunctionSection		= 3,
196 			SectionCount		= 4
197 		};
198 
199 		/**
200 		 * Crosshair position in real coordinates
201 		 */
202 		QPointF getCrosshairPosition() const;
203 
204 	public slots:
205 		/// Called when the user want to cancel the drawing
206 		void stopDrawing();
207 
208 		/// Called when the graph should be updated
209 		void drawPlot();
210 		/// Called when a function is deleted
211 		void functionRemoved( int id );
212 		///Slots for the three first items in popup menu
213 		void hideCurrentFunction();
214 		void removeCurrentPlot();
215 		void editCurrentPlot();
216 		void animateFunction();
217 		///Slots for the zoom menu
218 		void zoomIn();
219 		void zoomOut();
220 		void zoomToTrigonometric();
221 
222 	protected slots:
223 		/// Unchecks menu item when the slider window is closed
224 		void sliderWindowClosed();
225 		/// Restore the mouse cursor when a drawing is finished
226 		void updateCursor();
227 
228 	signals:
229 		void setStatusBarText(const QString &);
230 		void updateRootValue(bool haveRoot, double rootValue);
231 
232 	protected:
233 		/// called when focus is lost
234 		void focusOutEvent( QFocusEvent * ) Q_DECL_OVERRIDE;
235 		/// called when focus is gained
236 		void focusInEvent( QFocusEvent * ) Q_DECL_OVERRIDE;
237 		void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
238 		void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE;
239 		/// Updating the cross hair.
240 		void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE;
241 		/// Clearing the cross hair.
242 		void leaveEvent(QEvent *) Q_DECL_OVERRIDE;
243 		/// Toggles the trace mode if the cursor is near to a plot.
244 		void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
245 		/// when a key is pressed and the graph widget has focus
246 		void keyPressEvent(QKeyEvent * ) Q_DECL_OVERRIDE;
247 		/// called when a mouse key is released
248 		void mouseReleaseEvent ( QMouseEvent * e ) Q_DECL_OVERRIDE;
249 		/// called for zooming with Ctrl+mouse wheel
250 		void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
251 		/// Is needed to be reimplement so that the user can stop a preview-drawing
252 		bool event( QEvent * e ) Q_DECL_OVERRIDE;
253 		/**
254 		 * Updates csxpos and csypos from the current mouse position.
255 		 * @return whether the crosshair is within the bounds of the diagram.
256 		 */
257 		bool updateCrosshairPosition();
258 
259 	private:
260 		/**
261 		 * Fills the popup menu according to the currently selected plot.
262 		 */
263 		void fillPopupMenu();
264 		/**
265 		 * For using in automatic tic spacing. Given \p range (e.g. x_max-x_min)
266 		 * and the \p length_mm (in millimeters), it aims to find a "nice"
267 		 * spacing distance that is visually pleasing and also fits the base 10
268 		 * number system in use (i.e. is a decimal multiple of 1, 2 or 5).
269 		 */
270 		double niceTicSpacing( double length_mm, double range );
271 		/**
272 		 * For using in manual tic spacing. Given a size in screen \p pixels for
273 		 * the given \p range (e.g. x_max-x_min), make sure the \p spacing distance
274 		 * is at least \p minPixels large. If zooming out too far, the spacing is
275 		 * doubled until this conditions is met, effectively omitting tics. If zooming in
276 		 * too far, the spacing is halved until at least two tics are visible, effectively
277 		 * inserting additional tics.
278 		*/
279 		double validatedTicSpacing( double spacing, double range, double pixels, double minPixels );
280 		/**
281 		 * When zoomed in on part of a circle, it looks nearly straight. KmPlot
282 		 * uses this to quickly draw curves that are mostly straight. Given the
283 		 * curvature, this function returns the maximum length of line that can
284 		 * be used to draw a part of a curve with the given curvature without
285 		 * the curve starting to look jagged.
286 		 */
287 		static double maxSegmentLength( double curvature );
288 		/**
289 		 * \return an appropriate value to use in numerical differentiation.
290 		 */
291 		double h( const Plot & plot ) const;
292 		/**
293 		 * Initializes the size, scaling, etc variables from the given paint
294 		 * device.
295 		 */
296 		void initDrawing( QPaintDevice * device, PlotMedium medium );
297 		/**
298 		* Print out table with additional information. Only for printing.
299 		*/
300 		void drawHeaderTable(QPainter *);
301 		/// Draw the grid.
302 		void drawGrid( QPainter* );
303 		/**
304 		 * Draw the axes.
305 		 */
306 		void drawAxes( QPainter *painter );
307 		/**
308 		 * Draw the axes' labels.
309 		 */
310 		void drawLabels( QPainter *painter );
311 		/**
312 		 * Draw the labels for the x-axis (this function is called from
313 		 * drawLabels).
314 		 * \a painter The QPainter to draw the labels with
315 		 * \a endLabelWidth_mm the distance of the "x" label from the edge.
316 		 */
317 		void drawXAxisLabels( QPainter *painter, double endLabelWidth_mm );
318 		/**
319 		 * Draw the labels for the y-axis (this function is called from
320 		 * drawLabels).
321 		 */
322 		void drawYAxisLabels( QPainter *painter );
323 		/**
324 		 * Draw a non-implicit function.
325 		 */
326 		void drawFunction( Function * function, QPainter * painter );
327 		/**
328 		 * Draw the function plots (other than implicit).
329 		 */
330 		void drawPlot( const Plot & plot, QPainter*);
331 		/**
332 		 * Draw the tangent field (for a differential function).
333 		 */
334 		void drawTangentField( const Plot & plot, QPainter * painter );
335 		/**
336 		 * Draw an implicit function.
337 		 */
338 		void drawImplicit( Function * function, QPainter * );
339 		/**
340 		 * Draw the extrema points, function names, etc. This needs to be done
341 		 * after the functions have all been drawn so that the label positioning
342 		 * knows where the plots have been drawn.
343 		 */
344 		void drawFunctionInfo( QPainter * painter );
345 		/**
346 		 * Initializes for the drawLabel function, called before drawing has
347 		 * started.
348 		 */
349 		void initDrawLabels();
350 		/**
351 		 * Draw text (e.g. showing the value of an extrema point or a function
352 		 * name) at the given (real) position.
353 		 */
354 		void drawLabel( QPainter * painter, const QColor & color, const QPointF & realPos, const QString & text );
355 		/**
356 		 * Used by plotImplicit to draw the plot in the square associated with
357 		 * the given point.
358 		 */
359 		void drawImplicitInSquare( const Plot & plot, QPainter *, double x, double y, Qt::Orientations orientation, QList<QPointF> * singular );
360 		/**
361 		* \return whether should draw the pixel from the given line length,
362 		* according to the given pen style (used in plotfkt).
363 		*/
364 		bool penShouldDraw( double totalLength, const Plot & plot );
365 		/**
366 		* \return An appropriate pen for drawing the plot.
367 		*/
368 		QPen penForPlot( const Plot & plot, QPainter * painter ) const;
369 		/**
370 		 * Used in findRoot.
371 		 */
372 		enum RootAccuracy
373 		{
374 			PreciseRoot,	///< Will potential spend a long time finding a root to a high degree of accuracy
375 			RoughRoot		///< Won't spend too long making a root accurate, giving up quickly if failed to find root
376 		};
377 		/**
378 		 * Used in trace mode. Attempts to find the root of equation \p eq near
379 		 * \p x (which is then set to the exact root if found).
380 		 * \returns whether a root was found.
381 		 */
382 		bool findRoot( double * x, const Plot & plot, RootAccuracy accuracy );
383 		/**
384 		 * Equivalent function as above for implicit functions.
385 		 */
386 		bool findRoot( double * x, double * y, const Plot & plot, RootAccuracy accuracy );
387 		/**
388 		 * For use in the findRoot functions.
389 		 * \p max_k maximum number of iterations
390 		 * \p max_f the largest value of y which is deemed a root found
391 		 */
392 		void setupFindRoot( const Plot & plot, RootAccuracy accuracy, double * max_k, double * max_f, int * n );
393 		/**
394 		 * Finds the list of points (in function coordinates) at which the
395 		 * derivative of the given plot is zero in the range of the currently
396 		 * viewable segment of the plot.
397 		 */
398 		QList<QPointF> findStationaryPoints( const Plot & plot );
399 		/**
400 		 * Find all roots (at which the given plot is zero) in the range
401 		 * [min,max].
402 		 */
403 		QList<double> findRoots( const Plot & plot, double min, double max, RootAccuracy accuracy );
404 		/**
405 		 * Changes the text in the statusbar.
406 		 */
407 		void setStatusBar( const QString &text, StatusBarSection section );
408 		/**
409 		* \return whether the crosshairs should be shown for the current mouse
410 		* position, zoom mode, etc.
411 		*/
412 		bool shouldShowCrosshairs() const;
413 		/**
414 		* Zooms in by amount \p zoomFactor (which will zooming out if less than 1)
415 		* from clicking at \p mousePos (in widget coordinates).
416 		*/
417 		void zoomIn( const QPoint & mousePos, double zoomFactor );
418 		/**
419 		* Zooms in from having drawn \p zoomRect (which is in widget coordinates).
420 		*/
421 		void zoomIn( const QRectF & zoomRect );
422 		/**
423 		* Zooms out from havoutg drawn \p zoomRect (which is out widget
424 		* coordinates).
425 		*/
426 		void zoomOut( const QRectF & zoomRect );
427 		/**
428 		* Translates the view by \p dx, \p dy (in widget coordinates).
429 		*/
430 		void translateView( int dx, int dy );
431 		/**
432 		* Finds the plot (if any) under the last mouse pos as recorded by
433 		* updateCrosshairPosition(). This sets csmode, cstype, csparam. If no plot
434 		* was found, then csmode is set to -1.
435 		 * \return the function position of the closest plot if one was found.
436 		*/
437 		QPointF getPlotUnderMouse();
438 		/**
439 		* Finds the closest point to \p pos (which is in real coordinates) to
440 		 * the given function.
441 		* \return the parametization (angle, x or t) that gives the closest
442 		 * point.
443 		*/
444 		double getClosestPoint( const QPointF & pos, const Plot & plot );
445 		/**
446 		* Calculates the pixel distance from \p pos to the display point of the
447 		* given function at \p x.
448 		*/
449 		double pixelDistance( const QPointF & pos, const Plot & plot, double x, bool updateFunction );
450 		/**
451 		 * \param overlapEdge whether to give values that are slightly either
452 		 * side of the view; this is useful for thick pens
453 		 * \return an appropriate xmin value for the given function
454 		 * plotting.
455 		 */
456 		double getXmin( Function * function, bool overlapEdge = false );
457 		/**
458 		 * \param overlapEdge whether to give values that are slightly either
459 		 * side of the view; this is useful for thick pens
460 		 * \return an appropriate xmax value for the given function for
461 		 * plotting.
462 		 */
463 		double getXmax( Function * function, bool overlapEdge = false );
464 
465 		/**
466 		 * How to behave in the *ToPixel functions.
467 		 */
468 		enum ClipBehaviour
469 		{
470 			ClipAll,		///< Clips any points going over the edge of the diagram
471 			ClipInfinite	///< Clips only infinite and NaN points going over the edge
472 		};
473 		/**
474 		 * @name Transformations
475 		 * These functions convert real coordinates to pixel coordinates and vice
476 		 * versa.
477 		 */
478 		double xToPixel( double x, ClipBehaviour clipBehaviour = ClipAll, double xIfNaN = 0 );
479 		double yToPixel( double y, ClipBehaviour clipBehaviour = ClipAll, double yIfNaN = 0 );
480 		QPointF toPixel( const QPointF & real, ClipBehaviour clipBehaviour = ClipAll, const QPointF & pixelIfNaN = QPointF() );
481 		double xToReal( double x );
482 		double yToReal( double y );
483 		QPointF toReal( const QPointF & pixel );
484 		bool xclipflg;	///< clipflg is set to 1 if the plot is out of the plot area.
485 		bool yclipflg;	///< clipflg is set to 1 if the plot is out of the plot area.
486 		/**
487 		 * Contains the settings for drawing the area under a graph (when
488 		 * calculating the area from function tools.
489 		 */
490 		IntegralDrawSettings m_integralDrawSettings;
491 		/**
492 		 * Separation distance between the grid lines.
493 		 */
494 		Value ticSepX, ticSepY;
495 		/**
496 		 * Positions of the first grid line.
497 		 */
498 		double ticStartX, ticStartY;
499 
500 		/**
501 		 * Mouse pointer previous for zooming.
502 		 */
503 		QPoint m_previousMouseMovePos;
504 
505 		QPointF m_crosshairPixelCoords;
506 		QPointF m_crosshairPosition;	///< in real coordinates
507 
508 		/**
509 		 * The t- or x- (angle) coordinate of the traced curve - when tracing a
510 		 * polar or parametric curve.
511 		 */
512 		double m_trace_x;
513 		/**
514 		 * When tracing a Cartesian plot and the trace position nears the
515 		 * x-axis, an attempt to find a root will be found. If found, this will
516 		 * be set to true, and no further attempts will be made at finding a
517 		 * root. Once the plot position moves away from the x-axis again, this
518 		 * will be set to false.
519 		 */
520 		bool m_haveRoot;
521 
522 		/// @return whether cspos is in the range of the view or in the custom range for the given \p plot
523 		bool crosshairPositionValid( Function * plot ) const;
524 
525 		/// represents the Printer options set by user in the Print Dialog
526 		/// @see KPrinterDlg
527 		bool m_printHeaderTable;
528 		bool m_printBackground;
529 		double m_printWidth;
530 		double m_printHeight;
531 		/// if stop_calculating is true, the user has canceled drawing of an integral graph
532 		bool m_stopCalculating;
533 		/// the background color of the graph
534 		QColor m_backgroundColor;
535 		///buffer the current window so all functions don't need to be re-drawn
536 		QPixmap buffer;
537 		/// the popup menu
538 		QMenu *m_popupMenu;
539 		/// The pointer to the popup menu's title
540 		QAction *m_popupMenuTitle;
541 		/// is set to true if an integral is calculated
542 		bool m_isDrawing;
543 		/**
544 		 * Describes the state of the popup menu.
545 		 */
546 		enum PopupStatus
547 		{
548 			NoPopup,
549 			Popup,
550 			PopupDuringTrace
551 		};
552 		///status of the popup menu
553 		PopupStatus m_popupMenuStatus;
554 		/// False if KmPlot is started as a program, otherwise true
555 		bool const m_readonly;
556 		/// For drawing diagram labels
557 		QFont m_labelFont;
558 		/**
559 		 * The resolution of label positioning.
560 		 */
561 		static const int LabelGridSize = 50;
562 		/**
563 		 * Indicate which parts of the diagram have content (e.g. axis or
564 		 * plots), so that they can be avoided when drawing diagram labels
565 		 */
566 		bool m_usedDiagramArea[LabelGridSize][LabelGridSize];
567 		/**
568 		 * Marks the given diagram rectangle (in screen coords) as 'used'.
569 		 */
570 		void markDiagramAreaUsed( const QRectF & rect );
571 		/**
572 		 * Marks the given diagram point (in screen coords) as 'used'.
573 		 */
574 		void markDiagramPointUsed( const QPointF & point );
575 		/**
576 		 * \return the m_usedDiagramArea coords for the screen rect.
577 		 */
578 		QRect usedDiagramRect( const QRectF & rect ) const;
579 		/**
580 		 * \return the cost of occupying the given rectangle (as in whether it
581 		 * overlaps other diagram content, etc).
582 		 */
583 		int rectCost( QRectF rect ) const;
584 
585 		enum ZoomMode
586 		{
587 			Normal,				///< no zooming
588 			AnimatingZoom,		///< animating a current zooming
589 			ZoomIn,				///< zoom in
590 			ZoomOut,			///< zoom out
591 			ZoomInDrawing,		///< drawing a rectangle for zooming in
592 			ZoomOutDrawing,		///< drawing a rectangle for zooming out
593 			AboutToTranslate,	///< user has clicked on an empty spot, but hasn't moved the mouse yet
594 			Translating			///< dragging the view with the mouse
595 		};
596 
597 		/// The current editing status
598 		ZoomMode m_zoomMode;
599 		/// for zoom-mode
600 		QPoint m_zoomRectangleStart;
601 		/// for animating zoom; contains the rectangle (in real coordinates) to draw
602 		QRectF m_animateZoomRect;
603 		/// for translating the view via dragging
604 		QPoint m_prevDragMousePos;
605 		/// timer that is started when the mouse is pressed
606         QElapsedTimer * m_mousePressTimer;
607 		/** Current plot viewport. */
608 		const QRectF getViewport();
609 
610 		/**
611 		 * The rectangle (in painter, and hence pixel, coordinates) that the
612 		 * plots must be in. This is also the size of the image being drawn to,
613 		 * since the painter remains untransformed.
614 		 */
615 		QRect m_clipRect;
616 		/**
617 		 * This matrix transforms from real coordinates to painter coordinates.
618 		 * (Note that the painter does not have any transformation applied).
619 		 */
620 		QMatrix m_realToPixel;
621 		/**
622 		 * The inverse matrix of m_realToPixel; it maps from pixel coordinates
623 		 * to real X-Y coordinates.
624 		 */
625 		QMatrix m_pixelToReal;
626 
627 		QString m_statusBarText[4];
628 
629 		enum Cursor { CursorWait, CursorBlank, CursorArrow, CursorCross, CursorMagnify, CursorLessen, CursorMove };
630 		Cursor m_prevCursor;
631 
632 		static View * m_self;
633 
634 		KTextEdit * m_textEdit; ///< Contains m_textDocument
635 		QTextDocument * m_textDocument; ///< Used for layout of axis labels
636 
637 		/// Accumulates mouse or trackpad scrolling to enable Ctrl+mouse wheel scaling on faulty devices
638 		int m_AccumulatedDelta;
639 
640 		/// Animation for the viewport
641 		QPropertyAnimation * m_viewportAnimation;
642 
643 		/// Finishes animation of the viewport and get the View back to the Normal mode
644 		void finishAnimation( const QRectF & rect );
645 
646 	private slots:
647 		void setViewport( const QRectF & rect );
648 };
649 
650 #endif // View_included
651