FreeCAD

Форк
0
/
DynamicProperty.cpp 
353 строки · 11.3 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
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

24
#include "PreCompiled.h"
25

26
#include <Base/Reader.h>
27
#include <Base/Tools.h>
28
#include <Base/Writer.h>
29

30
#include "DynamicProperty.h"
31
#include "Application.h"
32
#include "Property.h"
33
#include "PropertyContainer.h"
34

35

36
FC_LOG_LEVEL_INIT("Property",true,true)
37

38

39
using namespace App;
40

41

42
DynamicProperty::DynamicProperty() = default;
43

44
DynamicProperty::~DynamicProperty()
45
{
46
    clear();
47
}
48

49
void DynamicProperty::clear() {
50
    auto &index = props.get<0>();
51
    for(auto &v : index)
52
        delete v.property;
53
    index.clear();
54
}
55

56
void DynamicProperty::getPropertyList(std::vector<Property*> &List) const
57
{
58
    for (auto &v : props.get<0>())
59
        List.push_back(v.property);
60
}
61

62
void DynamicProperty::getPropertyNamedList(std::vector<std::pair<const char*, Property*> > &List) const
63
{
64
    for (auto &v : props.get<0>())
65
        List.emplace_back(v.getName(),v.property);
66
}
67

68
void DynamicProperty::getPropertyMap(std::map<std::string,Property*> &Map) const
69
{
70
    for (auto &v : props.get<0>())
71
        Map[v.name] = v.property;
72
}
73

74
Property *DynamicProperty::getDynamicPropertyByName(const char* name) const
75
{
76
    auto &index = props.get<0>();
77
    auto it = index.find(name);
78
    if (it != index.end())
79
        return it->property;
80
    return nullptr;
81
}
82

83
std::vector<std::string> DynamicProperty::getDynamicPropertyNames() const
84
{
85
    std::vector<std::string> names;
86
    auto &index = props.get<0>();
87
    names.reserve(index.size());
88
    for(auto &v : index)
89
        names.push_back(v.name);
90
    return names;
91
}
92

93
short DynamicProperty::getPropertyType(const Property* prop) const
94
{
95
    return prop?prop->getType():0;
96
}
97

98
short DynamicProperty::getPropertyType(const char *name) const
99
{
100
    auto &index = props.get<0>();
101
    auto it = index.find(name);
102
    if (it != index.end()) {
103
        short attr = it->attr;
104
        if (it->hidden)
105
            attr |= Prop_Hidden;
106
        if (it->readonly)
107
            attr |= Prop_ReadOnly;
108
        return attr;
109
    }
110
    return 0;
111
}
112

113
const char* DynamicProperty::getPropertyGroup(const Property* prop) const
114
{
115
    auto &index = props.get<1>();
116
    auto it = index.find(const_cast<Property*>(prop));
117
    if(it!=index.end())
118
        return it->group.c_str();
119
    return nullptr;
120
}
121

122
const char* DynamicProperty::getPropertyGroup(const char *name) const
123
{
124
    auto &index = props.get<0>();
125
    auto it = index.find(name);
126
    if (it != index.end())
127
        return it->group.c_str();
128
    return nullptr;
129
}
130

131
const char* DynamicProperty::getPropertyDocumentation(const Property* prop) const
132
{
133
    auto &index = props.get<1>();
134
    auto it = index.find(const_cast<Property*>(prop));
135
    if(it!=index.end())
136
        return it->doc.c_str();
137
    return nullptr;
138
}
139

140
const char* DynamicProperty::getPropertyDocumentation(const char *name) const
141
{
142
    auto &index = props.get<0>();
143
    auto it = index.find(name);
144
    if (it != index.end())
145
        return it->doc.c_str();
146
    return nullptr;
147
}
148

149
Property* DynamicProperty::addDynamicProperty(PropertyContainer &pc, const char* type,
150
        const char* name, const char* group, const char* doc, short attr, bool ro, bool hidden)
