#ifndef BLOCKITEM_H #define BLOCKITEM_H #include #include #include #include #include #include #include #include #include #include #include "blockbase.h" #include "alignedtextitem.h" #include "chunkstream.h" /// data: /// 1002 - flag for move parent (true) /// 1003 - flag for visualize selection (true) /// 1004 - BlockItemPin ("pin") /// 1005 - BlockBusItem ("connection") /// 1006 - BlockItem ("item") /// 1007 - BlockItem selection ("item_selection") /// 1008 - item is NOT decor, ignore for function decors() (true) /// 1009 - item is scene decor ("decor") /// 1010 - BlockItem decor (src text for QGraphicsSimpleTextItem) /// 1011 - item is BlockItem decor ("decor") /// 1100 - flag for correct move (true) class BlockItem; class BlockBusItem; class BlockItemPin: public QGraphicsItem, public PropertyStorage { friend class BlockView; friend class BlockItem; public: BlockItemPin(Qt::Alignment a = Qt::AlignLeft, int bus_type = 0, const QString & text_ = QString(), QGraphicsItem * parent_ = 0); enum State { Disconnected, Connected, Hover, Drop, Accept, Reject }; enum Direction { None = 0x0, Input = 0x1, Output = 0x2, InputOutput = 0x3 }; struct Device { Device(const QString & n = QString(), const QString & p = QString(), bool e = false) {name = n; devFPath = p; editable = e;} QString name; QString devFPath; bool editable; }; void setPen(const QPen & p) {ell_item.setPen(p);} QPen pen() const {return ell_item.pen();} void setBrush(const QBrush & b) {ell_item.setBrush(b);} QBrush brush() const {return ell_item.brush();} int busType() const {return bus_type;} Qt::Alignment alignment() const {return align;} Direction direction() const {return dir;} QString text() const {return text_item.text();} const QMap & devices() const {return devices_;} QMap devicesPath() const; State state() const {return state_;} void setBusType(int type_) {bus_type = type_;} void setAlignment(Qt::Alignment a) {align = a; _init(true);} void setDirection(Direction d) {dir = d; _init(true);} void setText(const QString & t) {text_item.setText(t); _init(true);} void setState(State s) {state_ = s; setBrush(br[int(state_)]); update();} void addDevice(const QString & name, const QString & path, bool editable = false) {devices_[name] = Device(name, path, editable); _updateText();} void setDevicesPath(const QMap & dp); void removeDevice(const QString & name) {devices_.remove(name); _updateText();} void clearDevices() {devices_.clear(); _updateText();} void setDevices(const QMap & d) {devices_ = d; _updateText();} Device device(const QString & name) const {return devices_.value(name);} bool isDeviceExists(const QString & name) const {return devices_.contains(name);} void saveState() {sstate_.push(state_);} bool restoreState() {if (sstate_.isEmpty()) return false; setState(sstate_.pop()); return true;} void clearStateStack() {sstate_.clear();} BlockItem * parent() const {return parent_;} QList connectedBuses() const {return buses_;} enum {Type = UserType + 3}; protected: void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {} QRectF boundingRect() const {return ell_item.boundingRect().translated(ell_item.pos()) | text_item.boundingRect().translated(text_item.pos());} int type() const {return Type;} QVariant itemChange(GraphicsItemChange change, const QVariant & value); void hoverEnterEvent(QGraphicsSceneHoverEvent * e); void hoverLeaveEvent(QGraphicsSceneHoverEvent * e); void _init(bool affect_parent = false); void _reparent(); void _updateText(); int bus_type; State state_; QGraphicsEllipseItem ell_item; QGraphicsSimpleTextItem text_item; QStack sstate_; QList buses_; BlockItem * parent_; Qt::Alignment align; Direction dir; QMap devices_; QBrush br[6]; }; class BlockItem: public QGraphicsObject, public PropertyStorage { friend class BlockView; friend class BlockItemPin; friend class DrawTools; Q_OBJECT public: BlockItem(QGraphicsItem * parent = 0); ~BlockItem(); BlockItem * copy() const; BlockItemPin * addPin(BlockItemPin * pin, bool update_ = true); BlockItemPin * addPin(Qt::Alignment align, int bus_type, const QString & text, bool update_ = true); void removePin(BlockItemPin * pin); void addDecor(QGraphicsItem * item); void removeDecor(QGraphicsItem * item); QVector takePins(); void clearPins(); void clearDecors(); QVector pins() const; QList decors() const {return decors_;} QList connectedBuses() const; BlockItemPin * pinByText(const QString & t) const; BlockItemPin * pinAtBus(BlockBusItem * bus) const; /// TODO return list of connected pins QColor color() const {return col;} void setColor(QColor c) {col = c; _resize(size());} QSizeF size() const {return g_main.rect().size();} void setSize(QSizeF s) {_resize(s);} void setSize(qreal w, qreal h) {setSize(QSizeF(w, h));} void setWidth(qreal w) {setSize(QSizeF(w, size().height()));} void setHeight(qreal h) {setSize(QSizeF(size().width(), h));} QByteArray saveModel(); void loadModel(const QByteArray & data); QByteArray save(); void load(const QByteArray & data); void arrangePins(); enum {Type = UserType + 1}; protected: void _resize(QSizeF s); int type() const {return Type;} QRectF boundingRect() const; void mouseMoveEvent(QGraphicsSceneMouseEvent * event); double left() const {return boundingRect().left();} double right() const {return boundingRect().right();} double top() const {return boundingRect().top();} double bottom() const {return boundingRect().bottom();} void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0); QVariant itemChange(GraphicsItemChange change, const QVariant & value); QGraphicsRectItem g_main, g_selection; QColor col; QMap > pins_; QList decors_; }; inline QDataStream & operator <<(QDataStream & s, const BlockItemPin * p) { ChunkStream cs; cs << cs.chunk(1, int(p->alignment())) << cs.chunk(2, p->busType()) << cs.chunk(3, p->text()) << cs.chunk(4, p->devices()); s << cs.data(); return s;} inline QDataStream & operator >>(QDataStream & s, BlockItemPin *& p) { ChunkStream cs(s); p = new BlockItemPin(); while (!cs.atEnd()) { switch (cs.read()) { case 1: p->setAlignment((Qt::Alignment)cs.getData()); break; case 2: p->setBusType(cs.getData()); break; case 3: p->setText(cs.getData()); break; case 4: p->setDevices(cs.getData >()); break; } } return s; } inline QDataStream & operator <<(QDataStream & s, const BlockItemPin::Device & d) { ChunkStream cs; cs << cs.chunk(1, d.name) << cs.chunk(2, d.devFPath) << cs.chunk(3, d.editable); s << cs.data(); return s;} inline QDataStream & operator >>(QDataStream & s, BlockItemPin::Device & d) { ChunkStream cs(s); while (!cs.atEnd()) { switch (cs.read()) { case 1: d.name = cs.getData(); break; case 2: d.devFPath = cs.getData(); break; case 3: d.editable = cs.getData(); break; } } return s; } #endif // BLOCKITEM_H