From ceb2b9bcfd661a8a0efbb99078c4b8fe2d483cbb Mon Sep 17 00:00:00 2001 From: blacksun Date: Wed, 7 Jan 2015 19:21:17 +0000 Subject: [PATCH] Add help line for assist alignement of element git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@3591 bfdf4180-ca20-0410-9c96-a3a8aa849046 --- sources/diagram.cpp | 35 +++++- sources/diagram.h | 4 +- sources/qet.cpp | 31 ++++++ sources/qet.h | 13 ++- sources/qetgraphicsitem/terminal.cpp | 155 ++++++++++++++++++++++++++- sources/qetgraphicsitem/terminal.h | 32 +++--- 6 files changed, 242 insertions(+), 28 deletions(-) diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 394135e39..4d48a70a9 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -930,9 +930,12 @@ void Diagram::invertSelection() { } /** - @return Le rectangle (coordonnees par rapport a la scene) delimitant le bord du schema -*/ -QRectF Diagram::border() const { + * @brief Diagram::border + * @return The rectangle (coordinates relative to the scene) + * delimiting the edge of the diagram + */ +QRectF Diagram::border() const +{ return( QRectF( margin, @@ -943,6 +946,32 @@ QRectF Diagram::border() const { ); } +/** + * @brief Diagram::drawingRect + * @return The rectangle (coordinates relative to the scene) + * delimiting the drawing area of the diagram. + * It's like border without columns, rows, and titleblock + */ +QRectF Diagram::drawingRect() const +{ + QPointF topleft(margin, margin); + QSizeF size; + size.setWidth (border_and_titleblock.columnsTotalWidth()); + size.setHeight(border_and_titleblock.rowsTotalHeight()); + + if (border_and_titleblock.rowsAreDisplayed()) + topleft.rx() += border_and_titleblock.rowsHeaderWidth(); + else + size.rwidth() += border_and_titleblock.rowsHeaderWidth(); + + if (border_and_titleblock.columnsAreDisplayed()) + topleft.ry() += border_and_titleblock.columnsHeaderHeight(); + else + size.rheight() += border_and_titleblock.columnsHeaderHeight(); + + return (QRectF (topleft, size)); +} + /** @return le titre du cartouche */ diff --git a/sources/diagram.h b/sources/diagram.h index 9141a6ee9..40719e7b9 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -169,7 +169,9 @@ class Diagram : public QGraphicsScene bool drawColoredConductors() const; void setDrawColoredConductors(bool); - QRectF border() const; + QRectF border () const; + QRectF drawingRect () const; + QString title() const; bool toPaintDevice(QPaintDevice &, int = -1, int = -1, Qt::AspectRatioMode = Qt::KeepAspectRatio); QSize imageSize() const; diff --git a/sources/qet.cpp b/sources/qet.cpp index b66f832fa..661b3e7d3 100644 --- a/sources/qet.cpp +++ b/sources/qet.cpp @@ -62,6 +62,37 @@ bool Qet::surLeMemeAxe(Qet::Orientation a, Qet::Orientation b) { else return(false); } +/** + * @brief Qet::isOpposed + * @param a + * @param b + * @return true if a and b is opposed, else false; + */ +bool Qet::isOpposed(Qet::Orientation a, Qet::Orientation b) +{ + bool result = false; + + switch (a) + { + case Qet::North: + if (b == Qet::South) result = true; + break; + case Qet::East: + if (b == Qet::West) result = true; + break; + case Qet::South: + if (b == Qet::North) result = true; + break; + case Qet::West: + if (b == Qet::East) result = true; + break; + default: + break; + } + + return result; +} + /** Indique si une orientation de borne est horizontale (Est / Ouest). @param a L'orientation de borne diff --git a/sources/qet.h b/sources/qet.h index f17b252cf..bee7c31fb 100644 --- a/sources/qet.h +++ b/sources/qet.h @@ -180,11 +180,14 @@ class Qet : public QObject { West}; static Qet::Orientation nextOrientation(Qet::Orientation); static Qet::Orientation previousOrientation(Qet::Orientation); - static Qet::Orientation orientationFromString(const QString &); - static QString orientationToString(Qet::Orientation); - static bool surLeMemeAxe(Qet::Orientation, Qet::Orientation); - static bool estHorizontale(Qet::Orientation); - static bool estVerticale(Qet::Orientation); + + static Qet::Orientation orientationFromString (const QString &); + static QString orientationToString (Qet::Orientation); + + static bool surLeMemeAxe (Qet::Orientation, Qet::Orientation); + static bool isOpposed (Qet::Orientation a, Qet::Orientation b); + static bool estHorizontale (Qet::Orientation); + static bool estVerticale (Qet::Orientation); }; #endif diff --git a/sources/qetgraphicsitem/terminal.cpp b/sources/qetgraphicsitem/terminal.cpp index aa7968c9d..64565bd16 100644 --- a/sources/qetgraphicsitem/terminal.cpp +++ b/sources/qetgraphicsitem/terminal.cpp @@ -78,8 +78,10 @@ void Terminal::init(QPointF pf, Qet::Orientation o, QString number, QString name */ Terminal::Terminal(QPointF pf, Qet::Orientation o, Element *e) : QGraphicsItem(e), - parent_element_(e), - hovered_color_(Terminal::neutralColor) + m_draw_help_line(false), + m_help_line (nullptr), + parent_element_ (e), + hovered_color_ (Terminal::neutralColor) { init(pf, o, "_", "_", false); } @@ -94,8 +96,10 @@ Terminal::Terminal(QPointF pf, Qet::Orientation o, Element *e) : */ Terminal::Terminal(qreal pf_x, qreal pf_y, Qet::Orientation o, Element *e) : QGraphicsItem(e), - parent_element_(e), - hovered_color_(Terminal::neutralColor) + m_draw_help_line (false), + m_help_line (nullptr), + parent_element_ (e), + hovered_color_ (Terminal::neutralColor) { init(QPointF(pf_x, pf_y), o, "_", "_", false); } @@ -267,10 +271,91 @@ void Terminal::paint(QPainter *p, const QStyleOptionGraphicsItem *options, QWidg p -> setRenderHint(QPainter::Antialiasing, true); p -> drawEllipse(QRectF(c.x() - 2.5, c.y() - 2.5, 5.0, 5.0)); } else p -> drawPoint(c); + + + //Draw help line if needed, only if there isn't conductor + //docked to this terminal + if (m_draw_help_line && conductors().isEmpty()) + { + if (!m_help_line) + m_help_line = new QGraphicsLineItem(this); + + QLineF line(HelpLine()); + + Terminal *t = alignedWithTerminal(); + if (t) + { + line.setP2(t -> dockConductor()); + m_help_line -> setPen(QPen (Qt::darkGreen)); + } + else + { + m_help_line -> setPen(QPen (Qt::darkBlue)); + } + + //Map the line (in scene coordinate) to help_line coordinate + line.setP1(m_help_line -> mapFromScene(line.p1())); + line.setP2(m_help_line -> mapFromScene(line.p2())); + m_help_line -> setLine(line); + } p -> restore(); } +/** + * @brief Terminal::drawHelpLine + * @param draw : true, display the help line + * false, hide it. + */ +void Terminal::drawHelpLine(bool draw) +{ + if (m_draw_help_line == draw) return; + + m_draw_help_line = draw; + + if (!draw && m_help_line) + { + delete m_help_line; + m_help_line = nullptr; + } + + //update(); +} + +/** + * @brief Terminal::HelpLine + * @return a line with coordinate P1 the dock point of conductor + * and P2 the border of diagram, according to the orientation of terminal + * The line is in scene coordinate; + */ +QLineF Terminal::HelpLine() const +{ + QPointF scene_dock = dockConductor(); + QRectF rect = diagram() -> drawingRect(); + + QLineF line(scene_dock , QPointF()); + + //Set te second point of line to the edge of diagram, + //according with the orientation of this terminal + switch (orientation()) + { + case Qet::North: + line.setP2(QPointF(scene_dock.x(), rect.top())); + break; + case Qet::East: + line.setP2(QPointF(rect.right() , scene_dock.y())); + break; + case Qet::South: + line.setP2(QPointF(scene_dock.x(), rect.bottom())); + break; + case Qet::West: + line.setP2(QPointF(rect.left(), scene_dock.y())); + break; + } + + return line; +} + /** @return Le rectangle (en precision flottante) delimitant la borne et ses alentours. */ @@ -289,6 +374,68 @@ QRectF Terminal::boundingRect() const { return(*br_); } +/** + * @brief Terminal::alignedWithTerminal + * If this terminal is aligned with an other terminal + * and is orientation is opposed return the other terminal + * else return nullptr + * @return + */ +Terminal* Terminal::alignedWithTerminal() const +{ + QLineF line(HelpLine()); + + QPainterPath path; + path.moveTo(line.p1()); + path.lineTo(line.p2()); + + //Get all QGraphicsItem in the alignement of this terminal + QList qgi_list = diagram() -> items(path); + + //Remove all terminals of the parent element + foreach (Terminal *t, parent_element_ -> terminals()) + qgi_list.removeAll(t); + + if (qgi_list.isEmpty()) return nullptr; + + //Get terminals only if orientation is opposed with this terminal + QList available_terminals; + foreach (QGraphicsItem *qgi, qgi_list) + { + if (Terminal *tt = qgraphicsitem_cast (qgi)) + { + //Call QET::lineContainsPoint to be sure the line intersect + //the dock point and not an other part of terminal + if (Qet::isOpposed(orientation(), tt -> orientation()) && + QET::lineContainsPoint(line, tt -> dockConductor())) + { + available_terminals << tt; + } + } + } + + if (available_terminals.isEmpty()) return nullptr; + if (available_terminals.size() == 1) return (available_terminals.first()); + + //Available_terminals have several terminals, we get the nearest terminal + line.setP2(available_terminals.first() -> dockConductor()); + qreal current_lenght = line.length(); + Terminal *nearest_terminal = available_terminals.takeFirst(); + + //Search the nearest terminal to this one + foreach (Terminal *terminal, available_terminals) + { + line.setP2(terminal -> dockConductor()); + if (line.length() < current_lenght) + { + current_lenght = line.length(); + nearest_terminal = terminal; + } + } + + return nearest_terminal; +} + /** Gere l'entree de la souris sur la zone de la Borne. */ diff --git a/sources/qetgraphicsitem/terminal.h b/sources/qetgraphicsitem/terminal.h index 63200afc9..279dd0369 100644 --- a/sources/qetgraphicsitem/terminal.h +++ b/sources/qetgraphicsitem/terminal.h @@ -41,23 +41,22 @@ class Terminal : public QGraphicsItem { // methods public: - /** - Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a - Terminal - @return the QGraphicsItem type - */ - virtual int type() const { return Type; } + //Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a Terminal + //@return the QGraphicsItem type + virtual int type() const { return Type; } - // implementation of QGraphicsItem pure virtual methods - void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); - QRectF boundingRect() const; + void paint (QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + void drawHelpLine (bool draw = true); + QLineF HelpLine () const; + QRectF boundingRect () const; - // methods to manage conductors attached to the terminal - bool addConductor(Conductor *); - void removeConductor(Conductor *); - int conductorsCount() const; - Diagram *diagram() const; - Element *parentElement() const; + // methods to manage conductors attached to the terminal + Terminal* alignedWithTerminal () const; + bool addConductor (Conductor *); + void removeConductor (Conductor *); + int conductorsCount () const; + Diagram *diagram () const; + Element *parentElement () const; QList conductors() const; Qet::Orientation orientation() const; @@ -101,6 +100,9 @@ class Terminal : public QGraphicsItem { static QColor forbiddenColor; private: + bool m_draw_help_line; + QGraphicsLineItem *m_help_line; + /// Parent electrical element Element *parent_element_; /// docking point for conductors