FreeCAD

Форк
0
/
PropertyConstraintListItem.cpp 
393 строки · 15.1 Кб
1
/***************************************************************************
2
 * Copyright (c) 2014 Abdullah Tahiri <abdullah.tahiri.yo@gmail.com>        *
3
 *                                                                          *
4
 * This file is part of the FreeCAD CAx development system.                 *
5
 *                                                                          *
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.         *
10
 *                                                                          *
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.                     *
15
 *                                                                          *
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                                    *
20
 *                                                                          *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
#include <QDebug>
26
#include <QTextStream>
27
#include <memory>
28
#endif
29

30
#include <Base/Tools.h>
31
#include <Mod/Sketcher/App/PropertyConstraintList.h>
32

33
#include "PropertyConstraintListItem.h"
34

35

36
using namespace SketcherGui;
37
using namespace Gui::PropertyEditor;
38

39
PROPERTYITEM_SOURCE(SketcherGui::PropertyConstraintListItem)
40

41
PropertyConstraintListItem::PropertyConstraintListItem()
42
{
43
    blockEvent = false;
44
    onlyUnnamed = false;
45
}
46

47
PropertyConstraintListItem::~PropertyConstraintListItem()
48
{}
49

50
QVariant PropertyConstraintListItem::toString(const QVariant& prop) const
51
{
52
    const QList<Base::Quantity>& value = prop.value<QList<Base::Quantity>>();
53
    QString str;
54
    QTextStream out(&str);
55
    out << "[";
56
    for (QList<Base::Quantity>::const_iterator it = value.begin(); it != value.end(); ++it) {
57
        if (it != value.begin()) {
58
            out << ";";
59
        }
60
        out << it->getUserString();
61
    }
62
    out << "]";
63
    return QVariant(str);
64
}
65

66
void PropertyConstraintListItem::initialize()
67
{
68
    const Sketcher::PropertyConstraintList* list =
69
        static_cast<const Sketcher::PropertyConstraintList*>(getPropertyData()[0]);
70
    const std::vector<Sketcher::Constraint*>& vals = list->getValues();
71

72
    int id = 1;
73
    int iNamed = 0;
74

75
    std::vector<PropertyUnitItem*> unnamed;
76

77
    for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end();
78
         ++it, ++id) {
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) {
83

84
            PropertyUnitItem* item = static_cast<PropertyUnitItem*>(PropertyUnitItem::create());
85

86
            // Get the name
87
            QString internalName = QString::fromLatin1("Constraint%1").arg(id);
88
            QString name = QString::fromUtf8((*it)->Name.c_str());
89
            if (name.isEmpty()) {
90
                name = internalName;
91
                item->setPropertyName(name);
92
                unnamed.push_back(item);
93
            }
94
            else {
95
                iNamed++;
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.
104
                //
105
                // See also PropertyConstraintListItem::value()
106
                // See also PropertyConstraintListItem::event()
107
                item->setObjectName(internalName);
108
                this->appendChild(item);
109
            }
110

111
            item->bind(list->createPath(id - 1));
112
            item->setAutoApply(false);
113
        }
114
    }
115

116
    // now deal with the unnamed
117
    if (iNamed == 0) {
118
        onlyUnnamed = true;
119
        for (std::vector<PropertyUnitItem*>::const_iterator it = unnamed.begin();
120
             it != unnamed.end();
121
             ++it) {
122
            (*it)->setParent(this);
123
            this->appendChild((*it));
124
        }
125
    }
126
    else {
127
        onlyUnnamed = false;
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);
134

135
            for (std::vector<PropertyUnitItem*>::const_iterator it = unnamed.begin();
136
                 it != unnamed.end();
137
                 ++it) {
138
                (*it)->setParent(item);
139
                item->appendChild((*it));
140
            }
141
        }
142
    }
143
}
144

145
void PropertyConstraintListItem::assignProperty(const App::Property* prop)
146
{
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>()) {
151
        return;
152
    }
153

154
    const Sketcher::PropertyConstraintList* list =
155
        static_cast<const Sketcher::PropertyConstraintList*>(prop);
156
    const std::vector<Sketcher::Constraint*>& vals = list->getValues();
157

158
    // search for the group of unnamed items if available and take it out
159
    int numUnnamed = 0;
160
    PropertyConstraintListItem* unnamed = nullptr;
161
    for (int i = this->childCount() - 1; i >= 0; i--) {
162
        unnamed = qobject_cast<PropertyConstraintListItem*>(this->child(i));
163
        if (unnamed) {
164
            numUnnamed = unnamed->childCount();
165
            this->takeChild(i);
166
            break;
167
        }
168
    }
169

170
    int id = 1;
171
    int namedIndex = 0;
172
    int unnamedIndex = 0;
173
    int numNamed = this->childCount();
174
    this->onlyUnnamed = true;
175

176
    for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end();
177
         ++it, ++id) {
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) {
182

183
            PropertyUnitItem* child = nullptr;
184
            if ((*it)->Name.empty()) {
185
                // search inside the group item for unnamed constraints
186
                if (!unnamed) {
187
                    unnamed = static_cast<PropertyConstraintListItem*>(
188
                        PropertyConstraintListItem::create());
189
                    unnamed->setPropertyName(tr("Unnamed"));
190
                }
191

192
                if (unnamedIndex < numUnnamed) {
193
                    child = static_cast<PropertyUnitItem*>(unnamed->child(unnamedIndex));
194
                }
195
                else {
196
                    child = static_cast<PropertyUnitItem*>(PropertyUnitItem::create());
197
                    unnamed->appendChild(child);
198
                    child->setParent(unnamed);
199
                }
200
                unnamedIndex++;
201
            }
202
            else {
203
                // search inside this item
204
                if (namedIndex < numNamed) {
205
                    child = dynamic_cast<PropertyUnitItem*>(this->child(namedIndex));
206
                }
207

208
                if (!child) {
209
                    child = static_cast<PropertyUnitItem*>(PropertyUnitItem::create());
210
                    this->appendChild(child);
211
                    child->setParent(this);
212
                }
213
                namedIndex++;
214
                this->onlyUnnamed = false;
215
            }
216

217
            // Get the name
218
            QString internalName = QString::fromLatin1("Constraint%1").arg(id);
219
            QString name = QString::fromUtf8((*it)->Name.c_str());
220
            if (name.isEmpty()) {
221
                name = internalName;
222
            }
223

224
            if (child->objectName() != internalName) {
225
                child->setPropertyName(name);
226
                child->setObjectName(internalName);
227

228
                child->bind(list->createPath(id - 1));
229
                child->setAutoApply(false);
230
            }
231
        }
232
    }
233

234
    // at the Unnamed group at very the end
235
    if (unnamed) {
236
        this->appendChild(unnamed);
237
        unnamed->setParent(this);
238
    }
239
}
240

241
QVariant PropertyConstraintListItem::value(const App::Property* prop) const
242
{
243
    assert(prop && prop->isDerivedFrom<Sketcher::PropertyConstraintList>());
244

245
    PropertyConstraintListItem* self = const_cast<PropertyConstraintListItem*>(this);
246

247
    int id = 1;
248

249
    QList<Base::Quantity> quantities;
250
    QList<Base::Quantity> subquantities;
251
    bool onlyNamed = true;
252

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();
256
         ++it, ++id) {
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) {
261

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);
267
            }
268
            else {
269
                quant.setUnit(Base::Unit::Length);
270
                quant.setValue((*it)->getValue());
271
            }
272

273
            quantities.append(quant);
274

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);
278

279
            if ((*it)->Name.empty() && !onlyUnnamed) {
280
                onlyNamed = false;
281
                subquantities.append(quant);
282
                PropertyItem* child = self->child(self->childCount() - 1);
283
                PropertyConstraintListItem* unnamednode =
284
                    qobject_cast<PropertyConstraintListItem*>(child);
285
                if (unnamednode) {
286
                    unnamednode->blockEvent = true;
287
                    unnamednode->setProperty(internalName.toLatin1(),
288
                                             QVariant::fromValue<Base::Quantity>(quant));
289
                    unnamednode->blockEvent = false;
290
                }
291
                else {
292
                    qWarning() << "Item is not of type PropertyConstraintListItem but"
293
                               << typeid(*child).name();
294
                }
295
            }
296
            else {
297
                self->blockEvent = true;
298
                self->setProperty(internalName.toLatin1(),
299
                                  QVariant::fromValue<Base::Quantity>(quant));
300
                self->blockEvent = false;
301
            }
302
        }
303
    }
304

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;
310
    }
311

312
    return QVariant::fromValue<QList<Base::Quantity>>(quantities);
313
}
314

315
bool PropertyConstraintListItem::event(QEvent* ev)
316
{
317
    if (ev->type() == QEvent::DynamicPropertyChange) {
318
        if (!blockEvent) {
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>();
324

325
            Sketcher::PropertyConstraintList* item;
326

327
            int id = 0;
328
            if (dynamic_cast<SketcherGui::PropertyConstraintListItem*>(this->parent())) {
329
                item = static_cast<Sketcher::PropertyConstraintList*>(
330
                    this->parent()->getFirstProperty());
331
            }
332
            else {
333
                item = static_cast<Sketcher::PropertyConstraintList*>(getFirstProperty());
334
            }
335

336
            const std::vector<Sketcher::Constraint*>& vals = item->getValues();
337
            for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin();
338
                 it != vals.end();
339
                 ++it, ++id) {
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) {
344

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);
351
                        }
352
                        std::unique_ptr<Sketcher::Constraint> copy((*it)->clone());
353
                        copy->setValue(datum);
354
                        item->set1Value(id, copy.get());
355
                        break;
356
                    }
357
                }
358
            }
359
        }
360
    }
361

362
    return PropertyItem::event(ev);
363
}
364

365
void PropertyConstraintListItem::setValue(const QVariant& value)
366
{
367
    // see PropertyConstraintListItem::event
368
    Q_UNUSED(value);
369
}
370

371
QWidget* PropertyConstraintListItem::createEditor(QWidget* parent,
372
                                                  const std::function<void()>& method) const
373
{
374
    Q_UNUSED(method);
375
    QLineEdit* le = new QLineEdit(parent);
376
    le->setFrame(false);
377
    le->setReadOnly(true);
378
    return le;
379
}
380

381
void PropertyConstraintListItem::setEditorData(QWidget* editor, const QVariant& data) const
382
{
383
    QLineEdit* le = qobject_cast<QLineEdit*>(editor);
384
    le->setText(toString(data).toString());
385
}
386

387
QVariant PropertyConstraintListItem::editorData(QWidget* editor) const
388
{
389
    QLineEdit* le = qobject_cast<QLineEdit*>(editor);
390
    return QVariant(le->text());
391
}
392

393
#include "moc_PropertyConstraintListItem.cpp"
394

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.