#include "blockitem.h" BlockItemPin::BlockItemPin(Qt::Alignment a, int bus_type_, const QString & text_, QGraphicsItem * _parent): QGraphicsItem(_parent), ell_item(this), text_item(this) { parent_ = 0; setData(1004, "pin"); setAcceptHoverEvents(true); text_item.setData(1002, true); ell_item.setData(1003, true); br[Disconnected] = QBrush(Qt::lightGray); br[Connected] = QBrush(Qt::darkGreen); br[Hover] = QBrush(Qt::blue); br[Drop] = QBrush(Qt::green); br[Accept] = QBrush(Qt::green); br[Reject] = QBrush(Qt::red); setState(Disconnected); setAlignment(a); setBusType(bus_type_); setText(text_); setZValue(2.); setDirection(BlockItemPin::InputOutput); _reparent(); } void BlockItemPin::_init(bool affect_parent) { QRectF tbr = text_item.boundingRect(); const double r = 7.; ell_item.setRect(-r, -r, r+r, r+r); ell_item.setSpanAngle(16*180); text_item.resetTransform(); text_item.setPos(0, -tbr.height() / 2.); text_item.setTransformOriginPoint(0, tbr.height() / 2.); switch (align) { case Qt::AlignBottom: ell_item.setStartAngle(16*0); text_item.setRotation(-90.); text_item.moveBy(0, -r * 1.5); break; case Qt::AlignRight: ell_item.setStartAngle(16*90); text_item.setRotation(0.); text_item.moveBy(-tbr.width() - r * 1.5, 0); break; case Qt::AlignTop: ell_item.setStartAngle(16*180); text_item.setRotation(-90.); text_item.moveBy(0, tbr.width() + r * 1.5); break; case Qt::AlignLeft: ell_item.setStartAngle(16*270); text_item.setRotation(0.); text_item.moveBy(r * 1.5, 0); break; default: break; } if (affect_parent && parent_) parent_->arrangePins(); } void BlockItemPin::_reparent() { if (parentItem() == 0) return; if (qgraphicsitem_cast(parentItem()) == 0) return; QPen p = qgraphicsitem_cast(parentItem())->g_main.pen(); ell_item.setPen(p); } QVariant BlockItemPin::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { if (change == QGraphicsItem::ItemParentChange) _reparent(); return QGraphicsItem::itemChange(change, value); } void BlockItemPin::hoverEnterEvent(QGraphicsSceneHoverEvent * e) { bool m_pin_mc(false); if (scene()) if (!scene()->views().isEmpty()) QMetaObject::invokeMethod(scene()->views()[0], "getPinMC", Q_ARG(bool*, &m_pin_mc)); if ((state() != Disconnected) && !m_pin_mc) return; saveState(); setState(BlockItemPin::Hover); } void BlockItemPin::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) { //if (state() == Hover) restoreState(); } BlockItem::BlockItem(QGraphicsItem * parent): QGraphicsObject(parent), PropertyStorage(), g_main(this), g_selection(this) { setData(1006, "item"); setZValue(1.); setAcceptHoverEvents(true); setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); g_main.setData(1002, true); g_selection.setData(1007, "item_selection"); g_selection.setAcceptedMouseButtons(0); g_selection.setZValue(10.); g_selection.hide(); g_selection.setData(1003, true); col = Qt::lightGray; _resize(QSizeF(100., 60.)); QPen p(QColor(128, 128, 255), 1., Qt::DotLine); p.setCosmetic(true); g_selection.setPen(p); g_selection.setBrush(QColor(128, 128, 255, 32)); //g_main.setBrush(QColor(128, 128, 128, 64)); /* BlockItemPin * pin = new BlockItemPin(Qt::AlignRight, 0, this); pin->setText("text"); pin->setBusType(0); addPin(pin); pin = new BlockItemPin(Qt::AlignTop, this); pin->setBusType(0); addPin(pin); pin = new BlockItemPin(Qt::AlignLeft, this); pin->setBusType(1); addPin(pin); pin = new BlockItemPin(Qt::AlignRight, this); pin->setBusType(1); addPin(pin);*/ } BlockItem::~BlockItem() { clearDecors(); } void BlockItem::_resize(QSizeF s) { g_main.setRect(QRectF(QPointF(), s)); g_main.setPos(-g_main.rect().center()); g_selection.setRect(enlargedRect(g_main.rect(), 0, 0, 8)); g_selection.setPos(g_main.pos()); QRadialGradient g(g_main.rect().width() / 2., 0, qMax(g_main.rect().width() / 2., g_main.rect().height())); g.setSpread(QGradient::PadSpread); g.setCoordinateMode(QGradient::LogicalMode); g.setColorAt(0., col.darker(120.)); g.setColorAt(1., col.lighter(120.)); g_main.setBrush(QBrush(g)); prepareGeometryChange(); arrangePins(); } BlockItemPin * BlockItem::addPin(BlockItemPin * pin, bool update_) { pin->setParentItem(this); pins_[pin->alignment()] << pin; pin->parent_ = this; if (update_) arrangePins(); return pin; } BlockItemPin * BlockItem::addPin(Qt::Alignment align, int bus_type, const QString & text, bool update_) { BlockItemPin * pin = new BlockItemPin(align, bus_type, text, this); pin->parent_ = this; pins_[pin->alignment()] << pin; if (update_) arrangePins(); return pin; } void BlockItem::removePin(BlockItemPin * pin) { if (!pin) return; QMutableMapIterator > it(pins_); while (it.hasNext()) { it.next(); it.value().removeAll(pin); } delete pin; arrangePins(); } void BlockItem::addDecor(QGraphicsItem * item) { if (decors_.contains(item)) return; if (qgraphicsitem_cast(item)) qgraphicsitem_cast(item)->setTransformationMode(Qt::SmoothTransformation); if (qgraphicsitem_cast(item)) qgraphicsitem_cast(item)->setData(1010, qgraphicsitem_cast(item)->text()); if (qgraphicsitem_cast(item)) qgraphicsitem_cast(item)->setData(1010, qgraphicsitem_cast(item)->text()); item->setData(1002, true); item->setData(1011, "decor"); decors_ << item; item->setParentItem(this); } void BlockItem::removeDecor(QGraphicsItem * item) { if (scene() && item) scene()->sendEvent(item, new QGraphicsSceneEvent(QEvent::Close)); decors_.removeAll(item); delete item; } QVector BlockItem::takePins() { QVector ret = pins(); pins_.clear(); return ret; } void BlockItem::clearPins() { QList > mp = pins_.values(); for (int i = 0; i < mp.size(); ++i) qDeleteAll(mp[i]); pins_.clear(); } void BlockItem::clearDecors() { bool pbs = false; if (scene()) pbs = scene()->blockSignals(true); if (scene()) foreach (QGraphicsItem * i, decors_) scene()->sendEvent(i, new QGraphicsSceneEvent(QEvent::Close)); qDeleteAll(decors_); decors_.clear(); if (scene()) { scene()->blockSignals(pbs); QMetaObject::invokeMethod(scene(), "selectionChanged"); } } QVector BlockItem::pins() const { QList > mp = pins_.values(); QVector ret; for (int i = 0; i < mp.size(); ++i) ret << mp[i].toVector(); return ret; } QByteArray BlockItem::saveModel() { /*QDataStream s(&ret, QIODevice::ReadWrite); QVector ps = pins(); s << pos() << rotation() << size() << color() << ps.size(); foreach (BlockItemPin * p, ps) s << int(p->alignment()) << p->busType() << p->text() << p->devices(); s << decors_.size(); foreach (QGraphicsItem * i, decors_) s << i;*/ ChunkStream cs; cs << cs.chunk(1, pos()) << cs.chunk(2, rotation()) << cs.chunk(3, size()) << cs.chunk(4, color()) << cs.chunk(5, pins()) << cs.chunk(6, decors_); return cs.data(); } void BlockItem::loadModel(const QByteArray & data) { //qDebug() << "load from" << data.size() << "bytes"; clearPins(); clearDecors(); if (data.isEmpty()) return; /*QDataStream s(data); {QPointF _v; s >> _v;} {qreal _v; s >> _v;} {QSizeF _v; s >> _v; setSize(_v);} {QColor _v; s >> _v; setColor(_v);} int _s; s >> _s; for (int i = 0; i < _s; ++i) { BlockItemPin * pin = new BlockItemPin(); {int _v; s >> _v; pin->setAlignment((Qt::Alignment)_v);} {int _v; s >> _v; pin->setBusType(_v);} {QString _v; s >> _v; pin->setText(_v);} {QMap _v; s >> _v; pin->setDevices(_v);} addPin(pin); } s >> _s; for (int i = 0; i < _s; ++i) { if (s.atEnd()) break; QGraphicsItem * ni = 0; s >> ni; if (ni) { addDecor(ni); } }*/ ChunkStream cs(data); QVector tp; QList dl; while (!cs.atEnd()) { switch (cs.read()) { case 1: /*setPos(cs.getData());*/ break; case 2: /*setRotation(cs.getData());*/ break; case 3: setSize(cs.getData()); break; case 4: setColor(cs.getData()); break; case 5: tp = cs.getData >(); foreach (BlockItemPin * p, tp) addPin(p); break; case 6: dl = cs.getData >(); foreach (QGraphicsItem * d, dl) addDecor(d); break; } } } QByteArray BlockItem::save() { ChunkStream cs; QMap > pp; foreach (BlockItemPin * p, pins()) { pp[p->text()] = p->properties(); } cs << cs.chunk(1, pos()) << cs.chunk(2, rotation()) << cs.chunk(3, props) << cs.chunk(5, pp); return cs.data(); } void BlockItem::load(const QByteArray & data) { if (data.isEmpty()) return; ChunkStream cs(data); QMap > _p; while (!cs.atEnd()) { switch (cs.read()) { case 1: setPos(cs.getData()); break; case 2: setRotation(cs.getData()); break; case 3: props = cs.getData >(); break; case 5: _p = cs.getData > >(); foreach (BlockItemPin * p, pins()) if (_p.contains(p->text())) p->properties() = _p[p->text()]; break; } } } BlockItem * BlockItem::copy() const { BlockItem * ret = new BlockItem(); ret->setPos(pos()); ret->setSize(size()); ret->setColor(color()); ret->setSelected(false); ret->props = props; QVector mp = pins(); foreach (BlockItemPin * p, mp) { BlockItemPin * np = new BlockItemPin(); np->setBusType(p->busType()); np->setAlignment(p->alignment()); np->setText(p->text()); np->properties() = p->properties(); ret->addPin(np); } QByteArray ba; foreach (QGraphicsItem * i, decors_) { ba.clear(); QGraphicsItem * ni = 0; QDataStream s(&ba, QIODevice::ReadWrite); s << i; QDataStream s2(ba); s2 >> ni; if (ni) ret->addDecor(ni); } return ret; } QList BlockItem::connectedBuses() const { QList ret; foreach (BlockItemPin * p, pins()) ret << p->connectedBuses(); return ret; } BlockItemPin * BlockItem::pinByText(const QString & t) const { foreach (BlockItemPin * p, pins()) if (p->text() == t) return p; return 0; } BlockItemPin * BlockItem::pinAtBus(BlockBusItem * bus) const { if (bus == 0) return 0; foreach (BlockItemPin * p, pins()) if (p->connectedBuses().contains(bus)) return p; return 0; } QRectF BlockItem::boundingRect() const { return g_main.mapRectToParent(g_main.boundingRect()); } void BlockItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { //QGraphicsItem::mouseMoveEvent(event); } #define _POS (i - ((cp.size() - 1) / 2)) * 20 void BlockItem::arrangePins() { //double w = g_main.rect().width(), h = g_main.rect().height(); QVector pl = pins(); pins_.clear(); foreach (BlockItemPin * p, pl) pins_[p->alignment()] << p; QList cp = pins_.value(Qt::AlignBottom); for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(_POS, bottom()); cp = pins_.value(Qt::AlignTop); for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(_POS, top()); cp = pins_.value(Qt::AlignLeft); for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(left(), _POS); cp = pins_.value(Qt::AlignRight); for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(right(), _POS); } #undef _POS void BlockItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) { //if () } QVariant BlockItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { if (change == QGraphicsItem::ItemSelectedChange) g_selection.setVisible(value.toBool()); return QGraphicsItem::itemChange(change, value); }