App: fix memory leaks in Enumeration class and simplify code

This commit is contained in:
wmayer
2022-05-10 18:47:23 +02:00
committed by wwmayer
parent d7313598aa
commit 7db925d991
12 changed files with 329 additions and 340 deletions

View File

@@ -28,76 +28,81 @@
#include <Base/Exception.h>
#include "Enumeration.h"
#include <string_view>
using namespace App;
namespace {
struct StringCopy {
StringCopy(const char* str) : d(str) {
}
const char* data() const {
return d.data();
}
bool isEqual(const char* str) const {
return d == str;
}
bool isCustom() const {
return true;
}
private:
std::string d;
};
struct StringView {
StringView(const char* str) : d(str) {
}
const char* data() const {
return d.data();
}
bool isEqual(const char* str) const {
return d == str;
}
bool isCustom() const {
return false;
}
private:
std::string_view d;
};
}
Enumeration::Enumeration()
: _EnumArray(nullptr), _ownEnumArray(false), _index(0), _maxVal(-1)
: _index(0)
{
}
Enumeration::Enumeration(const Enumeration &other)
: _EnumArray(nullptr), _ownEnumArray(false), _index(0), _maxVal(-1)
{
if (other._ownEnumArray) {
setEnums(other.getEnumVector());
} else {
_EnumArray = other._EnumArray;
}
_ownEnumArray = other._ownEnumArray;
enumArray = other.enumArray;
_index = other._index;
_maxVal = other._maxVal;
}
Enumeration::Enumeration(const char *valStr)
: _ownEnumArray(true), _index(0), _maxVal(0)
: _index(0)
{
_EnumArray = new const char*[2];
#if defined (_MSC_VER)
_EnumArray[0] = _strdup(valStr);
#else
_EnumArray[0] = strdup(valStr);
#endif
_EnumArray[1] = nullptr;
enumArray.push_back(StringCopy(valStr));
setValue(valStr);
}
Enumeration::Enumeration(const char **list, const char *valStr)
: _EnumArray(list), _ownEnumArray(false)
: _index(0)
{
findMaxVal();
while (list && *list) {
enumArray.push_back(StringView(*list));
list++;
}
setValue(valStr);
}
Enumeration::~Enumeration()
{
if (_ownEnumArray) {
if (_EnumArray != nullptr) {
tearDown();
}
}
}
void Enumeration::tearDown(void)
{
// Ugly...
for(char **plEnums = (char **)_EnumArray; *plEnums != nullptr; ++plEnums) {
// Delete C Strings first
free(*plEnums);
}
delete [] _EnumArray;
_EnumArray = nullptr;
_ownEnumArray = false;
_maxVal = -1;
enumArray.clear();
}
void Enumeration::setEnums(const char **plEnums)
{
if(plEnums == _EnumArray)
return;
std::string oldValue;
bool preserve = (isValid() && plEnums != nullptr);
if (preserve) {
@@ -106,23 +111,15 @@ void Enumeration::setEnums(const char **plEnums)
oldValue = str;
}
// set _ownEnumArray
if (isValid() && _ownEnumArray) {
tearDown();
enumArray.clear();
while (plEnums && *plEnums) {
enumArray.push_back(StringView(*plEnums));
plEnums++;
}
// set...
_EnumArray = plEnums;
// set _maxVal
findMaxVal();
// set _index
if (_index < 0)
_index = 0;
else if (_index > _maxVal)
_index = _maxVal;
if (preserve) {
setValue(oldValue);
}
@@ -143,30 +140,14 @@ void Enumeration::setEnums(const std::vector<std::string> &values)
oldValue = str;
}
if (isValid() && _ownEnumArray) {
tearDown();
}
_EnumArray = new const char*[values.size() + 1];
int i = 0;
enumArray.clear();
for (std::vector<std::string>::const_iterator it = values.begin(); it != values.end(); ++it) {
#if defined (_MSC_VER)
_EnumArray[i++] = _strdup(it->c_str());
#else
_EnumArray[i++] = strdup(it->c_str());
#endif
enumArray.push_back(StringCopy(it->c_str()));
}
_EnumArray[i] = nullptr; // null termination
// Other state variables
_maxVal = static_cast<int>(values.size() - 1);
_ownEnumArray = true;
// set _index
if (_index < 0)
_index = 0;
else if (_index > _maxVal)
_index = _maxVal;
if (preserve) {
setValue(oldValue);
}
@@ -174,36 +155,18 @@ void Enumeration::setEnums(const std::vector<std::string> &values)
void Enumeration::setValue(const char *value)
{
// using string methods without set, use setEnums(const char** plEnums) first!
//assert(_EnumArray);
if (!_EnumArray) {
_index = 0;
return;
}
int i = 0;
const char **plEnums = _EnumArray;
// search for the right entry
while (1) {
// end of list? set zero
if (*plEnums == nullptr) {
_index = 0;
_index = 0;
for (std::size_t i = 0; i < enumArray.size(); i++) {
if (enumArray[i].isEqual(value)) {
_index = static_cast<int>(i);
break;
}
if (strcmp(*plEnums, value) == 0) {
_index = i;
break;
}
++plEnums;
++i;
}
}
void Enumeration::setValue(long value, bool checkRange)
{
if (value >= 0 && value <= _maxVal) {
if (value >= 0 && value < countItems()) {
_index = value;
} else {
if (checkRange) {
@@ -216,116 +179,104 @@ void Enumeration::setValue(long value, bool checkRange)
bool Enumeration::isValue(const char *value) const
{
// using string methods without set, use setEnums(const char** plEnums) first!
//assert(_EnumArray);
int i = getInt();
if (i == -1) {
return false;
} else {
return strcmp(_EnumArray[i], value) == 0;
return enumArray[i].isEqual(value);
}
}
bool Enumeration::contains(const char *value) const
{
// using string methods without set, use setEnums(const char** plEnums) first!
//assert(_EnumArray);
if (!getEnums()) {
if (!isValid()) {
return false;
}
const char **plEnums = _EnumArray;
// search for the right entry
while (1) {
// end of list?
if (*plEnums == nullptr)
return false;
if (strcmp(*plEnums, value) == 0)
for (const auto& it : enumArray) {
if (it.isEqual(value))
return true;
++plEnums;
}
return false;
}
const char * Enumeration::getCStr(void) const
const char * Enumeration::getCStr() const
{
// using string methods without set, use setEnums(const char** plEnums) first!
//assert(_EnumArray);
if (!isValid() || _index < 0 || _index > _maxVal) {
if (!isValid() || _index < 0 || _index >= countItems()) {
return nullptr;
}
return _EnumArray[_index];
return enumArray[_index].data();
}
int Enumeration::getInt(void) const
int Enumeration::getInt() const
{
if (!isValid() || _index < 0 || _index > _maxVal) {
if (!isValid() || _index < 0 || _index >= countItems()) {
return -1;
}
return _index;
}
std::vector<std::string> Enumeration::getEnumVector(void) const
std::vector<std::string> Enumeration::getEnumVector() const
{
// using string methods without set, use setEnums(const char** plEnums) first!
if (!_EnumArray)
return std::vector<std::string>();
std::vector<std::string> list;
for (const auto& it : enumArray)
list.emplace_back(it.data());
return list;
}
std::vector<std::string> result;
const char **plEnums = _EnumArray;
bool Enumeration::hasEnums() const
{
return (!enumArray.empty());
}
// end of list?
while (*plEnums != nullptr) {
result.push_back(*plEnums);
++plEnums;
bool Enumeration::isValid() const
{
return (!enumArray.empty() && _index >= 0 && _index < countItems());
}
int Enumeration::maxValue() const
{
int num = -1;
if (!enumArray.empty())
num = static_cast<int>(enumArray.size()) - 1;
return num;
}
bool Enumeration::isCustom() const
{
for (const auto& it : enumArray) {
if (it.isCustom())
return true;
}
return result;
}
const char ** Enumeration::getEnums(void) const
{
return _EnumArray;
}
bool Enumeration::isValid(void) const
{
return (_EnumArray != nullptr && _index >= 0 && _index <= _maxVal);
return false;
}
Enumeration & Enumeration::operator=(const Enumeration &other)
{
if (other._ownEnumArray) {
setEnums(other.getEnumVector());
} else {
_EnumArray = other._EnumArray;
}
if (this == &other)
return *this;
_ownEnumArray = other._ownEnumArray;
enumArray = other.enumArray;
_index = other._index;
_maxVal = other._maxVal;
return *this;
}
bool Enumeration::operator==(const Enumeration &other) const
{
if(_index != other._index || _maxVal != other._maxVal)
if (_index != other._index || enumArray.size() != other.enumArray.size()) {
return false;
if (_EnumArray == other._EnumArray)
return true;
for (int i=0; i<=_maxVal; ++i) {
if (_EnumArray[i] == other._EnumArray[i])
}
for (size_t i = 0; i < enumArray.size(); ++i) {
if (enumArray[i].data() == other.enumArray[i].data())
continue;
if (_EnumArray[i] == nullptr || other._EnumArray[i] == nullptr)
if (enumArray[i].data() == nullptr || other.enumArray[i].data() == nullptr)
return false;
if (strcmp(_EnumArray[i], other._EnumArray[i]) != 0)
if (!enumArray[i].isEqual(other.enumArray[i].data()))
return false;
}
return true;
@@ -340,24 +291,7 @@ bool Enumeration::operator==(const char *other) const
return (strcmp(getCStr(), other) == 0);
}
void Enumeration::findMaxVal(void)
int Enumeration::countItems() const
{
if (_EnumArray == nullptr) {
_maxVal = -1;
return;
}
const char **plEnums = _EnumArray;
// the NULL terminator doesn't belong to the range of
// valid values
int i = -1;
while (*(plEnums++) != nullptr) {
++i;
// very unlikely to have enums with more then 5000 entries!
assert(i < 5000);
}
_maxVal = i;
return static_cast<int>(enumArray.size());
}

View File

@@ -24,14 +24,13 @@
#ifndef BASE_ENUMERATION_H
#define BASE_ENUMERATION_H
#include <memory>
#include <string>
#include <vector>
#include <FCGlobal.h>
namespace App
{
class PropertyEnumeration;
/// A bidirectional string-integer mapping
/*!
* This is mainly intended for two purposes: working around the difficulty
@@ -52,144 +51,172 @@ namespace App
*/
class AppExport Enumeration
{
friend class App::PropertyEnumeration;
protected:
class Object {
public:
/// Constructs an empty Enumeration object
Enumeration();
template <typename T>
Object(T&& obj): object(std::make_shared<Model<T>>(std::forward<T>(obj))){}
const char* data() const {
return object->data();
}
bool isEqual(const char* str) const {
return object->isEqual(str);
}
bool isCustom() const {
return object->isCustom();
}
/// Standard copy constructor
Enumeration(const Enumeration& other);
struct Concept {
virtual ~Concept() {}
virtual const char* data() const = 0;
virtual bool isEqual(const char*) const = 0;
virtual bool isCustom() const = 0;
};
/// Constructs an Enumeration with a single element
Enumeration(const char *valStr);
template< typename T >
struct Model : Concept {
Model(const T& t) : object(t) {}
const char* data() const override {
return object.data();
}
bool isEqual(const char* str) const override {
return object.isEqual(str);
}
bool isCustom() const override {
return object.isCustom();
}
private:
T object;
};
/// Constructs an Enumeration using val within list
Enumeration(const char **list, const char *valStr);
std::shared_ptr<Concept> object;
};
/// Standard destructor
~Enumeration();
public:
/// Constructs an empty Enumeration object
Enumeration();
/** Sets the enumeration string list
* The list is a NULL terminated array of pointers to const
* char* strings.
* \code
* const char enums[] = {"Black","White","Other",NULL}
* \endcode
*
* If Enumeration was already valid, will attempt to preserve
* the string-representation value of the Enumeration
*
* Enumeration does not take ownership of the passed object
*/
void setEnums(const char **plEnums);
/// Standard copy constructor
Enumeration(const Enumeration& other);
/// Set all enum values as vector of strings
/*!
* This method causes the Enumeration to dynamically allocate
* it's own array of C Strings, which will be deleted by the
* destructor or subsequent calls to setEnums(). So, it is
* important to make sure the Enumeration stays in scope as
* long as values returned by getCStr are in use.
*
* If Enumeration was already valid, will attempt to preserve
* the string-representation value of the Enumeration
*/
void setEnums(const std::vector<std::string> &values);
/// Constructs an Enumeration with a single element
Enumeration(const char *valStr);
/// Set the enum using a C string
void setValue(const char *value);
/// Constructs an Enumeration using val within list
Enumeration(const char **list, const char *valStr);
/// Overload of setValue(const char *value)
void setValue(const std::string &value) {setValue(value.c_str());}
/// Standard destructor
~Enumeration();
/// Set the enum using a long
/*!
* if checkRange is set to true, throws Base::ValueError when
* values are set out of range
*
* Checks for boundaries via assert()
*/
void setValue(long value, bool checkRange = false);
/** Sets the enumeration string list
* The list is a NULL terminated array of pointers to const
* char* strings.
* \code
* const char enums[] = {"Black","White","Other",NULL}
* \endcode
*
* If Enumeration was already valid, will attempt to preserve
* the string-representation value of the Enumeration
*
* Enumeration does not take ownership of the passed object
*/
void setEnums(const char **plEnums);
/// Checks if the property is set to a certain string value
bool isValue(const char *value) const;
/// Set all enum values as vector of strings
/*!
* This method causes the Enumeration to dynamically allocate
* it's own array of C Strings, which will be deleted by the
* destructor or subsequent calls to setEnums(). So, it is
* important to make sure the Enumeration stays in scope as
* long as values returned by getCStr are in use.
*
* If Enumeration was already valid, will attempt to preserve
* the string-representation value of the Enumeration
*/
void setEnums(const std::vector<std::string> &values);
/// Checks if a string is included in the enumeration
bool contains(const char *value) const;
/// Set the enum using a C string
void setValue(const char *value);
/// Return the value as C string
/*!
* Returns NULL if the enumeration is invalid.
*/
const char * getCStr(void) const;
/// Overload of setValue(const char *value)
void setValue(const std::string &value) {setValue(value.c_str());}
/// Return value as integer
/*!
* Returns -1 if the Enumeration isn't valid
*/
int getInt(void) const;
/// Set the enum using a long
/*!
* if checkRange is set to true, throws Base::ValueError when
* values are set out of range
*
* Checks for boundaries via assert()
*/
void setValue(long value, bool checkRange = false);
/// get all possible enum values as vector of strings
std::vector<std::string> getEnumVector(void) const;
/// Checks if the property is set to a certain string value
bool isValue(const char *value) const;
/// get pointer to the enum list
const char ** getEnums(void) const;
/// Checks if a string is included in the enumeration
bool contains(const char *value) const;
/// Returns true if the instance is in a usable state
bool isValid(void) const;
/// Return the value as C string
/*!
* Returns NULL if the enumeration is invalid.
*/
const char * getCStr() const;
/// Returns the highest usable integer value for this enum
/*!
* Returns -1 if the enumeration is not valid according to isValid()
*/
int maxValue(void) const {return _maxVal;}
/// Return value as integer
/*!
* Returns -1 if the Enumeration isn't valid
*/
int getInt() const;
/// Assignment operator
Enumeration & operator=(const Enumeration &other);
/// get all possible enum values as vector of strings
std::vector<std::string> getEnumVector() const;
/// true iff our string representation matches other's
/*!
* Returns false if either Enumeration is not valid.
*/
bool operator==(const Enumeration &other) const;
/// returns true if the enum list is non-empty, false otherwise
bool hasEnums() const;
/// true iff our string representation matches other
/*!
* Returns false if Enumeration is not valid.
*/
bool operator==(const char *other) const;
protected:
/// Returns true if instance was not initialized via static string list
bool isCustom(void) const {return _ownEnumArray;}
/// Returns true if the instance is in a usable state
bool isValid() const;
/// Updates _maxVal
void findMaxVal(void);
/// Returns the highest usable integer value for this enum
/*!
* Returns -1 if the enumeration is not valid according to isValid()
*/
int maxValue() const;
/// De-allocates memory used in _EnumArray
/*!
* Important to not call this unless this Enumeration owns array.
*/
void tearDown(void);
/// Returns true if any of the items is a user-defined string
bool isCustom() const;
private:
/// Handle to C Strings of possible enumeration values
const char **_EnumArray;
/// Assignment operator
Enumeration & operator=(const Enumeration &other);
/// Whether instance owns _EnumArray
bool _ownEnumArray;
/// true iff our string representation matches other's
/*!
* Returns false if either Enumeration is not valid.
*/
bool operator==(const Enumeration &other) const;
/// Integer value of the enumeration
/*!
* This serves as an index into _EnumArray to get the string
* representation.
*/
int _index;
/// true iff our string representation matches other
/*!
* Returns false if Enumeration is not valid.
*/
bool operator==(const char *other) const;
protected:
/*! Cached result from findMaxVal()
* Value should either be the maximum allowable integer value for
* the Enumeration, or -1 if not initialized
*/
int _maxVal;
/// Number of items
int countItems() const;
private:
/// Handle to C Strings of possible enumeration values
std::vector<Object> enumArray;
/// Integer value of the enumeration
/*!
* This serves as an index into enumArray to get the string
* representation.
*/
int _index;
friend class PropertyEnumeration;
}; // class Enumeration
} // namespace App

View File

@@ -100,7 +100,7 @@ FeatureTest::FeatureTest()
ADD_PROPERTY_TYPE(TypeTransient,(4711),group,Prop_Transient ,"An example property which has the type 'Transient'" );
ADD_PROPERTY_TYPE(TypeNoRecompute,(4711),group,Prop_NoRecompute,"An example property which has the type 'NoRecompute'");
ADD_PROPERTY_TYPE(TypeAll ,(4711),group,(App::PropertyType) (Prop_Output|Prop_ReadOnly |Prop_Hidden ),
"An example property which has the types 'Output', 'ReadOnly', and 'Hidden'");
"An example property which has the types 'Output', 'ReadOnly' and 'Hidden'");
ADD_PROPERTY(QuantityLength,(1.0));
QuantityLength.setUnit(Base::Unit::Length);
@@ -118,13 +118,46 @@ FeatureTest::~FeatureTest()
}
short FeatureTest::mustExecute(void) const
short FeatureTest::mustExecute() const
{
return DocumentObject::mustExecute();
}
DocumentObjectExecReturn *FeatureTest::execute(void)
DocumentObjectExecReturn *FeatureTest::execute()
{
// Enum handling
Enumeration enumObj1 = Enum.getEnum();
enumObj1.setValue(7, false);
enumObj1.setValue(4, true);
Enumeration enumObj2 = Enum.getEnum();
enumObj2.setValue(4, true);
Enumeration enumObj3(enumObj2);
const char* val = enumObj3.getCStr();
enumObj3.isValue(val);
enumObj3.getEnumVector();
Enumeration enumObj4("Single item");
enumObj4.setEnums(enums);
std::ignore = enumObj4 == enumObj2;
enumObj4.setEnums(nullptr);
enumObj4 = enumObj2;
std::ignore = enumObj4 == enumObj4.getCStr();
Enumeration enumObj5(enums, enums[3]);
enumObj5.isValue(enums[2]);
enumObj5.isValue(enums[3]);
enumObj5.contains(enums[1]);
Enumeration enumObj6;
enumObj6.setEnums(enums);
enumObj6.setValue(enums[1]);
std::vector<std::string> list;
list.emplace_back("Hello");
list.emplace_back("World");
enumObj6.setEnums(list);
enumObj6.setValue(list.back());
/*
doc=App.newDocument()
obj=doc.addObject("App::FeatureTest")
@@ -189,7 +222,7 @@ FeatureTestException::FeatureTestException()
ADD_PROPERTY(ExceptionType,(Base::Exception::getClassTypeId().getKey()) );
}
DocumentObjectExecReturn *FeatureTestException::execute(void)
DocumentObjectExecReturn *FeatureTestException::execute()
{
//ExceptionType;
throw Base::RuntimeError("FeatureTestException::execute(): Testexception ;-)");

View File

@@ -232,14 +232,14 @@ void LinkBaseExtension::setProperty(int idx, Property *prop) {
case PropLinkMode: {
static const char *linkModeEnums[] = {"None","Auto Delete","Auto Link","Auto Unlink",nullptr};
auto propLinkMode = static_cast<PropertyEnumeration*>(prop);
if(!propLinkMode->getEnums())
if(!propLinkMode->hasEnums())
propLinkMode->setEnums(linkModeEnums);
break;
}
case PropLinkCopyOnChange: {
static const char *enums[] = {"Disabled","Enabled","Owned","Tracking",nullptr};
auto propEnum = static_cast<PropertyEnumeration*>(prop);
if(!propEnum->getEnums())
if(!propEnum->hasEnums())
propEnum->setEnums(enums);
break;
}

View File

@@ -392,9 +392,9 @@ void PropertyEnumeration::setEnumVector(const std::vector<std::string> &values)
hasSetValue();
}
const char ** PropertyEnumeration::getEnums() const
bool PropertyEnumeration::hasEnums() const
{
return _enum.getEnums();
return _enum.hasEnums();
}
bool PropertyEnumeration::isValid() const
@@ -447,7 +447,7 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader)
if (val < 0) {
// If the enum is empty at this stage do not print a warning
if (_enum.getEnums())
if (_enum.hasEnums())
Base::Console().Warning("Enumeration index %d is out of range, ignore it\n", val);
val = getValue();
}
@@ -598,13 +598,13 @@ bool PropertyEnumeration::getPyPathValue(const ObjectIdentifier &path, Py::Objec
if (p == ".Enum" || p == ".All") {
Base::PyGILStateLocker lock;
Py::Tuple res(_enum.maxValue()+1);
const char **enums = _enum.getEnums();
std::vector<std::string> enums = _enum.getEnumVector();
PropertyString tmp;
for(int i=0;i<=_enum.maxValue();++i) {
for(int i=0;i< int(enums.size());++i) {
tmp.setValue(enums[i]);
res.setItem(i,Py::asObject(tmp.getPyObject()));
}
if(p == ".Enum")
if (p == ".Enum")
r = res;
else {
Py::Tuple tuple(2);
@@ -1374,7 +1374,7 @@ PropertyString::~PropertyString()
void PropertyString::setValue(const char* newLabel)
{
if(!newLabel)
if(!newLabel)
return;
if(_cValue == newLabel)

View File

@@ -206,7 +206,7 @@ public:
/// set enum values as vector of strings
void setEnumVector(const std::vector<std::string> &);
/// get the pointer to the enum list
const char ** getEnums(void) const;
bool hasEnums() const;
/// Returns true if the instance is in a usable state
bool isValid(void) const;

View File

@@ -398,9 +398,9 @@ void DlgDisplayPropertiesImp::setDisplayModes(const std::vector<Gui::ViewProvide
App::Property* prop = (*it)->getPropertyByName("DisplayMode");
if (prop && prop->getTypeId() == App::PropertyEnumeration::getClassTypeId()) {
App::PropertyEnumeration* display = static_cast<App::PropertyEnumeration*>(prop);
if (!display->getEnums())
if (!display->hasEnums())
return;
const std::vector<std::string>& value = display->getEnumVector();
std::vector<std::string> value = display->getEnumVector();
if (it == views.begin()) {
for (std::vector<std::string>::const_iterator jt = value.begin(); jt != value.end(); ++jt)
commonModes << QLatin1String(jt->c_str());

View File

@@ -202,9 +202,9 @@ void TaskAppearance::setDisplayModes(const std::vector<Gui::ViewProvider*>& view
App::Property* prop = (*it)->getPropertyByName("DisplayMode");
if (prop && prop->getTypeId() == App::PropertyEnumeration::getClassTypeId()) {
App::PropertyEnumeration* display = static_cast<App::PropertyEnumeration*>(prop);
if (!display->getEnums())
if (!display->hasEnums())
return;
const std::vector<std::string>& value = display->getEnumVector();
std::vector<std::string> value = display->getEnumVector();
if (it == views.begin()) {
for (std::vector<std::string>::const_iterator jt = value.begin(); jt != value.end(); ++jt)
commonModes << QLatin1String(jt->c_str());

View File

@@ -2800,8 +2800,9 @@ QStringList PropertyEnumItem::getEnum() const
auto prop = getFirstProperty();
if (prop && prop->getTypeId().isDerivedFrom(App::PropertyEnumeration::getClassTypeId())) {
const App::PropertyEnumeration* prop_enum = static_cast<const App::PropertyEnumeration*>(prop);
for(int i=0; i<prop_enum->getEnum().maxValue(); ++i)
res.push_back(QString::fromUtf8(prop_enum->getEnums()[i]));
std::vector<std::string> enums = prop_enum->getEnumVector();
for (const auto& it : enums)
res.push_back(QString::fromStdString(it));
}
return res;
}
@@ -2887,7 +2888,7 @@ QWidget* PropertyEnumItem::createEditor(QWidget* parent, const QObject* receiver
for (std::vector<App::Property*>::const_iterator it = items.begin(); it != items.end(); ++it) {
if ((*it)->getTypeId() == App::PropertyEnumeration::getClassTypeId()) {
App::PropertyEnumeration* prop = static_cast<App::PropertyEnumeration*>(*it);
if (prop->getEnums() == nullptr) {
if (!prop->hasEnums()) {
commonModes.clear();
return nullptr;
}

View File

@@ -459,7 +459,7 @@ FemPostScalarClipFilter::~FemPostScalarClipFilter() {
DocumentObjectExecReturn* FemPostScalarClipFilter::execute(void) {
std::string val;
if (m_scalarFields.getEnums() && Scalars.getValue() >= 0)
if (m_scalarFields.hasEnums() && Scalars.getValue() >= 0)
val = Scalars.getValueAsString();
std::vector<std::string> array;
@@ -562,7 +562,7 @@ FemPostWarpVectorFilter::~FemPostWarpVectorFilter() {
DocumentObjectExecReturn* FemPostWarpVectorFilter::execute(void) {
std::string val;
if (m_vectorFields.getEnums() && Vector.getValue() >= 0)
if (m_vectorFields.hasEnums() && Vector.getValue() >= 0)
val = Vector.getValueAsString();
std::vector<std::string> array;

View File

@@ -249,7 +249,7 @@ void ViewProviderFemPostObject::updateProperties() {
//coloring
std::string val;
if (Field.getEnums() && Field.getValue() >= 0)
if (Field.hasEnums() && Field.getValue() >= 0)
val = Field.getValueAsString();
std::vector<std::string> colorArrays;
@@ -278,7 +278,7 @@ void ViewProviderFemPostObject::updateProperties() {
Field.purgeTouched();
//Vector mode
if (VectorMode.getEnums() && VectorMode.getValue() >= 0)
if (VectorMode.hasEnums() && VectorMode.getValue() >= 0)
val = VectorMode.getValueAsString();
colorArrays.clear();

View File

@@ -78,17 +78,15 @@ TaskHoleParameters::TaskHoleParameters(ViewProviderHole* HoleView, QWidget* pare
ui->ThreadType->setCurrentIndex(pcHole->ThreadType.getValue());
ui->ThreadSize->clear();
const char** cursor = pcHole->ThreadSize.getEnums();
while (*cursor) {
ui->ThreadSize->addItem(tr(*cursor));
++cursor;
std::vector<std::string> cursor = pcHole->ThreadSize.getEnumVector();
for (const auto& it : cursor) {
ui->ThreadSize->addItem(tr(it.c_str()));
}
ui->ThreadSize->setCurrentIndex(pcHole->ThreadSize.getValue());
ui->ThreadClass->clear();
cursor = pcHole->ThreadClass.getEnums();
while (*cursor) {
ui->ThreadClass->addItem(tr(*cursor));
++cursor;
cursor = pcHole->ThreadClass.getEnumVector();
for (const auto& it : cursor) {
ui->ThreadClass->addItem(tr(it.c_str()));
}
ui->ThreadClass->setCurrentIndex(pcHole->ThreadClass.getValue());
// Class is only enabled (sensible) if threaded
@@ -109,10 +107,9 @@ TaskHoleParameters::TaskHoleParameters(ViewProviderHole* HoleView, QWidget* pare
ui->directionRightHand->setEnabled(pcHole->Threaded.getValue());
ui->directionLeftHand->setEnabled(pcHole->Threaded.getValue());
ui->HoleCutType->clear();
cursor = pcHole->HoleCutType.getEnums();
while (*cursor) {
ui->HoleCutType->addItem(tr(*cursor));
++cursor;
cursor = pcHole->HoleCutType.getEnumVector();
for (const auto& it : cursor) {
ui->HoleCutType->addItem(tr(it.c_str()));
}
ui->HoleCutType->setCurrentIndex(pcHole->HoleCutType.getValue());
ui->HoleCutCustomValues->setChecked(pcHole->HoleCutCustomValues.getValue());
@@ -714,10 +711,9 @@ void TaskHoleParameters::changedObject(const App::Document&, const App::Property
ui->ThreadSize->blockSignals(true);
ui->ThreadSize->clear();
const char** cursor = pcHole->ThreadSize.getEnums();
while (*cursor) {
ui->ThreadSize->addItem(QString::fromLatin1(*cursor));
++cursor;
std::vector<std::string> cursor = pcHole->ThreadSize.getEnumVector();
for (const auto& it : cursor) {
ui->ThreadSize->addItem(QString::fromStdString(it));
}
ui->ThreadSize->setCurrentIndex(pcHole->ThreadSize.getValue());
ui->ThreadSize->blockSignals(false);
@@ -725,20 +721,18 @@ void TaskHoleParameters::changedObject(const App::Document&, const App::Property
// Thread type also updates HoleCutType and ThreadClass
ui->HoleCutType->blockSignals(true);
ui->HoleCutType->clear();
cursor = pcHole->HoleCutType.getEnums();
while (*cursor) {
ui->HoleCutType->addItem(QString::fromLatin1(*cursor));
++cursor;
cursor = pcHole->HoleCutType.getEnumVector();
for (const auto& it: cursor) {
ui->HoleCutType->addItem(QString::fromStdString(it));
}
ui->HoleCutType->setCurrentIndex(pcHole->HoleCutType.getValue());
ui->HoleCutType->blockSignals(false);
ui->ThreadClass->blockSignals(true);
ui->ThreadClass->clear();
cursor = pcHole->ThreadClass.getEnums();
while (*cursor) {
ui->ThreadClass->addItem(QString::fromLatin1(*cursor));
++cursor;
cursor = pcHole->ThreadClass.getEnumVector();
for (const auto& it : cursor) {
ui->ThreadClass->addItem(QString::fromStdString(it));
}
ui->ThreadClass->setCurrentIndex(pcHole->ThreadClass.getValue());
ui->ThreadClass->blockSignals(false);