1 /*
2 Copyright 2006-2019 The QElectroTech Team
3 This file is part of QElectroTech.
4
5 QElectroTech is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (at your option) any later version.
9
10 QElectroTech is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "polygoneditor.h"
19 #include "partpolygon.h"
20 #include "elementscene.h"
21 #include "qetmessagebox.h"
22 #include "styleeditor.h"
23 #include "QPropertyUndoCommand/qpropertyundocommand.h"
24
25 /**
26 Constructeur
27 @param editor L'editeur d'element concerne
28 @param p Le polygone a editer
29 @param parent le Widget parent
30 */
PolygonEditor(QETElementEditor * editor,PartPolygon * p,QWidget * parent)31 PolygonEditor::PolygonEditor(QETElementEditor *editor, PartPolygon *p, QWidget *parent) :
32 ElementItemEditor(editor, parent),
33 part(p),
34 points_list(this),
35 close_polygon(tr("Polygone fermé"), this)
36 {
37 style_ = new StyleEditor(editor);
38
39 // prepare la liste de points
40 points_list.setColumnCount(2);
41 QStringList headers;
42 headers << tr("x") << tr("y");
43 points_list.setHeaderLabels(headers);
44 points_list.setRootIsDecorated(false);
45 updateForm();
46
47 // layout
48 QVBoxLayout *layout = new QVBoxLayout(this);
49 layout -> addWidget(style_);
50 layout -> addWidget(new QLabel(tr("Points du polygone :")));
51 layout -> addWidget(&points_list);
52 layout -> addWidget(&close_polygon);
53 layout->addStretch();
54
55 updateForm();
56 }
57
58 /// Destructeur
~PolygonEditor()59 PolygonEditor::~PolygonEditor() {
60 }
61
62 /**
63 Met a jour les points du polygone et cree un objet d'annulation
64 */
updatePolygonPoints()65 void PolygonEditor::updatePolygonPoints()
66 {
67 if (!part) return;
68 QPolygonF points = getPointsFromTree();
69 if (points.count() < 2)
70 {
71 QET::QetMessageBox::warning(this, tr("Erreur", "message box title"), tr("Le polygone doit comporter au moins deux points.", "message box content"));
72 return;
73 }
74
75 if (points != part->polygon())
76 {
77 QPropertyUndoCommand *undo = new QPropertyUndoCommand(part, "polygon", part->property("polygon"), points);
78 undo->setText(tr("Modifier un polygone"));
79 undoStack().push(undo);
80 }
81 }
82
83 /**
84 Met a jour l'etat ferme ou non du polygone
85 */
updatePolygonClosedState()86 void PolygonEditor::updatePolygonClosedState()
87 {
88 if (!part) return;
89 bool close = close_polygon.isChecked();
90 if (close != part->isClosed())
91 {
92 QPropertyUndoCommand *undo = new QPropertyUndoCommand(part, "closed", part->property("closed"), close);
93 undo->setText(tr("Modifier un polygone"));
94 undoStack().push(undo);
95 }
96 }
97
98 /**
99 Met a jour le formulaire d'edition
100 */
updateForm()101 void PolygonEditor::updateForm() {
102 if (!part) return;
103 activeConnections(false);
104 while(points_list.takeTopLevelItem(0)) {}
105 foreach(QPointF point, part -> polygon()) {
106 point = part -> mapToScene(point);
107 QStringList qsl;
108 qsl << QString("%1").arg(point.x()) << QString("%1").arg(point.y());
109 QTreeWidgetItem *qtwi = new QTreeWidgetItem(qsl);
110 qtwi -> setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
111 points_list.addTopLevelItem(qtwi);
112 }
113 close_polygon.setChecked(part -> isClosed());
114 activeConnections(true);
115 }
116
117 /**
118 Permet de specifier a cet editeur quelle primitive il doit editer. A noter
119 qu'un editeur peut accepter ou refuser d'editer une primitive.
120 L'editeur de polygone acceptera d'editer la primitive new_part s'il s'agit
121 d'un objet de la classe PartPolygon.
122 @param new_part Nouvelle primitive a editer
123 @return true si l'editeur a accepter d'editer la primitive, false sinon
124 */
setPart(CustomElementPart * new_part)125 bool PolygonEditor::setPart(CustomElementPart *new_part)
126 {
127 if (!new_part)
128 {
129 if (part)
130 {
131 disconnect(part, &PartPolygon::polygonChanged, this, &PolygonEditor::updateForm);
132 disconnect(part, &PartPolygon::closedChange, this, &PolygonEditor::updateForm);
133 }
134 part = nullptr;
135 style_ -> setPart(nullptr);
136 return(true);
137 }
138 if (PartPolygon *part_polygon = dynamic_cast<PartPolygon *>(new_part))
139 {
140 if (part == part_polygon) return true;
141 if (part)
142 {
143 disconnect(part, &PartPolygon::polygonChanged, this, &PolygonEditor::updateForm);
144 disconnect(part, &PartPolygon::closedChange, this, &PolygonEditor::updateForm);
145 }
146 part = part_polygon;
147 style_ -> setPart(part);
148 updateForm();
149 connect(part, &PartPolygon::polygonChanged, this, &PolygonEditor::updateForm);
150 connect(part, &PartPolygon::closedChange, this, &PolygonEditor::updateForm);
151 return(true);
152 }
153 return(false);
154 }
155
156 /**
157 @return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
158 */
currentPart() const159 CustomElementPart *PolygonEditor::currentPart() const {
160 return(part);
161 }
162
163 /**
164 @return Un vecteur contenant les points composant le polygone a partir du
165 formulaire d'edition
166 */
getPointsFromTree()167 QVector<QPointF> PolygonEditor::getPointsFromTree() {
168 if (!part) return(QVector<QPointF>());
169 QVector<QPointF> points;
170 for(int i = 0 ; i < points_list.topLevelItemCount() ; ++ i) {
171 QTreeWidgetItem *qtwi = points_list.topLevelItem(i);
172 bool x_convert_ok, y_convert_ok;
173 qreal x = qtwi -> text(0).toDouble(&x_convert_ok);
174 qreal y = qtwi -> text(1).toDouble(&y_convert_ok);
175 if (!x_convert_ok || !y_convert_ok) continue;
176 points << part -> mapFromScene(QPointF(x, y));
177 }
178 return(points);
179 }
180
181 /**
182 @param qtwi QTreeWidgetItem a valider
183 @param column Colonne exacte du QTreeWidgetItem a valider
184 */
validColumn(QTreeWidgetItem * qtwi,int column)185 void PolygonEditor::validColumn(QTreeWidgetItem *qtwi, int column) {
186 bool convert_ok;
187 qtwi -> text(column).toDouble(&convert_ok);
188 if (convert_ok) {
189 points_list.closePersistentEditor(qtwi, column);
190 updatePolygonPoints();
191 } else points_list.openPersistentEditor(qtwi, column);
192 }
193
194 /**
195 Active ou desactive les connexionx signaux/slots entre les widgets internes.
196 @param active true pour activer les connexions, false pour les desactiver
197 */
activeConnections(bool active)198 void PolygonEditor::activeConnections(bool active) {
199 if (active) {
200 connect(&close_polygon, SIGNAL(stateChanged(int)), this, SLOT(updatePolygonClosedState()));
201 connect(&points_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(validColumn(QTreeWidgetItem *, int)));
202 } else {
203 disconnect(&close_polygon, SIGNAL(stateChanged(int)), this, SLOT(updatePolygonClosedState()));
204 disconnect(&points_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(validColumn(QTreeWidgetItem *, int)));
205 }
206 }
207