diff --git a/qad/blockview/blockitempin.cpp b/qad/blockview/blockitempin.cpp index c340ca0..fe0e2f8 100644 --- a/qad/blockview/blockitempin.cpp +++ b/qad/blockview/blockitempin.cpp @@ -125,6 +125,13 @@ void BlockItemPin::_reparent() { } +QGraphicsView * BlockItemPin::_view() const { + if (!scene()) return 0; + if (scene()->views().isEmpty()) return 0; + return scene()->views().back(); +} + + QVariant BlockItemPin::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { if (change == QGraphicsItem::ItemParentChange) _reparent(); @@ -133,9 +140,12 @@ QVariant BlockItemPin::itemChange(QGraphicsItem::GraphicsItemChange change, cons void BlockItemPin::hoverEnterEvent(QGraphicsSceneHoverEvent * e) { + QGraphicsView * v = _view(); bool m_pin_mc = false; - if (scene()) if (!scene()->views().isEmpty()) - QMetaObject::invokeMethod(scene()->views().back(), "getPinMC", Q_ARG(bool*, &m_pin_mc)); + if (v) { + QMetaObject::invokeMethod(v, "getPinMC", Q_ARG(bool*, &m_pin_mc)); + QMetaObject::invokeMethod(v, "pinHoverInOut", Qt::QueuedConnection, Q_ARG(BlockItemPin*, this)); + } if ((state() != Disconnected) && !m_pin_mc) return; saveState(); setState(BlockItemPin::Hover); @@ -145,8 +155,9 @@ void BlockItemPin::hoverEnterEvent(QGraphicsSceneHoverEvent * e) { void BlockItemPin::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) { + QGraphicsView * v = _view(); restoreState(); enlargePin(false); update(); + if (v) QMetaObject::invokeMethod(v, "pinHoverInOut", Q_ARG(BlockItemPin*, 0)); } - diff --git a/qad/blockview/blockitempin.h b/qad/blockview/blockitempin.h index 8cae5a8..a6795b0 100644 --- a/qad/blockview/blockitempin.h +++ b/qad/blockview/blockitempin.h @@ -85,6 +85,7 @@ protected: void hoverLeaveEvent(QGraphicsSceneHoverEvent * e); void _init(bool affect_parent = false); void _reparent(); + QGraphicsView * _view() const; int bus_type; State state_; QGraphicsEllipseItem ell_item; diff --git a/qad/blockview/blockview.cpp b/qad/blockview/blockview.cpp index b7bda26..b3610dc 100644 --- a/qad/blockview/blockview.cpp +++ b/qad/blockview/blockview.cpp @@ -237,19 +237,16 @@ bool BlockView::eventFilter(QObject * o, QEvent * e) { new_bus = false; unmarkPins(true); reconnectAll(); - tmp_bus.hide(); - tmp_bus.clear(); + hideTmpBuses(); } if (new_branch && mm_cancel) { new_branch = false; - tmp_bus.hide(); - tmp_bus.clear(); + hideTmpBuses(); } if (moved && mm_cancel) { moved = false; restoreSelState(); - tmp_bus.hide(); - tmp_bus.clear(); + hideTmpBuses(); } if (mm_cancel) return true; mm_mods = me->modifiers(); @@ -300,11 +297,19 @@ bool BlockView::eventFilter(QObject * o, QEvent * e) { if (qgraphicsitem_cast(mm_ci)->state() == BlockItemPin::Hover) { trace_from = mm_ci->scenePos(); qgraphicsitem_cast(mm_ci)->clearStateStack(); + hideTmpBuses(); tmp_bus.setBusType(qgraphicsitem_cast(mm_ci)->busType()); tmp_bus.setEndpointsNumber(3); - tmp_bus.clear(); tmp_bus.show(); new_bus = true; + qDeleteAll(tmp_buses); + tmp_buses.clear(); + foreach (BlockItemPin * p, last_multiconnect_pl) { + tmp_buses << new BlockBusItem(true); + tmp_buses.back()->setBusType(p->busType()); + addItem(tmp_buses.back()); + } + //qDebug() << "new" << ; newBusStarted(tmp_bus.busType()); markPins(tmp_bus.busType()); if (qgraphicsitem_cast(mm_ci)->alignment() == Qt::AlignLeft || @@ -353,6 +358,12 @@ bool BlockView::eventFilter(QObject * o, QEvent * e) { break; } trace(trace_from, me->scenePos(), &tmp_bus); + for (int i = 0; i < qMin(tmp_buses.size(), last_multiconnect_pl.size()); ++i) { + QPointF dp = last_multiconnect_pl[i]->scenePos() - trace_from; + //qDebug() << "trace" << i << dp; + trace(trace_from + dp, me->scenePos() + dp, tmp_buses[i], false); + tmp_buses[i]->show(); + } matchBus(); } } @@ -507,7 +518,7 @@ bool BlockView::eventFilter(QObject * o, QEvent * e) { } } if (new_branch) { - tmp_bus.hide(); + hideTmpBuses(false); } if (moved && pm_connect) { QList ci; @@ -525,6 +536,12 @@ bool BlockView::eventFilter(QObject * o, QEvent * e) { BlockBusItem * nb = new BlockBusItem(tmp_bus); loadBus(nb); addItem(nb); + //qDebug() << "also" << tmp_buses; + foreach (BlockBusItem * b, tmp_buses) { + nb = new BlockBusItem(*b); + loadBus(nb); + addItem(nb); + } } else { if (connectTmpToBus(match_bus)) { emitActionEvent(BlockItemBase::BusAdd, QList() << match_bus); @@ -532,8 +549,7 @@ bool BlockView::eventFilter(QObject * o, QEvent * e) { } } unmarkPins(); - tmp_bus.hide(); - tmp_bus.clear(); + hideTmpBuses(); reconnectAll(); } clearBusStates(); @@ -644,6 +660,13 @@ void BlockView::mouseMoveEvent(QMouseEvent * event) { void BlockView::keyPressEvent(QKeyEvent * e) { + BlockItemPin * pin = getPin(items(mapFromGlobal(QCursor::pos()))); + if (pin) { + //qDebug() << "pin" << pin->state(); + if (pin->state() == BlockItemPin::Hover) { + highlightNearPins(pin, e->modifiers()); + } + } if (e->key() == Qt::Key_Shift) { if (tmp_bus.isVisible()) { switch (wavetrace.preferredDirection()) { @@ -652,13 +675,31 @@ void BlockView::keyPressEvent(QKeyEvent * e) { case BlockViewWavetrace::Vertical: wavetrace.setPreferredDirection(BlockViewWavetrace::NoTrace); break; } trace(last_trace_from, trace_to, &tmp_bus); + for (int i = 0; i < qMin(tmp_buses.size(), last_multiconnect_pl.size()); ++i) { + QPointF dp = last_multiconnect_pl[i]->scenePos() - last_trace_from; + //qDebug() << "trace" << i << dp; + trace(last_trace_from + dp, trace_to + dp, tmp_buses[i], false); + tmp_buses[i]->show(); + } + return; } - return; } QGraphicsView::keyPressEvent(e); } +void BlockView::keyReleaseEvent(QKeyEvent * e) { + BlockItemPin * pin = getPin(items(mapFromGlobal(QCursor::pos()))); + if (pin) { + //qDebug() << "pin" << pin->state(); + if (pin->state() == BlockItemPin::Hover) { + highlightNearPins(pin, e->modifiers()); + } + } + QGraphicsView::keyReleaseEvent(e); +} + + void BlockView::resizeEvent(QResizeEvent * event) { QGraphicsView::resizeEvent(event); thick = lineThickness(); @@ -897,7 +938,8 @@ QList BlockView::blocks() const { QList BlockView::decors() const { QList ret, gi = scene_->items(); foreach (QGraphicsItem * i, gi) - if ((i->data(1009) == "decor") && !i->data(1008).toBool() && (i->parentItem() == 0) && (i != &sel_rect) && (i != &tmp_bus)) + if ((i->data(1009) == "decor") && !i->data(1008).toBool() && (i->parentItem() == 0) + && (i != &sel_rect) && (i != &tmp_bus) && !tmp_buses.contains((BlockBusItem*)i)) ret << i; return ret; } @@ -1040,7 +1082,7 @@ QRectF BlockView::itemsBoundingRect() const { bool f = true; QRectF ret; foreach (QGraphicsItem * i, gi) - if (i->isVisible() && (i != &tmp_bus)) { + if (i->isVisible() && (i != &tmp_bus) && !tmp_buses.contains((BlockBusItem*)i)) { if ((i->data(1007) != "item_selection") && !i->data(1008).toBool()) { QRectF br = i->mapRectToScene(i->boundingRect()); //qDebug() << br << i; @@ -1117,11 +1159,13 @@ void BlockView::applyGridStep() { } -void BlockView::trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus) { - if (hpin) - scene_pos_to = hpin->scenePos(); - last_trace_from = scene_pos_from; - trace_to = scene_pos_to; +void BlockView::trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus, bool primary) { + if (primary) { + if (hpin) + scene_pos_to = hpin->scenePos(); + last_trace_from = scene_pos_from; + trace_to = scene_pos_to; + } QRect sr = scene_->sceneRect().toRect(); int dx = sr.left() / grid_step, dy = sr.top() / grid_step; //qDebug() << dp; @@ -1433,6 +1477,74 @@ QList BlockView::internalBuses(const QList & item } +QList BlockView::nearPins(BlockItemPin * pin, Qt::KeyboardModifiers km) { + QList ret; + bool up = km.testFlag(Qt::ShiftModifier); + bool down = km.testFlag(Qt::ControlModifier); + bool ab = km.testFlag(Qt::AltModifier); + //qDebug() << "nearPins" << km; + if (!pin || (!up && !down)) return ret; + const BlockItem * src = pin->parent(); + if (!src) return ret; + bool dirs[2] = {up, down}; + double dy[2] = {-1, 1}; + for (int i = 0; i < 2; ++i) { + if (!dirs[i]) continue; + const BlockItem * cb = src; + BlockItemPin * cpin = pin; + //qDebug() << "dir" << dirs[i]; + while (cpin) { + //qDebug() << "cur" << cpin; + QList il = items(mapFromScene(cpin->scenePos() + QPointF(0., dy[i] * cb->pinsMargin()))); + BlockItemPin * np = getPin(il); + if (np == cpin) break; + cpin = np; + if (cpin) { + if (((cb != cpin->parent()) && !ab) || + (cpin->state() != BlockItemPin::Disconnected)) { + break; + } + cb = cpin->parent(); + ret << cpin; + } + } + } + return ret; +} + + +BlockItemPin * BlockView::getPin(const QList & list) const { + foreach (QGraphicsItem * i, list) { + if (i->data(1004) == "pin") + return qgraphicsitem_cast(i); + } + return 0; +} + + +void BlockView::highlightNearPins(BlockItemPin * pin, Qt::KeyboardModifiers km) { + //qDebug() << "restore for" << last_multiconnect_pl.size(); + foreach (BlockItemPin * p, last_multiconnect_pl) + p->restoreState(); + QList pl = nearPins(pin, km); + foreach (BlockItemPin * p, pl) { + p->saveState(); + p->setState(BlockItemPin::Hover); + } + last_multiconnect_pl = pl; +} + + +void BlockView::hideTmpBuses(bool clear) { + tmp_bus.hide(); + if (clear) { + tmp_bus.clear(); + qDeleteAll(tmp_buses); + tmp_buses.clear(); + } +} + + QList BlockView::selectedBlocks() const { QList ret; QList sil = scene()->selectedItems(); @@ -1519,6 +1631,12 @@ void BlockView::endBusPointMove() { } +void BlockView::pinHoverInOut(BlockItemPin * pin) { + //qDebug() << "pinHoverInOut" << pin << pin->state(); + highlightNearPins(pin, QApplication::keyboardModifiers()); +} + + void BlockView::newBranchTrace(BlockBusItem * item, QPointF to) { trace(item->press_pos, to, &tmp_bus); @@ -1577,8 +1695,7 @@ void BlockView::newBranchCancel() { unmarkPins(); //qDebug() << "cancel"; new_branch = false; - tmp_bus.hide(); - tmp_bus.clear(); + hideTmpBuses(); } @@ -1805,6 +1922,7 @@ void BlockView::removeSelected() { void BlockView::removeAll() { + last_multiconnect_pl.clear(); QList gi = scene_->items(), ai; blockSignals(true); foreach (QGraphicsItem * i, gi) { diff --git a/qad/blockview/blockview.h b/qad/blockview/blockview.h index 9f710ff..03f1c74 100644 --- a/qad/blockview/blockview.h +++ b/qad/blockview/blockview.h @@ -114,6 +114,7 @@ protected: void mousePressEvent(QMouseEvent * event); void mouseMoveEvent(QMouseEvent * event); void keyPressEvent(QKeyEvent * event); + void keyReleaseEvent(QKeyEvent * e); void resizeEvent(QResizeEvent * event); void scrollContentsBy(int dx, int dy); void drawBackground(QPainter * painter, const QRectF & rect); @@ -127,7 +128,7 @@ protected: void restoreBusesState(); void applySelRect(QGraphicsSceneMouseEvent * me); void applyGridStep(); - void trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus); + void trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus, bool primary = true); void clearBusStates(); void matchBus(); bool connectTmpToBus(BlockBusItem* bus); @@ -138,6 +139,10 @@ protected: void simplifyBuses(); void moveBuses(const QList & items, QPointF dp); QList internalBuses(const QList & items); + QList nearPins(BlockItemPin * pin, Qt::KeyboardModifiers km); + BlockItemPin * getPin(const QList & list) const; + void highlightNearPins(BlockItemPin * pin, Qt::KeyboardModifiers km); + void hideTmpBuses(bool clear = true); double _thumb() const {return _talpha;} QRectF _nav() const; void animateNav(QRectF d); @@ -158,7 +163,8 @@ protected: QGraphicsItem * mm_ci; QList sel_items; QList copy_items; - QList copy_buses; + QList last_multiconnect_pl; + QList copy_buses, tmp_buses; BlockBusItem tmp_bus, * match_bus, * bus_from; BlockItemPin * hpin; BlockItem * ghost_; @@ -196,6 +202,7 @@ protected slots: void _navFinished(); void startBusPointMove(int bus_type); void endBusPointMove(); + void pinHoverInOut(BlockItemPin * pin); public slots: void setGridPen(const QPen & pen) {grid_pen = pen; _updateBack();} diff --git a/qad/graphic/graphic.cpp b/qad/graphic/graphic.cpp index 0d2f589..e09db88 100644 --- a/qad/graphic/graphic.cpp +++ b/qad/graphic/graphic.cpp @@ -787,7 +787,7 @@ void Graphic::findGraphicsRect(double start_x, double end_x, double start_y, dou // return; // } // can_fast = false; - vx = DBL_MIN; + vx = -DBL_MAX; minY = minX = DBL_MAX; maxY = maxX = -DBL_MAX; foreach (const GraphicType & t, graphics) {