151
{
152
    if(!type)
153
        type = "<null>";
154

155
    std::string _name;
156

157
    static ParameterGrp::handle hGrp = GetApplication().GetParameterGroupByPath(
158
            "User parameter:BaseApp/Preferences/Document");
159
    if(hGrp->GetBool("AutoNameDynamicProperty",false)) {
160
        if(!name || !name[0])
161
            name = type;
162
        _name = getUniquePropertyName(pc,name);
163
        if(_name != name) {
164
            FC_WARN(pc.getFullName() << " rename dynamic property from '"
165
                    << name << "' to '" << _name << "'");
166
        }
167
        name = _name.c_str();
168
    } else if(!name)
169
        name = "<null>"; // setting a bad name to trigger exception
170

171
    auto prop = pc.getPropertyByName(name);
172
    if(prop && prop->getContainer()==&pc)
173
        FC_THROWM(Base::NameError, "Property " << pc.getFullName() << '.' << name << " already exists");
174

175
    if(Base::Tools::getIdentifier(name) != name)
176
        FC_THROWM(Base::NameError, "Invalid property name '" << name << "'");
177

178
    Base::Type propType = Base::Type::getTypeIfDerivedFrom(type, App::Property::getClassTypeId(), true);
179
    if (propType.isBad()) {
180
        FC_THROWM(Base::TypeError, "Invalid type "
181
                << type << " for property " << pc.getFullName() << '.' << name);
182
    }
183

184
    void* propInstance = propType.createInstance();
185
    if (!propInstance) {
186
        FC_THROWM(Base::RuntimeError, "Failed to create property "
187
                << pc.getFullName() << '.' << name << " of type " << type);
188
    }
189

190
    Property* pcProperty = static_cast<Property*>(propInstance);
191

192
    auto res = props.get<0>().emplace(pcProperty,name, nullptr, group, doc, attr, ro, hidden);
193

194
    pcProperty->setContainer(&pc);
195
    pcProperty->myName = res.first->name.c_str();
196

197
    if(ro)
198
        attr |= Prop_ReadOnly;
199
    if(hidden)
200
        attr |= Prop_Hidden;
201

202
    pcProperty->syncType(attr);
203
    pcProperty->StatusBits.set((size_t)Property::PropDynamic);
204

205
    GetApplication().signalAppendDynamicProperty(*pcProperty);
206

207
    return pcProperty;
208
}
209

210
bool DynamicProperty::addProperty(Property *prop)
211
{
212
    if(!prop || !prop->hasName())
213
        return false;
214
    auto &index = props.get<0>();
215
    if(index.count(prop->getName()))
216
        return false;
217
    index.emplace(prop,std::string(),prop->getName(),
218
            prop->getGroup(),prop->getDocumentation(),prop->getType(),false,false);
219
    return true;
220
}
221

222
bool DynamicProperty::removeProperty(const Property *prop)
223
{
224
    auto &index = props.get<1>();
225
    auto it = index.find(const_cast<Property*>(prop));
226
    if (it != index.end()) {
227
        index.erase(it);
228
        return true;
229
    }
230
    return false;
231
}
232

233
bool DynamicProperty::removeDynamicProperty(const char* name)
234
{
235
    auto &index = props.get<0>();
236
    auto it = index.find(name);
237
    if (it != index.end()) {
238
        if(it->property->testStatus(Property::LockDynamic))
239
            throw Base::RuntimeError("property is locked");
240
        else if(!it->property->testStatus(Property::PropDynamic))
241
            throw Base::RuntimeError("property is not dynamic");
242
        Property *prop = it->property;
243
        GetApplication().signalRemoveDynamicProperty(*prop);
244

245
        // Handle possible recursive calls of removeDynamicProperty
246
        if (prop->myName) {
247
            Property::destroy(prop);
248
            index.erase(it);
249
            // memory of myName has been freed
250
            prop->myName = nullptr;
251
        }
252
        return true;
253
    }
254

255
    return false;
256
}
257

