From 7e5d41b4743f24d20a13287f2da892fe0b475f4e Mon Sep 17 00:00:00 2001 From: joshua Date: Tue, 14 Oct 2025 22:12:38 +0200 Subject: [PATCH] Terminal strip Xref is clickable When user hover the Xref string of a terminal, the string color change to blue to advise user the xref is clickable. Double click on the blue Xref go the folio of the terminal and zoom the view to the terminal. --- .../GraphicsItem/terminalstripdrawer.cpp | 71 +++++++++++++++++-- .../GraphicsItem/terminalstripdrawer.h | 20 ++++++ .../GraphicsItem/terminalstripitem.cpp | 48 ++++++++++++- .../GraphicsItem/terminalstripitem.h | 3 +- sources/TerminalStrip/physicalterminal.cpp | 14 ++++ sources/TerminalStrip/physicalterminal.h | 1 + sources/qetgraphicsitem/qetgraphicsitem.cpp | 32 ++++++++- sources/qetgraphicsitem/qetgraphicsitem.h | 6 ++ 8 files changed, 186 insertions(+), 9 deletions(-) diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index f71542c3d..f805ef7c1 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -45,6 +45,7 @@ void TerminalStripDrawer::paint(QPainter *painter) { if (m_strip && m_pattern) { + m_united_xref_text_rect = QRectF(); //To draw text, QPainter need a Qrect. Instead of create an instance //for each text, we re-use the same instance of QRect. QRect text_rect; @@ -91,11 +92,10 @@ void TerminalStripDrawer::paint(QPainter *painter) const auto text_{m_strip->installation() + " " + m_strip->location() + " " + m_strip->name()}; painter->drawText(text_rect, text_, m_pattern->headerTextOption()); - painter->restore(); + painter->restore(); //Move painter pos to next drawing painter->translate(m_pattern->m_header_rect.width(),0); - qreal x_offset{m_pattern->m_header_rect.width()}; //Draw spacer @@ -120,6 +120,8 @@ void TerminalStripDrawer::paint(QPainter *painter) QHash> bridges_anchor_points; + m_hovered_xref = hoverTerminal{}; + int physical_index = 0; //Loop over physical terminals for (const auto &physical_t : m_strip->physicalTerminal()) { @@ -190,15 +192,40 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->restore(); //Draw xref - auto xref_string = shared_real_terminal->xref(); - painter->save(); xref_rect.setRect(0, xref_text_y, terminal_rect.width(), xref_text_height); + painter->save(); if (xref_text_orientation == Qt::Vertical) { painter->translate(xref_rect.bottomLeft()); painter->rotate(270); xref_rect.setRect(0, 0, xref_rect.height(), xref_rect.width()); } + + QTransform transform; + transform.translate(x_offset, 0); + + if (xref_text_orientation == Qt::Vertical) + { + transform.translate(0, xref_text_y + xref_text_height); + transform.rotate(270); + } + + auto xref_string = shared_real_terminal->xref(); + + const auto mapped_xref_text_rect = transform.mapRect(painter->boundingRect(xref_rect, xref_string, xref_text_option)); + if (m_united_xref_text_rect.isNull()) { + m_united_xref_text_rect = mapped_xref_text_rect; + } else { + m_united_xref_text_rect = m_united_xref_text_rect.united(mapped_xref_text_rect); + } + + //if mouse hover the xref text, draw it in blue to advise user the xref is clickable. + if (!m_mouse_hover_pos.isNull() && mapped_xref_text_rect.contains(m_mouse_hover_pos)) { + painter->setPen(Qt::blue); + m_hovered_xref.physical = physical_index; + m_hovered_xref.real = i; + } + painter->drawText(xref_rect, xref_string, xref_text_option); if (m_preview_draw) @@ -234,6 +261,7 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->translate(terminal_rect.width(),0); x_offset += terminal_rect.width(); } + physical_index++; } painter->restore(); @@ -269,6 +297,41 @@ void TerminalStripDrawer::setPreviewDraw(bool draw) { m_preview_draw = draw; } +void TerminalStripDrawer::setMouseHoverPos(const QPointF &pos) +{ + m_last_mouse_pos_in_xrefs_rect = m_united_xref_text_rect.contains(m_mouse_hover_pos); + m_mouse_hover_pos = pos; +} + +/** + * @brief TerminalStripDrawer::mouseHoverXref + * @return True if the mouse position (given through the function setMouseHoverPos) + * hover the rect of a xref. + */ +bool TerminalStripDrawer::mouseHoverXref() const { + return m_united_xref_text_rect.contains(m_mouse_hover_pos); +} + +bool TerminalStripDrawer::needUpdate() +{ + if (mouseHoverXref()) { + return true; + } else if (m_last_mouse_pos_in_xrefs_rect) { + return true; + } + return false; +} + +/** + * @brief TerminalStripDrawer::hoveredXref + * @return the current terminal hovered by the mouse + * in the xref bounding rectangle + */ +hoverTerminal TerminalStripDrawer::hoveredXref() const +{ + return m_hovered_xref; +} + qreal TerminalStripDrawer::height() const { if (m_pattern) diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h index 8fa5fd8e1..363bc2cdf 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h @@ -27,6 +27,17 @@ class TerminalStrip; namespace TerminalStripDrawer { + /** + * @brief The hoverTerminal struct + * Just a little struct use to know what is the physical and real terminal + * when the mouse hover the Xref string of a terminal. + * If mouse don't hover a Xref the value is set to -1; + */ + struct hoverTerminal{ + int physical{-1}; + int real{-1}; + }; + class AbstractBridgeInterface { public: @@ -80,6 +91,11 @@ namespace TerminalStripDrawer void setPreviewDraw(bool draw = true); + void setMouseHoverPos(const QPointF &pos); + bool mouseHoverXref() const; + bool needUpdate(); + hoverTerminal hoveredXref() const; + private: qreal height() const; qreal width() const; @@ -88,6 +104,10 @@ namespace TerminalStripDrawer QSharedPointer m_strip; QSharedPointer m_pattern; bool m_preview_draw { false }; + QPointF m_mouse_hover_pos; + QRectF m_united_xref_text_rect; + bool m_last_mouse_pos_in_xrefs_rect{false}; + hoverTerminal m_hovered_xref; }; } diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp index 77f28adee..ad9634b4d 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp @@ -22,6 +22,8 @@ #include "../../project/projectpropertieshandler.h" #include "../../qetgraphicsitem/qgraphicsitemutility.h" #include "../terminalstrip.h" +#include "../physicalterminal.h" +#include "../realterminal.h" #include "../ui/terminalstripeditorwindow.h" #include "trueterminalstrip.h" @@ -94,13 +96,53 @@ QString TerminalStripItem::name() const { return tr("plan de bornes"); } +void TerminalStripItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + QetGraphicsItem::hoverMoveEvent(event); + m_drawer.setMouseHoverPos(hoverMousePos()); + if (m_drawer.needUpdate()) { + update(); + } +} + +void TerminalStripItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + QetGraphicsItem::hoverLeaveEvent(event); + m_drawer.setMouseHoverPos(QPointF{}); +} + void TerminalStripItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED (event); - if (m_strip) { - TerminalStripEditorWindow::edit(m_strip); - } + const auto hovered = m_drawer.hoveredXref(); + + if (m_strip) { + if (hovered.physical >= 0 && + hovered.real >= 0) + { + if (const auto physical_terminal = m_strip->physicalTerminal(hovered.physical); + !physical_terminal.isNull()) + { + if (const auto real_terminal = physical_terminal->realTerminal(hovered.real); + !real_terminal.isNull() && + real_terminal->isElement()) + { + if (QPointer element = real_terminal->element(); + !element.isNull()) + { + //Unselect and ungrab mouse to prevent unwanted + //move when element is in the same scene of this. + setSelected(false); + ungrabMouse(); + QetGraphicsItem::showItem(element); + } + } + } + } else { + TerminalStripEditorWindow::edit(m_strip); + } + } } void TerminalStripItem::refreshPending() diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h index b26a6dd8b..f69e8595b 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h @@ -46,6 +46,8 @@ class TerminalStripItem : public QetGraphicsItem QRectF boundingRect() const override; QString name() const override; + void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override; + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; void refreshPending(); void setLayout(QSharedPointer layout); @@ -57,7 +59,6 @@ class TerminalStripItem : public QetGraphicsItem QPointer m_strip; TerminalStripDrawer::TerminalStripDrawer m_drawer; QUuid m_pending_strip_uuid; - }; #endif // TERMINALSTRIPITEM_H diff --git a/sources/TerminalStrip/physicalterminal.cpp b/sources/TerminalStrip/physicalterminal.cpp index 99165a20f..86eefb945 100644 --- a/sources/TerminalStrip/physicalterminal.cpp +++ b/sources/TerminalStrip/physicalterminal.cpp @@ -189,6 +189,20 @@ QVector> PhysicalTerminal::realTerminals() const { return m_real_terminal; } +/** + * @brief PhysicalTerminal::realTerminal + * @param pos + * @return the real terminal at position pos. + * Note that the returned QSharedPointer can be null + */ +QSharedPointer PhysicalTerminal::realTerminal(int pos) const +{ + if (pos < m_real_terminal.size()) { + return m_real_terminal.at(pos); + } + else return QSharedPointer{}; +} + /** * @brief uuid * @return the uuid of this physical terminal diff --git a/sources/TerminalStrip/physicalterminal.h b/sources/TerminalStrip/physicalterminal.h index 7d90ff681..4cb78e059 100644 --- a/sources/TerminalStrip/physicalterminal.h +++ b/sources/TerminalStrip/physicalterminal.h @@ -86,6 +86,7 @@ class PhysicalTerminal int levelCount() const; int levelOf(const QSharedPointer &terminal) const; QVector> realTerminals() const; + QSharedPointer realTerminal(int pos) const; QUuid uuid() const; int pos() const; int realTerminalCount() const; diff --git a/sources/qetgraphicsitem/qetgraphicsitem.cpp b/sources/qetgraphicsitem/qetgraphicsitem.cpp index fc1acc385..873a79fba 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.cpp +++ b/sources/qetgraphicsitem/qetgraphicsitem.cpp @@ -24,12 +24,31 @@ Default constructor @param parent : Parent Item */ +void QetGraphicsItem::showItem(QetGraphicsItem *item) +{ + if (item && item->diagram()) + { + item->diagram()->showMe(); + item->setSelected(true); + + //Zoom to the item + for(QGraphicsView *view : item->scene()->views()) + { + QRectF fit = item->sceneBoundingRect(); + fit.adjust(-200, -200, 200, 200); + view->fitInView(fit, Qt::KeepAspectRatioByExpanding); + } + } +} + QetGraphicsItem::QetGraphicsItem(QGraphicsItem *parent): QGraphicsObject(parent), is_movable_(true), m_first_move(true), snap_to_grid_(true) -{} +{ + setAcceptHoverEvents(true); +} QetGraphicsItem::~QetGraphicsItem() {} @@ -68,6 +87,11 @@ bool QetGraphicsItem::isHovered() const { return m_hovered; } +QPointF QetGraphicsItem::hoverMousePos() const +{ + return m_mouse_hover_pos; +} + /** @brief QetGraphicsItem::state @return the current state of this item @@ -166,6 +190,12 @@ void QetGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) QGraphicsObject::hoverEnterEvent(event); } +void QetGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + QGraphicsObject::hoverMoveEvent(event); + m_mouse_hover_pos = event->pos(); +} + void QetGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { m_hovered = false; diff --git a/sources/qetgraphicsitem/qetgraphicsitem.h b/sources/qetgraphicsitem/qetgraphicsitem.h index e6459403b..11a967a35 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.h +++ b/sources/qetgraphicsitem/qetgraphicsitem.h @@ -28,6 +28,9 @@ class QetGraphicsItem : public QGraphicsObject { Q_OBJECT + public : + static void showItem (QetGraphicsItem *item); + public: //constructor destructor QetGraphicsItem(QGraphicsItem *parent = nullptr); @@ -43,6 +46,7 @@ class QetGraphicsItem : public QGraphicsObject virtual void setMovable (bool movable) { is_movable_ = movable;} bool isHovered() const; + QPointF hoverMousePos() const; virtual void editProperty () {} virtual QString name ()const @@ -57,6 +61,7 @@ class QetGraphicsItem : public QGraphicsObject void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; + void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; protected: @@ -68,6 +73,7 @@ class QetGraphicsItem : public QGraphicsObject private: bool m_hovered{false}; + QPointF m_mouse_hover_pos; };