diff --git a/dev_doc/enum_type_of_QGraphicsItem b/dev_doc/enum_type_of_QGraphicsItem index 1dd7d02d7..67853f9e9 100644 --- a/dev_doc/enum_type_of_QGraphicsItem +++ b/dev_doc/enum_type_of_QGraphicsItem @@ -21,6 +21,3 @@ part terminal + 1106 part text + 1107 part text field + 1108 part rectangle + 1109 - -###QetGraphicsHandlerItem### -QetGraphicsHandlerItem = 1200 diff --git a/sources/QetGraphicsItemModeler/QetGraphicsItemModeler.pri b/sources/QetGraphicsItemModeler/QetGraphicsItemModeler.pri index ab89d8a6f..3e783a8be 100755 --- a/sources/QetGraphicsItemModeler/QetGraphicsItemModeler.pri +++ b/sources/QetGraphicsItemModeler/QetGraphicsItemModeler.pri @@ -1,5 +1,7 @@ HEADERS += \ - $$PWD/qetgraphicshandlerutility.h + $$PWD/qetgraphicshandlerutility.h \ + $$PWD/qetgraphicshandleritem.h SOURCES += \ - $$PWD/qetgraphicshandlerutility.cpp + $$PWD/qetgraphicshandlerutility.cpp \ + $$PWD/qetgraphicshandleritem.cpp diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.cpp b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.cpp new file mode 100644 index 000000000..e2be2e651 --- /dev/null +++ b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.cpp @@ -0,0 +1,99 @@ +/* + Copyright 2006-2017 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "qetgraphicshandleritem.h" +#include +#include + +/** + * @brief QetGraphicsHandlerItem::QetGraphicsHandlerItem + * @param size, the size of the handler + */ +QetGraphicsHandlerItem::QetGraphicsHandlerItem(qreal size) : + m_size(size) +{} + +/** + * @brief QetGraphicsHandlerItem::boundingRect + * @return + */ +QRectF QetGraphicsHandlerItem::boundingRect() const +{ + qreal rect_size = m_size * m_previous_zoom_factor; + QRectF rect(0-rect_size/2, 0-rect_size/2, rect_size, rect_size); + rect.adjust(-2, -2, 2, 2); + return rect; +} + +/** + * @brief QetGraphicsHandlerItem::setColor + * @param color, set the color of the handler + */ +void QetGraphicsHandlerItem::setColor(QColor color) +{ + m_color = color; + update(); +} + +/** + * @brief QetGraphicsHandlerItem::paint + * @param painter + * @param option + * @param widget + */ +void QetGraphicsHandlerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + qreal zoom_factor = 1.0/painter->transform().m11(); + if(zoom_factor != m_previous_zoom_factor) + { + prepareGeometryChange(); + m_previous_zoom_factor = zoom_factor; + } + + qreal rect_size = m_size * m_previous_zoom_factor; + QRectF rect(0-rect_size/2, 0-rect_size/2, rect_size, rect_size); + + painter->save(); + painter->setBrush(QBrush(m_color)); + QPen pen(QBrush(m_color), 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); + pen.setCosmetic(true); + painter->setPen(pen); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->drawEllipse(rect); + painter->restore(); +} + +/** + * @brief QetGraphicsHandlerItem::handlerForPoint + * @param points + * @return A list of handler with pos at point + */ +QVector QetGraphicsHandlerItem::handlerForPoint(const QVector &points, int size) +{ + QVector list_; + for (QPointF point : points) + { + QetGraphicsHandlerItem *qghi = new QetGraphicsHandlerItem(size); + qghi->setPos(point); + list_ << qghi; + } + + return list_; +} diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h new file mode 100644 index 000000000..9cf6646ce --- /dev/null +++ b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h @@ -0,0 +1,53 @@ +/* + Copyright 2006-2017 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef QETGRAPHICSHANDLERITEM_H +#define QETGRAPHICSHANDLERITEM_H + +#include + +/** + * @brief The QetGraphicsHandlerItem class + * This graphics item represents a point, destined to be used as an handler, + * for modifie the geometrie of a another graphics item (like shapes). + * The graphics item to be modified, must call "installSceneEventFilter" of this item with itself for argument,. + * The ghraphics item to be modified, need to reimplement "sceneEventFilter" for create the modification behavior. + */ +class QetGraphicsHandlerItem : public QGraphicsItem +{ + public: + QetGraphicsHandlerItem(qreal size = 15); + virtual QRectF boundingRect() const; + + enum { Type = UserType + 1200}; + virtual int type() const {return Type;} + + void setColor(QColor color); + + protected: + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + private: + qreal m_size, + m_previous_zoom_factor = 1; + QColor m_color; + + public: + static QVector handlerForPoint(const QVector &points, int size = 15); +}; + +#endif // QETGRAPHICSHANDLERITEM_H diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp index 656218016..23d8d940c 100644 --- a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp +++ b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp @@ -16,111 +16,10 @@ along with QElectroTech. If not, see . */ #include "qetgraphicshandlerutility.h" -#include +//#include +//#include +#include -/** - * @brief QetGraphicsHandlerUtility::QetGraphicsHandlerUtility - * Constructor - * @param size : the size of the handler - */ -QetGraphicsHandlerUtility::QetGraphicsHandlerUtility(qreal size) : - m_size (size) -{} - -/** - * @brief QetGraphicsHandlerUtility::drawHandler - * Draw the handler at pos @point, using the QPainter @painter. - * @param painter : painter to use for drawing the handler - * @param point : point to draw the handler - */ -void QetGraphicsHandlerUtility::drawHandler(QPainter *painter, const QPointF &point) -{ - //Setup the zoom factor to draw the handler in the same size at screen, - //no matter the zoom of the QPainter - m_zoom_factor = 1.0/painter->transform().m11(); - - painter->save(); - painter->setBrush(QBrush(m_inner_color)); - QPen square_pen(QBrush(m_outer_color), 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); - square_pen.setCosmetic(true); - painter->setPen(square_pen); - painter->drawRect(getRect(point)); - painter->restore(); -} - -/** - * @brief QetGraphicsHandlerUtility::drawHandler - * Conveniance method for void QetGraphicsHandlerUtility::drawHandler(QPainter *painter, const QPointF &point) - * @param painter - * @param points - * @param color2 - */ -void QetGraphicsHandlerUtility::drawHandler(QPainter *painter, const QVector &points) { - foreach(QPointF point, points) - drawHandler(painter, point); -} - -/** - * @brief QetGraphicsHandlerUtility::pointIsInHandler - * @param point : point to compare - * @param key_point : point at the center of handler (the point to modify, for exemple the corner of a rectangle) - * @return true if point is in a handler. else false - */ -bool QetGraphicsHandlerUtility::pointIsInHandler(const QPointF &point, const QPointF &key_point) const { - return (getRect(key_point).contains(point)); -} - -/** - * @brief QetGraphicsHandlerUtility::pointIsHoverHandler - * @param point : point to compare - * @param vector : vector of key_point (the point to modify, for exemple the corners of a rectangle) - * @return if point is hover an handler, return the index of the hovered key_point in the vector, else return -1 - */ -int QetGraphicsHandlerUtility::pointIsHoverHandler(const QPointF &point, const QVector &vector) const -{ - foreach (QPointF key_point, vector) - if (pointIsInHandler(point, key_point)) - return vector.indexOf(key_point); - - return -1; -} - -/** - * @brief QetGraphicsHandlerUtility::handlerRect - * Return the rect of the handler for all key_point in vector (the point to modify, for exemple the corners of a rectangle) - * The order of rect in the returned vector is the same as the given vector. - * @param vector - * @return - */ -QVector QetGraphicsHandlerUtility::handlerRect(const QVector &vector) const -{ - QVector rect_vector; - - foreach(QPointF point, vector) - rect_vector << getRect(point); - - return rect_vector; -} - -void QetGraphicsHandlerUtility::setInnerColor(QColor color) { - m_inner_color = color; -} - -void QetGraphicsHandlerUtility::setOuterColor(QColor color) { - m_outer_color = color; -} - -/** - * @brief QetGraphicsHandlerUtility::getRect - * @param point - * @return - */ -QRectF QetGraphicsHandlerUtility::getRect(const QPointF &point) const -{ - qreal rect_size = m_size * m_zoom_factor; - QRectF rect(point.x() - rect_size/2, point.y() - rect_size/2, rect_size, rect_size); - return rect; -} /** * @brief QetGraphicsHandlerUtility::pointsForRect @@ -169,7 +68,6 @@ QVector QetGraphicsHandlerUtility::pointsForLine(const QLineF &line) { return (QVector {line.p1(), line.p2()}); } -#include /** * @brief QetGraphicsHandlerUtility::pointsForArc * Return the points for the given arc. diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h index a550b9078..14e8e4b26 100644 --- a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h +++ b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h @@ -32,25 +32,6 @@ class QPainter; */ class QetGraphicsHandlerUtility { - public: - QetGraphicsHandlerUtility (qreal size = 1); - void setSize(qreal size) {m_size = size;} - void drawHandler (QPainter *painter, const QPointF & point); - void drawHandler(QPainter *painter, const QVector &points); - QPointF posForHandler(const QPointF &point) const; - bool pointIsInHandler (const QPointF &point, const QPointF &key_point) const; - int pointIsHoverHandler (const QPointF &point, const QVector &vector) const; - QVector handlerRect (const QVector &vector) const; - void setInnerColor (QColor color); - void setOuterColor (QColor color); - - private: - QRectF getRect (const QPointF &point) const; - qreal m_size; - qreal m_zoom_factor = 1; - QColor m_inner_color = Qt::white, - m_outer_color = Qt::blue; - public: static QVector pointsForRect (const QRectF &rect); static QVector pointsForLine (const QLineF &line); diff --git a/sources/conductorproperties.cpp b/sources/conductorproperties.cpp index a42217f2e..c3a4013c8 100644 --- a/sources/conductorproperties.cpp +++ b/sources/conductorproperties.cpp @@ -250,6 +250,10 @@ void ConductorProperties::toXml(QDomElement &e) const if (color != QColor(Qt::black)) e.setAttribute("color", color.name()); + e.setAttribute("bicolor", m_bicolor? "true" : "false"); + e.setAttribute("color2", m_color_2.name()); + e.setAttribute("dash-size", QString::number(m_dash_size)); + if (type == Single) singleLineProperties.toXml(e); @@ -281,6 +285,14 @@ void ConductorProperties::fromXml(QDomElement &e) QColor xml_color= QColor(e.attribute("color")); color = (xml_color.isValid()? xml_color : QColor(Qt::black)); + QString bicolor_str = e.attribute("bicolor", "false"); + m_bicolor = bicolor_str == "true"? true : false; + + QColor xml_color_2 = QColor(e.attribute("color2")); + m_color_2 = xml_color_2.isValid()? xml_color_2 : QColor(Qt::black); + + m_dash_size = e.attribute("dash-size", QString::number(1)).toInt(); + // read style of conductor readStyle(e.attribute("style")); @@ -317,6 +329,9 @@ void ConductorProperties::fromXml(QDomElement &e) void ConductorProperties::toSettings(QSettings &settings, const QString &prefix) const { settings.setValue(prefix + "color", color.name()); + settings.setValue(prefix + "bicolor", m_bicolor); + settings.setValue(prefix + "color2", m_color_2.name()); + settings.setValue(prefix + "dash-size", m_dash_size); settings.setValue(prefix + "style", writeStyle()); settings.setValue(prefix + "type", typeToString(type)); settings.setValue(prefix + "text", text); @@ -341,6 +356,12 @@ void ConductorProperties::fromSettings(QSettings &settings, const QString &prefi QColor settings_color = QColor(settings.value(prefix + "color").toString()); color = (settings_color.isValid()? settings_color : QColor(Qt::black)); + QColor settings_color_2 = QColor(settings.value(prefix + "color2").toString()); + m_color_2 = (settings_color_2.isValid()? settings_color_2 : QColor(Qt::black)); + + m_bicolor = settings.value(prefix + "bicolor", false).toBool(); + m_dash_size = settings.value(prefix + "dash-size", 1).toInt(); + QString setting_type = settings.value(prefix + "type", typeToString(Multi)).toString(); type = (setting_type == typeToString(Single)? Single : Multi); @@ -388,13 +409,18 @@ void ConductorProperties::setText(QString text) { */ void ConductorProperties::applyForEqualAttributes(QList list) { - if (list.isEmpty()) + const QList clist = list; + + if (clist.isEmpty()) return; - if (list.size() == 1) + if (clist.size() == 1) { - ConductorProperties cp = list.first(); + ConductorProperties cp = clist.first(); color = cp.color; + m_bicolor = cp.m_bicolor; + m_color_2 = cp.m_color_2; + m_dash_size = cp.m_dash_size; text = cp.text; m_formula = cp.m_formula; m_function = cp.m_function; @@ -410,9 +436,15 @@ void ConductorProperties::applyForEqualAttributes(QList lis } bool equal = true; + QColor c_value; + bool b_value; + QString s_value; + int i_value; + double d_value; + //Color - QColor c_value = list.first().color; - foreach(ConductorProperties cp, list) + c_value = clist.first().color; + for(ConductorProperties cp : clist) { if (cp.color != c_value) equal = false; @@ -420,10 +452,43 @@ void ConductorProperties::applyForEqualAttributes(QList lis if (equal) color = c_value; equal = true; + + //bicolor + b_value = clist.first().m_bicolor; + for(ConductorProperties cp : clist) + { + if (cp.m_bicolor != b_value) + equal = false; + } + if (equal) + m_bicolor = b_value; + equal = true; + + //second color + c_value = clist.first().m_color_2; + for(ConductorProperties cp : clist) + { + if (cp.m_color_2 != c_value) + equal = false; + } + if (equal) + m_color_2 = c_value; + equal = true; + + //Dash size + i_value = clist.first().m_dash_size; + for(ConductorProperties cp : clist) + { + if (cp.m_dash_size != i_value) + equal = false; + } + if (equal) + m_dash_size = i_value; + equal = true; //text - QString s_value = list.first().text; - foreach(ConductorProperties cp, list) + s_value = clist.first().text; + for(ConductorProperties cp : clist) { if (cp.text != s_value) equal = false; @@ -433,8 +498,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //formula - s_value = list.first().m_formula; - foreach(ConductorProperties cp, list) + s_value = clist.first().m_formula; + for(ConductorProperties cp : clist) { if (cp.m_formula != s_value) equal = false; @@ -444,8 +509,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //function - s_value = list.first().m_function; - foreach(ConductorProperties cp, list) + s_value = clist.first().m_function; + for(ConductorProperties cp : clist) { if (cp.m_function != s_value) equal = false; @@ -455,8 +520,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //Tension protocol - s_value = list.first().m_tension_protocol; - foreach(ConductorProperties cp, list) + s_value = clist.first().m_tension_protocol; + for(ConductorProperties cp : clist) { if (cp.m_tension_protocol != s_value) equal = false; @@ -466,8 +531,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //text size - int i_value = list.first().text_size; - foreach(ConductorProperties cp, list) + i_value = clist.first().text_size; + for(ConductorProperties cp : clist) { if (cp.text_size != i_value) equal = false; @@ -477,8 +542,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //conductor size - double d_value = list.first().cond_size; - foreach(ConductorProperties cp, list) + d_value = clist.first().cond_size; + for(ConductorProperties cp : clist) { if (cp.cond_size != d_value) equal = false; @@ -488,8 +553,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //show text - bool b_value = list.first().m_show_text; - foreach(ConductorProperties cp, list) + b_value = clist.first().m_show_text; + for(ConductorProperties cp : clist) { if (cp.m_show_text != b_value) equal = false; @@ -499,8 +564,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //One text per folio - b_value = list.first().m_one_text_per_folio; - foreach(ConductorProperties cp, list) + b_value = clist.first().m_one_text_per_folio; + for(ConductorProperties cp : clist) { if (cp.m_one_text_per_folio != b_value) equal = false; @@ -510,8 +575,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //Text rotation for vertical conducor - d_value = list.first().verti_rotate_text; - foreach(ConductorProperties cp, list) + d_value = clist.first().verti_rotate_text; + for(ConductorProperties cp : clist) { if (cp.verti_rotate_text != d_value) equal = false; @@ -521,8 +586,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis equal = true; //Text rotation for horizontal conducor - d_value = list.first().horiz_rotate_text; - foreach(ConductorProperties cp, list) + d_value = clist.first().horiz_rotate_text; + for(ConductorProperties cp : clist) { if (cp.horiz_rotate_text != d_value) equal = false; @@ -556,6 +621,9 @@ bool ConductorProperties::operator==(const ConductorProperties &other) const return( other.type == type &&\ other.color == color &&\ + other.m_bicolor == m_bicolor &&\ + other.m_color_2 == m_color_2 &&\ + other.m_dash_size == m_dash_size &&\ other.style == style &&\ other.text == text &&\ other.m_formula == m_formula &&\ diff --git a/sources/conductorproperties.h b/sources/conductorproperties.h index c5cb1f549..db5cdd829 100644 --- a/sources/conductorproperties.h +++ b/sources/conductorproperties.h @@ -77,18 +77,28 @@ class ConductorProperties //Attributes ConductorType type; - QColor color; + + QColor color, + m_color_2; + QString text, m_function, m_tension_protocol, m_formula; - int text_size; - double cond_size; - double verti_rotate_text; - double horiz_rotate_text; - bool m_show_text; - bool m_one_text_per_folio; + + int text_size, + m_dash_size = 1; + + double cond_size, + verti_rotate_text, + horiz_rotate_text; + + bool m_show_text, + m_one_text_per_folio, + m_bicolor = false; + Qt::PenStyle style; + SingleLineProperties singleLineProperties; // methods diff --git a/sources/diagram.cpp b/sources/diagram.cpp index be3995dc6..17a83e934 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -91,30 +91,31 @@ Diagram::Diagram(QETProject *project) : * @brief Diagram::~Diagram * Destructor */ -Diagram::~Diagram() -{ - //First clear every selection to close an hypothetical editor - clearSelection(); - // clear undo stack to prevent errors, because contains pointers to this diagram and is elements. +Diagram::~Diagram() { + // clear undo stack to prevent errors, because contains pointers to this diagram and is elements. undoStack().clear(); - //delete of QGIManager, every elements he knows are removed + //delete of QGIManager, every elements he knows are removed delete qgi_manager_; - // remove of conductor setter + // remove of conductor setter delete conductor_setter_; - // delete of object for manage movement + // delete of object for manage movement delete elements_mover_; delete element_texts_mover_; - if (m_event_interface) - delete m_event_interface; + if (m_event_interface) delete m_event_interface; - // list removable items + // list removable items QList deletable_items; for(QGraphicsItem *qgi : items()) - { - if (qgi -> parentItem()) continue; - if (qgraphicsitem_cast(qgi)) continue; + { + if (qgi->parentItem()) + continue; + if (qgi->type() == Conductor::Type) + continue; + if (qgi->type() == QetGraphicsHandlerItem::Type) + continue; + deletable_items << qgi; } @@ -377,6 +378,8 @@ void Diagram::keyReleaseEvent(QKeyEvent *e) * Diagram become the ownership of event_interface * If there is a previous interface, they will be delete before * and call init() to the new interface. + * The derivated class of DiagramEventInterface need to emit the signal "finish" when the job is done, + * diagram use this signal to delete the interface. If the signal isn't send, the interface will never be deleted. * @param event_interface */ void Diagram::setEventInterface(DiagramEventInterface *event_interface) diff --git a/sources/editor/elementprimitivedecorator.cpp b/sources/editor/elementprimitivedecorator.cpp index 594508d85..80a2bbace 100644 --- a/sources/editor/elementprimitivedecorator.cpp +++ b/sources/editor/elementprimitivedecorator.cpp @@ -24,23 +24,24 @@ #include #include #include +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" /** Constructor @param parent Parent QGraphicsItem */ ElementPrimitiveDecorator::ElementPrimitiveDecorator(QGraphicsItem *parent): - QGraphicsObject(parent), - m_handler(10) + QGraphicsObject(parent) { init(); - m_handler.setOuterColor(Qt::darkGreen); } /** Destructor */ -ElementPrimitiveDecorator::~ElementPrimitiveDecorator() { +ElementPrimitiveDecorator::~ElementPrimitiveDecorator() +{ + removeHandler(); } /** @@ -68,12 +69,7 @@ QRectF ElementPrimitiveDecorator::internalBoundingRect() const { */ QRectF ElementPrimitiveDecorator::boundingRect() const { - QVector rect_vector = m_handler.handlerRect(getResizingsPoints()); - - QRectF rect = effective_bounding_rect_; - rect |= rect_vector.first(); - rect |= rect_vector.last(); - return(rect); + return effective_bounding_rect_; } /** @@ -96,9 +92,6 @@ void ElementPrimitiveDecorator::paint(QPainter *painter, const QStyleOptionGraph pen.setCosmetic(true); painter -> setPen(pen); painter -> drawRect(modified_bounding_rect_); - - //Draw the handlers - m_handler.drawHandler(painter, getResizingsPoints()); // uncomment to draw the real bouding rect (=adjusted internal bounding rect) // painter -> setBrush(QBrush(QColor(240, 0, 0, 127))); @@ -109,45 +102,28 @@ void ElementPrimitiveDecorator::paint(QPainter *painter, const QStyleOptionGraph /** @param items the new list of items this decorator is suposed to manipulate. */ -void ElementPrimitiveDecorator::setItems(const QList &items) { - if (CustomElementPart *single_item = singleItem()) { - if (items.count() == 1 && items.first() == single_item) { - // no actual change - goto end_setItems; - } - - // break any connection between the former single selected item (if any) and - // the decorator - single_item -> setDecorator(0); - if (QGraphicsObject *single_object = dynamic_cast(single_item)) { - disconnect(single_object, 0, this, 0); - } - } - +void ElementPrimitiveDecorator::setItems(const QList &items) +{ decorated_items_ = items; - - // when only a single primitive is selected, the decorator behaves specially - // to enable extra features, such as text edition, internal points movements, - // etc. - if (CustomElementPart *single_item = singleItem()) { - single_item -> setDecorator(this); - } - - end_setItems: + adjust(); show(); if (focusItem() != this) { setFocus(); } + adjusteHandlerPos(); } /** @param items the new list of items this decorator is suposed to manipulate. */ -void ElementPrimitiveDecorator::setItems(const QList &items) { +void ElementPrimitiveDecorator::setItems(const QList &items) +{ QList primitives; - foreach (QGraphicsItem *item, items) { - if (CustomElementPart *part_item = dynamic_cast(item)) { + for(QGraphicsItem *item : items) + { + if (CustomElementPart *part_item = dynamic_cast(item)) + { primitives << part_item; } } @@ -178,96 +154,31 @@ QList ElementPrimitiveDecorator::graphicsItems() const { Adjust the visual decorator according to the currently assigned items. It is notably called by setItems(). */ -void ElementPrimitiveDecorator::adjust() { +void ElementPrimitiveDecorator::adjust() +{ saveOriginalBoundingRect(); modified_bounding_rect_ = original_bounding_rect_; adjustEffectiveBoundingRect(); } -/** - Handle events generated when the mouse hovers over the decorator. - @param event Object describing the hover event. -*/ -void ElementPrimitiveDecorator::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - int p = m_handler.pointIsHoverHandler(event->pos(), getResizingsPoints()); - - if (p == 0 || p == 7) - setCursor(Qt::SizeFDiagCursor); - else if (p == 2 || p == 5) - setCursor(Qt::SizeBDiagCursor); - else if (p == 1 || p ==6) - setCursor(Qt::SizeVerCursor); - else if (p == 3 || p == 4) - setCursor(Qt::SizeHorCursor); - else if (p == -1 && modified_bounding_rect_.normalized().contains(event->pos())) - setCursor(Qt::SizeAllCursor); - else - setCursor(Qt::ArrowCursor); -} - /** Handle event generated when mouse buttons are pressed. @param event Object describing the mouse event */ void ElementPrimitiveDecorator::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - QPointF pos = event -> pos(); - QVector points = getResizingsPoints(); - - current_operation_square_ = m_handler.pointIsHoverHandler(pos, points); - bool accept = false; - - if (current_operation_square_ != QET::NoOperation) - accept = true; - else +{ + if (internalBoundingRect().contains(event->pos())) { - if (internalBoundingRect().contains(pos)) - { - if (CustomElementPart *single_item = singleItem()) - { - bool event_accepted = single_item -> singleItemPressEvent(this, event); - if (event_accepted) - { - event -> ignore(); - return; - } - } - current_operation_square_ = QET::MoveArea; - accept = true; - } - } - - if (accept) - { - if (current_operation_square_ > QET::NoOperation) - first_pos_ = latest_pos_ = mapToScene(points.at(current_operation_square_)); - else - { - first_pos_ = decorated_items_.at(0) -> toItem() -> scenePos(); - latest_pos_ = event -> scenePos(); - mouse_offset_ = event -> scenePos() - first_pos_; - } + current_operation_square_ = QET::MoveArea; + + first_pos_ = decorated_items_.at(0) -> toItem() -> scenePos(); + latest_pos_ = event -> scenePos(); + mouse_offset_ = event -> scenePos() - first_pos_; startMovement(); - event -> accept(); + event->accept(); } else - event -> ignore(); -} - -/** - Handle events generated when mouse buttons are double clicked. - @param event Object describing the mouse event -*/ -void ElementPrimitiveDecorator::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { - //QGraphicsObject::mouseDoubleClickEvent(event); - if (CustomElementPart *single_item = singleItem()) { - bool event_accepted = single_item -> singleItemDoubleClickEvent(this, event); - if (event_accepted) { - event -> ignore(); - return; - } - } + event->ignore(); } /** @@ -280,70 +191,25 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event) QPointF scene_pos = event -> scenePos(); QPointF movement = scene_pos - latest_pos_; - if (current_operation_square_ > QET::NoOperation) { - // This is a scaling operation. - - // For convenience purposes, we may need to adjust mouse movements. - QET::ScalingMethod scaling_method = scalingMethod(event); - if (scaling_method > QET::FreeScaling) { - // real, non-rounded movement from the mouse press event - QPointF global_movement = scene_pos - first_pos_; - - QPointF rounded_global_movement; - if (scaling_method == QET::SnapScalingPointToGrid) { - // real, rounded movement from the mouse press event - rounded_global_movement = snapConstPointToGrid(global_movement); - } - else { - QRectF new_bounding_rect = original_bounding_rect_; - applyMovementToRect(current_operation_square_, global_movement, new_bounding_rect); - - const qreal scale_epsilon = 20.0; // rounds to 0.05 - QPointF delta = deltaForRoundScaling(original_bounding_rect_, new_bounding_rect, scale_epsilon); - - // real, rounded movement from the mouse press event - rounded_global_movement = global_movement + delta; - } - - // rounded position of the current mouse move event - QPointF rounded_scene_pos = first_pos_ + rounded_global_movement; - - // when scaling the selection, consider the center of the currently dragged resizing rectangle - QPointF current_position = mapToScene(getResizingsPoints().at(current_operation_square_)); - // determine the final, effective movement - movement = rounded_scene_pos - current_position; - } - } - else if (current_operation_square_ == QET::MoveArea) { + if (current_operation_square_ == QET::MoveArea) + { // When moving the selection, consider the position of the first selected item QPointF current_position = scene_pos - mouse_offset_; QPointF rounded_current_position = snapConstPointToGrid(current_position); movement = rounded_current_position - decorated_items_.at(0) -> toItem() -> scenePos(); - } - else { - // Neither a movement nor a scaling operation -- perhaps the underlying item - // is interested in the mouse event for custom operations? - if (CustomElementPart *single_item = singleItem()) { - bool event_accepted = single_item -> singleItemMoveEvent(this, event); - if (event_accepted) { - event -> ignore(); - return; - } + + QRectF bounding_rect = modified_bounding_rect_; + applyMovementToRect(current_operation_square_, movement, modified_bounding_rect_); + if (modified_bounding_rect_ != bounding_rect) { + adjustEffectiveBoundingRect(); } - } - - QRectF bounding_rect = modified_bounding_rect_; - applyMovementToRect(current_operation_square_, movement, modified_bounding_rect_); - if (modified_bounding_rect_ != bounding_rect) { - adjustEffectiveBoundingRect(); - } - latest_pos_ = event -> scenePos(); - - if (current_operation_square_ == QET::MoveArea) { + latest_pos_ = event -> scenePos(); translateItems(movement); - } else { - scaleItems(original_bounding_rect_, modified_bounding_rect_); } + + + + } /** @@ -352,39 +218,25 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event) @param event Object describing the mouse event @see QGraphicsScene::mouseGrabberItem() */ -void ElementPrimitiveDecorator::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { +void ElementPrimitiveDecorator::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ Q_UNUSED(event) ElementEditionCommand *command = 0; - if (current_operation_square_ > QET::NoOperation) { - ScalePartsCommand *scale_command = new ScalePartsCommand(); - scale_command -> setScaledPrimitives(items()); - scale_command -> setTransformation( - mapToScene(original_bounding_rect_).boundingRect(), - mapToScene(modified_bounding_rect_).boundingRect() - ); - command = scale_command; - } else if (current_operation_square_ == QET::MoveArea) { + + if (current_operation_square_ == QET::MoveArea) + { QPointF movement = mapToScene(modified_bounding_rect_.topLeft()) - mapToScene(original_bounding_rect_.topLeft()); - if (!movement.isNull()) { + if (!movement.isNull()) + { MovePartsCommand *move_command = new MovePartsCommand(movement, 0, graphicsItems()); command = move_command; } - } else { - if (CustomElementPart *single_item = singleItem()) { - bool event_accepted = single_item -> singleItemReleaseEvent(this, event); - if (event_accepted) { - event -> ignore(); - return; - } + + if (command) { + emit(actionFinished(command)); } - } - - if (command) { - emit(actionFinished(command)); - } - - if (current_operation_square_ != QET::NoOperation) { + adjust(); } @@ -440,7 +292,8 @@ void ElementPrimitiveDecorator::keyReleaseEvent(QKeyEvent *e) { /** Initialize an ElementPrimitiveDecorator */ -void ElementPrimitiveDecorator::init() { +void ElementPrimitiveDecorator::init() +{ setFlag(QGraphicsItem::ItemIsFocusable, true); grid_step_x_ = grid_step_y_ = 1; setAcceptHoverEvents(true); @@ -461,6 +314,7 @@ void ElementPrimitiveDecorator::adjustEffectiveBoundingRect() { prepareGeometryChange(); effective_bounding_rect_ = modified_bounding_rect_ | effective_bounding_rect_; update(); + adjusteHandlerPos(); } /** @@ -592,6 +446,152 @@ QVector ElementPrimitiveDecorator::getResizingsPoints() const return vector; } +/** + * @brief ElementPrimitiveDecorator::adjusteHandlerPos + */ +void ElementPrimitiveDecorator::adjusteHandlerPos() +{ + QVector points_vector = mapToScene(getResizingsPoints()); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); +} + +/** + * @brief ElementPrimitiveDecorator::handlerMousePressEvent + * @param qghi + * @param event + */ +void ElementPrimitiveDecorator::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + + QVector points = getResizingsPoints(); + + current_operation_square_ = m_handler_vector.indexOf(qghi); + + first_pos_ = latest_pos_ = mapToScene(points.at(current_operation_square_)); + startMovement(); +} + +/** + * @brief ElementPrimitiveDecorator::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void ElementPrimitiveDecorator::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + + QPointF scene_pos = event -> scenePos(); + QPointF movement = scene_pos - latest_pos_; + + // For convenience purposes, we may need to adjust mouse movements. + QET::ScalingMethod scaling_method = scalingMethod(event); + if (scaling_method > QET::FreeScaling) + { + // real, non-rounded movement from the mouse press event + QPointF global_movement = scene_pos - first_pos_; + + QPointF rounded_global_movement; + if (scaling_method == QET::SnapScalingPointToGrid) + { + // real, rounded movement from the mouse press event + rounded_global_movement = snapConstPointToGrid(global_movement); + } + else + { + QRectF new_bounding_rect = original_bounding_rect_; + applyMovementToRect(current_operation_square_, global_movement, new_bounding_rect); + + const qreal scale_epsilon = 20.0; // rounds to 0.05 + QPointF delta = deltaForRoundScaling(original_bounding_rect_, new_bounding_rect, scale_epsilon); + + // real, rounded movement from the mouse press event + rounded_global_movement = global_movement + delta; + } + + // rounded position of the current mouse move event + QPointF rounded_scene_pos = first_pos_ + rounded_global_movement; + + // when scaling the selection, consider the center of the currently dragged resizing rectangle + QPointF current_position = mapToScene(getResizingsPoints().at(current_operation_square_)); + // determine the final, effective movement + movement = rounded_scene_pos - current_position; + } + + QRectF bounding_rect = modified_bounding_rect_; + applyMovementToRect(current_operation_square_, movement, modified_bounding_rect_); + if (modified_bounding_rect_ != bounding_rect) { + adjustEffectiveBoundingRect(); + } + latest_pos_ = event -> scenePos(); + scaleItems(original_bounding_rect_, modified_bounding_rect_); +} + +/** + * @brief ElementPrimitiveDecorator::handlerMouseReleaseEvent + * @param qghi + * @param event + */ +void ElementPrimitiveDecorator::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + ElementEditionCommand *command = 0; + if (current_operation_square_ > QET::NoOperation) + { + ScalePartsCommand *scale_command = new ScalePartsCommand(); + scale_command -> setScaledPrimitives(items()); + scale_command -> setTransformation( + mapToScene(original_bounding_rect_).boundingRect(), + mapToScene(modified_bounding_rect_).boundingRect() + ); + command = scale_command; + } + + if (command) { + emit(actionFinished(command)); + } + + adjust(); + + current_operation_square_ = QET::NoOperation; +} + +/** + * @brief ElementPrimitiveDecorator::addHandler + * Add handlers for this item + */ +void ElementPrimitiveDecorator::addHandler() +{ + if (m_handler_vector.isEmpty() && scene()) + { + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapFromScene(getResizingsPoints())); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + scene()->addItem(handler); + handler->setColor(Qt::darkGreen); + handler->installSceneEventFilter(this); + handler->setZValue(this->zValue()+1); + } + } +} + +/** + * @brief ElementPrimitiveDecorator::removeHandler + * Remove the handlers of this item + */ +void ElementPrimitiveDecorator::removeHandler() +{ + if (!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + } +} + /** Receive two rects, assuming they share a common corner and current is a \a scaled version of \a original. @@ -661,3 +661,73 @@ QET::ScalingMethod ElementPrimitiveDecorator::scalingMethod(QGraphicsSceneMouseE } return QET::RoundScaleRatios; } + +/** + * @brief ElementPrimitiveDecorator::itemChange + * @param change + * @param value + * @return + */ +QVariant ElementPrimitiveDecorator::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemSceneHasChanged) + { + if(scene()) //Item is added to scene, we also add handlers + addHandler(); + else //Item is removed from scene, we also remove the handlers + removeHandler(); + } + else if (change == ItemVisibleHasChanged) + { + bool visible = value.toBool(); + for(QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setVisible(visible); + } + else if (change == ItemZValueHasChanged && !m_handler_vector.isEmpty()) + { + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setZValue(this->zValue()+1); + } + + return QGraphicsObject::itemChange(change, value); +} + +/** + * @brief ElementPrimitiveDecorator::sceneEventFilter + * @param watched + * @param event + * @return + */ +bool ElementPrimitiveDecorator::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) + { + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize + { + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) + { + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } + } + } + } + + return false; +} diff --git a/sources/editor/elementprimitivedecorator.h b/sources/editor/elementprimitivedecorator.h index 2b6ddfd48..67b5864d7 100644 --- a/sources/editor/elementprimitivedecorator.h +++ b/sources/editor/elementprimitivedecorator.h @@ -20,11 +20,11 @@ #include #include "qet.h" -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" class ElementEditionCommand; class ElementScene; class CustomElementPart; +class QetGraphicsHandlerItem; /** This class represents a decorator rendered above selected items so users @@ -42,73 +42,85 @@ class ElementPrimitiveDecorator : public QGraphicsObject Q_OBJECT public: - ElementPrimitiveDecorator(QGraphicsItem * = 0); - virtual ~ElementPrimitiveDecorator(); - - enum { Type = UserType + 2200 }; - - // methods - QRectF internalBoundingRect() const; - virtual QRectF boundingRect () const; - virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0); - virtual int type() const { return Type; } - void setItems(const QList &); - void setItems(const QList &); - QList items() const; - QList graphicsItems() const; + ElementPrimitiveDecorator(QGraphicsItem * = 0); + virtual ~ElementPrimitiveDecorator(); + + enum { Type = UserType + 2200 }; + + // methods + QRectF internalBoundingRect() const; + virtual QRectF boundingRect () const; + virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0); + virtual int type() const { return Type; } + void setItems(const QList &); + void setItems(const QList &); + QList items() const; + QList graphicsItems() const; public slots: - void adjust(); + void adjust(); signals: - void actionFinished(ElementEditionCommand *); + void actionFinished(ElementEditionCommand *); protected: - void hoverMoveEvent(QGraphicsSceneHoverEvent *); - void mousePressEvent(QGraphicsSceneMouseEvent *); - void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *); - void mouseMoveEvent(QGraphicsSceneMouseEvent *); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *); - void keyPressEvent(QKeyEvent *); - void keyReleaseEvent(QKeyEvent *); - QPointF deltaForRoundScaling(const QRectF &, const QRectF &, qreal); - QPointF snapConstPointToGrid(const QPointF &) const; - void snapPointToGrid(QPointF &) const; - bool mustSnapToGrid(QGraphicsSceneMouseEvent *); - QET::ScalingMethod scalingMethod(QGraphicsSceneMouseEvent *); + void mousePressEvent(QGraphicsSceneMouseEvent *); + void mouseMoveEvent(QGraphicsSceneMouseEvent *); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *); + void keyPressEvent(QKeyEvent *); + void keyReleaseEvent(QKeyEvent *); + QPointF deltaForRoundScaling(const QRectF &, const QRectF &, qreal); + QPointF snapConstPointToGrid(const QPointF &) const; + void snapPointToGrid(QPointF &) const; + bool mustSnapToGrid(QGraphicsSceneMouseEvent *); + QET::ScalingMethod scalingMethod(QGraphicsSceneMouseEvent *); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); private: - void init(); - void saveOriginalBoundingRect(); - void adjustEffectiveBoundingRect(); - void startMovement(); - void applyMovementToRect(int, const QPointF &, QRectF &); - CustomElementPart *singleItem() const; - void translateItems(const QPointF &); - void scaleItems(const QRectF &, const QRectF &); - QRectF getSceneBoundingRect(QGraphicsItem *) const; - QVector getResizingsPoints() const; + void init(); + void saveOriginalBoundingRect(); + void adjustEffectiveBoundingRect(); + void startMovement(); + void applyMovementToRect(int, const QPointF &, QRectF &); + CustomElementPart *singleItem() const; + void translateItems(const QPointF &); + void scaleItems(const QRectF &, const QRectF &); + QRectF getSceneBoundingRect(QGraphicsItem *) const; + QVector getResizingsPoints() const; - // attributes + private: - QList decorated_items_; - QRectF effective_bounding_rect_; ///< actual, effective bounding rect -- never shrinks - QRectF original_bounding_rect_; ///< original bounding rect - QRectF modified_bounding_rect_; ///< new bounding rect, after the user moved or resized items + void adjusteHandlerPos(); + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + + void addHandler(); + void removeHandler(); + + + + + QList decorated_items_; + QRectF effective_bounding_rect_; ///< actual, effective bounding rect -- never shrinks + QRectF original_bounding_rect_; ///< original bounding rect + QRectF modified_bounding_rect_; ///< new bounding rect, after the user moved or resized items - /** - Index of the square leading the current operation (resizing, etc.) or -1 if no - operation is occurring, -2 for a move operation. - */ - int current_operation_square_; - int grid_step_x_; ///< Grid horizontal step - int grid_step_y_; ///< Grid horizontal step - QPointF first_pos_; ///< First point involved within the current resizing operation - QPointF latest_pos_; ///< Latest point involved within the current resizing operation - QPointF mouse_offset_; ///< Offset between the mouse position and the point to be snapped to grid when moving selection - bool moving_by_keys_; ///< Whether we are currently moving our decorated items using the arrow keys - QPointF keys_movement_; ///< Movement applied to our decorated items using the arrow keys - QetGraphicsHandlerUtility m_handler; + /** + Index of the square leading the current operation (resizing, etc.) or -1 if no + operation is occurring, -2 for a move operation. + */ + int current_operation_square_; + int grid_step_x_; ///< Grid horizontal step + int grid_step_y_; ///< Grid horizontal step + QPointF first_pos_; ///< First point involved within the current resizing operation + QPointF latest_pos_; ///< Latest point involved within the current resizing operation + QPointF mouse_offset_; ///< Offset between the mouse position and the point to be snapped to grid when moving selection + bool moving_by_keys_; ///< Whether we are currently moving our decorated items using the arrow keys + QPointF keys_movement_; ///< Movement applied to our decorated items using the arrow keys + QVector m_handler_vector; + int m_vector_index = -1; }; #endif diff --git a/sources/editor/elementscene.cpp b/sources/editor/elementscene.cpp index 2a5d88b24..b57137142 100644 --- a/sources/editor/elementscene.cpp +++ b/sources/editor/elementscene.cpp @@ -32,8 +32,9 @@ #include "nameslist.h" #include "ui/elementpropertieseditorwidget.h" #include "eseventinterface.h" -#include +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" +#include #include /** @@ -524,27 +525,45 @@ QETElementEditor* ElementScene::editor() const { } /** - Selectionne une liste de parties - @param content liste des parties a selectionner -*/ -void ElementScene::slot_select(const ElementContent &content) { + * @brief ElementScene::slot_select + * Select the item in content, every others items in the scene are deselected + * @param content + */ +void ElementScene::slot_select(const ElementContent &content) +{ blockSignals(true); + + //Befor clear selection, we must to remove the handlers items in @content, + //because if in @content there are a selected item, but also its handlers items, + //When item is deselected, the item delete its handlers items, + //then handlers in content doesn't exist anymore and cause segfault + QList items_list; + for (QGraphicsItem *qgi : content) + { + if(qgi->type() != QetGraphicsHandlerItem::Type) + items_list << qgi; + } clearSelection(); - foreach(QGraphicsItem *qgi, content) qgi -> setSelected(true); + + foreach(QGraphicsItem *qgi, items_list) + qgi -> setSelected(true); + blockSignals(false); emit(selectionChanged()); } /** - Selectionne tout -*/ + * @brief ElementScene::slot_selectAll + * Select all items + */ void ElementScene::slot_selectAll() { slot_select(items()); } /** - Deselectionne tout -*/ + * @brief ElementScene::slot_deselectAll + * deselect all item + */ void ElementScene::slot_deselectAll() { slot_select(ElementContent()); } @@ -811,7 +830,15 @@ void ElementScene::reset() clearSelection(); undoStack().clear(); - foreach (QGraphicsItem *qgi, items()) + //We don't add handlers, because it's the role of the primitive or decorator to remove it. + QList items_list; + for (QGraphicsItem *qgi : items()) + { + if(qgi->type() != QetGraphicsHandlerItem::Type) + items_list << qgi; + } + + for (QGraphicsItem *qgi : items_list) { removeItem(qgi); qgiManager().release(qgi); @@ -1064,14 +1091,17 @@ void ElementScene::managePrimitivesGroups() // should we hide the decorator? QList selected_items = zItems(ElementScene::Selected | ElementScene::IncludeTerminals); - if (selected_items.size() == 0) + if (selected_items.size() <= 1) + { m_decorator -> hide(); - else if (selected_items.size() == 1 && - selected_items.first()->type() != PartText::Type && - selected_items.first()->type() != PartTextField::Type) - m_decorator->hide(); + } else { + for(QGraphicsItem *qgi : selected_items) + { + //We recall set selected, then every primitive will remove there handler because there are several item selected + qgi->setSelected(true); + } m_decorator -> setZValue(1000000); m_decorator -> setPos(0, 0); m_decorator -> setItems(selected_items); diff --git a/sources/editor/elementscene.h b/sources/editor/elementscene.h index 0211edaa5..39cb19473 100644 --- a/sources/editor/elementscene.h +++ b/sources/editor/elementscene.h @@ -51,7 +51,7 @@ class ElementScene : public QGraphicsScene NonSelected = 16, SelectedOrNot = 24 }; - Q_DECLARE_FLAGS(ItemOptions, ItemOption) + Q_DECLARE_FLAGS(ItemOptions, ItemOption) // constructors, destructor public: @@ -82,7 +82,7 @@ class ElementScene : public QGraphicsScene QETElementEditor *m_element_editor = nullptr; /// Variables to manage the paste area on the scene - QGraphicsRectItem *m_paste_area = nullptr; + QGraphicsRectItem *m_paste_area; QRectF m_defined_paste_area; /// Variables to handle copy/paste with offset @@ -168,15 +168,15 @@ class ElementScene : public QGraphicsScene void stackAction(ElementEditionCommand *); signals: - /// Signal emitted after one or several parts were added + /// Signal emitted after one or several parts were added void partsAdded(); - /// Signal emitted after one or several parts were removed + /// Signal emitted after one or several parts were removed void partsRemoved(); - /// Signal emitted when the zValue of one or several parts change + /// Signal emitted when the zValue of one or several parts change void partsZValueChanged(); - /// Signal emitted when users have defined the copy/paste area + /// Signal emitted when users have defined the copy/paste area void pasteAreaDefined(const QRectF &); - /// Signal emitted when need zoomFit + /// Signal emitted when need zoomFit void needZoomFit(); }; diff --git a/sources/editor/graphicspart/abstractpartellipse.cpp b/sources/editor/graphicspart/abstractpartellipse.cpp index 392ba0fae..27f171170 100644 --- a/sources/editor/graphicspart/abstractpartellipse.cpp +++ b/sources/editor/graphicspart/abstractpartellipse.cpp @@ -118,6 +118,7 @@ void AbstractPartEllipse::setRect(const QRectF &rect) if (rect == m_rect) return; prepareGeometryChange(); m_rect = rect; + emit rectChanged(); } diff --git a/sources/editor/graphicspart/abstractpartellipse.h b/sources/editor/graphicspart/abstractpartellipse.h index 323c867de..e196da118 100644 --- a/sources/editor/graphicspart/abstractpartellipse.h +++ b/sources/editor/graphicspart/abstractpartellipse.h @@ -20,6 +20,8 @@ #include "customelementgraphicpart.h" +class QetGraphicsHandlerItem; + /** * @brief The AbstractPartEllipse class * This is the base class for all ellipse based item like ellipse, circle, arc. @@ -61,20 +63,21 @@ class AbstractPartEllipse : public CustomElementGraphicPart virtual QPointF sceneTopLeft() const; QRectF rect() const; - void setRect (const QRectF &rect); + virtual void setRect (const QRectF &rect); virtual bool isUseless() const; int startAngle() const {return m_start_angle;} - void setStartAngle (const int &start_angle); + virtual void setStartAngle (const int &start_angle); int spanAngle () const {return m_span_angle;} - void setSpanAngle (const int &span_angle); + virtual void setSpanAngle (const int &span_angle); protected: QList saved_points_; QRectF m_rect; qreal m_start_angle; qreal m_span_angle; + QVector m_handler_vector; }; #endif // ABSTRACTPARTELLIPSE_H diff --git a/sources/editor/graphicspart/customelementgraphicpart.h b/sources/editor/graphicspart/customelementgraphicpart.h index a4bb52287..7a5ee0cc5 100644 --- a/sources/editor/graphicspart/customelementgraphicpart.h +++ b/sources/editor/graphicspart/customelementgraphicpart.h @@ -118,7 +118,7 @@ class CustomElementGraphicPart : public QGraphicsObject, public CustomElementPar Filling _filling ; Color _color; bool _antialiased; - QPointF m_origin_pos, m_mouse_to_origin_pos; + QPointF m_origin_pos; }; typedef CustomElementGraphicPart CEGP; diff --git a/sources/editor/graphicspart/customelementpart.cpp b/sources/editor/graphicspart/customelementpart.cpp index d2d046646..206c7b2ae 100644 --- a/sources/editor/graphicspart/customelementpart.cpp +++ b/sources/editor/graphicspart/customelementpart.cpp @@ -49,16 +49,6 @@ QGraphicsItem *CustomElementPart::toItem() { return(dynamic_cast(this)); } -/** - This method is called by the decorator when it manages only a single - primitive. This brings the possibility to implement custom behaviour, such - as text edition, points edition or specific resizing. - The default implementation does nothing. -*/ -void CustomElementPart::setDecorator(ElementPrimitiveDecorator *decorator) { - Q_UNUSED(decorator) -} - /** This method is called by the decorator when it needs to determine the best way to interactively scale a primitive. It is typically called when only a @@ -70,46 +60,6 @@ QET::ScalingMethod CustomElementPart::preferredScalingMethod() const { return(QET::SnapScalingPointToGrid); } -/** - This method is called by the decorator when it manages only a single - primitive and it received a mouse press event. - The implementation should return true if the primitive accepts the event, false otherwise. - The default implementation returns false. -*/ -bool CustomElementPart::singleItemPressEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *) { - return(false); -} - -/** - This method is called by the decorator when it manages only a single - primitive and it received a mouse move event. - The implementation should return true if the primitive accepts the event, false otherwise. - The default implementation returns false. -*/ -bool CustomElementPart::singleItemMoveEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *) { - return(false); -} - -/** - This method is called by the decorator when it manages only a single - primitive and it received a mouse release event. - The implementation should return true if the primitive accepts the event, false otherwise. - The default implementation returns false. -*/ -bool CustomElementPart::singleItemReleaseEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *) { - return(false); -} - -/** - This method is called by the decorator when it manages only a single - primitive and it received a mouse double click event. - The implementation should return true if the primitive accepts the event, false otherwise. - The default implementation returns false. -*/ -bool CustomElementPart::singleItemDoubleClickEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *) { - return(false); -} - /** Helper method to map points in CustomElementPart::handleUserTransformation() @param initial_selection_rect Selection rectangle when the movement started, in scene coordinates diff --git a/sources/editor/graphicspart/customelementpart.h b/sources/editor/graphicspart/customelementpart.h index 4f7ba63a2..f0ff98108 100644 --- a/sources/editor/graphicspart/customelementpart.h +++ b/sources/editor/graphicspart/customelementpart.h @@ -103,12 +103,7 @@ class CustomElementPart { virtual QGraphicsItem *toItem(); - virtual void setDecorator(ElementPrimitiveDecorator *); virtual QET::ScalingMethod preferredScalingMethod() const; - virtual bool singleItemPressEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemMoveEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemReleaseEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemDoubleClickEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); protected: QList mapPoints(const QRectF &, const QRectF &, const QList &); diff --git a/sources/editor/graphicspart/partarc.cpp b/sources/editor/graphicspart/partarc.cpp index 09aaaad3f..90df79d43 100644 --- a/sources/editor/graphicspart/partarc.cpp +++ b/sources/editor/graphicspart/partarc.cpp @@ -18,6 +18,8 @@ #include "partarc.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" #include "elementscene.h" +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" +#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" /** @@ -37,8 +39,10 @@ PartArc::PartArc(QETElementEditor *editor, QGraphicsItem *parent) : * @brief PartArc::~PartArc * Destructor */ -PartArc::~PartArc() { +PartArc::~PartArc() +{ if(m_undo_command) delete m_undo_command; + removeHandler(); } /** @@ -82,15 +86,7 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, drawShadowShape(painter); if (isSelected()) - { drawCross(m_rect.center(), painter); - if (scene()->selectedItems().size() == 1) { - if (m_resize_mode == 3) - m_handler.drawHandler(painter, m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16)); - else - m_handler.drawHandler(painter, m_handler.pointsForRect(m_rect)); - } - } } /** @@ -129,16 +125,6 @@ void PartArc::fromXml(const QDomElement &qde) { m_span_angle = qde.attribute("angle", "-1440").toDouble() * 16; } -QRectF PartArc::boundingRect() const -{ - QRectF r = AbstractPartEllipse::boundingRect(); - - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect))) - r |= rect; - - return r; -} - /** * @brief PartArc::shape * @return the shape of this item @@ -153,10 +139,6 @@ QPainterPath PartArc::shape() const pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); shape = pps.createStroke(shape); - if (isSelected()) - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect))) - shape.addRect(rect); - return shape; } @@ -172,135 +154,6 @@ QPainterPath PartArc::shadowShape() const return (pps.createStroke(shape)); } -void PartArc::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - if (!isSelected()) - { - CustomElementGraphicPart::hoverMoveEvent(event); - return; - } - - if (m_resize_mode == 1 || m_resize_mode == 2) { - int handler = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect)); - - if (handler >= 0) - { - if (handler == 0 || handler == 2 || handler == 5 || handler == 7) - setCursor(Qt::SizeAllCursor); - else if (handler == 1 || handler == 6) - setCursor(Qt::SizeVerCursor); - else if (handler == 3 || handler == 4) - setCursor(Qt::SizeHorCursor); - - return; - } - } - else if (m_resize_mode == 3) { - if (m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16)) >= 0) { - setCursor(Qt::SizeAllCursor); - return; - } - } - - CustomElementGraphicPart::hoverMoveEvent(event); -} - -/** - * @brief PartArc::mousePressEvent - * Handle mouse press event - * @param event - */ -void PartArc::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - { - setCursor(Qt::ClosedHandCursor); - if (isSelected()) - { - //resize rect - if (m_resize_mode == 1 || m_resize_mode == 2) { - m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect)); - - if(m_handler_index >= 0 && m_handler_index <= 7) //User click on an handler - { - m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect)); - m_undo_command->setText(tr("Modifier un arc")); - m_undo_command->enableAnimation(); - return; - } - } - //resize angle - if (m_resize_mode == 3) { - m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16)); - if (m_handler_index == 0) { - m_span_point = m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16).at(1); - - m_undo_command = new QPropertyUndoCommand(this, "startAngle", QVariant(m_start_angle)); - m_undo_command->setText(tr("Modifier un arc")); - m_undo_command->enableAnimation(); - - m_undo_command2 = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle), m_undo_command); - m_undo_command2->setText(tr("Modifier un arc")); - m_undo_command2->enableAnimation(); - - return; - } - else if (m_handler_index == 1) { - m_undo_command = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle)); - m_undo_command->setText(tr("Modifier un arc")); - m_undo_command->enableAnimation(); - - return; - } - } - - } - } - - CustomElementGraphicPart::mousePressEvent(event); -} - -/** - * @brief PartArc::mouseMoveEvent - * Handle mouse move event - * @param event - */ -void PartArc::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - if (m_resize_mode == 1 || m_resize_mode == 2) { - if (m_handler_index >= 0 && m_handler_index <= 7) { - QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); - prepareGeometryChange(); - - if (m_resize_mode == 1) - setRect(m_handler.rectForPosAtIndex(m_rect, pos_, m_handler_index)); - else - setRect(m_handler.mirrorRectForPosAtIndex(m_rect, pos_, m_handler_index)); - - return; - } - } - else if (m_resize_mode == 3) { - if (m_handler_index == 0 || m_handler_index == 1) { - QLineF line(m_rect.center(), event->pos()); - prepareGeometryChange(); - - if (m_handler_index == 0) { - setStartAngle(line.angle()*16); - setSpanAngle(line.angleTo(QLineF(m_rect.center(), m_span_point))*16); - } - else if (m_handler_index == 1) { - QLineF line2(m_rect.center(), m_handler.pointsForArc(m_rect, m_start_angle/16, m_span_angle/16).at(0)); - setSpanAngle (line2.angleTo(line)*16); - } - - return; - } - } - - CustomElementGraphicPart::mouseMoveEvent(event); -} - /** * @brief PartArc::mouseReleaseEvent * Handle mouse release event @@ -308,59 +161,317 @@ void PartArc::mouseMoveEvent(QGraphicsSceneMouseEvent *event) */ void PartArc::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::LeftButton) { - setCursor(Qt::OpenHandCursor); - if (event->buttonDownPos(Qt::LeftButton) == event->pos()) - switchResizeMode(); - } + if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos()) + switchResizeMode(); - if (m_resize_mode == 1 || m_resize_mode == 2) { - if (m_handler_index >= 0 && m_handler_index <= 7) { - if (!m_rect.isValid()) - m_rect = m_rect.normalized(); + CustomElementGraphicPart::mouseReleaseEvent(event); +} - m_undo_command->setNewValue(QVariant(m_rect)); - elementScene()->undoStack().push(m_undo_command); - m_undo_command = nullptr; - m_handler_index = -1; - return; +/** + * @brief PartArc::itemChange + * @param change + * @param value + * @return + */ +QVariant PartArc::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemSelectedHasChanged && scene()) + { + if (value.toBool() == true) + { + //When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler, + //according to the number of selected items. + connect(scene(), &QGraphicsScene::selectionChanged, this, &PartArc::sceneSelectionChanged); + + if (scene()->selectedItems().size() == 1) + addHandler(); + } + else + { + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartArc::sceneSelectionChanged); + removeHandler(); } } - else if (m_resize_mode == 3) { - if (m_handler_index == 0) { + else if (change == ItemPositionHasChanged) + { + adjusteHandlerPos(); + } + else if (change == ItemSceneChange) + { + if(scene()) + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartArc::sceneSelectionChanged); + + setSelected(false); //This is item removed from scene, then we deselect this, and so, the handlers is also removed. + } + + return QGraphicsItem::itemChange(change, value); +} + +/** + * @brief PartArc::sceneEventFilter + * @param watched + * @param event + * @return + */ +bool PartArc::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) + { + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize + { + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) + { + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } + } + } + } + + return false; +} + +/** + * @brief PartArc::switchResizeMode + */ +void PartArc::switchResizeMode() +{ + if (m_resize_mode == 1) + { + m_resize_mode = 2; + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::darkGreen); + } + else if (m_resize_mode == 2) + { + m_resize_mode = 3; + + //From rect mode to angle mode, then numbers of handlers change + removeHandler(); + addHandler(); + + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::magenta); + } + else + { + m_resize_mode = 1; + + //From angle mode to rect mode, then numbers of handlers change + removeHandler(); + addHandler(); + + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::blue); + } +} + +/** + * @brief PartArc::adjusteHandlerPos + */ +void PartArc::adjusteHandlerPos() +{ + if (m_handler_vector.isEmpty()) + return; + + QVector points_vector; + + if(m_resize_mode == 3) + points_vector = QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle/16, m_span_angle/16); + else + points_vector = QetGraphicsHandlerUtility::pointsForRect(m_rect); + + + if (m_handler_vector.size() == points_vector.size()) + { + points_vector = mapToScene(points_vector); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); + } +} + +/** + * @brief PartArc::handlerMousePressEvent + * @param qghi + * @param event + */ +void PartArc::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + if (m_resize_mode == 3) //Resize angle + { + if (m_vector_index == 0) + { + m_span_point = QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle /16, m_span_angle /16).at(1); + + m_undo_command = new QPropertyUndoCommand(this, "startAngle", QVariant(m_start_angle)); + m_undo_command->setText(tr("Modifier un arc")); + m_undo_command->enableAnimation(); + + m_undo_command2 = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle), m_undo_command); + m_undo_command2->setText(tr("Modifier un arc")); + m_undo_command2->enableAnimation(); + } + else if (m_vector_index == 1) + { + m_undo_command = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle)); + m_undo_command->setText(tr("Modifier un arc")); + m_undo_command->enableAnimation(); + } + } + else //resize rect + { + m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect)); + m_undo_command->setText(tr("Modifier un arc")); + m_undo_command->enableAnimation(); + } +} + +/** + * @brief PartArc::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void PartArc::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + + QPointF new_pos = event->scenePos(); + if (event->modifiers() != Qt::ControlModifier) + new_pos = elementScene()->snapToGrid(event->scenePos()); + new_pos = mapFromScene(new_pos); + + if (m_resize_mode == 1) + setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(m_rect, new_pos, m_vector_index)); + else if (m_resize_mode == 2) + setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(m_rect, new_pos, m_vector_index)); + else + { + QLineF line(m_rect.center(), mapFromItem(qghi, event->pos())); + prepareGeometryChange(); + + if (m_vector_index == 0) { + setStartAngle(line.angle()*16); + setSpanAngle(line.angleTo(QLineF(m_rect.center(), m_span_point))*16); + } + else if (m_vector_index == 1) { + QLineF line2(m_rect.center(), QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle/16, m_span_angle/16).at(0)); + setSpanAngle (line2.angleTo(line)*16); + } + } +} + +/** + * @brief PartArc::handlerMouseReleaseEvent + * @param qghi + * @param event + */ +void PartArc::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + if (m_resize_mode == 3) + { + if (m_vector_index == 0) + { m_undo_command->setNewValue(QVariant(m_start_angle)); m_undo_command2->setNewValue(QVariant(m_span_angle)); elementScene()->undoStack().push(m_undo_command); m_undo_command = nullptr; m_undo_command2 = nullptr; - m_handler_index = -1; - return; + m_vector_index = -1; } - else if (m_handler_index == 1) { + else if (m_vector_index == 1) + { m_undo_command->setNewValue(QVariant(m_span_angle)); elementScene()->undoStack().push(m_undo_command); m_undo_command = nullptr; - m_handler_index = -1; - return; + m_vector_index = -1; } } + else + { + if (!m_rect.isValid()) + m_rect = m_rect.normalized(); - CustomElementGraphicPart::mouseReleaseEvent(event); + m_undo_command->setNewValue(QVariant(m_rect)); + elementScene()->undoStack().push(m_undo_command); + m_undo_command = nullptr; + m_vector_index = -1; + } } -void PartArc::switchResizeMode() +/** + * @brief PartArc::sceneSelectionChanged + * When the scene selection change, if there are several primitive selected, we remove the handler of this item + */ +void PartArc::sceneSelectionChanged() { - if (m_resize_mode == 1) { - m_resize_mode = 2; - m_handler.setOuterColor(Qt::darkGreen); - } - else if (m_resize_mode == 2 ) { - m_resize_mode = 3; - m_handler.setOuterColor(Qt::magenta); - } - else { - m_resize_mode = 1; - m_handler.setOuterColor(Qt::blue); - } - update(); + if (this->isSelected() && scene()->selectedItems().size() == 1) + addHandler(); + else + removeHandler(); +} + +/** + * @brief PartArc::addHandler + * Add handlers for this item + */ +void PartArc::addHandler() +{ + if (m_handler_vector.isEmpty() && scene()) + { + if(m_resize_mode == 3) + { + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle/16, m_span_angle/16))); + } + else + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForRect(m_rect))); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + QColor color = Qt::blue; + if (m_resize_mode == 2) + color = Qt::darkGreen; + else if (m_resize_mode == 3) + color = Qt::magenta; + + handler->setColor(color); + scene()->addItem(handler); + handler->installSceneEventFilter(this); + handler->setZValue(this->zValue()+1); + } + } +} + +/** + * @brief PartArc::removeHandler + * Remove the handlers of this item + */ +void PartArc::removeHandler() +{ + if (!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + } } diff --git a/sources/editor/graphicspart/partarc.h b/sources/editor/graphicspart/partarc.h index 1bd156b17..348e96506 100644 --- a/sources/editor/graphicspart/partarc.h +++ b/sources/editor/graphicspart/partarc.h @@ -19,9 +19,9 @@ #define PART_ARC_H #include "abstractpartellipse.h" -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" class QPropertyUndoCommand; +class QetGraphicsHandlerItem; /** * @brief The PartArc class @@ -54,25 +54,34 @@ class PartArc : public AbstractPartEllipse virtual const QDomElement toXml (QDomDocument &) const; virtual void fromXml (const QDomElement &); - virtual QRectF boundingRect() const; virtual QPainterPath shape() const; virtual QPainterPath shadowShape() const; + virtual void setRect(const QRectF &rect) {AbstractPartEllipse::setRect(rect); adjusteHandlerPos();} + virtual void setStartAngle(const int &start_angle) {AbstractPartEllipse::setStartAngle(start_angle); adjusteHandlerPos();} + virtual void setSpanAngle(const int &span_angle) {AbstractPartEllipse::setSpanAngle(span_angle); adjusteHandlerPos();} protected: - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); private: void switchResizeMode(); + void adjusteHandlerPos(); + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void sceneSelectionChanged (); + + void addHandler(); + void removeHandler(); private: - QetGraphicsHandlerUtility m_handler = 10; - int m_handler_index = -1; QPropertyUndoCommand *m_undo_command = nullptr; QPropertyUndoCommand *m_undo_command2 = nullptr; - int m_resize_mode = 1; + int m_resize_mode = 1, + m_vector_index = -1; QPointF m_span_point; + QVector m_handler_vector; }; #endif diff --git a/sources/editor/graphicspart/partellipse.cpp b/sources/editor/graphicspart/partellipse.cpp index 93f76486c..97ae2a718 100644 --- a/sources/editor/graphicspart/partellipse.cpp +++ b/sources/editor/graphicspart/partellipse.cpp @@ -18,6 +18,8 @@ #include "partellipse.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" #include "elementscene.h" +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" +#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" /** * @brief PartEllipse::PartEllipse @@ -27,8 +29,6 @@ */ PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent) : AbstractPartEllipse(editor, parent), - m_handler(10), - m_handler_index(-1), m_undo_command(nullptr) {} @@ -36,8 +36,10 @@ PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent) : * @brief PartEllipse::~PartEllipse * Destructor */ -PartEllipse::~PartEllipse() { +PartEllipse::~PartEllipse() +{ if(m_undo_command) delete m_undo_command; + removeHandler(); } /** @@ -65,11 +67,7 @@ void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio drawShadowShape(painter); if (isSelected()) - { drawCross(m_rect.center(), painter); - if (scene()->selectedItems().size() == 1) - m_handler.drawHandler(painter, m_handler.pointsForRect(m_rect)); - } } /** @@ -125,16 +123,6 @@ void PartEllipse::fromXml(const QDomElement &qde) QSizeF(width, height)); } -QRectF PartEllipse::boundingRect() const -{ - QRectF r = AbstractPartEllipse::boundingRect(); - - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect))) - r |= rect; - - return r; -} - /** * @brief PartEllipse::shape * @return the shape of this item @@ -148,10 +136,6 @@ QPainterPath PartEllipse::shape() const pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); shape = pps.createStroke(shape); - if (isSelected()) - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect))) - shape.addRect(rect); - return shape; } @@ -166,77 +150,6 @@ QPainterPath PartEllipse::shadowShape() const return (pps.createStroke(shape)); } -void PartEllipse::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - if (!isSelected()) - { - CustomElementGraphicPart::hoverMoveEvent(event); - return; - } - - int handler = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect)); - - if (handler >= 0) - { - if (handler == 0 || handler == 2 || handler == 5 || handler == 7) - setCursor(Qt::SizeAllCursor); - else if (handler == 1 || handler == 6) - setCursor(Qt::SizeVerCursor); - else if (handler == 3 || handler == 4) - setCursor(Qt::SizeHorCursor); - } - else - CustomElementGraphicPart::hoverMoveEvent(event); -} - -/** - * @brief PartEllipse::mousePressEvent - * Handle mouse press event - * @param event - */ -void PartEllipse::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - { - setCursor(Qt::ClosedHandCursor); - if (isSelected()) - { - m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect)); - - if(m_handler_index >= 0 && m_handler_index <= 7) //User click on an handler - { - m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect)); - m_undo_command->setText(tr("Modifier une ellipse")); - m_undo_command->enableAnimation(); - return; - } - } - } - - CustomElementGraphicPart::mousePressEvent(event); -} - -/** - * @brief PartEllipse::mouseMoveEvent - * Handle mouse move event - * @param event - */ -void PartEllipse::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - if(m_handler_index >= 0 && m_handler_index <= 7) - { - QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); - prepareGeometryChange(); - - if (m_resize_mode == 1) - setRect(m_handler.rectForPosAtIndex(m_rect, pos_, m_handler_index)); - else - setRect(m_handler.mirrorRectForPosAtIndex(m_rect, pos_, m_handler_index)); - } - else - CustomElementGraphicPart::mouseMoveEvent(event); -} - /** * @brief PartEllipse::mouseReleaseEvent * Handle mouse release event @@ -244,35 +157,225 @@ void PartEllipse::mouseMoveEvent(QGraphicsSceneMouseEvent *event) */ void PartEllipse::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::LeftButton) { - setCursor(Qt::OpenHandCursor); - if (event->buttonDownPos(Qt::LeftButton) == event->pos()) - switchResizeMode(); - } + if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos()) + switchResizeMode(); + + CustomElementGraphicPart::mouseReleaseEvent(event); +} - if (m_handler_index >= 0 && m_handler_index <= 7) +/** + * @brief PartEllipse::itemChange + * @param change + * @param value + * @return + */ +QVariant PartEllipse::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemSelectedHasChanged && scene()) { - if (!m_rect.isValid()) - m_rect = m_rect.normalized(); - - m_undo_command->setNewValue(QVariant(m_rect)); - elementScene()->undoStack().push(m_undo_command); - m_undo_command = nullptr; - m_handler_index = -1; + if (value.toBool() == true) + { + //When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler, + //according to the number of selected items. + connect(scene(), &QGraphicsScene::selectionChanged, this, &PartEllipse::sceneSelectionChanged); + + if (scene()->selectedItems().size() == 1) + addHandler(); + } + else + { + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartEllipse::sceneSelectionChanged); + removeHandler(); + } } - else - CustomElementGraphicPart::mouseReleaseEvent(event); + else if (change == ItemPositionHasChanged) + { + adjusteHandlerPos(); + } + else if (change == ItemSceneChange) + { + if(scene()) + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartEllipse::sceneSelectionChanged); + + setSelected(false); //This item is removed from scene, then we deselect this, and so, the handlers is also removed. + } + + return QGraphicsItem::itemChange(change, value); +} + +/** + * @brief PartEllipse::sceneEventFilter + * @param watched + * @param event + * @return + */ +bool PartEllipse::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) + { + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize + { + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) + { + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } + } + } + } + + return false; } void PartEllipse::switchResizeMode() { - if (m_resize_mode == 1) { + if (m_resize_mode == 1) + { m_resize_mode = 2; - m_handler.setOuterColor(Qt::darkGreen); + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::darkGreen); } - else { + else + { m_resize_mode = 1; - m_handler.setOuterColor(Qt::blue); + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::blue); + } +} + +/** + * @brief PartEllipse::adjusteHandlerPos + */ +void PartEllipse::adjusteHandlerPos() +{ + if (m_handler_vector.isEmpty()) + return; + + QVector points_vector = QetGraphicsHandlerUtility::pointsForRect(m_rect); + + if (m_handler_vector.size() == points_vector.size()) + { + points_vector = mapToScene(points_vector); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); + } +} + +/** + * @brief PartEllipse::handlerMousePressEvent + * @param qghi + * @param event + */ +void PartEllipse::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect)); + m_undo_command->setText(tr("Modifier un rectangle")); + m_undo_command->enableAnimation(); + return; +} + +/** + * @brief PartEllipse::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void PartEllipse::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + + QPointF new_pos = event->scenePos(); + if (event->modifiers() != Qt::ControlModifier) + new_pos = elementScene()->snapToGrid(event->scenePos()); + new_pos = mapFromScene(new_pos); + + if (m_resize_mode == 1) + setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(m_rect, new_pos, m_vector_index)); + else + setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(m_rect, new_pos, m_vector_index)); + + adjusteHandlerPos(); +} + +/** + * @brief PartEllipse::handlerMouseReleaseEvent + * @param qghi + * @param event + */ +void PartEllipse::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command->setNewValue(QVariant(m_rect)); + elementScene()->undoStack().push(m_undo_command); + m_undo_command = nullptr; + m_vector_index = -1; +} + +/** + * @brief PartEllipse::sceneSelectionChanged + * When the scene selection change, if there are several primitive selected, we remove the handler of this item + */ +void PartEllipse::sceneSelectionChanged() +{ + if (this->isSelected() && scene()->selectedItems().size() == 1) + addHandler(); + else + removeHandler(); +} + +/** + * @brief PartEllipse::addHandler + * Add handlers for this item + */ +void PartEllipse::addHandler() +{ + if (m_handler_vector.isEmpty() && scene()) + { + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForRect(m_rect))); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + QColor color = Qt::blue; + if (m_resize_mode == 2) + color = Qt::darkGreen; + + handler->setColor(color); + scene()->addItem(handler); + handler->installSceneEventFilter(this); + handler->setZValue(this->zValue()+1); + } + } +} + +/** + * @brief PartEllipse::removeHandler + * Remove the handlers of this item + */ +void PartEllipse::removeHandler() +{ + if (!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); } - update(); } diff --git a/sources/editor/graphicspart/partellipse.h b/sources/editor/graphicspart/partellipse.h index 7fe10594a..8369c8aec 100644 --- a/sources/editor/graphicspart/partellipse.h +++ b/sources/editor/graphicspart/partellipse.h @@ -19,7 +19,6 @@ #define PART_ELLIPSE_H #include "abstractpartellipse.h" -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" class QPropertyUndoCommand; @@ -55,24 +54,29 @@ class PartEllipse : public AbstractPartEllipse virtual QString xmlName() const { return(QString("ellipse")); } virtual const QDomElement toXml (QDomDocument &) const; virtual void fromXml (const QDomElement &); - - virtual QRectF boundingRect() const; virtual QPainterPath shape() const; virtual QPainterPath shadowShape() const; + virtual void setRect(const QRectF &rect) {AbstractPartEllipse::setRect(rect); adjusteHandlerPos();} protected: - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); private: void switchResizeMode(); + void adjusteHandlerPos(); + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void sceneSelectionChanged (); + + void addHandler(); + void removeHandler(); private: - QetGraphicsHandlerUtility m_handler; - int m_handler_index; QPropertyUndoCommand *m_undo_command; - int m_resize_mode = 1; + int m_resize_mode = 1, + m_vector_index = -1; }; #endif diff --git a/sources/editor/graphicspart/partline.cpp b/sources/editor/graphicspart/partline.cpp index 1985aae0f..05ed70612 100644 --- a/sources/editor/graphicspart/partline.cpp +++ b/sources/editor/graphicspart/partline.cpp @@ -19,6 +19,7 @@ #include #include "elementscene.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" /** @@ -33,14 +34,16 @@ PartLine::PartLine(QETElementEditor *editor, QGraphicsItem *parent) : first_length(1.5), second_end(Qet::None), second_length(1.5), - m_handler(10), - m_handler_index(-1), m_undo_command(nullptr) {} /// Destructeur -PartLine::~PartLine() { - if(m_undo_command) delete m_undo_command; +PartLine::~PartLine() +{ + if(m_undo_command) + delete m_undo_command; + + removeHandler(); } /** @@ -90,9 +93,6 @@ void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, if (m_hovered) drawShadowShape(painter); - if (isSelected() && scene()->selectedItems().size() == 1) - m_handler.drawHandler(painter, m_handler.pointsForLine(m_line)); - painter->restore(); } @@ -140,69 +140,206 @@ void PartLine::fromXml(const QDomElement &qde) { } /** - * @brief PartLine::mousePressEvent - * Handle mouse press event - * @param event + * @brief PartLine::itemChange + * @param change + * @param value + * @return */ -void PartLine::mousePressEvent(QGraphicsSceneMouseEvent *event) +QVariant PartLine::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { - if(event->button() == Qt::LeftButton) + if (change == ItemSelectedHasChanged && scene()) { - setCursor(Qt::ClosedHandCursor); - - if (isSelected()) + if (value.toBool() == true) { - m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForLine(m_line)); + //When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler, + //according to the number of selected items. + connect(scene(), &QGraphicsScene::selectionChanged, this, &PartLine::sceneSelectionChanged); + + if (scene()->selectedItems().size() == 1) + addHandler(); + } + else + { + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartLine::sceneSelectionChanged); + removeHandler(); + } + } + else if (change == ItemPositionHasChanged) + { + adjusteHandlerPos(); + } + else if (change == ItemSceneChange) + { + if(scene()) + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartLine::sceneSelectionChanged); + + setSelected(false); //This is item removed from scene, then we deselect this, and so, the handlers is also removed. + } + + return QGraphicsItem::itemChange(change, value); +} - if(m_handler_index >= 0 && m_handler_index <= 1) //User click on an handler +/** + * @brief PartLine::sceneEventFilter + * @param watched + * @param event + * @return + */ +bool PartLine::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) + { + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize + { + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) { - m_undo_command = new QPropertyUndoCommand(this, "line", QVariant(m_line)); - m_undo_command->setText(tr("Modifier une ligne")); - m_undo_command->enableAnimation(); - return; + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } } } } - - CustomElementGraphicPart::mousePressEvent(event); + + return false; } /** - * @brief PartLine::mouseMoveEvent - * Handle pouse move event - * @param event + * @brief PartLine::adjusteHandlerPos + * Adjust the position of the handler item */ -void PartLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +void PartLine::adjusteHandlerPos() { - if(m_handler_index >= 0 && m_handler_index <= 1) + if(m_handler_vector.isEmpty()) + return; + + QVector points_vector; + points_vector << m_line.p1() << m_line.p2(); + + if (m_handler_vector.size() == points_vector.size()) { - QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); - prepareGeometryChange(); - setLine(m_handler.lineForPosAtIndex(m_line, pos_, m_handler_index)); + points_vector = mapToScene(points_vector); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); } - else - CustomElementGraphicPart::mouseMoveEvent(event); } /** - * @brief PartLine::mouseReleaseEvent - * Handle mouse release event + * @brief PartLine::handlerMousePressEvent + * @param qghi * @param event */ -void PartLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +void PartLine::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::LeftButton) - setCursor(Qt::OpenHandCursor); + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command = new QPropertyUndoCommand(this, "line", QVariant(m_line)); + m_undo_command->setText(tr("Modifier une ligne")); + m_undo_command->enableAnimation(); + return; +} - if (m_handler_index >= 0 && m_handler_index <= 1) - { - m_undo_command->setNewValue(QVariant(m_line)); - elementScene()->undoStack().push(m_undo_command); - m_undo_command = nullptr; - m_handler_index = -1; - } +/** + * @brief PartLine::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void PartLine::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + + QPointF new_pos = event->scenePos(); + if (event->modifiers() != Qt::ControlModifier) + new_pos = elementScene()->snapToGrid(event->scenePos()); + new_pos = mapFromScene(new_pos); + + prepareGeometryChange(); + if (m_vector_index == 0) + m_line.setP1(new_pos); else - CustomElementGraphicPart::mouseReleaseEvent(event); + m_line.setP2(new_pos); + + adjusteHandlerPos(); +} + +/** + * @brief PartLine::handlerMouseReleaseEvent + * @param qghi + * @param event + */ +void PartLine::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command->setNewValue(QVariant(m_line)); + elementScene()->undoStack().push(m_undo_command); + m_undo_command = nullptr; + m_vector_index = -1; +} + +/** + * @brief PartLine::sceneSelectionChanged + * When the scene selection change, if there are several primitive selected, we remove the handler of this item + */ +void PartLine::sceneSelectionChanged() +{ + if (this->isSelected() && scene()->selectedItems().size() == 1) + addHandler(); + else + removeHandler(); +} + +/** + * @brief PartLine::addHandler + * Add handlers for this item + */ +void PartLine::addHandler() +{ + if (m_handler_vector.isEmpty() && scene()) + { + QVector points_vector; + points_vector << m_line.p1() << m_line.p2(); + + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(points_vector)); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + handler->setColor(Qt::blue); + scene()->addItem(handler); + handler->installSceneEventFilter(this); + handler->setZValue(this->zValue()+1); + } + } +} + +/** + * @brief PartLine::removeHandler + * Remove the handlers of this item + */ +void PartLine::removeHandler() +{ + if (!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + } } /** @@ -243,10 +380,6 @@ QPainterPath PartLine::shape() const pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); shape = pps.createStroke(shape); - if (isSelected()) - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForLine(m_line))) - shape.addRect(rect); - return shape; } @@ -402,9 +535,6 @@ QRectF PartLine::boundingRect() const bound = bound.normalized(); bound.adjust(-adjust, -adjust, adjust, adjust); - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForLine(m_line))) - bound |= rect; - return bound; } @@ -496,6 +626,7 @@ void PartLine::setLine(const QLineF &line) if (m_line == line) return; prepareGeometryChange(); m_line = line; + adjusteHandlerPos(); emit lineChanged(); } @@ -533,20 +664,6 @@ void PartLine::setSecondEndLength(const qreal &l) emit secondEndLengthChanged(); } -void PartLine::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - if (!isSelected()) - { - CustomElementGraphicPart::hoverMoveEvent(event); - return; - } - - if (m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForLine(m_line)) >= 0) - setCursor(Qt::SizeAllCursor); - else - CustomElementGraphicPart::hoverMoveEvent(event); -} - /** * @brief PartLine::path * @return this line has a QPainterPath. diff --git a/sources/editor/graphicspart/partline.h b/sources/editor/graphicspart/partline.h index b28582b77..3a0cc1bf7 100644 --- a/sources/editor/graphicspart/partline.h +++ b/sources/editor/graphicspart/partline.h @@ -20,9 +20,9 @@ #include "customelementgraphicpart.h" #include "qet.h" -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" class QPropertyUndoCommand; +class QetGraphicsHandlerItem; /** This class represents a line primitive which may be used to compose the @@ -96,19 +96,26 @@ class PartLine : public CustomElementGraphicPart void setSecondEndLength(const qreal &l); protected: - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); + private: + void adjusteHandlerPos(); + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void sceneSelectionChanged (); + + void addHandler(); + void removeHandler(); + QPainterPath path() const; - QList fourShapePoints() const; QRectF firstEndCircleRect() const; QRectF secondEndCircleRect() const; void debugPaint(QPainter *); + /*****************/ Qet::EndType first_end; qreal first_length; @@ -116,8 +123,8 @@ class PartLine : public CustomElementGraphicPart qreal second_length; QList saved_points_; QLineF m_line; - QetGraphicsHandlerUtility m_handler; - int m_handler_index; + int m_vector_index = -1; QPropertyUndoCommand *m_undo_command; + QVector m_handler_vector; }; #endif diff --git a/sources/editor/graphicspart/partpolygon.cpp b/sources/editor/graphicspart/partpolygon.cpp index 09ef418eb..8d157325f 100644 --- a/sources/editor/graphicspart/partpolygon.cpp +++ b/sources/editor/graphicspart/partpolygon.cpp @@ -18,6 +18,7 @@ #include "partpolygon.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" #include "elementscene.h" +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" /** @@ -29,16 +30,16 @@ PartPolygon::PartPolygon(QETElementEditor *editor, QGraphicsItem *parent) : CustomElementGraphicPart(editor, parent), m_closed(false), - m_handler(10), - m_handler_index(-1), m_undo_command(nullptr) {} /** * @brief PartPolygon::~PartPolygon */ -PartPolygon::~PartPolygon() { +PartPolygon::~PartPolygon() +{ if(m_undo_command) delete m_undo_command; + removeHandler(); } /** @@ -64,9 +65,6 @@ void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio if (m_hovered) drawShadowShape(painter); - - if (isSelected() && scene()->selectedItems().size() == 1) - m_handler.drawHandler(painter, m_polygon); } /** @@ -199,6 +197,7 @@ void PartPolygon::setPolygon(const QPolygonF &polygon) if (m_polygon == polygon) return; prepareGeometryChange(); m_polygon = polygon; + adjusteHandlerPos(); emit polygonChanged(); } @@ -248,83 +247,195 @@ void PartPolygon::setClosed(bool close) emit closedChange(); } -void PartPolygon::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +/** + * @brief PartPolygon::itemChange + * @param change + * @param value + * @return + */ +QVariant PartPolygon::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { - if (!isSelected()) + if (change == ItemSelectedHasChanged && scene()) { - CustomElementGraphicPart::hoverMoveEvent(event); - return; + if (value.toBool() == true) + { + //When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler, + //according to the number of selected items. + connect(scene(), &QGraphicsScene::selectionChanged, this, &PartPolygon::sceneSelectionChanged); + + if (scene()->selectedItems().size() == 1) + addHandler(); + } + else + { + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartPolygon::sceneSelectionChanged); + removeHandler(); + } } - - if (m_handler.pointIsHoverHandler(event->pos(), m_polygon) >= 0) - setCursor(Qt::SizeAllCursor); - else - CustomElementGraphicPart::hoverMoveEvent(event); + else if (change == ItemPositionHasChanged) + { + adjusteHandlerPos(); + } + else if (change == ItemSceneChange) + { + if(scene()) + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartPolygon::sceneSelectionChanged); + + setSelected(false); //This is item removed from scene, then we deselect this, and so, the handlers is also removed. + } + + return QGraphicsItem::itemChange(change, value); } /** - * @brief PartPolygon::mousePressEvent - * Handle mouse press event + * @brief PartPolygon::sceneEventFilter + * @param watched * @param event + * @return */ -void PartPolygon::mousePressEvent(QGraphicsSceneMouseEvent *event) +bool PartPolygon::sceneEventFilter(QGraphicsItem *watched, QEvent *event) { - if (event->button() == Qt::LeftButton) + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) { - setCursor(Qt::ClosedHandCursor); - if(isSelected()) + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize { - m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_polygon); - - if(m_handler_index >= 0) //User click on an handler + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) { - m_undo_command = new QPropertyUndoCommand(this, "polygon", QVariant(m_polygon)); - m_undo_command->setText(tr("Modifier un polygone")); - return; + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } } } } - - CustomElementGraphicPart::mousePressEvent(event); + + return false; } /** - * @brief PartPolygon::mouseMoveEvent - * Handle mouse move event - * @param event + * @brief PartPolygon::adjusteHandlerPos */ -void PartPolygon::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +void PartPolygon::adjusteHandlerPos() { - if(m_handler_index >= 0) + if(m_handler_vector.isEmpty()) + return; + + if (m_handler_vector.size() == m_polygon.size()) { - QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); - prepareGeometryChange(); - m_polygon.replace(m_handler_index, pos_); - emit polygonChanged(); + QVector points_vector = mapToScene(m_polygon); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); } - else - CustomElementGraphicPart::mouseMoveEvent(event); } /** - * @brief PartPolygon::mouseReleaseEvent - * Handle mouse release event + * @brief PartPolygon::handlerMousePressEvent + * @param qghi * @param event */ -void PartPolygon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +void PartPolygon::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::LeftButton) - setCursor(Qt::OpenHandCursor); + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command = new QPropertyUndoCommand(this, "polygon", QVariant(m_polygon)); + m_undo_command->setText(tr("Modifier un polygone")); +} - if (m_handler_index >= 0) - { - m_undo_command->setNewValue(QVariant(m_polygon)); - elementScene()->undoStack().push(m_undo_command); - m_undo_command = nullptr; - m_handler_index = -1; - } +/** + * @brief PartPolygon::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void PartPolygon::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + + QPointF new_pos = event->scenePos(); + if (event->modifiers() != Qt::ControlModifier) + new_pos = elementScene()->snapToGrid(event->scenePos()); + new_pos = mapFromScene(new_pos); + + prepareGeometryChange(); + m_polygon.replace(m_vector_index, new_pos); + adjusteHandlerPos(); + emit polygonChanged(); +} + +/** + * @brief PartPolygon::handlerMouseReleaseEvent + * @param qghi + * @param event + */ +void PartPolygon::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command->setNewValue(QVariant(m_polygon)); + elementScene()->undoStack().push(m_undo_command); + m_undo_command = nullptr; + m_vector_index = -1; +} + +/** + * @brief PartPolygon::sceneSelectionChanged + * When the scene selection change, if there are several primitive selected, we remove the handler of this item + */ +void PartPolygon::sceneSelectionChanged() +{ + if (this->isSelected() && scene()->selectedItems().size() == 1) + addHandler(); else - CustomElementGraphicPart::mouseReleaseEvent(event); + removeHandler(); +} + +/** + * @brief PartPolygon::addHandler + * Add handlers for this item + */ +void PartPolygon::addHandler() +{ + if (m_handler_vector.isEmpty() && scene()) + { + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(m_polygon)); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + handler->setColor(Qt::blue); + scene()->addItem(handler); + handler->installSceneEventFilter(this); + handler->setZValue(this->zValue()+1); + } + } +} + +/** + * @brief PartPolygon::removeHandler + * Remove the handlers of this item + */ +void PartPolygon::removeHandler() +{ + if (!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + } } /** @@ -343,10 +454,6 @@ QPainterPath PartPolygon::shape() const pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); shape = pps.createStroke(shape); - if (isSelected()) - foreach(QRectF rect, m_handler.handlerRect(m_polygon)) - shape.addRect(rect); - return shape; } @@ -379,8 +486,5 @@ QRectF PartPolygon::boundingRect() const r.adjust(-adjust, -adjust, adjust, adjust); - foreach(QRectF rect, m_handler.handlerRect(m_polygon)) - r |=rect; - return(r); } diff --git a/sources/editor/graphicspart/partpolygon.h b/sources/editor/graphicspart/partpolygon.h index ea0e9dbf0..371c46f14 100644 --- a/sources/editor/graphicspart/partpolygon.h +++ b/sources/editor/graphicspart/partpolygon.h @@ -20,10 +20,9 @@ #include #include "customelementgraphicpart.h" -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" - class QPropertyUndoCommand; +class QetGraphicsHandlerItem; /** * @brief The PartPolygon class @@ -85,17 +84,25 @@ class PartPolygon : public CustomElementGraphicPart void setClosed (bool close); protected: - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); private: + void adjusteHandlerPos(); + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void sceneSelectionChanged (); + + void addHandler(); + void removeHandler(); + + bool m_closed; QList saved_points_; QPolygonF m_polygon; - QetGraphicsHandlerUtility m_handler; - int m_handler_index; QPropertyUndoCommand *m_undo_command; + int m_vector_index = -1; + QVector m_handler_vector; }; #endif diff --git a/sources/editor/graphicspart/partrectangle.cpp b/sources/editor/graphicspart/partrectangle.cpp index 9c238df3b..31400b645 100644 --- a/sources/editor/graphicspart/partrectangle.cpp +++ b/sources/editor/graphicspart/partrectangle.cpp @@ -18,6 +18,8 @@ #include "partrectangle.h" #include "elementscene.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" +#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" /** * @brief PartRectangle::PartRectangle @@ -27,16 +29,16 @@ */ PartRectangle::PartRectangle(QETElementEditor *editor, QGraphicsItem *parent) : CustomElementGraphicPart(editor, parent), - m_handler(10), - m_handler_index(-1), m_undo_command(nullptr) {} /** * @brief PartRectangle::~PartRectangle */ -PartRectangle::~PartRectangle() { +PartRectangle::~PartRectangle() +{ if(m_undo_command) delete m_undo_command; + removeHandler(); } /** @@ -69,11 +71,7 @@ void PartRectangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt drawShadowShape(painter); if (isSelected()) - { drawCross(m_rect.center(), painter); - if (scene()->selectedItems().size() == 1) - m_handler.drawHandler(painter, m_handler.pointsForRect(m_rect)); - } } /** @@ -129,6 +127,7 @@ void PartRectangle::setRect(const QRectF &rect) if (rect == m_rect) return; prepareGeometryChange(); m_rect = rect; + adjusteHandlerPos(); emit rectChanged(); } @@ -164,10 +163,6 @@ QPainterPath PartRectangle::shape() const pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); shape = pps.createStroke(shape); - if (isSelected()) - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect))) - shape.addRect(rect); - return shape; } @@ -196,9 +191,6 @@ QRectF PartRectangle::boundingRect() const QRectF r = m_rect.normalized(); r.adjust(-adjust, -adjust, adjust, adjust); - foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect))) - r |= rect; - return(r); } @@ -237,77 +229,6 @@ void PartRectangle::handleUserTransformation(const QRectF &initial_selection_rec setRect(QRectF(mapFromScene(mapped_points.at(0)), mapFromScene(mapped_points.at(1)))); } -void PartRectangle::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - if (!isSelected()) - { - CustomElementGraphicPart::hoverMoveEvent(event); - return; - } - - int handler = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect)); - - if (handler >= 0) - { - if (handler == 0 || handler == 2 || handler == 5 || handler == 7) - setCursor(Qt::SizeAllCursor); - else if (handler == 1 || handler == 6) - setCursor(Qt::SizeVerCursor); - else if (handler == 3 || handler == 4) - setCursor(Qt::SizeHorCursor); - } - else - CustomElementGraphicPart::hoverMoveEvent(event); -} - -/** - * @brief PartRectangle::mousePressEvent - * Handle mouse press event - * @param event - */ -void PartRectangle::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - { - setCursor(Qt::ClosedHandCursor); - if(isSelected()) - { - m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect)); - - if(m_handler_index >= 0 && m_handler_index <= 7) //User click on an handler - { - m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect)); - m_undo_command->setText(tr("Modifier un rectangle")); - m_undo_command->enableAnimation(); - return; - } - } - } - - CustomElementGraphicPart::mousePressEvent(event); -} - -/** - * @brief PartRectangle::mouseMoveEvent - * Handle mouse press event - * @param event - */ -void PartRectangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - if(m_handler_index >= 0 && m_handler_index <= 7) - { - QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); - prepareGeometryChange(); - - if (m_resize_mode == 1) - setRect(m_handler.rectForPosAtIndex(m_rect, pos_, m_handler_index)); - else - setRect(m_handler.mirrorRectForPosAtIndex(m_rect, pos_, m_handler_index)); - } - else - CustomElementGraphicPart::mouseMoveEvent(event); -} - /** * @brief PartRectangle::mouseReleaseEvent * Handle mouse release event @@ -315,35 +236,223 @@ void PartRectangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) */ void PartRectangle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::LeftButton) { - setCursor(Qt::OpenHandCursor); - if (event->buttonDownPos(Qt::LeftButton) == event->pos()) - switchResizeMode(); - } - - if (m_handler_index >= 0 && m_handler_index <= 7) - { - if (!m_rect.isValid()) - m_rect = m_rect.normalized(); - - m_undo_command->setNewValue(QVariant(m_rect)); - elementScene()->undoStack().push(m_undo_command); - m_undo_command = nullptr; - m_handler_index = -1; - } - else - CustomElementGraphicPart::mouseReleaseEvent(event); + if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos()) + switchResizeMode(); + + CustomElementGraphicPart::mouseReleaseEvent(event); } +/** + * @brief PartRectangle::itemChange + * @param change + * @param value + * @return + */ +QVariant PartRectangle::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemSelectedHasChanged && scene()) + { + if (value.toBool() == true) + { + //When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler, + //according to the number of selected items. + connect(scene(), &QGraphicsScene::selectionChanged, this, &PartRectangle::sceneSelectionChanged); + + if (scene()->selectedItems().size() == 1) + addHandler(); + } + else + { + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartRectangle::sceneSelectionChanged); + removeHandler(); + } + } + else if (change == ItemPositionHasChanged) + { + adjusteHandlerPos(); + } + else if (change == ItemSceneChange) + { + if(scene()) + disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartRectangle::sceneSelectionChanged); + + setSelected(false); //This item is removed from scene, then we deselect this, and so, the handlers is also removed. + } + + return QGraphicsItem::itemChange(change, value); +} + +/** + * @brief PartRectangle::sceneEventFilter + * @param watched + * @param event + * @return + */ +bool PartRectangle::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) + { + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize + { + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) + { + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } + } + } + } + + return false; +} + +/** + * @brief PartRectangle::switchResizeMode + */ void PartRectangle::switchResizeMode() { - if (m_resize_mode == 1) { + if (m_resize_mode == 1) + { m_resize_mode = 2; - m_handler.setOuterColor(Qt::darkGreen); + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::darkGreen); } - else { + else + { m_resize_mode = 1; - m_handler.setOuterColor(Qt::blue); + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::blue); + } +} + +/** + * @brief PartRectangle::adjusteHandlerPos + */ +void PartRectangle::adjusteHandlerPos() +{ + if (m_handler_vector.isEmpty()) + return; + + QVector points_vector = QetGraphicsHandlerUtility::pointsForRect(m_rect); + + if (m_handler_vector.size() == points_vector.size()) + { + points_vector = mapToScene(points_vector); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); + } +} + +/** + * @brief PartRectangle::handlerMousePressEvent + * @param qghi + * @param event + */ +void PartRectangle::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect)); + m_undo_command->setText(tr("Modifier un rectangle")); + m_undo_command->enableAnimation(); + return; +} + +/** + * @brief PartRectangle::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void PartRectangle::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + + QPointF new_pos = event->scenePos(); + if (event->modifiers() != Qt::ControlModifier) + new_pos = elementScene()->snapToGrid(event->scenePos()); + new_pos = mapFromScene(new_pos); + + if (m_resize_mode == 1) + setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(m_rect, new_pos, m_vector_index)); + else + setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(m_rect, new_pos, m_vector_index)); + + adjusteHandlerPos(); +} + +void PartRectangle::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_undo_command->setNewValue(QVariant(m_rect)); + elementScene()->undoStack().push(m_undo_command); + m_undo_command = nullptr; + m_vector_index = -1; +} + +/** + * @brief PartRectangle::sceneSelectionChanged + * When the scene selection change, if there are several primitive selected, we remove the handler of this item + */ +void PartRectangle::sceneSelectionChanged() +{ + if (this->isSelected() && scene()->selectedItems().size() == 1) + addHandler(); + else + removeHandler(); +} + +/** + * @brief PartRectangle::addHandler + * Add handlers for this item + */ +void PartRectangle::addHandler() +{ + if (m_handler_vector.isEmpty() && scene()) + { + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForRect(m_rect))); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + QColor color = Qt::blue; + if (m_resize_mode == 2) + color = Qt::darkGreen; + + handler->setColor(color); + scene()->addItem(handler); + handler->installSceneEventFilter(this); + handler->setZValue(this->zValue()+1); + } + } +} + +/** + * @brief PartRectangle::removeHandler + * Remove the handlers of this item + */ +void PartRectangle::removeHandler() +{ + if (!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); } - update(); } diff --git a/sources/editor/graphicspart/partrectangle.h b/sources/editor/graphicspart/partrectangle.h index b840920b5..014941b85 100644 --- a/sources/editor/graphicspart/partrectangle.h +++ b/sources/editor/graphicspart/partrectangle.h @@ -19,9 +19,9 @@ #define PART_RECTANGLE_H #include "customelementgraphicpart.h" -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" class QPropertyUndoCommand; +class QetGraphicsHandlerItem; /** * This class represents a rectangle primitive which may be used to compose the @@ -75,20 +75,27 @@ class PartRectangle : public CustomElementGraphicPart virtual void handleUserTransformation(const QRectF &, const QRectF &); protected: - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); private: void switchResizeMode(); + void adjusteHandlerPos(); + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void sceneSelectionChanged (); + + void addHandler(); + void removeHandler(); private: QRectF m_rect; QList saved_points_; - QetGraphicsHandlerUtility m_handler; - int m_handler_index; QPropertyUndoCommand *m_undo_command; - int m_resize_mode = 1; + int m_resize_mode = 1, + m_vector_index = -1; + QVector m_handler_vector; }; #endif diff --git a/sources/editor/graphicspart/parttext.cpp b/sources/editor/graphicspart/parttext.cpp index 81599d0d1..bc1eb8290 100644 --- a/sources/editor/graphicspart/parttext.cpp +++ b/sources/editor/graphicspart/parttext.cpp @@ -26,20 +26,17 @@ Constructeur @param editor L'editeur d'element concerne @param parent Le QGraphicsItem parent de ce texte statique - @param scene La scene sur laquelle figure ce texte statique */ -PartText::PartText(QETElementEditor *editor, QGraphicsItem *parent, ElementScene *scene) : +PartText::PartText(QETElementEditor *editor, QGraphicsItem *parent) : QGraphicsTextItem(parent), CustomElementPart(editor), - previous_text(), - decorator_(0) + previous_text() { - Q_UNUSED(scene) document() -> setDocumentMargin(1.0); setDefaultTextColor(Qt::black); setFont(QETApp::diagramTextsFont()); real_font_size_ = font().pointSize(); - setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges); + setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsMovable); setAcceptHoverEvents(true); setDefaultTextColor(Qt::black); setPlainText(QObject::tr("T", "default text when adding a text in the element editor")); @@ -231,150 +228,37 @@ void PartText::handleUserTransformation(const QRectF &initial_selection_rect, co setProperty("real_size", qMax(1, qRound(new_font_size))); } -/** - Dessine le texte statique. - @param painter QPainter a utiliser pour effectuer le rendu - @param qsogi Pptions de dessin - @param widget Widget sur lequel on dessine (facultatif) -*/ -void PartText::paint(QPainter *painter, const QStyleOptionGraphicsItem *qsogi, QWidget *widget) { - // According to the source code of QGraphicsTextItem::paint(), this should - // avoid the drawing of the dashed rectangle around the text. - QStyleOptionGraphicsItem our_qsogi(*qsogi); - our_qsogi.state = QStyle::State_None; - - QGraphicsTextItem::paint(painter, &our_qsogi, widget); - -#ifdef QET_DEBUG_EDITOR_TEXTS - painter -> setPen(Qt::blue); - painter -> drawRect(boundingRect()); - - painter -> setPen(Qt::red); - drawPoint(painter, QPointF(0, 0)); - - painter -> setPen(Qt::green); - drawPoint(painter, mapFromScene(pos())); -#endif + +void PartText::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if((event->buttons() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable)) + { + QPointF pos = event->scenePos() + (m_origine_pos - event->buttonDownScenePos(Qt::LeftButton)); + event->modifiers() == Qt::ControlModifier ? setPos(pos) : setPos(elementScene()->snapToGrid(pos)); + } + else + QGraphicsObject::mouseMoveEvent(event); } -/** - Handle context menu events. - @param event Object describing the context menu event to handle. -*/ -void PartText::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { - Q_UNUSED(event); +void PartText::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) + m_origine_pos = this->pos(); + + QGraphicsObject::mousePressEvent(event); } -/** - Handle events generated when the mouse hovers over the decorator. - @param event Object describing the hover event. -*/ -void PartText::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { - // force the cursor when the text is being edited - if (hasFocus() && decorator_) { - decorator_ -> setCursor(Qt::IBeamCursor); - } - QGraphicsTextItem::hoverMoveEvent(event); -} +void PartText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if((event->button() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable) && m_origine_pos != pos()) + { + QPropertyUndoCommand *undo = new QPropertyUndoCommand(this, "pos", QVariant(m_origine_pos), QVariant(pos())); + undo->setText(tr("Déplacer un texte")); + undo->enableAnimation(); + elementScene()->undoStack().push(undo); + } -/** - @reimp CustomElementPart::setDecorator(ElementPrimitiveDecorator *) - Install or remove a sceneEventFilter on the decorator and ensure it will - adjust itself while the text is being edited. -*/ -void PartText::setDecorator(ElementPrimitiveDecorator *decorator) { - if (decorator) { - decorator -> installSceneEventFilter(this); - // ensure the decorator will adjust itself when the text area expands or shrinks - connect(document(), SIGNAL(contentsChanged()), decorator, SLOT(adjust())); - } - else { - decorator_ -> removeSceneEventFilter(this); - endEdition(); - } - decorator_ = decorator; -} - -/** - @reimp QGraphicsItem::sceneEventFilter(QGraphicsItem *, QEvent *). - Intercepts events before they reach the watched target, i.e. typically the - primitives decorator. - This method mainly works with key strokes (F2, escape) and double clicks to - begin or end text edition. -*/ -bool PartText::sceneEventFilter(QGraphicsItem *watched, QEvent *event) { - if (watched != decorator_) return(false); - - QPointF event_scene_pos = QET::graphicsSceneEventPos(event); - if (!event_scene_pos.isNull()) { - if (contains(mapFromScene(event_scene_pos))) { - if (hasFocus()) { - return sceneEvent(event); // manually deliver the event to this item - return(true); // prevent this event from being delivered to any item - } else { - if (event -> type() == QEvent::GraphicsSceneMouseDoubleClick) { - mouseDoubleClickEvent(static_cast(event)); - } - } - } - } - else if (event -> type() == QEvent::KeyRelease || event -> type() == QEvent::KeyPress) { - // Intercept F2 and escape keystrokes to focus in and out - QKeyEvent *key_event = static_cast(event); - if (!hasFocus() && key_event -> key() == Qt::Key_F2) { - setEditable(true); - QTextCursor qtc = textCursor(); - qtc.setPosition(qMax(0, document()->characterCount() - 1)); - setTextCursor(qtc); - } else if (hasFocus() && key_event -> key() == Qt::Key_Escape) { - endEdition(); - } - if (hasFocus()) { - sceneEvent(event); // manually deliver the event to this item - return(true); // prevent this event from being delivered to any item - } - } - return(false); -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartText::singleItemPressEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - Q_UNUSED(event) - return(hasFocus()); -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartText::singleItemMoveEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - Q_UNUSED(event) - return(hasFocus()); -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartText::singleItemReleaseEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - Q_UNUSED(event) - return(hasFocus()); -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartText::singleItemDoubleClickEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - // calling mouseDoubleClickEvent() will set this text item editable and grab keyboard focus - if (event -> button() == Qt::LeftButton) { - mouseDoubleClickEvent(event); - return(true); - } - return(false); + QGraphicsObject::mouseReleaseEvent(event); } /** @@ -442,27 +326,4 @@ void PartText::endEdition() setTextCursor(qtc); setEditable(false); - if (decorator_) { - decorator_ -> setFocus(); - } } - -#ifdef QET_DEBUG_EDITOR_TEXTS -/** - Dessine deux petites fleches pour mettre un point en valeur - @param painter QPainter a utiliser pour effectuer le rendu - @param point Point a dessiner -*/ -void PartText::drawPoint(QPainter *painter, const QPointF &point) { - qreal px = point.x(); - qreal py = point.y(); - qreal size_1 = 5.0; - qreal size_2 = 1.0; - painter -> drawLine(QLineF(px, py, px + size_1, py)); - painter -> drawLine(QLineF(px + size_1 - size_2, py - size_2, px + size_1, py)); - painter -> drawLine(QLineF(px + size_1 - size_2, py + size_2, px + size_1, py)); - painter -> drawLine(QLineF(px, py, px, py + size_1)); - painter -> drawLine(QLineF(px, py + size_1, px - size_2, py + size_1 - size_2)); - painter -> drawLine(QLineF(px, py + size_1, px + size_2, py + size_1 - size_2)); -} -#endif diff --git a/sources/editor/graphicspart/parttext.h b/sources/editor/graphicspart/parttext.h index 593455ee7..1fa9bef47 100644 --- a/sources/editor/graphicspart/parttext.h +++ b/sources/editor/graphicspart/parttext.h @@ -31,7 +31,7 @@ class PartText : public QGraphicsTextItem, public CustomElementPart { // constructors, destructor public: - PartText(QETElementEditor *, QGraphicsItem * = 0, ElementScene * = 0); + PartText(QETElementEditor *, QGraphicsItem * = 0); virtual ~PartText(); private: @@ -55,12 +55,6 @@ class PartText : public QGraphicsTextItem, public CustomElementPart { virtual QRectF sceneGeometricRect() const; virtual void startUserTransformation(const QRectF &); virtual void handleUserTransformation(const QRectF &, const QRectF &); - virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0 ); - virtual void setDecorator(ElementPrimitiveDecorator *); - virtual bool singleItemPressEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemMoveEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemReleaseEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemDoubleClickEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); ///PROPERTY void setProperty(const char *name, const QVariant &value) {QGraphicsTextItem::setProperty(name, value);} @@ -81,31 +75,29 @@ class PartText : public QGraphicsTextItem, public CustomElementPart { Q_PROPERTY(QString text READ toPlainText WRITE setPlainText) public slots: - void adjustItemPosition(int = 0); - void setEditable(bool); - void startEdition(); - void endEdition(); + void adjustItemPosition(int = 0); + void setEditable(bool); + void startEdition(); + void endEdition(); protected: - virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *); - virtual bool sceneEventFilter(QGraphicsItem *, QEvent *); - virtual void focusInEvent(QFocusEvent *); - virtual void focusOutEvent(QFocusEvent *); - virtual void keyPressEvent(QKeyEvent *); - virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *); - virtual QVariant itemChange(GraphicsItemChange, const QVariant &); - QRectF boundingRect() const; + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void focusInEvent(QFocusEvent *); + virtual void focusOutEvent(QFocusEvent *); + virtual void keyPressEvent(QKeyEvent *); + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *); + virtual QVariant itemChange(GraphicsItemChange, const QVariant &); + QRectF boundingRect() const; private: - QPointF margin() const; -#ifdef QET_DEBUG_EDITOR_TEXTS - void drawPoint(QPainter *, const QPointF &); -#endif - QString previous_text; - qreal real_font_size_; - QPointF saved_point_; - qreal saved_font_size_; - QGraphicsItem *decorator_; + QPointF margin() const; + QString previous_text; + qreal real_font_size_; + QPointF saved_point_; + qreal saved_font_size_; + QGraphicsItem *decorator_; + QPointF m_origine_pos; }; #endif diff --git a/sources/editor/graphicspart/parttextfield.cpp b/sources/editor/graphicspart/parttextfield.cpp index c53a36a91..aad893a02 100644 --- a/sources/editor/graphicspart/parttextfield.cpp +++ b/sources/editor/graphicspart/parttextfield.cpp @@ -20,26 +20,24 @@ #include "elementprimitivedecorator.h" #include "qetapp.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" +#include "elementscene.h" /** Constructeur @param editor L'editeur d'element concerne @param parent Le QGraphicsItem parent de ce champ de texte - @param scene La scene sur laquelle figure ce champ de texte */ -PartTextField::PartTextField(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : +PartTextField::PartTextField(QETElementEditor *editor, QGraphicsItem *parent) : QGraphicsTextItem(parent), CustomElementPart(editor), follow_parent_rotations(true), m_tagg("none"), - previous_text(), - decorator_(0) + previous_text() { - Q_UNUSED(scene); setDefaultTextColor(Qt::black); setFont(QETApp::diagramTextsFont()); real_font_size_ = font().pointSize(); - setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges); + setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsMovable); setAcceptHoverEvents(true); setPlainText(QObject::tr("_", "default text when adding a textfield in the element editor")); @@ -112,73 +110,43 @@ QPointF PartTextField::margin() const { return(QPointF(0.0, boundingRect().bottom() / 2.0)); } -/** - Handle context menu events. - @param event Object describing the context menu event to handle. -*/ -void PartTextField::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { - Q_UNUSED(event); +void PartTextField::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if((event->buttons() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable)) + { + QPointF pos = event->scenePos() + (m_origine_pos - event->buttonDownScenePos(Qt::LeftButton)); + event->modifiers() == Qt::ControlModifier ? setPos(pos) : setPos(elementScene()->snapToGrid(pos)); + } + else + QGraphicsObject::mouseMoveEvent(event); +} + +void PartTextField::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) + m_origine_pos = this->pos(); + + QGraphicsObject::mousePressEvent(event); +} + +void PartTextField::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if((event->button() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable) && m_origine_pos != pos()) + { + QPropertyUndoCommand *undo = new QPropertyUndoCommand(this, "pos", QVariant(m_origine_pos), QVariant(pos())); + undo->setText(tr("Déplacer un champ texte")); + undo->enableAnimation(); + elementScene()->undoStack().push(undo); + } + + QGraphicsObject::mouseReleaseEvent(event); } /** - Handle events generated when the mouse hovers over the decorator. - @param event Object describing the hover event. -*/ -void PartTextField::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { - // force the cursor when the text is being edited - if (hasFocus() && decorator_) { - decorator_ -> setCursor(Qt::IBeamCursor); - } - QGraphicsTextItem::hoverMoveEvent(event); -} - -/** - @reimp QGraphicsItem::sceneEventFilter(QGraphicsItem *, QEvent *). - Intercepts events before they reach the watched target, i.e. typically the - primitives decorator. - This method mainly works with key strokes (F2, escape) and double clicks to - begin or end text edition. -*/ -bool PartTextField::sceneEventFilter(QGraphicsItem *watched, QEvent *event) { - if (watched != decorator_) return(false); - - QPointF event_scene_pos = QET::graphicsSceneEventPos(event); - if (!event_scene_pos.isNull()) { - if (contains(mapFromScene(event_scene_pos))) { - if (hasFocus()) { - return sceneEvent(event); // manually deliver the event to this item - return(true); // prevent this event from being delivered to any item - } else { - if (event -> type() == QEvent::GraphicsSceneMouseDoubleClick) { - mouseDoubleClickEvent(static_cast(event)); - } - } - } - } - else if (event -> type() == QEvent::KeyRelease || event -> type() == QEvent::KeyPress) { - // Intercept F2 and escape keystrokes to focus in and out - QKeyEvent *key_event = static_cast(event); - if (!hasFocus() && key_event -> key() == Qt::Key_F2) { - setEditable(true); - QTextCursor qtc = textCursor(); - qtc.setPosition(qMax(0, document()->characterCount() - 1)); - setTextCursor(qtc); - } else if (hasFocus() && key_event -> key() == Qt::Key_Escape) { - endEdition(); - } - if (hasFocus()) { - sceneEvent(event); // manually deliver the event to this item - return(true); // prevent this event from being delivered to any item - } - } - return(false); -} - -/* - @reimp QGraphicsItem::focusInEvent(QFocusEvent *) - @param e The QFocusEvent object describing the focus gain. - Start text edition when the item gains focus. -*/ + * @brief PartTextField::focusInEvent + * @param e The QFocusEvent object describing the focus gain. + Start text edition when the item gains focus. + */ void PartTextField::focusInEvent(QFocusEvent *e) { startEdition(); QGraphicsTextItem::focusInEvent(e); @@ -286,88 +254,6 @@ void PartTextField::handleUserTransformation(const QRectF &initial_selection_rec qreal new_font_size = saved_font_size_ * sy; setProperty("real_size", qMax(1, qRound(new_font_size))); } -/** - Dessine le texte statique. - @param painter QPainter a utiliser pour effectuer le rendu - @param qsogi Pptions de dessin - @param widget Widget sur lequel on dessine (facultatif) -*/ -void PartTextField::paint(QPainter *painter, const QStyleOptionGraphicsItem *qsogi, QWidget *widget) { - // According to the source code of QGraphicsTextItem::paint(), this should - // avoid the drawing of the dashed rectangle around the text. - QStyleOptionGraphicsItem our_qsogi(*qsogi); - our_qsogi.state = QStyle::State_None; - - QGraphicsTextItem::paint(painter, &our_qsogi, widget); -#ifdef QET_DEBUG_EDITOR_TEXTS - painter -> setPen(Qt::blue); - painter -> drawRect(boundingRect()); - - painter -> setPen(Qt::red); - drawPoint(painter, QPointF(0, 0)); - - painter -> setPen(QColor("#800000")); - drawPoint(painter, mapFromScene(pos())); -#endif -} - -/** - @reimp CustomElementPart::setDecorator(ElementPrimitiveDecorator *) - Install or remove a sceneEventFilter on the decorator and ensure it will - adjust itself while the text is being edited. -*/ -void PartTextField::setDecorator(ElementPrimitiveDecorator *decorator) { - if (decorator) { - decorator -> installSceneEventFilter(this); - // ensure the decorator will adjust itself when the text area expands or shrinks - connect(document(), SIGNAL(contentsChanged()), decorator, SLOT(adjust())); - } - else { - decorator_ -> removeSceneEventFilter(this); - endEdition(); - } - decorator_ = decorator; -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartTextField::singleItemPressEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - Q_UNUSED(event) - return(hasFocus()); -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartTextField::singleItemMoveEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - Q_UNUSED(event) - return(hasFocus()); -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartTextField::singleItemReleaseEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - Q_UNUSED(event) - return(hasFocus()); -} - -/** - Accept the mouse \a event relayed by \a decorator if this text item has focus. -*/ -bool PartTextField::singleItemDoubleClickEvent(ElementPrimitiveDecorator *decorator, QGraphicsSceneMouseEvent *event) { - Q_UNUSED(decorator) - // calling mouseDoubleClickEvent() will set this text item editable and grab keyboard focus - if (event -> button() == Qt::LeftButton) { - mouseDoubleClickEvent(event); - return(true); - } - return(false); -} /** Cette methode s'assure que la position du champ de texte est coherente @@ -434,27 +320,4 @@ void PartTextField::endEdition() setTextCursor(qtc); setEditable(false); - if (decorator_) { - decorator_ -> setFocus(); - } } - -#ifdef QET_DEBUG_EDITOR_TEXTS -/** - Dessine deux petites fleches pour mettre un point en valeur - @param painter QPainter a utiliser pour effectuer le rendu - @param point Point a dessiner -*/ -void PartTextField::drawPoint(QPainter *painter, const QPointF &point) { - qreal px = point.x(); - qreal py = point.y(); - qreal size_1 = 5.0; - qreal size_2 = 1.0; - painter -> drawLine(QLineF(px, py, px + size_1, py)); - painter -> drawLine(QLineF(px + size_1 - size_2, py - size_2, px + size_1, py)); - painter -> drawLine(QLineF(px + size_1 - size_2, py + size_2, px + size_1, py)); - painter -> drawLine(QLineF(px, py, px, py + size_1)); - painter -> drawLine(QLineF(px, py + size_1, px - size_2, py + size_1 - size_2)); - painter -> drawLine(QLineF(px, py + size_1, px + size_2, py + size_1 - size_2)); -} -#endif diff --git a/sources/editor/graphicspart/parttextfield.h b/sources/editor/graphicspart/parttextfield.h index 63200fe82..32ed24641 100644 --- a/sources/editor/graphicspart/parttextfield.h +++ b/sources/editor/graphicspart/parttextfield.h @@ -29,12 +29,13 @@ class ElementPrimitiveDecorator; a default value. The field will remain editable once the element is added onto a diagram. lorsque l'element sera pose sur un schema. */ -class PartTextField : public QGraphicsTextItem, public CustomElementPart { +class PartTextField : public QGraphicsTextItem, public CustomElementPart +{ Q_OBJECT // constructors, destructor public: - PartTextField(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0); + PartTextField(QETElementEditor *, QGraphicsItem * = 0); virtual ~PartTextField(); private: @@ -61,12 +62,6 @@ class PartTextField : public QGraphicsTextItem, public CustomElementPart { virtual QRectF sceneGeometricRect() const; virtual void startUserTransformation(const QRectF &); virtual void handleUserTransformation(const QRectF &, const QRectF &); - virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0 ); - virtual void setDecorator(ElementPrimitiveDecorator *); - virtual bool singleItemPressEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemMoveEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemReleaseEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); - virtual bool singleItemDoubleClickEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *); ///PROPERTY virtual void setProperty(const char *name, const QVariant &value) {QGraphicsTextItem::setProperty(name, value);} @@ -101,26 +96,23 @@ class PartTextField : public QGraphicsTextItem, public CustomElementPart { void startEdition(); void endEdition(); - protected: - virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *); - virtual bool sceneEventFilter(QGraphicsItem *, QEvent *); - virtual void focusInEvent(QFocusEvent *); - virtual void focusOutEvent(QFocusEvent *); - virtual void keyPressEvent(QKeyEvent *); - virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *); - virtual QVariant itemChange(GraphicsItemChange, const QVariant &); - QRectF boundingRect() const; + protected: + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void focusInEvent(QFocusEvent *); + virtual void focusOutEvent(QFocusEvent *); + virtual void keyPressEvent(QKeyEvent *); + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *); + virtual QVariant itemChange(GraphicsItemChange, const QVariant &); + QRectF boundingRect() const; private: - QPointF margin() const; -#ifdef QET_DEBUG_EDITOR_TEXTS - void drawPoint(QPainter *, const QPointF &); -#endif - QString previous_text; - qreal real_font_size_; - QPointF saved_point_; - qreal saved_font_size_; - QGraphicsItem *decorator_; + QPointF margin() const; + QString previous_text; + qreal real_font_size_; + QPointF saved_point_; + qreal saved_font_size_; + QPointF m_origine_pos; }; #endif diff --git a/sources/qetgraphicsitem/conductor.cpp b/sources/qetgraphicsitem/conductor.cpp index 9fc15a632..a094fc974 100644 --- a/sources/qetgraphicsitem/conductor.cpp +++ b/sources/qetgraphicsitem/conductor.cpp @@ -78,17 +78,16 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) : terminal1(p1), terminal2(p2), m_mouse_over(false), - m_handler(10), m_text_item(0), segments(NULL), - moving_segment(false), + m_moving_segment(false), modified_path(false), has_to_save_profile(false), must_highlight_(Conductor::None) { //set Zvalue at 11 to be upper than the DiagramImageItem and element setZValue(11); - previous_z_value = zValue(); + m_previous_z_value = zValue(); //Add this conductor to the list of conductor of each of the two terminal bool ajout_p1 = terminal1 -> addConductor(this); @@ -117,7 +116,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) : //Generate the path of this conductor. generateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation()); - setFlags(QGraphicsItem::ItemIsSelectable); + setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsScenePositionChanges); setAcceptHoverEvents(true); // Add the text field @@ -137,6 +136,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) : */ Conductor::~Conductor() { + removeHandler(); terminal1->removeConductor(this); terminal2->removeConductor(this); deleteSegments(); @@ -171,30 +171,39 @@ void Conductor::updatePath(const QRectF &rect) { } /** - Genere le QPainterPath a partir de la liste des points -*/ -void Conductor::segmentsToPath() { - // chemin qui sera dessine + * @brief Conductor::segmentsToPath + * Generate the QPainterPath from the list of points + */ +void Conductor::segmentsToPath() +{ QPainterPath path; - // s'il n'y a pa des segments, on arrete la - if (segments == NULL) setPath(path); + if (segments == NULL) + setPath(path); - // demarre le chemin + //Start the path path.moveTo(segments -> firstPoint()); - - // parcourt les segments pour dessiner le chemin + //Each segments ConductorSegment *segment = segments; while(segment -> hasNextSegment()) { path.lineTo(segment -> secondPoint()); segment = segment -> nextSegment(); } - - // termine le chemin + //Finish the path path.lineTo(segment -> secondPoint()); - // affecte le chemin au conducteur setPath(path); + + //If conductor is selected and he's not being modified + //we update the position of the handlers + if (isSelected() && !m_moving_segment) + { + if(handlerPoints().size() == m_handler_vector.size()) + adjusteHandlerPos(); + else + removeHandler(); + addHandler(); + } } /** @@ -467,7 +476,7 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi qp -> save(); qp -> setRenderHint(QPainter::Antialiasing, false); - // determine la couleur du conducteur + // Set the color of conductor QColor final_conductor_color(m_properties.color); if (must_highlight_ == Normal) { final_conductor_color = QColor::fromRgb(69, 137, 255, 255); @@ -486,24 +495,38 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi //Draw the conductor bigger when is hovered conductor_pen.setWidthF(m_mouse_over? (m_properties.cond_size) +4 : (m_properties.cond_size)); - // affectation du QPen et de la QBrush modifies au QPainter + //Set the QPen and QBrush to the QPainter qp -> setBrush(conductor_brush); QPen final_conductor_pen = conductor_pen; - // modification du QPen generique pour lui affecter la couleur et le style adequats + //Set the conductor style final_conductor_pen.setColor(final_conductor_color); final_conductor_pen.setStyle(m_properties.style); - final_conductor_pen.setJoinStyle(Qt::SvgMiterJoin); // meilleur rendu des pointilles + final_conductor_pen.setJoinStyle(Qt::SvgMiterJoin); // better rendering with dot - // utilisation d'un trait "cosmetique" en-dessous d'un certain zoom + //Use a cosmetique line, below a certain zoom if (options && options -> levelOfDetail < 1.0) { final_conductor_pen.setCosmetic(true); } qp -> setPen(final_conductor_pen); - // dessin du conducteur + //Draw the conductor qp -> drawPath(path()); + //Draw the second color + if(m_properties.m_bicolor) + { + final_conductor_pen.setColor(m_properties.m_color_2); + final_conductor_pen.setStyle(Qt::CustomDashLine); + QVector dash_pattern; + dash_pattern << m_properties.m_dash_size-2 << m_properties.m_dash_size; + final_conductor_pen.setDashPattern(dash_pattern); + qp->save(); + qp->setPen(final_conductor_pen); + qp->drawPath(path()); + qp->restore(); + } + if (m_properties.type == ConductorProperties::Single) { qp -> setBrush(final_conductor_color); m_properties.singleLineProperties.draw( @@ -514,11 +537,7 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi if (isSelected()) qp -> setBrush(Qt::NoBrush); } - //Draw the squares used to modify the path of conductor when he is selected - if (isSelected()) - m_handler.drawHandler(qp, handlerPoints()); - - // dessine les eventuelles jonctions + //Draw the junctions QList junctions_list = junctions(); if (!junctions_list.isEmpty()) { final_conductor_pen.setStyle(Qt::SolidLine); @@ -587,70 +606,18 @@ void Conductor::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { */ void Conductor::mousePressEvent(QGraphicsSceneMouseEvent *event) { - //Left clic - if (event->buttons() & Qt::LeftButton) - { - //If user click on a handler (square used to modify the path of conductor), - //we get the segment corresponding to the handler - int index = m_handler.pointIsHoverHandler(event->pos(), handlerPoints()); - if (index > -1) - { - moving_segment = true; - moved_segment = segmentsList().at(index+1); - before_mov_text_pos_ = m_text_item -> pos(); - } - } - QGraphicsPathItem::mousePressEvent(event); - - if (event -> modifiers() & Qt::ControlModifier) + + if (event->modifiers() & Qt::ControlModifier) setSelected(!isSelected()); } -/** - * @brief Conductor::mouseMoveEvent - * Manage the mouse move event - * @param event - */ -void Conductor::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - //Left clic - if ((event->buttons() & Qt::LeftButton) && moving_segment) - { - //Snap the mouse pos to grid - QPointF pos_ = Diagram::snapToGrid(event->pos()); - - //Position of the last point - QPointF p = moved_segment -> middle(); - - //Calcul the movement - moved_segment -> moveX(pos_.x() - p.x()); - moved_segment -> moveY(pos_.y() - p.y()); - - //Apply the movement - modified_path = true; - has_to_save_profile = true; - segmentsToPath(); - calculateTextItemPosition(); - } - - QGraphicsPathItem::mouseMoveEvent(event); -} - /** * @brief Conductor::mouseReleaseEvent - * Manage the mouse release event * @param event */ void Conductor::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - moving_segment = false; - if (has_to_save_profile) - { - saveProfile(); - has_to_save_profile = false; - } - if (!(event -> modifiers() & Qt::ControlModifier)) QGraphicsPathItem::mouseReleaseEvent(event); } @@ -678,56 +645,209 @@ void Conductor::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { } /** - * @brief Conductor::hoverMoveEvent conductor - * @param e QGraphicsSceneHoverEvent describing the event + * @brief Conductor::itemChange + * @param change + * @param value + * @return */ -void Conductor::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +QVariant Conductor::itemChange(GraphicsItemChange change, const QVariant &value) { - if (isSelected()) + if (change == QGraphicsItem::ItemSelectedChange) { - //If user hover an handler (square used to modify the path of conductor), - //we get the segment corresponding to the handler - int index = m_handler.pointIsHoverHandler(event->pos(), handlerPoints()); - if (index > -1) + if (value.toBool()) { - ConductorSegment *segment_ = segmentsList().at(index+1); - if (m_handler.pointIsInHandler(event->pos(), segment_->secondPoint())) - setCursor(Qt::ForbiddenCursor); - else if (m_handler.pointIsInHandler(event->pos(), segment_->middle())) - setCursor(segmentsList().at(index+1)->isVertical() ? Qt::SplitHCursor : Qt::SplitVCursor); + m_previous_z_value = zValue(); + setZValue(qAbs(m_previous_z_value) + 10000); + addHandler(); } else - setCursor(Qt::ArrowCursor); + { + setZValue(m_previous_z_value); + removeHandler(); + } } - - QGraphicsPathItem::hoverMoveEvent(event); + else if (change == QGraphicsItem::ItemSceneHasChanged) + { + calculateTextItemPosition(); + + if(!scene()) + removeHandler(); + else if (scene() && isSelected()) + addHandler(); + } + else if (change == QGraphicsItem::ItemVisibleHasChanged) { + calculateTextItemPosition(); + } + else if (change == QGraphicsItem::ItemPositionHasChanged && isSelected()) { + adjusteHandlerPos(); + } + + return(QGraphicsPathItem::itemChange(change, value)); } /** - Gere les changements relatifs au conducteur - Reimplemente ici pour : - * positionner le conducteur en avant-plan lorsqu'il est selectionne - @param change Type de changement - @param value Valeur relative au changement -*/ -QVariant Conductor::itemChange(GraphicsItemChange change, const QVariant &value) { - if (change == QGraphicsItem::ItemSelectedChange) { - if (value.toBool()) { - // le conducteur vient de se faire selectionner - previous_z_value = zValue(); - setZValue(qAbs(previous_z_value) + 10000); - } else { - // le conducteur vient de se faire deselectionner - setZValue(previous_z_value); + * @brief Conductor::sceneEventFilter + * @param watched + * @param event + * @return + */ +bool Conductor::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) + { + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize + { + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) + { + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } + } } - } else if (change == QGraphicsItem::ItemSceneHasChanged) { - // permet de positionner correctement le texte du conducteur lors de son ajout a un schema - calculateTextItemPosition(); - } else if (change == QGraphicsItem::ItemVisibleHasChanged) { - // permet de positionner correctement le texte du conducteur lors de son ajout a un schema - calculateTextItemPosition(); } - return(QGraphicsPathItem::itemChange(change, value)); + + return false; +} + +/** + * @brief Conductor::adjusteHandlerPos + * Adjust the position of the handler item + */ +void Conductor::adjusteHandlerPos() +{ + if (m_handler_vector.isEmpty()) + return; + + if (m_handler_vector.size() == handlerPoints().size()) + { + QVector points_vector = mapToScene(handlerPoints()); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); + } +} + +/** + * @brief Conductor::handlerMousePressEvent + * @param qghi + * @param event + */ +void Conductor::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + + //we get the segment corresponding to the handler + if (m_vector_index > -1) + { + qghi->setColor(Qt::cyan); + m_moving_segment = true; + m_moved_segment = segmentsList().at(m_vector_index+1); + before_mov_text_pos_ = m_text_item -> pos(); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + if(handler != qghi) + handler->hide(); + } +} + +/** + * @brief Conductor::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void Conductor::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + if (m_moving_segment) + { + //Snap the mouse pos to grid + QPointF pos_ = Diagram::snapToGrid(mapFromItem(qghi, event->pos())); + + //Position of the last point + QPointF p = m_moved_segment -> middle(); + + //Calcul the movement + m_moved_segment -> moveX(pos_.x() - p.x()); + m_moved_segment -> moveY(pos_.y() - p.y()); + + //Apply the movement + modified_path = true; + has_to_save_profile = true; + segmentsToPath(); + calculateTextItemPosition(); + qghi->setPos(mapToScene(m_moved_segment->middle())); + } +} + +/** + * @brief Conductor::handlerMouseReleaseEvent + * @param qghi + * @param event + */ +void Conductor::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + Q_UNUSED(qghi); + + m_vector_index = -1; + + m_moving_segment = false; + if (has_to_save_profile) + { + saveProfile(); + has_to_save_profile = false; + } + //When handler is released, the conductor can have more segment than befor the handler was moved + //then we remove all handles and new ones are added + removeHandler(); + addHandler(); +} + +/** + * @brief Conductor::addHandler + * Add handlers for this item + */ +void Conductor::addHandler() +{ + if (m_handler_vector.isEmpty() && scene()) + { + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(handlerPoints())); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + handler->setColor(Qt::blue); + scene()->addItem(handler); + handler->installSceneEventFilter(this); + handler->setZValue(this->zValue()+1); + } + } +} + +/** + * @brief Conductor::removeHandler + * Remove the handlers of this item + */ +void Conductor::removeHandler() +{ + if (!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + } } /** @@ -752,23 +872,7 @@ QPainterPath Conductor::shape() const pps.setJoinStyle(conductor_pen.joinStyle()); QPainterPath shape_(pps.createStroke(path())); - - /** - Add handle rect to path, occur a weird bug. - when the conductor is removed from the scene he continue to be painted in the scene and make artefact. - If we save (exactly when we clear the undo stack of project when saving), Qet crash, - Don't add the handle rect to the path seem to work well. - More information here : - https://qelectrotech.org/bugtracker/view.php?id=107 - https://qelectrotech.org/forum/viewtopic.php?pid=5619#p5619 - https://qelectrotech.org/forum/viewtopic.php?pid=5067#p5067 - **/ -// if (isSelected()) { -// foreach (QRectF rect, m_handler.handlerRect(handlerPoints())) { -// shape_.addRect(rect); -// } -// } - + return shape_; } diff --git a/sources/qetgraphicsitem/conductor.h b/sources/qetgraphicsitem/conductor.h index dfedb50d4..e8630441d 100644 --- a/sources/qetgraphicsitem/conductor.h +++ b/sources/qetgraphicsitem/conductor.h @@ -20,7 +20,6 @@ #include "conductorproperties.h" #include -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" #include "assignvariables.h" class ConductorProfile; @@ -32,6 +31,8 @@ class ConductorTextItem; class Element; class QETDiagramEditor; class NumerotationContext; +class QetGraphicsHandlerItem; + typedef QPair ConductorBend; typedef QHash ConductorProfilesGroup; /** @@ -133,36 +134,45 @@ class Conductor : public QObject, public QGraphicsPathItem protected: virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); virtual QVariant itemChange(GraphicsItemChange, const QVariant &); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); private: + void adjusteHandlerPos(); + + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void addHandler(); + void removeHandler(); + + + QVector m_handler_vector; + int m_vector_index = -1; bool m_mouse_over; - QetGraphicsHandlerUtility m_handler; - /// Functional properties + /// Functional properties ConductorProperties m_properties; - /// Text input for non simple, non-singleline conductors + /// Text input for non simple, non-singleline conductors ConductorTextItem *m_text_item; - /// Segments composing the conductor + /// Segments composing the conductor ConductorSegment *segments; - /// Attributs related to mouse interaction - bool moving_segment; + /// Attributs related to mouse interaction + bool m_moving_segment; int moved_point; - qreal previous_z_value; - ConductorSegment *moved_segment; + qreal m_previous_z_value; + ConductorSegment *m_moved_segment; QPointF before_mov_text_pos_; - /// Whether the conductor was manually modified by users + /// Whether the conductor was manually modified by users bool modified_path; - /// Whether the current profile should be saved as soon as possible + /// Whether the current profile should be saved as soon as possible bool has_to_save_profile; - /// conductor profile: "photography" of what the conductor is supposed to look - /// like - there is one profile per kind of traject + /// conductor profile: "photography" of what the conductor is supposed to look + /// like - there is one profile per kind of traject ConductorProfilesGroup conductor_profiles; - /// Define whether and how the conductor should be highlighted + /// Define whether and how the conductor should be highlighted Highlight must_highlight_; bool m_valid; bool m_freeze_label = false; diff --git a/sources/qetgraphicsitem/qetshapeitem.cpp b/sources/qetgraphicsitem/qetshapeitem.cpp index 2f1d6e4d6..01665c790 100644 --- a/sources/qetgraphicsitem/qetshapeitem.cpp +++ b/sources/qetgraphicsitem/qetshapeitem.cpp @@ -22,6 +22,7 @@ #include "shapegraphicsitempropertieswidget.h" #include "PropertiesEditor/propertieseditordialog.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" +#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" #include "qetxml.h" /** @@ -37,18 +38,20 @@ QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem m_shapeType(type), m_P1 (p1), m_P2 (p2), - m_hovered(false), - m_mouse_grab_handler(false), - m_handler(10) + m_hovered(false) { if (type == Polygon) m_polygon << m_P1 << m_P2; - setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); + setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges); setAcceptHoverEvents(true); m_pen.setStyle(Qt::DashLine); } -QetShapeItem::~QetShapeItem() {} +QetShapeItem::~QetShapeItem() +{ + if(!m_handler_vector.isEmpty()) + qDeleteAll(m_handler_vector); +} /** * @brief QetShapeItem::setPen @@ -109,6 +112,7 @@ bool QetShapeItem::setLine(const QLineF &line) prepareGeometryChange(); m_P1 = line.p1(); m_P2 = line.p2(); + adjusteHandlerPos(); return true; } @@ -125,6 +129,7 @@ bool QetShapeItem::setRect(const QRectF &rect) prepareGeometryChange(); m_P1 = rect.topLeft(); m_P2 = rect.bottomRight(); + adjusteHandlerPos(); return true; } @@ -142,6 +147,7 @@ bool QetShapeItem::setPolygon(const QPolygonF &polygon) if (Q_UNLIKELY(m_shapeType != Polygon)) return false; prepareGeometryChange(); m_polygon = polygon; + adjusteHandlerPos(); return true; } @@ -246,23 +252,6 @@ QPainterPath QetShapeItem::shape() const pps.setJoinStyle(Qt::RoundJoin); path = pps.createStroke(path); - if (isSelected()) - { - QVector vector; - - if (m_shapeType == Line) - vector << m_P1 << m_P2; - else if (m_shapeType == Rectangle || m_shapeType == Ellipse) { - QRectF rect (m_P1, m_P2); - vector << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft(); - } - else - vector = m_polygon; - - foreach(QRectF r, m_handler.handlerRect(vector)) - path.addRect(r); - } - return (path); } @@ -293,35 +282,16 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti painter -> drawPath (shape()); painter -> restore (); } - - //Draw the shape and handlers if is selected - switch (m_shapeType) - { - case Line: - painter->drawLine(QLineF(m_P1, m_P2)); - if (isSelected()) - m_handler.drawHandler(painter, QVector{m_P1, m_P2}); - break; - - case Rectangle: - painter->drawRect(QRectF(m_P1, m_P2)); - if (isSelected()) - m_handler.drawHandler(painter, m_handler.pointsForRect(QRectF(m_P1, m_P2))); - break; - - case Ellipse: - painter->drawEllipse(QRectF(m_P1, m_P2)); - if (isSelected()) - m_handler.drawHandler(painter, m_handler.pointsForRect(QRectF(m_P1, m_P2))); - break; - - case Polygon: - m_close ? painter->drawPolygon(m_polygon) : painter->drawPolyline(m_polygon); - if (isSelected()) - m_handler.drawHandler(painter, m_polygon); - break; - } - painter->restore(); + + switch (m_shapeType) + { + case Line: painter->drawLine(QLineF(m_P1, m_P2)); break; + case Rectangle: painter->drawRect(QRectF(m_P1, m_P2)); break; + case Ellipse: painter->drawEllipse(QRectF(m_P1, m_P2)); break; + case Polygon: m_close ? painter->drawPolygon(m_polygon) : painter->drawPolyline(m_polygon); break; + } + + painter->restore(); } /** @@ -329,142 +299,23 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti * Handle hover enter event * @param event */ -void QetShapeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { +void QetShapeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ m_hovered = true; QetGraphicsItem::hoverEnterEvent(event); } -void QetShapeItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - if (!isSelected()) return; - - QVector vector; - switch (m_shapeType) - { - case Line: vector << m_P1 << m_P2; break; - case Rectangle: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break; - case Ellipse: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break; - case Polygon: vector = m_polygon; break; - } - - int handler = m_handler.pointIsHoverHandler(event->pos(), vector); - if (handler >= 0) - { - if (m_shapeType & (Line | Polygon)) { - setCursor(Qt::SizeAllCursor); - return; - } - - if (handler == 0 || handler == 2 || handler == 5 || handler == 7) - setCursor(Qt::SizeAllCursor); - else if (handler == 1 || handler == 6) - setCursor(Qt::SizeVerCursor); - else if (handler == 3 || handler == 4) - setCursor(Qt::SizeHorCursor); - } - else - setCursor(Qt::OpenHandCursor); -} - /** * @brief QetShapeItem::hoverLeaveEvent * Handle hover leave event * @param event */ -void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { +void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ m_hovered = false; - unsetCursor(); QetGraphicsItem::hoverLeaveEvent(event); } -/** - * @brief QetShapeItem::mousePressEvent - * Handle mouse press event - * @param event - */ -void QetShapeItem::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - { - setCursor(Qt::ClosedHandCursor); - //Shape is selected, we see if user click in a handler - if (isSelected()) - { - QVector vector; - switch (m_shapeType) - { - case Line: vector << m_P1 << m_P2; break; - case Rectangle: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break; - case Ellipse: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break; - case Polygon: vector = m_polygon; break; - } - - m_vector_index = m_handler.pointIsHoverHandler(event->pos(), vector); - if (m_vector_index != -1) - { - //User click on an handler - m_mouse_grab_handler = true; - m_old_P1 = m_P1; - m_old_P2 = m_P2; - m_old_polygon = m_polygon; - return; - } - } - } - - QetGraphicsItem::mousePressEvent(event); -} - -/** - * @brief QetShapeItem::mouseMoveEvent - * Handle move event - * @param event - */ -void QetShapeItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - if (m_mouse_grab_handler) - { - QPointF new_pos = event->pos(); - if (event->modifiers() != Qt::ControlModifier) - new_pos = mapFromScene(Diagram::snapToGrid(event->scenePos())); - - switch (m_shapeType) - { - case Line: - prepareGeometryChange(); - m_vector_index == 0 ? m_P1 = new_pos : m_P2 = new_pos; - break; - - case Rectangle: - if (m_resize_mode == 1) { - setRect(m_handler.rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); - break; - } - else { - setRect(m_handler.mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); - break; - } - case Ellipse: - if (m_resize_mode == 1) { - setRect(m_handler.rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); - break; - } - else { - setRect(m_handler.mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); - break; - } - - case Polygon: - prepareGeometryChange(); - m_polygon.replace(m_vector_index, new_pos); - break; - } //End switch - return; - } - - QetGraphicsItem::mouseMoveEvent(event); -} - /** * @brief QetShapeItem::mouseReleaseEvent * Handle mouse release event @@ -472,52 +323,251 @@ void QetShapeItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) */ void QetShapeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if ((m_shapeType & (Rectangle | Ellipse)) && event->buttonDownPos(Qt::LeftButton) == event->pos()) + if (event->buttonDownPos(Qt::LeftButton) == event->pos()) switchResizeMode(); - if (m_mouse_grab_handler) - { - m_mouse_grab_handler = false; - if (diagram()) - { - QPropertyUndoCommand *undo = nullptr; - if ((m_shapeType & (Line | Rectangle | Ellipse)) && (m_P1 != m_old_P1 || m_P2 != m_old_P2)) - { - switch(m_shapeType) - { - case Line: undo = new QPropertyUndoCommand(this, "line",QLineF(m_old_P1, m_old_P2), QLineF(m_P1, m_P2)); break; - case Rectangle: undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2)); break; - case Ellipse: undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2)); break; - case Polygon: break; - } - if (undo) undo->enableAnimation(); - } - else if (m_shapeType == Polygon && (m_polygon != m_old_polygon)) - undo = new QPropertyUndoCommand(this, "polygon", m_old_polygon, m_polygon); - - if(undo) - { - undo->setText(tr("Modifier %1").arg(name())); - diagram()->undoStack().push(undo); - } - } - setCursor(Qt::OpenHandCursor); - } - - QetGraphicsItem::mouseReleaseEvent(event); + QetGraphicsItem::mouseReleaseEvent(event); } +/** + * @brief QetShapeItem::itemChange + * @param change + * @param value + * @return + */ +QVariant QetShapeItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemSelectedHasChanged) + { + if (value.toBool() == true) //If this is selected, wa add handlers. + { + QVector points_vector; + switch (m_shapeType) + { + case Line: points_vector << m_P1 << m_P2; break; + case Rectangle: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; + case Ellipse: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; + case Polygon: points_vector = m_polygon; break; + } + + if(!points_vector.isEmpty() && scene()) + { + m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(points_vector)); + + for(QetGraphicsHandlerItem *handler : m_handler_vector) + { + handler->setColor(Qt::blue); + scene()->addItem(handler); + handler->installSceneEventFilter(this); + } + } + } + else //Else this is deselected, we remove handlers + { + if(!m_handler_vector.isEmpty()) + { + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + } + } + } + else if (change == ItemPositionHasChanged) + { + adjusteHandlerPos(); + } + else if (change == ItemSceneHasChanged) + { + if (!scene()) //This is removed from scene, then we deselect this, and so, the handlers is also removed. + { + setSelected(false); + } + } + + return QGraphicsItem::itemChange(change, value); +} + +/** + * @brief QetShapeItem::sceneEventFilter + * @param watched + * @param event + * @return + */ +bool QetShapeItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + //Watched must be an handler + if(watched->type() == QetGraphicsHandlerItem::Type) + { + QetGraphicsHandlerItem *qghi = qgraphicsitem_cast(watched); + + if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize + { + m_vector_index = m_handler_vector.indexOf(qghi); + if (m_vector_index != -1) + { + if(event->type() == QEvent::GraphicsSceneMousePress) //Click + { + handlerMousePressEvent(qghi, static_cast(event)); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move + { + handlerMouseMoveEvent(qghi, static_cast(event)); + return true; + } + else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release + { + handlerMouseReleaseEvent(qghi, static_cast(event)); + return true; + } + } + } + } + + return false; +} + +/** + * @brief QetShapeItem::switchResizeMode + */ void QetShapeItem::switchResizeMode() { - if (m_resize_mode == 1) { - m_resize_mode = 2; - m_handler.setOuterColor(Qt::darkGreen); + if (m_shapeType & (Rectangle | Ellipse)) + { + if (m_resize_mode == 1) + { + m_resize_mode = 2; + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::darkGreen); + } + else + { + m_resize_mode = 1; + for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qghi->setColor(Qt::blue); + } } - else { - m_resize_mode = 1; - m_handler.setOuterColor(Qt::blue); +} + +/** + * @brief QetShapeItem::adjusteHandlerPos + * Adjust the position of the handler item + */ +void QetShapeItem::adjusteHandlerPos() +{ + QVector points_vector; + switch (m_shapeType) + { + case Line: points_vector << m_P1 << m_P2; break; + case Rectangle: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; + case Ellipse: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; + case Polygon: points_vector = m_polygon; break; + } + + if (m_handler_vector.size() == points_vector.size()) + { + points_vector = mapToScene(points_vector); + for (int i = 0 ; i < points_vector.size() ; ++i) + m_handler_vector.at(i)->setPos(points_vector.at(i)); + } +} + +/** + * @brief QetShapeItem::handlerMousePressEvent + * @param qghi + * @param event + */ +void QetShapeItem::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + m_old_P1 = m_P1; + m_old_P2 = m_P2; + m_old_polygon = m_polygon; +} + +/** + * @brief QetShapeItem::handlerMouseMoveEvent + * @param qghi + * @param event + */ +void QetShapeItem::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + + QPointF new_pos = event->scenePos(); + if (event->modifiers() != Qt::ControlModifier) + new_pos = Diagram::snapToGrid(event->scenePos()); + new_pos = mapFromScene(new_pos); + + switch (m_shapeType) + { + case Line: + prepareGeometryChange(); + m_vector_index == 0 ? m_P1 = new_pos : m_P2 = new_pos; + adjusteHandlerPos(); + break; + + case Rectangle: + if (m_resize_mode == 1) { + setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); + break; + } + else { + setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); + break; + } + case Ellipse: + if (m_resize_mode == 1) { + setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); + break; + } + else { + setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); + break; + } + + case Polygon: + prepareGeometryChange(); + m_polygon.replace(m_vector_index, new_pos); + adjusteHandlerPos(); + break; + } //End switch +} + +/** + * @brief QetShapeItem::handlerMouseReleaseEvent + * @param qghi + * @param event + */ +void QetShapeItem::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(qghi); + Q_UNUSED(event); + + if (diagram()) + { + QPropertyUndoCommand *undo = nullptr; + if ((m_shapeType & (Line | Rectangle | Ellipse)) && (m_P1 != m_old_P1 || m_P2 != m_old_P2)) + { + switch(m_shapeType) + { + case Line: undo = new QPropertyUndoCommand(this, "line",QLineF(m_old_P1, m_old_P2), QLineF(m_P1, m_P2)); break; + case Rectangle: undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2)); break; + case Ellipse: undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2)); break; + case Polygon: break; + } + if (undo) undo->enableAnimation(); + } + else if (m_shapeType == Polygon && (m_polygon != m_old_polygon)) + undo = new QPropertyUndoCommand(this, "polygon", m_old_polygon, m_polygon); + + if(undo) + { + undo->setText(tr("Modifier %1").arg(name())); + diagram()->undoStack().push(undo); + } } - update(); } /** diff --git a/sources/qetgraphicsitem/qetshapeitem.h b/sources/qetgraphicsitem/qetshapeitem.h index 01d72115a..fdbf94efd 100644 --- a/sources/qetgraphicsitem/qetshapeitem.h +++ b/sources/qetgraphicsitem/qetshapeitem.h @@ -20,10 +20,11 @@ #include #include "qetgraphicsitem.h" -#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" +#include "QetGraphicsItemModeler/qetgraphicshandleritem.h" class QDomElement; class QDomDocument; +class QetGraphicsHandlerItem; /** * @brief The QetShapeItem class @@ -96,14 +97,18 @@ class QetShapeItem : public QetGraphicsItem protected: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual void hoverEnterEvent (QGraphicsSceneHoverEvent *event); - virtual void hoverMoveEvent (QGraphicsSceneHoverEvent *event); virtual void hoverLeaveEvent (QGraphicsSceneHoverEvent *event); - virtual void mousePressEvent (QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent (QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); private: void switchResizeMode(); + void adjusteHandlerPos(); + + void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); + void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); ///ATTRIBUTES private: @@ -112,11 +117,10 @@ class QetShapeItem : public QetGraphicsItem QBrush m_brush; QPointF m_P1, m_P2, m_old_P1, m_old_P2; QPolygonF m_polygon, m_old_polygon; - bool m_hovered, - m_mouse_grab_handler; + bool m_hovered; int m_vector_index; - QetGraphicsHandlerUtility m_handler; bool m_close = false; int m_resize_mode = 1; + QVector m_handler_vector; }; #endif // QETSHAPEITEM_H diff --git a/sources/ui/conductorpropertieswidget.cpp b/sources/ui/conductorpropertieswidget.cpp index 515daec3d..792a421f1 100644 --- a/sources/ui/conductorpropertieswidget.cpp +++ b/sources/ui/conductorpropertieswidget.cpp @@ -68,13 +68,18 @@ ConductorPropertiesWidget::~ConductorPropertiesWidget() */ void ConductorPropertiesWidget::setProperties(const ConductorProperties &properties) { - if (m_properties == properties) return; + if (m_properties == properties) + return; + m_properties = properties; setColorButton(m_properties.color); + setColorButton2(m_properties.m_color_2); int index = ui -> m_line_style_cb -> findData(QPen(m_properties.style)); if (index != -1) ui -> m_line_style_cb -> setCurrentIndex(index); + ui->m_color_2_gb -> setChecked (m_properties.m_bicolor); + ui->m_dash_size_sb -> setValue (m_properties.m_dash_size); ui->m_formula_le -> setText (m_properties.m_formula); ui->m_text_le -> setText (m_properties.text); ui->m_function_le -> setText (m_properties.m_function); @@ -107,6 +112,9 @@ ConductorProperties ConductorPropertiesWidget::properties() const else if (ui -> m_singlewire_gb -> isChecked()) properties_.type = ConductorProperties::Single; properties_.color = ui -> m_color_pb->palette().color(QPalette::Button); + properties_.m_bicolor = ui->m_color_2_gb->isChecked(); + properties_.m_color_2 = ui->m_color_2_pb->palette().color(QPalette::Button); + properties_.m_dash_size = ui->m_dash_size_sb->value(); properties_.style = ui -> m_line_style_cb->itemData(ui->m_line_style_cb->currentIndex()).value().style(); properties_.m_formula = ui->m_formula_le->text(); properties_.text = ui -> m_text_le -> text(); @@ -295,12 +303,24 @@ void ConductorPropertiesWidget::on_m_color_pb_clicked() { * Set m_color_pb to @color * @param color */ -void ConductorPropertiesWidget::setColorButton(const QColor &color) { +void ConductorPropertiesWidget::setColorButton(const QColor &color){ QPalette palette; palette.setColor(QPalette::Button, color); ui -> m_color_pb -> setStyleSheet(QString("background-color: %1; min-height: 1.5em; border-style: outset; border-width: 2px; border-color: gray; border-radius: 4px;").arg(color.name())); } +/** + * @brief ConductorPropertiesWidget::setColorButton2 + * Set m_color_2_pb to @color + * @param color + */ +void ConductorPropertiesWidget::setColorButton2(const QColor &color) +{ + QPalette palette; + palette.setColor(QPalette::Button, color); + ui->m_color_2_pb->setStyleSheet(QString("background-color: %1; min-height: 1.5em; border-style: outset; border-width: 2px; border-color: gray; border-radius: 4px;").arg(color.name())); +} + /** * @brief ConductorPropertiesWidget::on_m_update_preview_pb_clicked * Update the preview of single line. @@ -311,3 +331,14 @@ void ConductorPropertiesWidget::setColorButton(const QColor &color) { void ConductorPropertiesWidget::on_m_update_preview_pb_clicked() { updatePreview(); } + +/** + * @brief ConductorPropertiesWidget::on_m_color_2_pb_clicked + * Open a color dialog, for choose the second color of conductor + */ +void ConductorPropertiesWidget::on_m_color_2_pb_clicked() +{ + QColor color = QColorDialog::getColor(m_properties.m_color_2, this); + if (color.isValid()) + setColorButton2(color); +} diff --git a/sources/ui/conductorpropertieswidget.h b/sources/ui/conductorpropertieswidget.h index f84d89f7d..07a968748 100644 --- a/sources/ui/conductorpropertieswidget.h +++ b/sources/ui/conductorpropertieswidget.h @@ -65,8 +65,11 @@ class ConductorPropertiesWidget : public QWidget void on_m_neutral_cb_toggled(bool checked); void on_m_color_pb_clicked(); void setColorButton (const QColor &color); + void setColorButton2 (const QColor &color); void on_m_update_preview_pb_clicked(); + void on_m_color_2_pb_clicked(); + private: Ui::ConductorPropertiesWidget *ui; ConductorProperties m_properties; diff --git a/sources/ui/conductorpropertieswidget.ui b/sources/ui/conductorpropertieswidget.ui index 182432a3e..7a7694c60 100644 --- a/sources/ui/conductorpropertieswidget.ui +++ b/sources/ui/conductorpropertieswidget.ui @@ -390,7 +390,7 @@ - + Qt::Vertical @@ -426,6 +426,55 @@ + + + + Couleur secondaire : + + + true + + + true + + + false + + + + + + px + + + 2 + + + + + + + + + + + + + + Couleur : + + + + + + + Taille de trait : + + + + + +