1
/***************************************************************************
2
* Copyright (c) 2014 Abdullah Tahiri <abdullah.tahiri.yo@gmail.com> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
30
#include <Base/Tools.h>
31
#include <Mod/Sketcher/App/PropertyConstraintList.h>
33
#include "PropertyConstraintListItem.h"
36
using namespace SketcherGui;
37
using namespace Gui::PropertyEditor;
39
PROPERTYITEM_SOURCE(SketcherGui::PropertyConstraintListItem)
41
PropertyConstraintListItem::PropertyConstraintListItem()
47
PropertyConstraintListItem::~PropertyConstraintListItem()
50
QVariant PropertyConstraintListItem::toString(const QVariant& prop) const
52
const QList<Base::Quantity>& value = prop.value<QList<Base::Quantity>>();
54
QTextStream out(&str);
56
for (QList<Base::Quantity>::const_iterator it = value.begin(); it != value.end(); ++it) {
57
if (it != value.begin()) {
60
out << it->getUserString();
66
void PropertyConstraintListItem::initialize()
68
const Sketcher::PropertyConstraintList* list =
69
static_cast<const Sketcher::PropertyConstraintList*>(getPropertyData()[0]);
70
const std::vector<Sketcher::Constraint*>& vals = list->getValues();
75
std::vector<PropertyUnitItem*> unnamed;
77
for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end();
79
if ((*it)->Type == Sketcher::Distance || // Datum constraint
80
(*it)->Type == Sketcher::DistanceX || (*it)->Type == Sketcher::DistanceY
81
|| (*it)->Type == Sketcher::Radius || (*it)->Type == Sketcher::Diameter
82
|| (*it)->Type == Sketcher::Angle) {
84
PropertyUnitItem* item = static_cast<PropertyUnitItem*>(PropertyUnitItem::create());
87
QString internalName = QString::fromLatin1("Constraint%1").arg(id);
88
QString name = QString::fromUtf8((*it)->Name.c_str());
91
item->setPropertyName(name);
92
unnamed.push_back(item);
96
item->setParent(this);
97
item->setPropertyName(name);
98
// The call of 'setPropertyName' calls 'setObjectName'. But 'name' can contain
99
// some non-7-bit ASCII characters and thus the delegation of a property to the
100
// parent item may fail because 'qPrintable(objectName())' is used therefore and
101
// may return a different string. See 'PropertyItem::setData()' for more details.
102
// To make the delegation to work properly we set a different object name which is
103
// guaranteed to be 7-bit ASCII.
105
// See also PropertyConstraintListItem::value()
106
// See also PropertyConstraintListItem::event()
107
item->setObjectName(internalName);
108
this->appendChild(item);
111
item->bind(list->createPath(id - 1));
112
item->setAutoApply(false);
116
// now deal with the unnamed
119
for (std::vector<PropertyUnitItem*>::const_iterator it = unnamed.begin();
122
(*it)->setParent(this);
123
this->appendChild((*it));
128
if (!unnamed.empty()) {
129
PropertyConstraintListItem* item =
130
static_cast<PropertyConstraintListItem*>(PropertyConstraintListItem::create());
131
item->setParent(this);
132
item->setPropertyName(tr("Unnamed"));
133
this->appendChild(item);
135
for (std::vector<PropertyUnitItem*>::const_iterator it = unnamed.begin();
138
(*it)->setParent(item);
139
item->appendChild((*it));
145
void PropertyConstraintListItem::assignProperty(const App::Property* prop)
147
// Hint: When renaming a constraint that was unnamed before then it can happen that
148
// a constraint appears twice in the property editor, one time in this group and a
149
// second time inside the Unnamed group
150
if (!prop->isDerivedFrom<Sketcher::PropertyConstraintList>()) {
154
const Sketcher::PropertyConstraintList* list =
155
static_cast<const Sketcher::PropertyConstraintList*>(prop);
156
const std::vector<Sketcher::Constraint*>& vals = list->getValues();
158
// search for the group of unnamed items if available and take it out
160
PropertyConstraintListItem* unnamed = nullptr;
161
for (int i = this->childCount() - 1; i >= 0; i--) {
162
unnamed = qobject_cast<PropertyConstraintListItem*>(this->child(i));
164
numUnnamed = unnamed->childCount();
172
int unnamedIndex = 0;
173
int numNamed = this->childCount();
174
this->onlyUnnamed = true;
176
for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end();
178
if ((*it)->Type == Sketcher::Distance || // Datum constraint
179
(*it)->Type == Sketcher::DistanceX || (*it)->Type == Sketcher::DistanceY
180
|| (*it)->Type == Sketcher::Radius || (*it)->Type == Sketcher::Diameter
181
|| (*it)->Type == Sketcher::Angle) {
183
PropertyUnitItem* child = nullptr;
184
if ((*it)->Name.empty()) {
185
// search inside the group item for unnamed constraints
187
unnamed = static_cast<PropertyConstraintListItem*>(
188
PropertyConstraintListItem::create());
189
unnamed->setPropertyName(tr("Unnamed"));
192
if (unnamedIndex < numUnnamed) {
193
child = static_cast<PropertyUnitItem*>(unnamed->child(unnamedIndex));
196
child = static_cast<PropertyUnitItem*>(PropertyUnitItem::create());
197
unnamed->appendChild(child);
198
child->setParent(unnamed);
203
// search inside this item
204
if (namedIndex < numNamed) {
205
child = dynamic_cast<PropertyUnitItem*>(this->child(namedIndex));
209
child = static_cast<PropertyUnitItem*>(PropertyUnitItem::create());
210
this->appendChild(child);
211
child->setParent(this);
214
this->onlyUnnamed = false;
218
QString internalName = QString::fromLatin1("Constraint%1").arg(id);
219
QString name = QString::fromUtf8((*it)->Name.c_str());
220
if (name.isEmpty()) {
224
if (child->objectName() != internalName) {
225
child->setPropertyName(name);
226
child->setObjectName(internalName);
228
child->bind(list->createPath(id - 1));
229
child->setAutoApply(false);
234
// at the Unnamed group at very the end
236
this->appendChild(unnamed);
237
unnamed->setParent(this);
241
QVariant PropertyConstraintListItem::value(const App::Property* prop) const
243
assert(prop && prop->isDerivedFrom<Sketcher::PropertyConstraintList>());
245
PropertyConstraintListItem* self = const_cast<PropertyConstraintListItem*>(this);
249
QList<Base::Quantity> quantities;
250
QList<Base::Quantity> subquantities;
251
bool onlyNamed = true;
253
const std::vector<Sketcher::Constraint*>& vals =
254
static_cast<const Sketcher::PropertyConstraintList*>(prop)->getValues();
255
for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end();
257
if ((*it)->Type == Sketcher::Distance || // Datum constraint
258
(*it)->Type == Sketcher::DistanceX || (*it)->Type == Sketcher::DistanceY
259
|| (*it)->Type == Sketcher::Radius || (*it)->Type == Sketcher::Diameter
260
|| (*it)->Type == Sketcher::Angle) {
262
Base::Quantity quant;
263
if ((*it)->Type == Sketcher::Angle) {
264
double datum = Base::toDegrees<double>((*it)->getValue());
265
quant.setUnit(Base::Unit::Angle);
266
quant.setValue(datum);
269
quant.setUnit(Base::Unit::Length);
270
quant.setValue((*it)->getValue());
273
quantities.append(quant);
275
// Use a 7-bit ASCII string for the internal name.
276
// See also comment in PropertyConstraintListItem::initialize()
277
QString internalName = QString::fromLatin1("Constraint%1").arg(id);
279
if ((*it)->Name.empty() && !onlyUnnamed) {
281
subquantities.append(quant);
282
PropertyItem* child = self->child(self->childCount() - 1);
283
PropertyConstraintListItem* unnamednode =
284
qobject_cast<PropertyConstraintListItem*>(child);
286
unnamednode->blockEvent = true;
287
unnamednode->setProperty(internalName.toLatin1(),
288
QVariant::fromValue<Base::Quantity>(quant));
289
unnamednode->blockEvent = false;
292
qWarning() << "Item is not of type PropertyConstraintListItem but"
293
<< typeid(*child).name();
297
self->blockEvent = true;
298
self->setProperty(internalName.toLatin1(),
299
QVariant::fromValue<Base::Quantity>(quant));
300
self->blockEvent = false;
305
// The quantities of unnamed constraints are only needed for display purposes inside toString()
306
if (!onlyUnnamed && !onlyNamed) {
307
self->blockEvent = true;
308
self->setProperty("Unnamed", QVariant::fromValue<QList<Base::Quantity>>(subquantities));
309
self->blockEvent = false;
312
return QVariant::fromValue<QList<Base::Quantity>>(quantities);
315
bool PropertyConstraintListItem::event(QEvent* ev)
317
if (ev->type() == QEvent::DynamicPropertyChange) {
319
QDynamicPropertyChangeEvent* ce = static_cast<QDynamicPropertyChangeEvent*>(ev);
320
// Get property via internal name of a PropertyUnit
321
QVariant prop = property(ce->propertyName());
322
QString propName = QString::fromLatin1(ce->propertyName());
323
Base::Quantity quant = prop.value<Base::Quantity>();
325
Sketcher::PropertyConstraintList* item;
328
if (dynamic_cast<SketcherGui::PropertyConstraintListItem*>(this->parent())) {
329
item = static_cast<Sketcher::PropertyConstraintList*>(
330
this->parent()->getFirstProperty());
333
item = static_cast<Sketcher::PropertyConstraintList*>(getFirstProperty());
336
const std::vector<Sketcher::Constraint*>& vals = item->getValues();
337
for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin();
340
if ((*it)->Type == Sketcher::Distance || // Datum constraint
341
(*it)->Type == Sketcher::DistanceX || (*it)->Type == Sketcher::DistanceY
342
|| (*it)->Type == Sketcher::Radius || (*it)->Type == Sketcher::Diameter
343
|| (*it)->Type == Sketcher::Angle) {
345
// Get the internal name
346
QString internalName = QString::fromLatin1("Constraint%1").arg(id + 1);
347
if (internalName == propName) {
348
double datum = quant.getValue();
349
if ((*it)->Type == Sketcher::Angle) {
350
datum = Base::toRadians<double>(datum);
352
std::unique_ptr<Sketcher::Constraint> copy((*it)->clone());
353
copy->setValue(datum);
354
item->set1Value(id, copy.get());
362
return PropertyItem::event(ev);
365
void PropertyConstraintListItem::setValue(const QVariant& value)
367
// see PropertyConstraintListItem::event
371
QWidget* PropertyConstraintListItem::createEditor(QWidget* parent,
372
const std::function<void()>& method) const
375
QLineEdit* le = new QLineEdit(parent);
377
le->setReadOnly(true);
381
void PropertyConstraintListItem::setEditorData(QWidget* editor, const QVariant& data) const
383
QLineEdit* le = qobject_cast<QLineEdit*>(editor);
384
le->setText(toString(data).toString());
387
QVariant PropertyConstraintListItem::editorData(QWidget* editor) const
389
QLineEdit* le = qobject_cast<QLineEdit*>(editor);
390
return QVariant(le->text());
393
#include "moc_PropertyConstraintListItem.cpp"