/* Copyright 2006-2019 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 "shapegraphicsitempropertieswidget.h" #include "ui_shapegraphicsitempropertieswidget.h" #include "qetshapeitem.h" #include "diagram.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" /** * @brief ShapeGraphicsItemPropertiesWidget::ShapeGraphicsItemPropertiesWidget * Constructor * @param item : shape to edit * @param parent : parent widget */ ShapeGraphicsItemPropertiesWidget::ShapeGraphicsItemPropertiesWidget(QetShapeItem *item, QWidget *parent) : PropertiesEditorWidget(parent), ui(new Ui::ShapeGraphicsItemPropertiesWidget), m_shape(nullptr) { ui->setupUi(this); setItem(item); } ShapeGraphicsItemPropertiesWidget::ShapeGraphicsItemPropertiesWidget(QList items_list, QWidget *parent) : PropertiesEditorWidget (parent), ui(new Ui::ShapeGraphicsItemPropertiesWidget) { ui->setupUi(this); setItems(items_list); } /** * @brief ShapeGraphicsItemPropertiesWidget::~ShapeGraphicsItemPropertiesWidget * Destructor */ ShapeGraphicsItemPropertiesWidget::~ShapeGraphicsItemPropertiesWidget() { delete ui; } /** * @brief ShapeGraphicsItemPropertiesWidget::setItem * Set @shape as the current edited item * @param shape */ void ShapeGraphicsItemPropertiesWidget::setItem(QetShapeItem *shape) { if (m_shape != shape) { for (QMetaObject::Connection c : m_connect_list) { disconnect(c); } m_connect_list.clear(); } if (!shape) { return; } m_shape = shape; ui->m_close_polygon->setVisible(m_shape->shapeType() == QetShapeItem::Polygon); ui->m_filling_gb->setHidden(m_shape->shapeType() == QetShapeItem::Line); if (m_live_edit) { m_connect_list << connect(m_shape, &QetShapeItem::penChanged, this, &ShapeGraphicsItemPropertiesWidget::updateUi); m_connect_list << connect(m_shape, &QetShapeItem::brushChanged, this, &ShapeGraphicsItemPropertiesWidget::updateUi); m_connect_list << connect(m_shape, &QetShapeItem::closeChanged, this, &ShapeGraphicsItemPropertiesWidget::updateUi); } setUpEditConnection(); updateUi(); } /** * @brief ShapeGraphicsItemPropertiesWidget::setItems * Set a list of shapes to be edited * @param shapes_list */ void ShapeGraphicsItemPropertiesWidget::setItems(QList shapes_list) { for (QMetaObject::Connection c : m_connect_list) { disconnect(c); } m_connect_list.clear(); m_shapes_list.clear(); m_shape = nullptr; if (shapes_list.size() == 0) { updateUi(); } else if (shapes_list.size() == 1) { setItem(shapes_list.first()); } else { for (QetShapeItem *shape : shapes_list) { m_shapes_list.append(QPointer(shape)); } updateUi(); } setUpEditConnection(); } /** * @brief ShapeGraphicsItemPropertiesWidget::apply * Apply the current change, by pushing an undo command to the * undo stack of the shape diagram. */ void ShapeGraphicsItemPropertiesWidget::apply() { Diagram *d = nullptr; if (m_shape && m_shape->diagram()) { d = m_shape->diagram(); } else if (!m_shapes_list.isEmpty()) { for (QPointer qsi : m_shapes_list) { if (qsi->diagram()) { d = qsi->diagram(); break; } } } if (d) { QUndoCommand *undo = associatedUndo(); if (undo) { d->undoStack().push(undo); } } } /** * @brief ShapeGraphicsItemPropertiesWidget::reset * Reset the change */ void ShapeGraphicsItemPropertiesWidget::reset() { updateUi(); } /** * @brief ShapeGraphicsItemPropertiesWidget::associatedUndo * @return an undo command that represent the change edited by this widget. * The returned undo command is a QPropertyUndoCommand with the properties "pen". * If there isn't change, return nullptr */ QUndoCommand* ShapeGraphicsItemPropertiesWidget::associatedUndo() const { if (m_live_edit) { //One shape is edited if (m_shapes_list.isEmpty()) { QPropertyUndoCommand *undo = nullptr; QPen old_pen = m_shape->pen(); QPen new_pen = old_pen; new_pen.setStyle(Qt::PenStyle(ui->m_style_cb->currentIndex() + 1)); new_pen.setWidthF(ui->m_size_dsb->value()); if (ui->m_style_cb->currentIndex() ==5) { new_pen.setDashPattern( QVector() << 10 << 10 ); new_pen.setStyle( Qt::CustomDashLine ); } //painter.setPen( new_pen ); new_pen.setColor(ui->m_color_kpb->color()); if (new_pen != old_pen) { undo = new QPropertyUndoCommand(m_shape, "pen", old_pen, new_pen); undo->setText(tr("Modifier le trait d'une forme")); } QBrush old_brush = m_shape->brush(); QBrush new_brush = old_brush; new_brush.setStyle(Qt::BrushStyle(ui->m_brush_style_cb->currentIndex())); new_brush.setColor(ui->m_brush_color_kpb->color()); if (new_brush != old_brush) { if (undo) new QPropertyUndoCommand(m_shape, "brush", old_brush, new_brush, undo); else { undo = new QPropertyUndoCommand(m_shape, "brush", old_brush, new_brush); undo->setText(tr("Modifier le remplissage d'une forme")); } } if (ui->m_close_polygon->isChecked() != m_shape->isClosed()) { if (undo) new QPropertyUndoCommand(m_shape, "close", m_shape->isClosed(), ui->m_close_polygon->isChecked(), undo); else { undo = new QPropertyUndoCommand(m_shape, "close", m_shape->isClosed(), ui->m_close_polygon->isChecked(), undo); undo->setText(tr("Fermer le polygone")); } } return undo; } else if (!m_shapes_list.isEmpty()) //seberal shapes are edited { QUndoCommand *parent_undo = nullptr; QetShapeItem *shape_ = m_shapes_list.first().data(); //Pen QHash pen_H; if (ui->m_style_cb->currentIndex() != -1 && Qt::PenStyle(ui->m_style_cb->currentIndex() + 1) != shape_->pen().style()) { for (QPointer qsi : m_shapes_list) { QPen pen = qsi->pen(); if (ui->m_style_cb->currentIndex() ==5) { pen.setDashPattern( QVector() << 10 << 10 ); pen.setStyle( Qt::CustomDashLine ); } else { pen.setStyle(Qt::PenStyle(ui->m_style_cb->currentIndex() + 1)); } pen_H.insert(qsi, pen); } } if (ui->m_size_dsb->value() > 0 && ui->m_size_dsb->value() != shape_->pen().widthF()) { for (QPointer qsi : m_shapes_list) { QPen pen = pen_H.contains(qsi) ? pen_H.value(qsi) : qsi->pen(); pen.setWidthF(ui->m_size_dsb->value()); pen_H.insert(qsi, pen); } } QColor c =ui->m_color_kpb->color(); if (c != QPalette().color(QPalette::Button) && shape_->pen().color() != c) { for (QPointer qsi : m_shapes_list) { QPen pen = pen_H.contains(qsi) ? pen_H.value(qsi) : qsi->pen(); pen.setColor(c); pen_H.insert(qsi, pen); } } for (QPointer qsi : pen_H.keys()) { if (!parent_undo) { parent_undo = new QUndoCommand(tr("Modifier une forme simple")); } new QPropertyUndoCommand(qsi, "pen", qsi->pen(), pen_H.value(qsi), parent_undo); } //Brush QHash brush_H; if (ui->m_brush_style_cb->currentIndex() != -1 && shape_->brush().style() != Qt::BrushStyle(ui->m_brush_style_cb->currentIndex())) { for (QPointer qsi : m_shapes_list) { QBrush brush = qsi->brush(); brush.setStyle(Qt::BrushStyle(ui->m_brush_style_cb->currentIndex())); brush_H.insert(qsi, brush); } } c = ui->m_brush_color_kpb->color(); if (c != QPalette().color(QPalette::Button) && shape_->brush().color() != c) { for (QPointer qsi : m_shapes_list) { QBrush brush = brush_H.contains(qsi) ? brush_H.value(qsi) : qsi->brush(); brush.setColor(c); brush_H.insert(qsi, brush); } } for (QPointer qsi : brush_H.keys()) { if (!parent_undo) { parent_undo = new QUndoCommand(tr("Modifier une forme simple")); } new QPropertyUndoCommand(qsi, "brush", qsi->brush(), brush_H.value(qsi), parent_undo); } return parent_undo; } } //In mode not live edit, only one shape can be edited else if (m_shapes_list.isEmpty()) { QUndoCommand *undo = new QUndoCommand(tr("Modifier les propriétés d'une forme simple")); QPen old_pen = m_shape->pen(); QPen new_pen = old_pen; new_pen.setStyle(Qt::PenStyle(ui->m_style_cb->currentIndex() + 1)); new_pen.setWidthF(ui->m_size_dsb->value()); if (ui->m_style_cb->currentIndex() ==5) { new_pen.setDashPattern( QVector() << 10 << 10 ); new_pen.setStyle( Qt::CustomDashLine ); } //painter.setPen( new_pen ); new_pen.setColor(ui->m_color_kpb->color()); if (new_pen != old_pen) { new QPropertyUndoCommand(m_shape, "pen", old_pen, new_pen, undo); } QBrush old_brush = m_shape->brush(); QBrush new_brush = old_brush; new_brush.setStyle(Qt::BrushStyle(ui->m_brush_style_cb->currentIndex())); new_brush.setColor(ui->m_brush_color_kpb->color()); if (new_brush != old_brush) { new QPropertyUndoCommand(m_shape, "brush", old_brush, new_brush, undo); } if (ui->m_close_polygon->isChecked() != m_shape->isClosed()) { QPropertyUndoCommand(m_shape, "close", m_shape->isClosed(), ui->m_close_polygon->isChecked(), undo); } if (undo->childCount()) { return undo; } else { delete undo; return nullptr; } } else { return nullptr; } } /** * @brief ShapeGraphicsItemPropertiesWidget::updateUi */ void ShapeGraphicsItemPropertiesWidget::updateUi() { if (!m_shape && m_shapes_list.isEmpty()) { return; } //Disconnect every connections of editor widgets //to avoid an unwanted edition (QSpinBox emit valueChanged no matter if changer by user or by program) for (QMetaObject::Connection c : m_edit_connection) { disconnect(c); } m_edit_connection.clear(); if (m_shape) { //Pen ui->m_style_cb->setCurrentIndex(static_cast(m_shape->pen().style()) - 1); ui->m_size_dsb ->setValue(m_shape->pen().widthF()); ui->m_color_kpb->setColor(m_shape->pen().color()); ui->m_color_kpb->setColor(m_shape->pen().color()); //Brush if (m_shape->shapeType() == QetShapeItem::Polygon) ui->m_filling_gb->setVisible(m_shape->isClosed()); ui->m_brush_style_cb->setCurrentIndex(static_cast(m_shape->brush().style())); ui->m_brush_color_kpb->setColor(m_shape->brush().color()); ui->m_lock_pos_cb->setChecked(!m_shape->isMovable()); ui->m_close_polygon->setChecked(m_shape->isClosed()); } else if (m_shapes_list.size() >= 2) { ui->m_close_polygon->setHidden(true); bool same = true; //Pen Qt::PenStyle ps = m_shapes_list.first()->pen().style(); for (QetShapeItem *qsi : m_shapes_list) { if (qsi->pen().style() != ps) { same = false; break; } } ui->m_style_cb->setCurrentIndex(same ? static_cast(ps) - 1 : -1); same = true; qreal pw = m_shapes_list.first()->pen().widthF(); for (QetShapeItem *qsi : m_shapes_list) { if (qsi->pen().widthF() != pw) { same = false; break; } } ui->m_size_dsb->setValue(same ? pw : 0); same = true; QColor pc = m_shapes_list.first()->pen().color(); for (QetShapeItem *qsi : m_shapes_list) { if (qsi->pen().color() != pc) { same = false; break; } } ui->m_color_kpb->setColor(same ? pc : QColor()); //Brush ui->m_filling_gb->setVisible(true); same = true; Qt::BrushStyle bs = m_shapes_list.first()->brush().style(); for (QetShapeItem *qsi : m_shapes_list) { if (qsi->brush().style() != bs) { same = false; break; } } ui->m_brush_style_cb->setCurrentIndex(same ? static_cast(bs) : -1); same = true; QColor bc = m_shapes_list.first()->brush().color(); for (QetShapeItem *qsi : m_shapes_list) { if (qsi->brush().color() != bc) { same = false; break; } } ui->m_brush_color_kpb->setColor(same ? bc : QColor()); ui->m_lock_pos_cb->setChecked(false); ui->m_close_polygon->setChecked(false); } setUpEditConnection(); } /** * @brief ShapeGraphicsItemPropertiesWidget::setLiveEdit * @param live_edit * @return always true */ bool ShapeGraphicsItemPropertiesWidget::setLiveEdit(bool live_edit) { if (live_edit == m_live_edit) { return true; } m_live_edit = live_edit; if (m_live_edit) { setUpEditConnection(); } else { for (QMetaObject::Connection c : m_edit_connection) { disconnect(c); } m_edit_connection.clear(); } return true; } /** * @brief ShapeGraphicsItemPropertiesWidget::setUpEditConnection * Disconnect the previous connection, and reconnect the connection between the editors widgets and void ShapeGraphicsItemPropertiesWidget::apply function */ void ShapeGraphicsItemPropertiesWidget::setUpEditConnection() { for (QMetaObject::Connection c : m_edit_connection) { disconnect(c); } m_edit_connection.clear(); if (m_shape || !m_shapes_list.isEmpty()) { m_edit_connection << connect (ui->m_style_cb, SIGNAL(activated(int)), this, SLOT(apply())); m_edit_connection << connect (ui->m_size_dsb, SIGNAL(valueChanged(double)), this, SLOT(apply())); m_edit_connection << connect (ui->m_brush_style_cb, SIGNAL(activated(int)), this, SLOT(apply())); m_edit_connection << connect (ui->m_close_polygon, &QCheckBox::clicked, this, &ShapeGraphicsItemPropertiesWidget::apply); m_edit_connection << connect (m_shape, &QetShapeItem::penChanged, this, &ShapeGraphicsItemPropertiesWidget::updateUi); m_edit_connection << connect (m_shape, &QetShapeItem::closeChanged, this, &ShapeGraphicsItemPropertiesWidget::updateUi); } } void ShapeGraphicsItemPropertiesWidget::on_m_lock_pos_cb_clicked() { if (m_shape) { m_shape->setMovable(!ui->m_lock_pos_cb->isChecked()); } else if (!m_shapes_list.isEmpty()) { for (QPointer qsi : m_shapes_list) { qsi->setMovable(!ui->m_lock_pos_cb->isChecked()); } } } void ShapeGraphicsItemPropertiesWidget::on_m_color_kpb_changed(const QColor &newColor) { if(newColor.isValid() && m_live_edit) { apply(); } } void ShapeGraphicsItemPropertiesWidget::on_m_brush_color_kpb_changed(const QColor &newColor) { if(newColor.isValid() && m_live_edit) { apply(); } }