/*************************************************************************** qscobject.h ------------------- begin : Sun Jan 9 2000 copyright : (C) 2000 by Kamil Dobkowski email : kamildbk@friko.onet.pl ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef QSCOBJECT_H #define QSCOBJECT_H #include"qsdrv.h" #include"qsserializable.h" #include //-------------------------------------------------------------------------------------------------// class QSCObject; template class QSChildList; /** * \brief List of QSCObject's * * Object collection- it holds a list of QSCObjects. QSCGroup and QSPage contains object collections. * Selection in QSPlotView is also an object collection. See also: QSCObject */ class QSCObjectCollection : public QObject, public QSSerializable { Q_OBJECT public: /** * Constructor. set 'autoDelete' to false if you dont want objects * to be deleted when collection is deleted or when callig 'removeDelete'. */ QSCObjectCollection( QObject *parent=NULL, bool autoDelete=true ); /** * Destructor. If autoDelete is true deletes all objects */ ~QSCObjectCollection(); /** * Blocks / Enables and sends sigListChanged and sigChanged */ void setAutoUpdates( bool enable ); /** * Returns auto updates setting. */ bool autoUpdates() const { return m_auto_updates; } /** * Returns true if selection doesn't contain any object. */ bool isEmpty() const { return count() == 0; } /** * Number of objects in collection. */ int count() const; /** * Deletes ( if autoDelete is false - only removes ) all objects in collection. */ void clear(); /** * Adds a new object to the collection. */ void add( QSCObject *newObject ); /** * Insert object into the collection at the given position ( 0 - at the back, count() - at the front ). */ virtual void insert( int position, QSCObject *object ); /** * Removes an object at the position 'index' from the collection */ virtual void remove( int index ); /** * Removes an object at the position 'index' from the collection and deletes it ( if autoDelete is true ). */ void removeDelete( int index ); /** * Raises an object at the position 'index'. */ void raise( int index ); /** * Lowers an object at the position 'index'. */ void lower( int index ); /** * Brings to front an object at the position 'index'. */ void toFront( int index ); /** * Sends to back an object at the position 'index'. */ void toBack( int index ); /** * Moves to position 'position' an object at the position 'index'. */ void reorder( int position, int index ); /** * Returns the position of the object 'object'. */ int find( QSCObject *object ) const; /** * Returns object at the position 'index' */ QSCObject *object( int index ) const; /** * Paints skeletons of all objects. */ void paintSkeleton( QPainter *p, double dpi = 72.0 ); /** * Paints all object. If 'blocking' is false painter is copied using QSDrvQt::copyPainter * each object gets its own painter object, and paints itself in the background. */ void paint( QPainter *p, double dpi = 72.0, bool blocking=true, bool transparent=true ); /** * Draws all object using the given driver. If blocking is false, driver is copied using * QSDrv::copy() and each object gets its own driver object and draws itself in the background. */ void draw( QSDrv *drv, bool blocking=true, bool transparent=true ); /** * Returns if there is a busy object in this group. */ bool busy() const; /** * Stops drawing. */ void stop(); /** * Returns object at position 'p'. */ QSCObject *objectAt( const QSPt2f &p, QSDrv* drv, bool recursive=false ); /** * Returns if selection contains given object */ bool contains( QSCObject *object, bool recursive=false ); /** * Saves all objects */ virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); /** * Loads all objects */ virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); signals: /** * Emitted before collection is changed */ void sigParametersChanging(); /** * Emitted after collection was changed */ void sigParametersChanged(); /** * Object added. */ void sigAdded( QSCObject *o ); /** * Object added to the collection 'collection' ( which is this collection or the collection of any QSCGroup object in this collection ). */ void sigAdded( QSCObjectCollection *collection, QSCObject *o ); /** * Object removed from this collection */ void sigRemoved( QSCObject *o ); /** * Object added to the collection 'collection'. */ void sigRemoved( QSCObjectCollection *collection, QSCObject *o ); /** * Object raised, lowered, reordered. */ void sigOrderChanged(); /** * Order of objects changed ( including all grouped object ) */ void sigOrderChanged( QSCObjectCollection *collection ); /** * Object list changed. */ void sigListChanged(); /** * Object list changed. */ void sigListChanged( QSCObjectCollection *collection ); /** * Emitted when QSData child object list ( QSAxis and QSPlot are child objects of QSAxes ) has changed. * Emmitted for all QSData objects ( QSAxes ) in this collection. I really needed such signal. */ void sigDataChildListChanged(); /** * Object on the list changed. Collection needs redrawing */ void sigChanged(); /** * Draw ends. */ void sigDrawEnds(); protected: bool m_auto_updates; QSChildList *m_objects; virtual void parametersChanging(); virtual void parametersChanged(); virtual void orderChanged(); virtual void listChanged(); virtual void changed(); bool tempAutoUpdatesOff(); void tempAutoUpdatesRestore( bool enable ); private slots: void slot_object_changed(); void slot_data_child_list_changed(); void slot_added(QSCObjectCollection*,QSCObject*); void slot_removed(QSCObjectCollection*,QSCObject*); void slot_order_changed(QSCObjectCollection*); void slot_list_changed(QSCObjectCollection*); void slot_draw_ends(QSCObject*); }; //-------------------------------------------------------------------------------------------------// class QSAxes; class QSAxis; class QSData; class QSCGroup; #define SET_COBJECT_PROPERTY( property, new_value ) if ((property)!=(new_value)) { parametersChanging(); (property)=(new_value); parametersChanged(); } /** * \brief Base class for canvas objects which can be displayed on a page. * * It can paint itself using the given painter - see paint(). Sometimes it takes much time to draw some * objects such as graphs with many datapoints, so it supports drawing in the background. See paint() ( 'blocking' argument ), * busy(), stop(), sigDrawEnds() methods. QSCObject is usually a member of some object collection, see collection(). It can be * the main object collection of QSPage, but it can be also QSCGroup collection if object is grouped with others. In this case group() * method returns a pointer to this group. QSCObject can be bound to some QSAxes object - see setParentAxes(). It is useful when, for example, * QSCArrow should point at some data point in your graph. You can transform coordinates between various coordinate systems * using mixedToCanvas(), canvasToMixed(). Notice that a single QSAxes object can have many coordinate systems, defined by * every set of its axes. So you can choose which axes you want to use - see setDefaultXAxis(), setDefaultYAxis(), setDefaultZAxis(). * OQSCObject notifies when its parameters are changing, so it needs redrawing - see sigUpdate(). Use setBox() for positioning and resizing * the object. * @author Kamil Dobkowski */ class QSCObject : public QObject, public QSSerializable { friend class QSCObjectCollection; friend class QSCGroup; Q_OBJECT Q_PROPERTY( int defaultXAxis READ defaultXAxis WRITE setDefaultXAxis ) Q_PROPERTY( int defaultYAxis READ defaultYAxis WRITE setDefaultYAxis ) Q_PROPERTY( int defaultZAxis READ defaultZAxis WRITE setDefaultZAxis ) public: /** * Constructor. */ QSCObject( QObject *parent=NULL ); /** * Destructor. Removes an object from a parent child list. */ virtual ~QSCObject(); /** * Returns object's parent group if it is grouped or NULL. */ QSCGroup *group() const { return m_group; } /** * Returns collection to which this object belongs to or NULL. If collection is not autoDelete * object doesn't belong to it. */ QSCObjectCollection *collection() const { return m_collection; } /** * Returns a root group of this object It digs through all group hierarchy. * It will be usually the main object collection on QSPage. */ QSCObjectCollection *rootCollection(); /** * Sets a parent axes object. Position of this object can be set * as a relative to the parent object position. This function is called by * QSAxes object ( or rather by its shadow QSCObject ), when this object is * grouped with axes. */ virtual void setParentAxes( QSAxes *axes ); /** * Returns a parent axes or NULL */ QSAxes *parentAxes() const { return m_parent_axes; } /** * Style of this object. */ enum Style { Rotateable = 1U<<0, Resizeable = 1U<<1, Moveable = 1U<<2 }; /** * Returns a bitwise-OR of Style values. Informs the parent what actions * on this object are allowed. Currently not used. */ virtual int style() { return 0; } /** * Control whether sigParametersChnged emits sigUpdate */ virtual void setAutoUpdates( bool enabled ); /** * Returns auto-update state */ bool autoUpdates() const { return m_auto_updates; } /** * Raises object on a parent collection stack. */ virtual void raise(); /** * Lowers object on a parent collection stack. */ virtual void lower(); /** * Brings object to front on a parent collection stack. */ virtual void toFront(); /** * Sends object to back on a parent collection stack. */ virtual void toBack(); /** * Moves object to position 'newPosition' on a parent collection stack. */ virtual void reorder( int newPosition ); /** * Paint simplified version of this object ( called when resizing, redrawing ). */ virtual void paintSkeleton( QPainter *p, double dpi = 72.0 ); /** * Requests a repaint operation. If blocking is false the painter is copied using QSDrvQt::copyPainter(), * this function returns and drawing is performed in the background */ virtual void paint( QPainter *p, double dpi = 72.0, bool blocking=true, bool transparent=true ); /** * Requests a repaint operation. If blocking is false the driver is copied using QSDrv::copy(), * this function returns and drawing is performed in the background */ virtual void draw( QSDrv *drv, bool blocking=true, bool transparent=true ) = 0; /** * When drawing is in background */ virtual bool busy() const { return false; } /** * Stops repainting immediately. This should be reimplemented if you allowind to repaint * object in background. */ virtual void stop() {} /** * Return true if object is hit by mouse click. */ virtual bool isHit( const QSPt2f &p, QSDrv* drv ) { return box(drv).contains(p); } /** * Resize to canvas rect. Rect can be unnormalized ( size can be < 0 ). * Drv ( its dpi value ) is used to map this values to mm's, * calculating sizes of text labels, etc. */ virtual void setBox( const QSRectf& canvas_rect, QSDrv *drv ); /** * Return a bounding box of the object. Result rect can be unnormalized ( size can be < 0 ) * Drv is used to obtains size of text labels etc. */ virtual QSRectf box( QSDrv *drv ); /** * Called when a new angle is set. */ virtual void setAngle( int deg ); /** * Returns the current angle */ virtual int angle() const { return 0; } /** * Return a center of a rotation. */ virtual QSPt2f rCenter( QSDrv *drv ); /** * Returns an object's name ( for a list of object etc. ) */ virtual QString name() { return tr("Unknown object"); } /** * Don't change it. It must always return 'false'. Do not reimplement this function in your own objects !. */ virtual bool isAxesShadow() { return false; } /** * Sets default X,Y or Z axia. Does not emit sigUpdate. */ void setDefaultAxis( QSAxis *axis ); /** * Default X,Y or Z axis. */ QSAxis *defaultAxis( int axisType ) const; /** * Maps position 'pos' to canvas ( screen ) coords. It is a simple wrapper around * QSAxes::mixedToCanvas(). If there are no parent axes it always maps mmToPixels * Returns a depth also. See QSAxes::CoordinateSystem */ QSPt3f mixedToCanvas( const QSPt3f& pos, int xCoordIn, int yCoordIn, int zCoordIn, double dpi ); /** * If there are no parent axes it always maps pixlesToMM. Useful tool to use in your own objects. * See QSAxes::CoordinateSystem */ QSPt3f canvasToMixed( const QSPt3f& pos, int xCoordOut, int yCoordOut, int zCoordOut, double dpi ); /** * Sets the default axis. */ void setDefaultXAxis( int axisIndex ); /** * Sets the default axis. */ void setDefaultYAxis( int axisIndex ); /** * Sets the default axis. */ void setDefaultZAxis( int axisIndex ); /** * Returns an index of the default axis */ int defaultXAxis() const; /** * Returns an index of the default axis */ int defaultYAxis() const; /** * Returns an index of the default axis */ int defaultZAxis() const; /** * Saves all QObject properties */ virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); /** * Restores all QObject properties */ virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); public slots: /** * Calls stop() */ virtual void parametersChanging(); /** * Emits sigUpdate() */ virtual void parametersChanged(); /** * Emits sigUpdate() */ virtual void forceUpdate(); signals: void sigDrawEnds( QSCObject *me ); /** * Parameters has changed */ void sigUpdate( QSCObject *me ); /** * Parameters has changed ( the same as a signal above ). */ void sigUpdate(); protected: QSAxes *m_parent_axes; QSAxis *m_default_axis[3]; bool m_auto_updates; QSCObjectCollection *m_collection; QSCGroup *m_group; /** * Called by collection when this object is inserted or removed (collection=NULL) from its list. */ virtual void setCollection( QSCObjectCollection *collection ); /** * Called when object is grouped or ungrouped(group=NULL) */ virtual void setGroup( QSCGroup *group ); private slots: /** * Checks if default axis is removed, if it is binds to another axis */ void axisRemoved( QSData *removedObject ); /** * Checks if parent axes are removed, Sets a parent axes to NULL in this case. */ void parentAxesRemoved( QSData *removedObject ); }; //-------------------------------------------------------------------------------------------------// /** * \brief Group of QSCObject s, which is also QSCObject. * * All its functionality is exposed through its object collection - see objects(). */ class QSCGroup : public QSCObject { Q_OBJECT public: /** * Constructor */ QSCGroup( QObject *parent=NULL ); /** * Destructor */ virtual ~QSCGroup(); /** * Sets parent axes in all contained objects. */ virtual void setParentAxes( QSAxes *axes ); /** * Returns a list of grouped object. */ QSCObjectCollection *objects() const { return m_objects; } /** * Default style is Moveable | Resizeable */ virtual int style() { return Moveable | Resizeable; } /** * Reimplemented */ virtual void paintSkeleton( QPainter *p, double dpi = 72.0 ); /** * Reimplemented */ virtual void paint( QPainter *p, double dpi = 72.0, bool blocking=true, bool transparent=true ); /** * Reimplemented */ virtual void draw( QSDrv *drv, bool blocking=true, bool transparent=true ); /** * Reimplemented */ virtual bool busy() const; /** * Reimplemented */ virtual void stop(); /** * Reimplemented */ virtual bool isHit( const QSPt2f &p, QSDrv* drv ); /** * Reimplemented */ virtual void setBox( const QSRectf& canvas_rect, QSDrv *drv ); /** * Reimplemented */ virtual QSRectf box( QSDrv *drv ); /** * Reimplemented */ virtual QString name(); /** * Reimplemented */ virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); /** * Reimplemented */ virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); protected: QSCObjectCollection *m_objects; bool m_w_minus; bool m_h_minus; protected slots: void slot_draw_ends(); void slot_collection_changed(); void slot_object_added( QSCObject * ); void slot_object_removed( QSCObject * ); }; #endif