258
std::string DynamicProperty::getUniquePropertyName(PropertyContainer &pc, const char *Name) const
259
{
260
    std::string CleanName = Base::Tools::getIdentifier(Name);
261

262
    // name in use?
263
    std::map<std::string,Property*> objectProps;
264
    pc.getPropertyMap(objectProps);
265
    auto pos = objectProps.find(CleanName);
266

267
    if (pos == objectProps.end()) {
268
        // if not, name is OK
269
        return CleanName;
270
    }
271
    else {
272
        std::vector<std::string> names;
273
        names.reserve(objectProps.size());
274
        for (pos = objectProps.begin();pos != objectProps.end();++pos) {
275
            names.push_back(pos->first);
276
        }
277
        return Base::Tools::getUniqueName(CleanName, names);
278
    }
279
}
280

281
void DynamicProperty::save(const Property *prop, Base::Writer &writer) const
282
{
283
    auto &index = props.get<1>();
284
    auto it = index.find(const_cast<Property*>(prop));
285
    if(it != index.end()) {
286
        auto &data = *it;
287
        writer.Stream() << "\" group=\"" << Base::Persistence::encodeAttribute(data.group)
288
                        << "\" doc=\"" << Base::Persistence::encodeAttribute(data.doc)
289
                        << "\" attr=\"" << data.attr << "\" ro=\"" << data.readonly
290
                        << "\" hide=\"" << data.hidden;
291
    }
292
}
293

294
Property *DynamicProperty::restore(PropertyContainer &pc,
295
        const char *PropName, const char *TypeName, Base::XMLReader &reader)
296
{
297
    if (!reader.hasAttribute("group"))
298
        return nullptr;
299

300
    short attribute = 0;
301
    bool readonly = false, hidden = false;
302
    const char *group=nullptr, *doc=nullptr, *attr=nullptr, *ro=nullptr, *hide=nullptr;
303
    group = reader.getAttribute("group");
304
    if (reader.hasAttribute("doc"))
305
        doc = reader.getAttribute("doc");
306
    if (reader.hasAttribute("attr")) {
307
        attr = reader.getAttribute("attr");
308
        if (attr) {
309
            std::istringstream str(attr);
310
            str >> attribute;
311
        }
312
    }
313
    if (reader.hasAttribute("ro")) {
314
        ro = reader.getAttribute("ro");
315
        if (ro) readonly = (ro[0]-48) != 0;
316
    }
317
    if (reader.hasAttribute("hide")) {
318
        hide = reader.getAttribute("hide");
319
        if (hide) hidden = (hide[0]-48) != 0;
320
    }
321

322
    return addDynamicProperty(pc,TypeName, PropName, group, doc, attribute, readonly, hidden);
323
}
324

325
DynamicProperty::PropData DynamicProperty::getDynamicPropertyData(const Property *prop) const
326
{
327
    auto &index = props.get<1>();
328
    auto it = index.find(const_cast<Property*>(prop));
329
    if(it != index.end())
330
        return *it;
331
    return {};
332
}
333

334
bool DynamicProperty::changeDynamicProperty(const Property *prop, const char *group, const char *doc) {
335
    auto &index = props.get<1>();
336
    auto it = index.find(const_cast<Property*>(prop));
337
    if (it == index.end())
338
        return false;
339
    if(group)
340
        it->group = group;
341
    if(doc)
342
        it->doc = doc;
343
    return true;
344
}
345

346
const char *DynamicProperty::getPropertyName(const Property *prop) const
347
{
348
    auto &index = props.get<1>();
349
    auto it = index.find(const_cast<Property*>(prop));
350
    if(it != index.end())
351
        return it->getName();
352
    return nullptr;
353
}
354

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

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

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

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