App: Apply clang format (part 2)

This commit is contained in:
wmayer
2024-11-21 21:17:42 +01:00
committed by wwmayer
parent fcea9343b3
commit 5771c94523
44 changed files with 12162 additions and 8774 deletions
+9 -10
View File
@@ -35,15 +35,14 @@ using namespace App;
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
Color::Color(float red, float green, float blue, float alpha)
: r(red)
, g(green)
, b(blue)
, a(alpha)
{
}
: r(red)
, g(green)
, b(blue)
, a(alpha)
{}
Color::Color(uint32_t rgba)
: Color{}
: Color {}
{
setPackedValue(rgba);
}
@@ -159,7 +158,7 @@ bool Color::fromHexString(const std::string& hex)
if (hex.size() == 7) {
std::stringstream ss(hex);
unsigned int rgb;
char ch{};
char ch {};
ss >> ch >> std::hex >> rgb;
int rc = (rgb >> 16) & 0xff;
@@ -176,13 +175,13 @@ bool Color::fromHexString(const std::string& hex)
if (hex.size() == 9) {
std::stringstream ss(hex);
unsigned int rgba;
char ch{};
char ch {};
ss >> ch >> std::hex >> rgba;
int rc = (rgba >> 24) & 0xff;
int gc = (rgba >> 16) & 0xff;
int bc = (rgba >> 8) & 0xff;
int ac = rgba & 0xff;
int ac = rgba & 0xff;
r = rc / 255.0F;
g = gc / 255.0F;
+4 -4
View File
@@ -72,7 +72,7 @@ struct color_traits
}
static color_type makeColor(int red, int green, int blue, int alpha = 255)
{
return color_type{red, green, blue, alpha};
return color_type {red, green, blue, alpha};
}
private:
@@ -146,7 +146,7 @@ public:
template<typename T>
static uint32_t asPackedRGBA(const T& color)
{
color_traits<T> ct{color};
color_traits<T> ct {color};
return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8) | ct.alpha();
}
@@ -162,7 +162,7 @@ public:
template<typename T>
static uint32_t asPackedRGB(const T& color)
{
color_traits<T> ct{color};
color_traits<T> ct {color};
return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8);
}
@@ -179,7 +179,7 @@ public:
template<typename T>
void setValue(const T& q)
{
color_traits<T> ct{q};
color_traits<T> ct {q};
set(ct.redF(), ct.greenF(), ct.blueF());
}
/**
+151 -121
View File
@@ -23,7 +23,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cstdlib>
#include <cstdlib>
#endif
#include <Base/Exception.h>
@@ -36,66 +36,66 @@ using namespace App;
ColorModelPack ColorModelPack::createRedGreenBlue()
{
ColorModelPack pack{ColorModelBlueGreenRed(),
ColorModelGreenYellowRed(),
ColorModelBlueCyanGreen(),
"Red-Yellow-Green-Cyan-Blue"};
ColorModelPack pack {ColorModelBlueGreenRed(),
ColorModelGreenYellowRed(),
ColorModelBlueCyanGreen(),
"Red-Yellow-Green-Cyan-Blue"};
return pack;
}
ColorModelPack ColorModelPack::createBlueGreenRed()
{
ColorModelPack pack{ColorModelRedGreenBlue(),
ColorModelGreenCyanBlue(),
ColorModelRedYellowGreen(),
"Blue-Cyan-Green-Yellow-Red"};
ColorModelPack pack {ColorModelRedGreenBlue(),
ColorModelGreenCyanBlue(),
ColorModelRedYellowGreen(),
"Blue-Cyan-Green-Yellow-Red"};
return pack;
}
ColorModelPack ColorModelPack::createWhiteBlack()
{
ColorModelPack pack{ColorModelBlackWhite(),
ColorModelGrayWhite(),
ColorModelBlackGray(),
"White-Black"};
ColorModelPack pack {ColorModelBlackWhite(),
ColorModelGrayWhite(),
ColorModelBlackGray(),
"White-Black"};
return pack;
}
ColorModelPack ColorModelPack::createBlackWhite()
{
ColorModelPack pack{ColorModelWhiteBlack(),
ColorModelGrayBlack(),
ColorModelWhiteGray(),
"Black-White"};
ColorModelPack pack {ColorModelWhiteBlack(),
ColorModelGrayBlack(),
ColorModelWhiteGray(),
"Black-White"};
return pack;
}
ColorModelPack ColorModelPack::createRedWhiteBlue()
{
ColorModelPack pack{ColorModelBlueWhiteRed(),
ColorModelWhiteRed(),
ColorModelBlueWhite(),
"Red-White-Blue"};
ColorModelPack pack {ColorModelBlueWhiteRed(),
ColorModelWhiteRed(),
ColorModelBlueWhite(),
"Red-White-Blue"};
return pack;
}
ColorField::ColorField ()
ColorField::ColorField()
{
set(ColorModelBlueGreenRed(), -1.0f, 1.0f, 13);
}
ColorField::ColorField (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt)
ColorField::ColorField(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt)
{
set(rclModel, fMin, fMax, usCt);
}
ColorField& ColorField::operator = (const ColorField &rclCF)
ColorField& ColorField::operator=(const ColorField& rclCF)
{
colorField = rclCF.colorField;
return *this;
}
void ColorField::set (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt)
void ColorField::set(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt)
{
auto bounds = std::minmax(fMin, fMax);
if (bounds.second <= bounds.first) {
@@ -109,34 +109,37 @@ void ColorField::set (const ColorModel &rclModel, float fMin, float fMax, std::s
rebuild();
}
void ColorField::setColorModel (const ColorModel &rclModel)
void ColorField::setColorModel(const ColorModel& rclModel)
{
colorModel = rclModel;
rebuild();
}
void ColorField::rebuild ()
void ColorField::rebuild()
{
colorField.resize(ctColors);
std::size_t usStep = std::min<std::size_t>(ctColors / (colorModel.getCountColors() - 1), ctColors - 1);
std::size_t usStep =
std::min<std::size_t>(ctColors / (colorModel.getCountColors() - 1), ctColors - 1);
std::size_t usInd1 = 0;
std::size_t usInd2 = usStep;
for (std::size_t i = 0; i < (colorModel.getCountColors() - 1); i++) {
interpolate(colorModel.colors[i], usInd1, colorModel.colors[i+1], usInd2);
interpolate(colorModel.colors[i], usInd1, colorModel.colors[i + 1], usInd2);
usInd1 = usInd2;
if ((i + 1) == (colorModel.getCountColors() - 2))
if ((i + 1) == (colorModel.getCountColors() - 2)) {
usInd2 = ctColors - 1;
else
}
else {
usInd2 += usStep;
}
}
fAscent = float(ctColors) / (fMax - fMin);
fAscent = float(ctColors) / (fMax - fMin);
fConstant = -fAscent * fMin;
}
// fuellt das Array von Farbe 1, Index 1 bis Farbe 2, Index 2
void ColorField::interpolate (Color clCol1, std::size_t usInd1, Color clCol2, std::size_t usInd2)
void ColorField::interpolate(Color clCol1, std::size_t usInd1, Color clCol2, std::size_t usInd2)
{
float fStep = 1.0f, fLen = float(usInd2 - usInd1);
@@ -161,28 +164,37 @@ ColorGradientProfile::ColorGradientProfile() = default;
bool ColorGradientProfile::isEqual(const ColorGradientProfile& cg) const
{
if (tStyle != cg.tStyle)
if (tStyle != cg.tStyle) {
return false;
if (fMin != cg.fMin)
}
if (fMin != cg.fMin) {
return false;
if (fMax != cg.fMax)
}
if (fMax != cg.fMax) {
return false;
if (!visibility.isEqual(cg.visibility))
}
if (!visibility.isEqual(cg.visibility)) {
return false;
if (tColorModel != cg.tColorModel)
}
if (tColorModel != cg.tColorModel) {
return false;
}
return true;
}
ColorGradient::ColorGradient ()
ColorGradient::ColorGradient()
{
createStandardPacks();
setColorModel();
set(-1.0f, 1.0f, 13, ColorBarStyle::ZERO_BASED, Visibility::Default);
}
ColorGradient::ColorGradient (float fMin, float fMax, std::size_t usCtColors, ColorBarStyle tS, VisibilityFlags flags)
ColorGradient::ColorGradient(float fMin,
float fMax,
std::size_t usCtColors,
ColorBarStyle tS,
VisibilityFlags flags)
{
createStandardPacks();
setColorModel();
@@ -202,8 +214,9 @@ std::vector<std::string> ColorGradient::getColorModelNames() const
{
std::vector<std::string> names;
names.reserve(modelPacks.size());
for (const auto& it : modelPacks)
for (const auto& it : modelPacks) {
names.push_back(it.description);
}
return names;
}
@@ -214,7 +227,11 @@ void ColorGradient::setProfile(const ColorGradientProfile& pro)
rebuild();
}
void ColorGradient::set (float fMin, float fMax, std::size_t usCt, ColorBarStyle tS, VisibilityFlags flags)
void ColorGradient::set(float fMin,
float fMax,
std::size_t usCt,
ColorBarStyle tS,
VisibilityFlags flags)
{
auto bounds = std::minmax(fMin, fMax);
if (bounds.second <= bounds.first) {
@@ -229,74 +246,79 @@ void ColorGradient::set (float fMin, float fMax, std::size_t usCt, ColorBarStyle
rebuild();
}
void ColorGradient::rebuild ()
void ColorGradient::rebuild()
{
switch (profile.tStyle)
{
case ColorBarStyle::FLOW:
{
colorField1.set(currentModelPack.totalModel, profile.fMin, profile.fMax, profile.ctColors);
switch (profile.tStyle) {
case ColorBarStyle::FLOW: {
colorField1.set(currentModelPack.totalModel,
profile.fMin,
profile.fMax,
profile.ctColors);
break;
}
case ColorBarStyle::ZERO_BASED:
{
if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f))
{
colorField1.set(currentModelPack.bottomModel, profile.fMin, 0.0f, profile.ctColors / 2);
colorField2.set(currentModelPack.topModel, 0.0f, profile.fMax, profile.ctColors / 2);
case ColorBarStyle::ZERO_BASED: {
if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) {
colorField1.set(currentModelPack.bottomModel,
profile.fMin,
0.0f,
profile.ctColors / 2);
colorField2.set(currentModelPack.topModel,
0.0f,
profile.fMax,
profile.ctColors / 2);
}
else if (profile.fMin >= 0.0f)
else if (profile.fMin >= 0.0f) {
colorField1.set(currentModelPack.topModel, 0.0f, profile.fMax, profile.ctColors);
else
}
else {
colorField1.set(currentModelPack.bottomModel, profile.fMin, 0.0f, profile.ctColors);
}
break;
}
}
}
std::size_t ColorGradient::getMinColors () const
std::size_t ColorGradient::getMinColors() const
{
switch (profile.tStyle)
{
case ColorBarStyle::FLOW:
return colorField1.getMinColors();
case ColorBarStyle::ZERO_BASED:
{
if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f))
switch (profile.tStyle) {
case ColorBarStyle::FLOW:
return colorField1.getMinColors();
case ColorBarStyle::ZERO_BASED: {
if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) {
return colorField1.getMinColors() + colorField2.getMinColors();
else
}
else {
return colorField1.getMinColors();
}
}
}
return 2;
}
void ColorGradient::setColorModel (std::size_t tModel)
void ColorGradient::setColorModel(std::size_t tModel)
{
profile.tColorModel = tModel;
setColorModel();
rebuild();
}
void ColorGradient::setColorModel ()
void ColorGradient::setColorModel()
{
if (profile.tColorModel < modelPacks.size())
if (profile.tColorModel < modelPacks.size()) {
currentModelPack = modelPacks[profile.tColorModel];
}
switch (profile.tStyle)
{
case ColorBarStyle::FLOW:
{
colorField1.setColorModel(currentModelPack.totalModel);
colorField2.setColorModel(currentModelPack.bottomModel);
break;
}
case ColorBarStyle::ZERO_BASED:
{
colorField1.setColorModel(currentModelPack.topModel);
colorField2.setColorModel(currentModelPack.bottomModel);
break;
}
switch (profile.tStyle) {
case ColorBarStyle::FLOW: {
colorField1.setColorModel(currentModelPack.totalModel);
colorField2.setColorModel(currentModelPack.bottomModel);
break;
}
case ColorBarStyle::ZERO_BASED: {
colorField1.setColorModel(currentModelPack.topModel);
colorField2.setColorModel(currentModelPack.bottomModel);
break;
}
}
}
@@ -317,60 +339,65 @@ ColorLegend::ColorLegend()
values.push_back(1.0f);
}
bool ColorLegend::operator == (const ColorLegend &rclCL) const
bool ColorLegend::operator==(const ColorLegend& rclCL) const
{
return (colorFields.size() == rclCL.colorFields.size()) &&
(names.size() == rclCL.names.size()) &&
(values.size() == rclCL.values.size()) &&
std::equal(colorFields.begin(), colorFields.end(), rclCL.colorFields.begin()) &&
std::equal(names.begin(), names.end(), rclCL.names.begin()) &&
std::equal(values.begin(), values.end(), rclCL.values.begin()) &&
outsideGrayed == rclCL.outsideGrayed;
return (colorFields.size() == rclCL.colorFields.size()) && (names.size() == rclCL.names.size())
&& (values.size() == rclCL.values.size())
&& std::equal(colorFields.begin(), colorFields.end(), rclCL.colorFields.begin())
&& std::equal(names.begin(), names.end(), rclCL.names.begin())
&& std::equal(values.begin(), values.end(), rclCL.values.begin())
&& outsideGrayed == rclCL.outsideGrayed;
}
float ColorLegend::getValue (std::size_t ulPos) const
float ColorLegend::getValue(std::size_t ulPos) const
{
if (ulPos < values.size())
if (ulPos < values.size()) {
return values[ulPos];
else
}
else {
return 0.0f;
}
}
bool ColorLegend::setValue (std::size_t ulPos, float fVal)
bool ColorLegend::setValue(std::size_t ulPos, float fVal)
{
if (ulPos < values.size())
{
if (ulPos < values.size()) {
values[ulPos] = fVal;
return true;
}
else
else {
return false;
}
}
Color ColorLegend::getColor (std::size_t ulPos) const
Color ColorLegend::getColor(std::size_t ulPos) const
{
if (ulPos < colorFields.size())
if (ulPos < colorFields.size()) {
return colorFields[ulPos];
else
}
else {
return Color();
}
}
// color as: 0x00rrggbb
uint32_t ColorLegend::getPackedColor (std::size_t ulPos) const
uint32_t ColorLegend::getPackedColor(std::size_t ulPos) const
{
Color clRGB = getColor(ulPos);
return clRGB.getPackedValue();
}
std::string ColorLegend::getText (std::size_t ulPos) const
std::string ColorLegend::getText(std::size_t ulPos) const
{
if (ulPos < names.size())
if (ulPos < names.size()) {
return names[ulPos];
else
}
else {
return "";
}
}
std::size_t ColorLegend::addMin (const std::string &rclName)
std::size_t ColorLegend::addMin(const std::string& rclName)
{
names.push_front(rclName);
values.push_front(values.front() - 1.0f);
@@ -385,7 +412,7 @@ std::size_t ColorLegend::addMin (const std::string &rclName)
return colorFields.size() - 1;
}
std::size_t ColorLegend::addMax (const std::string &rclName)
std::size_t ColorLegend::addMax(const std::string& rclName)
{
names.push_back(rclName);
values.push_back(values.back() + 1.0f);
@@ -400,7 +427,7 @@ std::size_t ColorLegend::addMax (const std::string &rclName)
return colorFields.size() - 1;
}
bool ColorLegend::remove (std::size_t ulPos)
bool ColorLegend::remove(std::size_t ulPos)
{
if (ulPos < colorFields.size()) {
colorFields.erase(colorFields.begin() + ulPos);
@@ -413,7 +440,7 @@ bool ColorLegend::remove (std::size_t ulPos)
return false;
}
void ColorLegend::removeFirst ()
void ColorLegend::removeFirst()
{
if (!colorFields.empty()) {
colorFields.erase(colorFields.begin());
@@ -422,33 +449,36 @@ void ColorLegend::removeFirst ()
}
}
void ColorLegend::removeLast ()
void ColorLegend::removeLast()
{
if (!colorFields.empty()) {
colorFields.erase(colorFields.end()-1);
names.erase(names.end()-1);
values.erase(values.end()-1);
colorFields.erase(colorFields.end() - 1);
names.erase(names.end() - 1);
values.erase(values.end() - 1);
}
}
void ColorLegend::resize (std::size_t ulCt)
void ColorLegend::resize(std::size_t ulCt)
{
if ((ulCt < 2) || (ulCt == colorFields.size()))
if ((ulCt < 2) || (ulCt == colorFields.size())) {
return;
}
if (ulCt > colorFields.size()) {
int k = ulCt - colorFields.size();
for (int i = 0; i < k; i++)
for (int i = 0; i < k; i++) {
addMin("new");
}
}
else {
int k = colorFields.size() - ulCt;
for (int i = 0; i < k; i++)
for (int i = 0; i < k; i++) {
removeLast();
}
}
}
bool ColorLegend::setColor (std::size_t ulPos, float ucRed, float ucGreen, float ucBlue)
bool ColorLegend::setColor(std::size_t ulPos, float ucRed, float ucGreen, float ucBlue)
{
if (ulPos < names.size()) {
colorFields[ulPos] = Color(ucRed, ucGreen, ucBlue);
@@ -459,15 +489,15 @@ bool ColorLegend::setColor (std::size_t ulPos, float ucRed, float ucGreen, float
}
// color as 0x00rrggbb
bool ColorLegend::setColor (std::size_t ulPos, unsigned long ulColor)
bool ColorLegend::setColor(std::size_t ulPos, unsigned long ulColor)
{
unsigned char ucRed = (unsigned char)((ulColor & 0x00ff0000) >> 16);
unsigned char ucRed = (unsigned char)((ulColor & 0x00ff0000) >> 16);
unsigned char ucGreen = (unsigned char)((ulColor & 0x0000ff00) >> 8);
unsigned char ucBlue = (unsigned char)(ulColor & 0x000000ff);
unsigned char ucBlue = (unsigned char)(ulColor & 0x000000ff);
return setColor(ulPos, ucRed, ucGreen, ucBlue);
}
bool ColorLegend::setText (std::size_t ulPos, const std::string &rclName)
bool ColorLegend::setText(std::size_t ulPos, const std::string& rclName)
{
if (ulPos < names.size()) {
names[ulPos] = rclName;
+264 -178
View File
@@ -36,7 +36,8 @@
namespace App
{
enum class Visibility {
enum class Visibility
{
Default,
Grayed,
Invisible
@@ -44,12 +45,13 @@ enum class Visibility {
using VisibilityFlags = Base::Flags<Visibility>;
enum class ColorBarStyle {
enum class ColorBarStyle
{
FLOW,
ZERO_BASED
};
}
} // namespace App
ENABLE_BITMASK_OPERATORS(App::Visibility)
@@ -65,8 +67,8 @@ public:
virtual Color getColor(float fVal) const = 0;
protected:
ValueFloatToRGB () = default;
virtual ~ValueFloatToRGB () = default;
ValueFloatToRGB() = default;
virtual ~ValueFloatToRGB() = default;
};
@@ -74,22 +76,26 @@ class AppExport ColorModel
{
public:
ColorModel() = default;
explicit ColorModel (std::size_t usCt) {
explicit ColorModel(std::size_t usCt)
{
colors.resize(usCt);
}
ColorModel(const ColorModel&) = default;
virtual ~ColorModel () = default;
ColorModel& operator = (const ColorModel&) = default;
std::size_t getCountColors() const {
virtual ~ColorModel() = default;
ColorModel& operator=(const ColorModel&) = default;
std::size_t getCountColors() const
{
return colors.size();
}
std::vector<Color> colors;
};
class AppExport ColorModelBlueGreenRed : public ColorModel
class AppExport ColorModelBlueGreenRed: public ColorModel
{
public:
ColorModelBlueGreenRed () : ColorModel(5) {
ColorModelBlueGreenRed()
: ColorModel(5)
{
colors[0] = Color(0, 0, 1);
colors[1] = Color(0, 1, 1);
colors[2] = Color(0, 1, 0);
@@ -98,30 +104,36 @@ public:
}
};
class AppExport ColorModelBlueCyanGreen : public ColorModel
class AppExport ColorModelBlueCyanGreen: public ColorModel
{
public:
ColorModelBlueCyanGreen () : ColorModel(3) {
ColorModelBlueCyanGreen()
: ColorModel(3)
{
colors[0] = Color(0, 0, 1);
colors[1] = Color(0, 1, 1);
colors[2] = Color(0, 1, 0);
}
};
class AppExport ColorModelGreenYellowRed : public ColorModel
class AppExport ColorModelGreenYellowRed: public ColorModel
{
public:
ColorModelGreenYellowRed () : ColorModel(3) {
ColorModelGreenYellowRed()
: ColorModel(3)
{
colors[0] = Color(0, 1, 0);
colors[1] = Color(1, 1, 0);
colors[2] = Color(1, 0, 0);
}
};
class AppExport ColorModelRedGreenBlue : public ColorModel
class AppExport ColorModelRedGreenBlue: public ColorModel
{
public:
ColorModelRedGreenBlue () : ColorModel(5) {
ColorModelRedGreenBlue()
: ColorModel(5)
{
colors[0] = Color(1, 0, 0);
colors[1] = Color(1, 1, 0);
colors[2] = Color(0, 1, 0);
@@ -130,30 +142,36 @@ public:
}
};
class AppExport ColorModelGreenCyanBlue : public ColorModel
class AppExport ColorModelGreenCyanBlue: public ColorModel
{
public:
ColorModelGreenCyanBlue () : ColorModel(3) {
ColorModelGreenCyanBlue()
: ColorModel(3)
{
colors[0] = Color(0, 1, 0);
colors[1] = Color(0, 1, 1);
colors[2] = Color(0, 0, 1);
}
};
class AppExport ColorModelRedYellowGreen : public ColorModel
class AppExport ColorModelRedYellowGreen: public ColorModel
{
public:
ColorModelRedYellowGreen () : ColorModel(3) {
ColorModelRedYellowGreen()
: ColorModel(3)
{
colors[0] = Color(1, 0, 0);
colors[1] = Color(1, 1, 0);
colors[2] = Color(0, 1, 0);
}
};
class AppExport ColorModelBlueWhiteRed : public ColorModel
class AppExport ColorModelBlueWhiteRed: public ColorModel
{
public:
ColorModelBlueWhiteRed () : ColorModel(5) {
ColorModelBlueWhiteRed()
: ColorModel(5)
{
colors[0] = Color(0, 0, 1);
colors[1] = Color(float(85.0 / 255), float(170.0 / 255), 1);
colors[2] = Color(1, 1, 1);
@@ -162,75 +180,91 @@ public:
}
};
class AppExport ColorModelBlueWhite : public ColorModel
class AppExport ColorModelBlueWhite: public ColorModel
{
public:
ColorModelBlueWhite () : ColorModel(3) {
ColorModelBlueWhite()
: ColorModel(3)
{
colors[0] = Color(0, 0, 1);
colors[1] = Color(float(85.0 / 255), float(170.0 / 255), 1);
colors[2] = Color(1, 1, 1);
}
};
class AppExport ColorModelWhiteRed : public ColorModel
class AppExport ColorModelWhiteRed: public ColorModel
{
public:
ColorModelWhiteRed () : ColorModel(3) {
ColorModelWhiteRed()
: ColorModel(3)
{
colors[0] = Color(1, 1, 1);
colors[1] = Color(1, float(85.0 / 255), 0);
colors[2] = Color(1, 0, 0);
}
};
class AppExport ColorModelBlackWhite : public ColorModel
class AppExport ColorModelBlackWhite: public ColorModel
{
public:
ColorModelBlackWhite () : ColorModel(2) {
ColorModelBlackWhite()
: ColorModel(2)
{
colors[0] = Color(0, 0, 0);
colors[1] = Color(1, 1, 1);
}
};
class AppExport ColorModelBlackGray : public ColorModel
class AppExport ColorModelBlackGray: public ColorModel
{
public:
ColorModelBlackGray () : ColorModel(2) {
ColorModelBlackGray()
: ColorModel(2)
{
colors[0] = Color(0.0f, 0.0f, 0.0f);
colors[1] = Color(0.5f, 0.5f, 0.5f);
}
};
class AppExport ColorModelGrayWhite : public ColorModel
class AppExport ColorModelGrayWhite: public ColorModel
{
public:
ColorModelGrayWhite () : ColorModel(2) {
ColorModelGrayWhite()
: ColorModel(2)
{
colors[0] = Color(0.5f, 0.5f, 0.5f);
colors[1] = Color(1.0f, 1.0f, 1.0f);
}
};
class AppExport ColorModelWhiteBlack : public ColorModel
class AppExport ColorModelWhiteBlack: public ColorModel
{
public:
ColorModelWhiteBlack () : ColorModel(2) {
ColorModelWhiteBlack()
: ColorModel(2)
{
colors[0] = Color(1, 1, 1);
colors[1] = Color(0, 0, 0);
}
};
class AppExport ColorModelWhiteGray : public ColorModel
class AppExport ColorModelWhiteGray: public ColorModel
{
public:
ColorModelWhiteGray () : ColorModel(2) {
ColorModelWhiteGray()
: ColorModel(2)
{
colors[0] = Color(1.0f, 1.0f, 1.0f);
colors[1] = Color(0.5f, 0.5f, 0.5f);
}
};
class AppExport ColorModelGrayBlack : public ColorModel
class AppExport ColorModelGrayBlack: public ColorModel
{
public:
ColorModelGrayBlack () : ColorModel(2) {
ColorModelGrayBlack()
: ColorModel(2)
{
colors[0] = Color(0.5f, 0.5f, 0.5f);
colors[1] = Color(0.0f, 0.0f, 0.0f);
}
@@ -252,48 +286,59 @@ struct AppExport ColorModelPack
class AppExport ColorField
{
public:
ColorField ();
ColorField (const ColorField &rclCF) = default;
ColorField (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt);
virtual ~ColorField () = default;
ColorField();
ColorField(const ColorField& rclCF) = default;
ColorField(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt);
virtual ~ColorField() = default;
ColorField& operator = (const ColorField &rclCF);
ColorField& operator=(const ColorField& rclCF);
std::size_t getCountColors () const {
std::size_t getCountColors() const
{
return ctColors;
}
void set (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt);
void setCountColors (std::size_t usCt) {
void set(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt);
void setCountColors(std::size_t usCt)
{
set(colorModel, fMin, fMax, usCt);
}
void setRange (float fMin, float fMax) {
void setRange(float fMin, float fMax)
{
set(colorModel, fMin, fMax, ctColors);
}
void getRange (float &rfMin, float &rfMax) {
rfMin = fMin; rfMax = fMax;
void getRange(float& rfMin, float& rfMax)
{
rfMin = fMin;
rfMax = fMax;
}
std::size_t getMinColors () const {
std::size_t getMinColors() const
{
return colorModel.getCountColors();
}
void setColorModel (const ColorModel &rclModel);
const ColorModel& getColorModel () const {
void setColorModel(const ColorModel& rclModel);
const ColorModel& getColorModel() const
{
return colorModel;
}
void setDirect (std::size_t usInd, Color clCol) {
void setDirect(std::size_t usInd, Color clCol)
{
colorField[usInd] = clCol;
}
float getMinValue () const {
float getMinValue() const
{
return fMin;
}
float getMaxValue () const {
float getMaxValue() const
{
return fMax;
}
Color getColor (std::size_t usIndex) const {
Color getColor(std::size_t usIndex) const
{
return colorField[usIndex];
}
inline Color getColor (float fVal) const;
inline std::size_t getColorIndex (float fVal) const;
inline Color getColor(float fVal) const;
inline std::size_t getColorIndex(float fVal) const;
protected:
ColorModel colorModel;
@@ -302,32 +347,34 @@ protected:
std::size_t ctColors;
std::vector<Color> colorField;
void rebuild ();
void interpolate (Color clCol1, std::size_t usPos1, Color clCol2, std::size_t usPos2);
void rebuild();
void interpolate(Color clCol1, std::size_t usPos1, Color clCol2, std::size_t usPos2);
};
inline Color ColorField::getColor (float fVal) const
inline Color ColorField::getColor(float fVal) const
{
// if the value is outside or at the border of the range
std::size_t ct = colorModel.getCountColors() - 1;
if ( fVal <= fMin )
if (fVal <= fMin) {
return colorModel.colors[0];
else if ( fVal >= fMax )
}
else if (fVal >= fMax) {
return colorModel.colors[ct];
}
// get the color field position (with 0 < t < 1)
float t = (fVal - fMin) / (fMax - fMin);
Color col(1.0f, 1.0f, 1.0f); // white as default
for (std::size_t i=0; i<ct; i++) {
float r = (float)(i+1)/(float)ct;
Color col(1.0f, 1.0f, 1.0f); // white as default
for (std::size_t i = 0; i < ct; i++) {
float r = (float)(i + 1) / (float)ct;
if (t < r) {
// calculate the exact position in the subrange
float s = t * float(ct) - float(i);
Color c1 = colorModel.colors[i];
Color c2 = colorModel.colors[i+1];
col.r = (1.0f-s) * c1.r + s * c2.r;
col.g = (1.0f-s) * c1.g + s * c2.g;
col.b = (1.0f-s) * c1.b + s * c2.b;
Color c2 = colorModel.colors[i + 1];
col.r = (1.0f - s) * c1.r + s * c2.r;
col.g = (1.0f - s) * c1.g + s * c2.g;
col.b = (1.0f - s) * c1.b + s * c2.b;
break;
}
}
@@ -335,23 +382,24 @@ inline Color ColorField::getColor (float fVal) const
return col;
}
inline std::size_t ColorField::getColorIndex (float fVal) const
inline std::size_t ColorField::getColorIndex(float fVal) const
{
return std::size_t(std::min<int>(std::max<int>(int(fConstant + fAscent * fVal), 0), int(ctColors - 1)));
return std::size_t(
std::min<int>(std::max<int>(int(fConstant + fAscent * fVal), 0), int(ctColors - 1)));
}
struct AppExport ColorGradientProfile
{
ColorBarStyle tStyle{ColorBarStyle::FLOW};
float fMin{};
float fMax{};
std::size_t ctColors{};
std::size_t tColorModel{};
VisibilityFlags visibility{Visibility::Default};
ColorBarStyle tStyle {ColorBarStyle::FLOW};
float fMin {};
float fMax {};
std::size_t ctColors {};
std::size_t tColorModel {};
VisibilityFlags visibility {Visibility::Default};
ColorGradientProfile();
ColorGradientProfile (const ColorGradientProfile &) = default;
ColorGradientProfile& operator = (const ColorGradientProfile &) = default;
ColorGradientProfile(const ColorGradientProfile&) = default;
ColorGradientProfile& operator=(const ColorGradientProfile&) = default;
bool isEqual(const ColorGradientProfile&) const;
};
@@ -359,184 +407,217 @@ struct AppExport ColorGradientProfile
class AppExport ColorGradient
{
public:
ColorGradient ();
ColorGradient (float fMin, float fMax, std::size_t usCtColors, ColorBarStyle tS, VisibilityFlags fl = Visibility::Default);
ColorGradient (const ColorGradient &) = default;
ColorGradient& operator = (const ColorGradient &) = default;
const ColorGradientProfile& getProfile() const {
ColorGradient();
ColorGradient(float fMin,
float fMax,
std::size_t usCtColors,
ColorBarStyle tS,
VisibilityFlags fl = Visibility::Default);
ColorGradient(const ColorGradient&) = default;
ColorGradient& operator=(const ColorGradient&) = default;
const ColorGradientProfile& getProfile() const
{
return profile;
}
void setProfile(const ColorGradientProfile& pro);
void set (float fMin, float fMax, std::size_t usCt, ColorBarStyle tS, VisibilityFlags fl);
void setRange (float fMin, float fMax) {
void set(float fMin, float fMax, std::size_t usCt, ColorBarStyle tS, VisibilityFlags fl);
void setRange(float fMin, float fMax)
{
set(fMin, fMax, profile.ctColors, profile.tStyle, profile.visibility);
}
void getRange (float &rfMin, float &rfMax) const {
void getRange(float& rfMin, float& rfMax) const
{
rfMin = profile.fMin;
rfMax = profile.fMax;
}
bool isOutOfRange(float fVal) const {
bool isOutOfRange(float fVal) const
{
return ((fVal < profile.fMin) || (fVal > profile.fMax));
}
std::size_t getCountColors () const {
std::size_t getCountColors() const
{
return profile.ctColors;
}
void setCountColors (std::size_t usCt) {
void setCountColors(std::size_t usCt)
{
set(profile.fMin, profile.fMax, usCt, profile.tStyle, profile.visibility);
}
void setStyle (ColorBarStyle tS) {
void setStyle(ColorBarStyle tS)
{
set(profile.fMin, profile.fMax, profile.ctColors, tS, profile.visibility);
}
std::size_t getMinColors () const;
ColorBarStyle getStyle () const {
std::size_t getMinColors() const;
ColorBarStyle getStyle() const
{
return profile.tStyle;
}
void setOutsideGrayed (bool value) {
void setOutsideGrayed(bool value)
{
profile.visibility.setFlag(Visibility::Grayed, value);
}
bool isOutsideGrayed () const {
bool isOutsideGrayed() const
{
return profile.visibility.testFlag(Visibility::Grayed);
}
void setOutsideInvisible (bool value) {
void setOutsideInvisible(bool value)
{
profile.visibility.setFlag(Visibility::Invisible, value);
}
bool isOutsideInvisible () const {
bool isOutsideInvisible() const
{
return profile.visibility.testFlag(Visibility::Invisible);
}
void setColorModel (std::size_t tModel);
std::size_t getColorModelType () const {
void setColorModel(std::size_t tModel);
std::size_t getColorModelType() const
{
return profile.tColorModel;
}
inline const ColorModel& getColorModel () const;
inline const ColorModel& getColorModel() const;
std::vector<std::string> getColorModelNames() const;
float getMinValue () const {
float getMinValue() const
{
return profile.fMin;
}
float getMaxValue () const {
float getMaxValue() const
{
return profile.fMax;
}
inline Color getColor (float fVal) const;
inline std::size_t getColorIndex (float fVal) const;
inline Color getColor(float fVal) const;
inline std::size_t getColorIndex(float fVal) const;
private:
inline Color _getColor (float fVal) const;
inline Color _getColor(float fVal) const;
protected:
void createStandardPacks();
protected:
ColorGradientProfile profile;
ColorField colorField1, colorField2;
ColorField colorField1, colorField2;
ColorModelPack currentModelPack;
std::vector<ColorModelPack> modelPacks;
void rebuild ();
void setColorModel ();
void rebuild();
void setColorModel();
};
class AppExport ColorLegend
{
public:
ColorLegend ();
ColorLegend (const ColorLegend &rclCL) = default;
virtual ~ColorLegend () = default;
ColorLegend();
ColorLegend(const ColorLegend& rclCL) = default;
virtual ~ColorLegend() = default;
ColorLegend& operator = (const ColorLegend &rclCL) = default;
bool operator == (const ColorLegend &rclCL) const;
bool operator != (const ColorLegend &rclCL) const {
ColorLegend& operator=(const ColorLegend& rclCL) = default;
bool operator==(const ColorLegend& rclCL) const;
bool operator!=(const ColorLegend& rclCL) const
{
return !(*this == rclCL);
}
void resize (std::size_t ulN);
std::size_t addMin (const std::string &rclName);
std::size_t addMax (const std::string &rclName);
bool remove (std::size_t ulPos);
void removeFirst ();
void removeLast ();
void resize(std::size_t ulN);
std::size_t addMin(const std::string& rclName);
std::size_t addMax(const std::string& rclName);
bool remove(std::size_t ulPos);
void removeFirst();
void removeLast();
Color getColor (std::size_t ulPos) const;
uint32_t getPackedColor (std::size_t ulPos) const;
bool setColor (std::size_t ulPos, float ucRed, float ucGreen, float ucBlue);
bool setColor (std::size_t ulPos, unsigned long ulColor);
float getValue (std::size_t ulPos) const;
bool setValue (std::size_t ulPos, float fVal);
std::string getText (std::size_t ulPos) const;
bool setText (std::size_t ulPos, const std::string &rclName);
std::size_t hasNumberOfFields () const {
Color getColor(std::size_t ulPos) const;
uint32_t getPackedColor(std::size_t ulPos) const;
bool setColor(std::size_t ulPos, float ucRed, float ucGreen, float ucBlue);
bool setColor(std::size_t ulPos, unsigned long ulColor);
float getValue(std::size_t ulPos) const;
bool setValue(std::size_t ulPos, float fVal);
std::string getText(std::size_t ulPos) const;
bool setText(std::size_t ulPos, const std::string& rclName);
std::size_t hasNumberOfFields() const
{
return colorFields.size();
}
void setOutsideGrayed (bool bOS) {
void setOutsideGrayed(bool bOS)
{
outsideGrayed = bOS;
}
bool isOutsideGrayed () const {
bool isOutsideGrayed() const
{
return outsideGrayed;
}
inline float getMinValue () const;
inline float getMaxValue () const;
inline float getMinValue() const;
inline float getMaxValue() const;
inline Color getColor (float fVal) const;
inline std::size_t getColorIndex (float fVal) const;
inline Color getColor(float fVal) const;
inline std::size_t getColorIndex(float fVal) const;
protected:
std::deque<Color> colorFields;
std::deque<std::string> names;
std::deque<float> values;
bool outsideGrayed{false};
bool outsideGrayed {false};
};
inline Color ColorLegend::getColor (float fVal) const
inline Color ColorLegend::getColor(float fVal) const
{
std::deque<float>::const_iterator pI;
for (pI = values.begin(); pI != values.end(); ++pI) {
if (fVal < *pI)
if (fVal < *pI) {
break;
}
}
if (outsideGrayed) {
if ((pI == values.begin()) || (pI == values.end()))
if ((pI == values.begin()) || (pI == values.end())) {
return Color(0.5f, 0.5f, 0.5f);
else
}
else {
return colorFields[pI - values.begin() - 1];
}
}
if (pI == values.begin())
if (pI == values.begin()) {
return *colorFields.begin();
else if (pI == values.end())
return *(colorFields.end()-1);
else
}
else if (pI == values.end()) {
return *(colorFields.end() - 1);
}
else {
return colorFields[pI - values.begin() - 1];
}
}
inline std::size_t ColorLegend::getColorIndex (float fVal) const
inline std::size_t ColorLegend::getColorIndex(float fVal) const
{
std::deque<float>::const_iterator pI;
for (pI = values.begin(); pI != values.end(); ++pI) {
if (fVal < *pI)
if (fVal < *pI) {
break;
}
}
if (pI == values.begin())
if (pI == values.begin()) {
return 0;
else if (pI == values.end())
}
else if (pI == values.end()) {
return (std::size_t)(colorFields.size() - 1);
else
}
else {
return pI - values.begin() - 1;
}
}
inline float ColorLegend::getMinValue () const
inline float ColorLegend::getMinValue() const
{
return values.front();
}
inline float ColorLegend::getMaxValue () const
inline float ColorLegend::getMaxValue() const
{
return values.back();
}
inline Color ColorGradient::getColor (float fVal) const
inline Color ColorGradient::getColor(float fVal) const
{
Color color = _getColor(fVal);
if (isOutsideInvisible()) {
@@ -548,73 +629,78 @@ inline Color ColorGradient::getColor (float fVal) const
return color;
}
inline Color ColorGradient::_getColor (float fVal) const
inline Color ColorGradient::_getColor(float fVal) const
{
if (isOutsideGrayed()) {
if (isOutOfRange(fVal))
if (isOutOfRange(fVal)) {
return Color(0.5f, 0.5f, 0.5f);
}
}
switch (profile.tStyle) {
case ColorBarStyle::ZERO_BASED:
{
case ColorBarStyle::ZERO_BASED: {
if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) {
if (fVal < 0.0f)
if (fVal < 0.0f) {
return colorField1.getColor(fVal);
else
}
else {
return colorField2.getColor(fVal);
}
}
else {
return colorField1.getColor(fVal);
}
}
default:
case ColorBarStyle::FLOW:
{
default:
case ColorBarStyle::FLOW: {
return colorField1.getColor(fVal);
}
}
}
inline std::size_t ColorGradient::getColorIndex (float fVal) const
inline std::size_t ColorGradient::getColorIndex(float fVal) const
{
switch (profile.tStyle) {
case ColorBarStyle::ZERO_BASED:
{
case ColorBarStyle::ZERO_BASED: {
if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) {
if (fVal < 0.0f)
if (fVal < 0.0f) {
return colorField1.getColorIndex(fVal);
else
return std::size_t(colorField1.getCountColors() + colorField2.getColorIndex(fVal));
}
else {
return std::size_t(colorField1.getCountColors()
+ colorField2.getColorIndex(fVal));
}
}
else {
return colorField1.getColorIndex(fVal);
}
}
default:
case ColorBarStyle::FLOW:
{
default:
case ColorBarStyle::FLOW: {
return colorField1.getColorIndex(fVal);
}
}
}
inline const ColorModel& ColorGradient::getColorModel () const
inline const ColorModel& ColorGradient::getColorModel() const
{
if (profile.tStyle == ColorBarStyle::ZERO_BASED) {
if (profile.fMax <= 0.0f)
if (profile.fMax <= 0.0f) {
return currentModelPack.bottomModel;
else if ( profile.fMin >= 0.0f )
}
else if (profile.fMin >= 0.0f) {
return currentModelPack.topModel;
else
}
else {
return currentModelPack.totalModel;
}
}
return currentModelPack.totalModel;
}
} // namespace App
} // namespace App
#endif // APP_COLORMODEL_H
#endif // APP_COLORMODEL_H
+14 -12
View File
@@ -184,20 +184,20 @@ bool ComplexGeoData::getCenterOfGravity(Base::Vector3d& unused) const
return false;
}
const std::string &ComplexGeoData::elementMapPrefix() {
const std::string& ComplexGeoData::elementMapPrefix()
{
static std::string prefix(ELEMENT_MAP_PREFIX);
return prefix;
}
std::string ComplexGeoData::getElementMapVersion() const {
std::string ComplexGeoData::getElementMapVersion() const
{
return "4";
}
bool ComplexGeoData::checkElementMapVersion(const char * ver) const
bool ComplexGeoData::checkElementMapVersion(const char* ver) const
{
return !boost::equals(ver, "3")
&& !boost::equals(ver, "4")
&& !boost::starts_with(ver, "3.");
return !boost::equals(ver, "3") && !boost::equals(ver, "4") && !boost::starts_with(ver, "3.");
}
size_t ComplexGeoData::getElementMapSize(bool flush) const
@@ -301,8 +301,9 @@ ElementMapPtr ComplexGeoData::resetElementMap(ElementMapPtr elementMap)
_elementMap.swap(elementMap);
// We expect that if the ComplexGeoData ( TopoShape ) has a hasher, then its elementMap will
// have the same one. Make sure that happens.
if ( _elementMap && ! _elementMap->hasher )
if (_elementMap && !_elementMap->hasher) {
_elementMap->hasher = Hasher;
}
return elementMap;
}
@@ -329,7 +330,6 @@ ElementMapPtr ComplexGeoData::ensureElementMap(bool flush)
resetElementMap(std::make_shared<Data::ElementMap>());
}
return elementMap(flush);
}
void ComplexGeoData::flushElementMap() const
@@ -656,12 +656,13 @@ unsigned int ComplexGeoData::getMemSize() const
return 0;
}
std::vector<IndexedName> ComplexGeoData::getHigherElements(const char *, bool) const
std::vector<IndexedName> ComplexGeoData::getHigherElements(const char*, bool) const
{
return {};
}
void ComplexGeoData::setMappedChildElements(const std::vector<Data::ElementMap::MappedChildElements> & children)
void ComplexGeoData::setMappedChildElements(
const std::vector<Data::ElementMap::MappedChildElements>& children)
{
// DO NOT reset element map if there is one. Because we allow mixing child
// mapping and normal mapping
@@ -690,8 +691,9 @@ void ComplexGeoData::beforeSave() const
void ComplexGeoData::hashChildMaps()
{
flushElementMap();
if (_elementMap)
if (_elementMap) {
_elementMap->hashChildMaps(Tag);
}
}
bool ComplexGeoData::hasChildElementMap() const
@@ -704,7 +706,7 @@ void ComplexGeoData::dumpElementMap(std::ostream& stream) const
{
auto map = getElementMap();
std::sort(map.begin(), map.end());
for ( auto& element : map ) {
for (auto& element : map) {
stream << element.index << " : " << element.name << std::endl;
}
}
+123 -90
View File
@@ -37,7 +37,7 @@
#include "StringHasher.h"
#ifdef __GNUC__
# include <cstdint>
#include <cstdint>
#endif
@@ -45,16 +45,18 @@ namespace Base
{
class Placement;
class Rotation;
template <class _Precision> class BoundBox3;// NOLINT
template<class _Precision>
class BoundBox3; // NOLINT
using BoundBox3d = BoundBox3<double>;
}
} // namespace Base
namespace Data
{
//struct MappedChildElements;
// struct MappedChildElements;
/// Option for App::GeoFeature::searchElementCache()
enum class SearchOption {
enum class SearchOption
{
/// Whether to compare shape geometry
CheckGeometry = 1,
SingleResult = 2,
@@ -67,11 +69,11 @@ typedef Base::Flags<SearchOption> SearchOptions;
*/
class AppExport Segment: public Base::BaseClass
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT
TYPESYSTEM_HEADER_WITH_OVERRIDE(); // NOLINT
public:
~Segment() override = default;
virtual std::string getName() const=0;
virtual std::string getName() const = 0;
};
enum ElementMapResetPolicy
@@ -84,12 +86,22 @@ enum ElementMapResetPolicy
*/
class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT
TYPESYSTEM_HEADER_WITH_OVERRIDE(); // NOLINT
public:
struct Line {uint32_t I1; uint32_t I2;};
struct Facet {uint32_t I1; uint32_t I2; uint32_t I3;};
struct Domain {
struct Line
{
uint32_t I1;
uint32_t I2;
};
struct Facet
{
uint32_t I1;
uint32_t I2;
uint32_t I3;
};
struct Domain
{
std::vector<Base::Vector3d> points;
std::vector<Facet> facets;
};
@@ -105,26 +117,24 @@ public:
* List of different sub-element types
* its NOT a list of the sub-elements itself
*/
virtual std::vector<const char*> getElementTypes() const=0;
virtual unsigned long countSubElements(const char* Type) const=0;
virtual std::vector<const char*> getElementTypes() const = 0;
virtual unsigned long countSubElements(const char* Type) const = 0;
/// Returns a generic element type and index. The determined element type isn't
/// necessarily supported by this geometry.
static std::pair<std::string, unsigned long> getTypeAndIndex(const char* Name);
/// get the sub-element by type and number
virtual Segment* getSubElement(const char* Type, unsigned long) const=0;
virtual Segment* getSubElement(const char* Type, unsigned long) const = 0;
/// get sub-element by combined name
virtual Segment* getSubElementByName(const char* Name) const;
/** Get lines from segment */
virtual void getLinesFromSubElement(
const Segment*,
std::vector<Base::Vector3d> &Points,
std::vector<Line> &lines) const;
virtual void getLinesFromSubElement(const Segment*,
std::vector<Base::Vector3d>& Points,
std::vector<Line>& lines) const;
/** Get faces from segment */
virtual void getFacesFromSubElement(
const Segment*,
std::vector<Base::Vector3d> &Points,
std::vector<Base::Vector3d> &PointNormals,
std::vector<Facet> &faces) const;
virtual void getFacesFromSubElement(const Segment*,
std::vector<Base::Vector3d>& Points,
std::vector<Base::Vector3d>& PointNormals,
std::vector<Facet>& faces) const;
//@}
/** @name Placement control */
@@ -147,7 +157,7 @@ public:
* This method has to be handled by the child classes.
* the actual placement and matrix is not part of this class.
*/
virtual void setTransform(const Base::Matrix4D& rclTrf)=0;
virtual void setTransform(const Base::Matrix4D& rclTrf) = 0;
/** Return the current matrix
* This method has to be handled by the child classes.
* the actual placement and matrix is not part of this class.
@@ -158,7 +168,7 @@ public:
/** @name Modification */
//@{
/// Applies a transformation on the real geometric data type
virtual void transformGeometry(const Base::Matrix4D &rclMat) = 0;
virtual void transformGeometry(const Base::Matrix4D& rclMat) = 0;
//@}
/** @name Getting basic geometric entities */
@@ -166,21 +176,25 @@ public:
/// Get the standard accuracy to be used with getPoints, getLines or getFaces
virtual double getAccuracy() const;
/// Get the bound box
virtual Base::BoundBox3d getBoundBox() const=0;
virtual Base::BoundBox3d getBoundBox() const = 0;
/** Get point from line object intersection */
virtual Base::Vector3d getPointFromLineIntersection(
const Base::Vector3f& base,
const Base::Vector3f& dir) const;
virtual Base::Vector3d getPointFromLineIntersection(const Base::Vector3f& base,
const Base::Vector3f& dir) const;
/** Get points from object with given accuracy */
virtual void getPoints(std::vector<Base::Vector3d> &Points,
std::vector<Base::Vector3d> &Normals,
double Accuracy, uint16_t flags=0) const;
virtual void getPoints(std::vector<Base::Vector3d>& Points,
std::vector<Base::Vector3d>& Normals,
double Accuracy,
uint16_t flags = 0) const;
/** Get lines from object with given accuracy */
virtual void getLines(std::vector<Base::Vector3d> &Points,std::vector<Line> &lines,
double Accuracy, uint16_t flags=0) const;
virtual void getLines(std::vector<Base::Vector3d>& Points,
std::vector<Line>& lines,
double Accuracy,
uint16_t flags = 0) const;
/** Get faces from object with given accuracy */
virtual void getFaces(std::vector<Base::Vector3d> &Points,std::vector<Facet> &faces,
double Accuracy, uint16_t flags=0) const;
virtual void getFaces(std::vector<Base::Vector3d>& Points,
std::vector<Facet>& faces,
double Accuracy,
uint16_t flags = 0) const;
/** Get the center of gravity
* If this method is implemented then true is returned and the center of gravity.
* The default implementation only returns false.
@@ -188,7 +202,7 @@ public:
virtual bool getCenterOfGravity(Base::Vector3d& center) const;
//@}
static const std::string &elementMapPrefix();
static const std::string& elementMapPrefix();
/** @name Element name mapping */
//@{
@@ -200,8 +214,7 @@ public:
*
* @return Returns an indexed name.
*/
IndexedName getIndexedName(const MappedName & name,
ElementIDRefs *sid = nullptr) const;
IndexedName getIndexedName(const MappedName& name, ElementIDRefs* sid = nullptr) const;
/** Get element mapped name
*
@@ -212,9 +225,9 @@ public:
* @param sid: optional output of and App::StringID involved forming this mapped name
* @return Returns the mapped name.
*/
MappedName getMappedName(const IndexedName & element,
MappedName getMappedName(const IndexedName& element,
bool allowUnmapped = false,
ElementIDRefs *sid = nullptr) const;
ElementIDRefs* sid = nullptr) const;
/** Return a pair of indexed name and mapped name
*
@@ -233,9 +246,8 @@ public:
* it will be treated as indexed name. Or else, it will be treated as
* mapped name.
*/
MappedElement getElementName(const char * name,
ElementIDRefs *sid = nullptr,
bool copy = false) const;
MappedElement
getElementName(const char* name, ElementIDRefs* sid = nullptr, bool copy = false) const;
/** Add a sub-element name mapping.
*
@@ -259,11 +271,13 @@ public:
const MappedName& name,
long masterTag,
const ElementIDRefs* sid = nullptr,
bool overwrite = false) {
return _elementMap -> setElementName(element, name, masterTag, sid, overwrite);
bool overwrite = false)
{
return _elementMap->setElementName(element, name, masterTag, sid, overwrite);
}
bool hasElementMap() {
bool hasElementMap()
{
return _elementMap != nullptr;
}
@@ -276,8 +290,8 @@ public:
* @return a list of mapped names of the give element along with their
* associated string ID references
*/
std::vector<std::pair<MappedName, ElementIDRefs> >
getElementMappedNames(const IndexedName & element, bool needUnmapped=false) const;
std::vector<std::pair<MappedName, ElementIDRefs>>
getElementMappedNames(const IndexedName& element, bool needUnmapped = false) const;
/// Hash the child element map postfixes to shorten element name from hierarchical maps
void hashChildMaps();
@@ -286,29 +300,31 @@ public:
bool hasChildElementMap() const;
/// Append the Tag (if and only if it is non zero) into the element map
virtual void reTagElementMap(long tag,
App::StringHasherRef hasher,
const char *postfix=nullptr) {
virtual void
reTagElementMap(long tag, App::StringHasherRef hasher, const char* postfix = nullptr)
{
(void)tag;
(void)hasher;
(void)postfix;
}
// NOTE: getElementHistory is now in ElementMap
long getElementHistory(const MappedName & name,
MappedName *original=nullptr, std::vector<MappedName> *history=nullptr) const {
if ( _elementMap != nullptr ) {
long getElementHistory(const MappedName& name,
MappedName* original = nullptr,
std::vector<MappedName>* history = nullptr) const
{
if (_elementMap != nullptr) {
return _elementMap->getElementHistory(name, Tag, original, history);
}
return 0;
};
void setMappedChildElements(const std::vector<Data::ElementMap::MappedChildElements> & children);
void setMappedChildElements(const std::vector<Data::ElementMap::MappedChildElements>& children);
std::vector<Data::ElementMap::MappedChildElements> getMappedChildElements() const;
char elementType(const Data::MappedName &) const;
char elementType(const Data::IndexedName &) const;
char elementType(const char *name) const;
char elementType(const Data::MappedName&) const;
char elementType(const Data::IndexedName&) const;
char elementType(const char* name) const;
/** Reset/swap the element map
*
@@ -322,19 +338,19 @@ public:
std::vector<MappedElement> getElementMap() const;
/// Set the entire element map
void setElementMap(const std::vector<MappedElement> &elements);
void setElementMap(const std::vector<MappedElement>& elements);
/// Get the current element map size
size_t getElementMapSize(bool flush=true) const;
size_t getElementMapSize(bool flush = true) const;
/// Return the higher level element names of the given element
virtual std::vector<IndexedName> getHigherElements(const char *name, bool silent=false) const;
virtual std::vector<IndexedName> getHigherElements(const char* name, bool silent = false) const;
/// Return the current element map version
virtual std::string getElementMapVersion() const;
/// Return true to signal element map version change
virtual bool checkElementMapVersion(const char * ver) const;
virtual bool checkElementMapVersion(const char* ver) const;
/// Check if the given sub-name only contains an element name
static bool isElementName(const char* subName)
@@ -359,15 +375,21 @@ public:
/** @name Save/restore */
//@{
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void SaveDocFile(Base::Writer &writer) const override;
void RestoreDocFile(Base::Reader &reader) override;
unsigned int getMemSize () const override;
void setPersistenceFileName(const char *name) const;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
void SaveDocFile(Base::Writer& writer) const override;
void RestoreDocFile(Base::Reader& reader) override;
unsigned int getMemSize() const override;
void setPersistenceFileName(const char* name) const;
virtual void beforeSave() const;
bool isRestoreFailed() const { return _restoreFailed; }
void resetRestoreFailure() const { _restoreFailed = true; }
bool isRestoreFailed() const
{
return _restoreFailed;
}
void resetRestoreFailure() const
{
_restoreFailed = true;
}
//@}
/**
@@ -382,51 +404,60 @@ public:
const std::string dumpElementMap() const;
protected:
/// from local to outside
inline Base::Vector3d transformPointToOutside(const Base::Vector3f& vec) const
{
// clang-format off
return getTransform() * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
// clang-format on
}
/// from local to outside
template<typename Vec>
inline std::vector<Base::Vector3d> transformPointsToOutside(const std::vector<Vec>& input) const
{
// clang-format off
std::vector<Base::Vector3d> output;
output.reserve(input.size());
Base::Matrix4D mat(getTransform());
std::transform(input.cbegin(), input.cend(), std::back_inserter(output), [&mat](const Vec& vec) {
return mat * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
});
std::transform(input.cbegin(), input.cend(), std::back_inserter(output),
[&mat](const Vec& vec) {
return mat * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
});
return output;
// clang-format on
}
inline Base::Vector3d transformVectorToOutside(const Base::Vector3f& vec) const
{
// clang-format off
Base::Matrix4D mat(getTransform());
mat.setCol(3, Base::Vector3d());
return mat * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
static_cast<double>(vec.y),
static_cast<double>(vec.z));
// clang-format on
}
template<typename Vec>
std::vector<Base::Vector3d> transformVectorsToOutside(const std::vector<Vec>& input) const
{
// clang-format off
std::vector<Base::Vector3d> output;
output.reserve(input.size());
Base::Matrix4D mat(getTransform());
mat.setCol(3, Base::Vector3d());
std::transform(input.cbegin(), input.cend(), std::back_inserter(output), [&mat](const Vec& vec) {
return mat * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
});
std::transform(input.cbegin(), input.cend(), std::back_inserter(output),
[&mat](const Vec& vec) {
return mat * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
});
return output;
// clang-format on
}
/// from local to inside
inline Base::Vector3f transformPointToInside(const Base::Vector3d& vec) const
@@ -438,23 +469,25 @@ protected:
static_cast<float>(tmp.y),
static_cast<float>(tmp.z));
}
public:
mutable long Tag{0};
mutable long Tag {0};
/// String hasher for element name shortening
mutable App::StringHasherRef Hasher;
protected:
void restoreStream(std::istream & stream, std::size_t count);
void restoreStream(std::istream& stream, std::size_t count);
void readElements(Base::XMLReader& reader, size_t count);
/// from local to outside
inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const
{
// clang-format off
return getTransform() * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
// clang-format on
}
/// from local to inside
inline Base::Vector3f transformToInside(const Base::Vector3d& vec) const
@@ -468,8 +501,8 @@ protected:
}
protected:
ElementMapPtr elementMap(bool flush=true) const;
ElementMapPtr ensureElementMap(bool flush=true);
ElementMapPtr elementMap(bool flush = true) const;
ElementMapPtr ensureElementMap(bool flush = true);
private:
ElementMapPtr _elementMap;
@@ -479,7 +512,7 @@ protected:
mutable bool _restoreFailed = false;
};
} //namespace App
} // namespace Data
ENABLE_BITMASK_OPERATORS(Data::SearchOption)
#endif
+1285 -892
View File
File diff suppressed because it is too large Load Diff
+183 -151
View File
@@ -37,33 +37,32 @@
#include <vector>
#include <QString>
namespace Base {
class Writer;
}
namespace App
namespace Base
{
class TransactionalObject;
class DocumentObject;
class DocumentObjectExecReturn;
class Document;
class DocumentPy; // the python document class
class Application;
class Transaction;
class StringHasher;
using StringHasherRef = Base::Reference<StringHasher>;
class Writer;
}
namespace App
{
class TransactionalObject;
class DocumentObject;
class DocumentObjectExecReturn;
class Document;
class DocumentPy;
class Application;
class Transaction;
class StringHasher;
using StringHasherRef = Base::Reference<StringHasher>;
/// The document class
class AppExport Document : public App::PropertyContainer
class AppExport Document: public App::PropertyContainer
{
PROPERTY_HEADER_WITH_OVERRIDE(App::Document);
public:
enum Status {
// clang-format off
enum Status
{
SkipRecompute = 0,
KeepTrailingDigits = 1,
Closable = 2,
@@ -72,14 +71,16 @@ public:
PartialRestore = 5,
Importing = 6,
PartialDoc = 7,
AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set
TempDoc = 9, // Mark as temporary document without prompt for save
AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set
TempDoc = 9, // Mark as temporary document without prompt for save
RestoreError = 10,
LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed
IgnoreErrorOnRecompute = 12, // Don't report errors if the recompute failed
RecomputeOnRestore = 13, // Mark pending recompute on restore for migration purposes
LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed
IgnoreErrorOnRecompute = 12, // Don't report errors if the recompute failed
RecomputeOnRestore = 13, // Mark pending recompute on restore for migration purposes
};
// clang-format on
// NOLINTBEGIN
/** @name Properties */
//@{
/// holds the long name of the document (utf-8 coded)
@@ -124,67 +125,66 @@ public:
/** @name Signals of the document */
//@{
// clang-format off
/// signal before changing an doc property
boost::signals2::signal<void (const App::Document&, const App::Property&)> signalBeforeChange;
boost::signals2::signal<void(const App::Document&, const App::Property&)> signalBeforeChange;
/// signal on changed doc property
boost::signals2::signal<void (const App::Document&, const App::Property&)> signalChanged;
boost::signals2::signal<void(const App::Document&, const App::Property&)> signalChanged;
/// signal on new Object
boost::signals2::signal<void (const App::DocumentObject&)> signalNewObject;
//boost::signals2::signal<void (const App::DocumentObject&)> m_sig;
boost::signals2::signal<void(const App::DocumentObject&)> signalNewObject;
/// signal on deleted Object
boost::signals2::signal<void (const App::DocumentObject&)> signalDeletedObject;
boost::signals2::signal<void(const App::DocumentObject&)> signalDeletedObject;
/// signal before changing an Object
boost::signals2::signal<void (const App::DocumentObject&, const App::Property&)> signalBeforeChangeObject;
boost::signals2::signal<void(const App::DocumentObject&, const App::Property&)> signalBeforeChangeObject;
/// signal on changed Object
boost::signals2::signal<void (const App::DocumentObject&, const App::Property&)> signalChangedObject;
boost::signals2::signal<void(const App::DocumentObject&, const App::Property&)> signalChangedObject;
/// signal on manually called DocumentObject::touch()
boost::signals2::signal<void (const App::DocumentObject&)> signalTouchedObject;
boost::signals2::signal<void(const App::DocumentObject&)> signalTouchedObject;
/// signal on relabeled Object
boost::signals2::signal<void (const App::DocumentObject&)> signalRelabelObject;
boost::signals2::signal<void(const App::DocumentObject&)> signalRelabelObject;
/// signal on activated Object
boost::signals2::signal<void (const App::DocumentObject&)> signalActivatedObject;
boost::signals2::signal<void(const App::DocumentObject&)> signalActivatedObject;
/// signal on created object
boost::signals2::signal<void (const App::DocumentObject&, Transaction*)> signalTransactionAppend;
boost::signals2::signal<void(const App::DocumentObject&, Transaction*)> signalTransactionAppend;
/// signal on removed object
boost::signals2::signal<void (const App::DocumentObject&, Transaction*)> signalTransactionRemove;
boost::signals2::signal<void(const App::DocumentObject&, Transaction*)> signalTransactionRemove;
/// signal on undo
boost::signals2::signal<void (const App::Document&)> signalUndo;
boost::signals2::signal<void(const App::Document&)> signalUndo;
/// signal on redo
boost::signals2::signal<void (const App::Document&)> signalRedo;
boost::signals2::signal<void(const App::Document&)> signalRedo;
/** signal on load/save document
* this signal is given when the document gets streamed.
* you can use this hook to write additional information in
* the file (like the Gui::Document does).
*/
boost::signals2::signal<void (Base::Writer &)> signalSaveDocument;
boost::signals2::signal<void (Base::XMLReader&)> signalRestoreDocument;
boost::signals2::signal<void (const std::vector<App::DocumentObject*>&,
Base::Writer &)> signalExportObjects;
boost::signals2::signal<void (const std::vector<App::DocumentObject*>&,
Base::Writer &)> signalExportViewObjects;
boost::signals2::signal<void (const std::vector<App::DocumentObject*>&,
Base::XMLReader&)> signalImportObjects;
boost::signals2::signal<void (const std::vector<App::DocumentObject*>&, Base::Reader&,
const std::map<std::string, std::string>&)> signalImportViewObjects;
boost::signals2::signal<void (const std::vector<App::DocumentObject*>&)> signalFinishImportObjects;
//signal starting a save action to a file
boost::signals2::signal<void (const App::Document&, const std::string&)> signalStartSave;
//signal finishing a save action to a file
boost::signals2::signal<void (const App::Document&, const std::string&)> signalFinishSave;
boost::signals2::signal<void (const App::Document&)> signalBeforeRecompute;
boost::signals2::signal<void (const App::Document&, const std::vector<App::DocumentObject*>&)> signalRecomputed;
boost::signals2::signal<void (const App::DocumentObject&)> signalRecomputedObject;
//signal a new opened transaction
boost::signals2::signal<void (const App::Document&, std::string)> signalOpenTransaction;
boost::signals2::signal<void(Base::Writer&)> signalSaveDocument;
boost::signals2::signal<void(Base::XMLReader&)> signalRestoreDocument;
boost::signals2::signal<void(const std::vector<App::DocumentObject*>&, Base::Writer&)> signalExportObjects;
boost::signals2::signal<void(const std::vector<App::DocumentObject*>&, Base::Writer&)> signalExportViewObjects;
boost::signals2::signal<void(const std::vector<App::DocumentObject*>&, Base::XMLReader&)> signalImportObjects;
boost::signals2::signal<void(const std::vector<App::DocumentObject*>&, Base::Reader&,
const std::map<std::string, std::string>&)> signalImportViewObjects;
boost::signals2::signal<void(const std::vector<App::DocumentObject*>&)> signalFinishImportObjects;
// signal starting a save action to a file
boost::signals2::signal<void(const App::Document&, const std::string&)> signalStartSave;
// signal finishing a save action to a file
boost::signals2::signal<void(const App::Document&, const std::string&)> signalFinishSave;
boost::signals2::signal<void(const App::Document&)> signalBeforeRecompute;
boost::signals2::signal<void(const App::Document&, const std::vector<App::DocumentObject*>&)> signalRecomputed;
boost::signals2::signal<void(const App::DocumentObject&)> signalRecomputedObject;
// signal a new opened transaction
boost::signals2::signal<void(const App::Document&, std::string)> signalOpenTransaction;
// signal a committed transaction
boost::signals2::signal<void (const App::Document&)> signalCommitTransaction;
boost::signals2::signal<void(const App::Document&)> signalCommitTransaction;
// signal an aborted transaction
boost::signals2::signal<void (const App::Document&)> signalAbortTransaction;
boost::signals2::signal<void (const App::Document&, const std::vector<App::DocumentObject*>&)> signalSkipRecompute;
boost::signals2::signal<void (const App::DocumentObject&)> signalFinishRestoreObject;
boost::signals2::signal<void (const App::Document&,const App::Property&)> signalChangePropertyEditor;
boost::signals2::signal<void(const App::Document&)> signalAbortTransaction;
boost::signals2::signal<void(const App::Document&, const std::vector<App::DocumentObject*>&)> signalSkipRecompute;
boost::signals2::signal<void(const App::DocumentObject&)> signalFinishRestoreObject;
boost::signals2::signal<void(const App::Document&, const App::Property&)> signalChangePropertyEditor;
boost::signals2::signal<void(std::string)> signalLinkXsetValue;
// clang-format on
//@}
boost::signals2::signal<void (std::string)> signalLinkXsetValue;
// NOLINTEND
void clearDocument();
@@ -192,21 +192,23 @@ public:
/** @name File handling of the document */
//@{
/// Save the Document under a new Name
//void saveAs (const char* Name);
// void saveAs (const char* Name);
/// Save the document to the file in Property Path
bool save ();
bool save();
bool saveAs(const char* file);
bool saveCopy(const char* file) const;
/// Restore the document from the file in Property Path
void restore (const char *filename=nullptr,
bool delaySignal=false, const std::vector<std::string> &objNames={});
bool afterRestore(bool checkPartial=false);
bool afterRestore(const std::vector<App::DocumentObject *> &, bool checkPartial=false);
enum ExportStatus {
void restore(const char* filename = nullptr,
bool delaySignal = false,
const std::vector<std::string>& objNames = {});
bool afterRestore(bool checkPartial = false);
bool afterRestore(const std::vector<App::DocumentObject*>&, bool checkPartial = false);
enum ExportStatus
{
NotExporting,
Exporting,
};
ExportStatus isExporting(const App::DocumentObject *obj) const;
ExportStatus isExporting(const App::DocumentObject* obj) const;
void exportObjects(const std::vector<App::DocumentObject*>&, std::ostream&);
void exportGraphviz(std::ostream&) const;
std::vector<App::DocumentObject*> importObjects(Base::XMLReader& reader);
@@ -222,10 +224,10 @@ public:
*
* @return the list of imported objects
*/
std::vector<App::DocumentObject*> importLinks(
const std::vector<App::DocumentObject*> &objs = {});
std::vector<App::DocumentObject*>
importLinks(const std::vector<App::DocumentObject*>& objs = {});
/// Opens the document from its file name
//void open (void);
// void open (void);
/// Is the document already saved to a file?
bool isSaved() const;
/// Get the document name
@@ -241,31 +243,39 @@ public:
const char* getFileName() const;
//@}
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
/// returns the complete document memory consumption, including all managed DocObjects and Undo Redo.
unsigned int getMemSize () const override;
/// returns the complete document memory consumption, including all managed DocObjects and Undo
/// Redo.
unsigned int getMemSize() const override;
/** @name Object handling */
//@{
/** Add a feature of sType with sName (ASCII) to this document and set it active.
* Unicode names are set through the Label property.
* @param sType the type of created object
* @param pObjectName if nonNULL use that name otherwise generate a new unique name based on the \a sType
* @param isNew if false don't call the \c DocumentObject::setupObject() callback (default is true)
* @param pObjectName if nonNULL use that name otherwise generate a new unique name based on the
* \a sType
* @param isNew if false don't call the \c DocumentObject::setupObject() callback (default
* is true)
* @param viewType override object's view provider name
* @param isPartial indicate if this object is meant to be partially loaded
*/
DocumentObject *addObject(const char* sType, const char* pObjectName=nullptr,
bool isNew=true, const char *viewType=nullptr, bool isPartial=false);
DocumentObject* addObject(const char* sType,
const char* pObjectName = nullptr,
bool isNew = true,
const char* viewType = nullptr,
bool isPartial = false);
/** Add an array of features of the given types and names.
* Unicode names are set through the Label property.
* @param sType The type of created object
* @param objectNames A list of object names
* @param isNew If false don't call the \c DocumentObject::setupObject() callback (default is true)
* @param isNew If false don't call the \c DocumentObject::setupObject() callback (default
* is true)
*/
std::vector<DocumentObject *>addObjects(const char* sType, const std::vector<std::string>& objectNames, bool isNew=true);
std::vector<DocumentObject*>
addObjects(const char* sType, const std::vector<std::string>& objectNames, bool isNew = true);
/// Remove a feature out of the document
void removeObject(const char* sName);
/** Add an existing feature with sName (ASCII) to this document and set it active.
@@ -275,7 +285,7 @@ public:
* \note The passed feature must not yet be added to a document, otherwise an exception
* is raised.
*/
void addObject(DocumentObject*, const char* pObjectName=nullptr);
void addObject(DocumentObject*, const char* pObjectName = nullptr);
/** Copy objects from another document to this document
@@ -289,40 +299,44 @@ public:
*
* @return Returns the list of objects copied.
*/
std::vector<DocumentObject*> copyObject(
const std::vector<DocumentObject*> &objs,
bool recursive=false, bool returnAll=false);
std::vector<DocumentObject*> copyObject(const std::vector<DocumentObject*>& objs,
bool recursive = false,
bool returnAll = false);
/** Move an object from another document to this document
* If \a recursive is true then all objects this object depends on
* are moved as well. By default \a recursive is false.
* Returns the moved object itself or 0 if the object is already part of this
* document..
*/
DocumentObject* moveObject(DocumentObject* obj, bool recursive=false);
DocumentObject* moveObject(DocumentObject* obj, bool recursive = false);
/// Returns the active Object of this document
DocumentObject *getActiveObject() const;
DocumentObject* getActiveObject() const;
/// Returns a Object of this document
DocumentObject *getObject(const char *Name) const;
DocumentObject* getObject(const char* Name) const;
/// Returns a Object of this document by its id
DocumentObject *getObjectByID(long id) const;
DocumentObject* getObjectByID(long id) const;
/// Returns true if the DocumentObject is contained in this document
bool isIn(const DocumentObject *pFeat) const;
bool isIn(const DocumentObject* pFeat) const;
/// Returns a Name of an Object or 0
const char *getObjectName(DocumentObject *pFeat) const;
const char* getObjectName(DocumentObject* pFeat) const;
/// Returns a Name of an Object or 0
std::string getUniqueObjectName(const char *Name) const;
std::string getUniqueObjectName(const char* Name) const;
/// Returns a name of the form prefix_number. d specifies the number of digits.
std::string getStandardObjectName(const char *Name, int d) const;
std::string getStandardObjectName(const char* Name, int d) const;
/// Returns a list of document's objects including the dependencies
std::vector<DocumentObject*> getDependingObjects() const;
/// Returns a list of all Objects
const std::vector<DocumentObject*> &getObjects() const;
const std::vector<DocumentObject*>& getObjects() const;
std::vector<DocumentObject*> getObjectsOfType(const Base::Type& typeId) const;
/// Returns all object with given extensions. If derived=true also all objects with extensions derived from the given one
std::vector<DocumentObject*> getObjectsWithExtension(const Base::Type& typeId, bool derived = true) const;
std::vector<DocumentObject*> findObjects(const Base::Type& typeId, const char* objname, const char* label) const;
/// Returns all object with given extensions. If derived=true also all objects with extensions
/// derived from the given one
std::vector<DocumentObject*> getObjectsWithExtension(const Base::Type& typeId,
bool derived = true) const;
std::vector<DocumentObject*>
findObjects(const Base::Type& typeId, const char* objname, const char* label) const;
/// Returns an array with the correct types already.
template<typename T> inline std::vector<T*> getObjectsOfType() const;
template<typename T>
inline std::vector<T*> getObjectsOfType() const;
int countObjectsOfType(const Base::Type& typeId) const;
/// get the number of objects in the document
int countObjects() const;
@@ -338,7 +352,7 @@ public:
/// check if there is any object must execute in this document
bool mustExecute() const;
/// returns all touched objects
std::vector<App::DocumentObject *> getTouched() const;
std::vector<App::DocumentObject*> getTouched() const;
/// set the document to be closable, this is on by default.
void setClosable(bool);
/// check whether the document can be closed
@@ -348,10 +362,12 @@ public:
* @param objs: specify a sub set of objects to recompute. If empty, then
* all object in this document is checked for recompute
*/
int recompute(const std::vector<App::DocumentObject*> &objs={},
bool force=false,bool *hasError=nullptr, int options=0);
int recompute(const std::vector<App::DocumentObject*>& objs = {},
bool force = false,
bool* hasError = nullptr,
int options = 0);
/// Recompute only one feature
bool recomputeFeature(DocumentObject* Feat,bool recursive=false);
bool recomputeFeature(DocumentObject* Feat, bool recursive = false);
/// get the text of the error of a specified object
const char* getErrorDescription(const App::DocumentObject*) const;
/// return the status bits
@@ -392,9 +408,9 @@ public:
* to setup a potential transaction which will only be created if there is
* actual changes.
*/
void openTransaction(const char* name=nullptr);
void openTransaction(const char* name = nullptr);
/// Rename the current transaction if the id matches
void renameTransaction(const char *name, int id);
void renameTransaction(const char* name, int id);
/// Commit the Command transaction. Do nothing If there is no Command transaction open.
void commitTransaction();
/// Abort the actually running transaction.
@@ -402,49 +418,51 @@ public:
/// Check if a transaction is open
bool hasPendingTransaction() const;
/// Return the undo/redo transaction ID starting from the back
int getTransactionID(bool undo, unsigned pos=0) const;
int getTransactionID(bool undo, unsigned pos = 0) const;
/// Check if a transaction is open and its list is empty.
/// If no transaction is open true is returned.
bool isTransactionEmpty() const;
/// Set the Undo limit in Byte!
void setUndoLimit(unsigned int UndoMemSize=0);
void setUndoLimit(unsigned int UndoMemSize = 0);
/// Returns the actual memory consumption of the Undo redo stuff.
unsigned int getUndoMemSize () const;
unsigned int getUndoMemSize() const;
/// Set the Undo limit as stack size
void setMaxUndoStackSize(unsigned int UndoMaxStackSize=20);
void setMaxUndoStackSize(unsigned int UndoMaxStackSize = 20); // NOLINT
/// Set the Undo limit as stack size
unsigned int getMaxUndoStackSize()const;
unsigned int getMaxUndoStackSize() const;
/// Remove all stored Undos and Redos
void clearUndos();
/// Returns the number of stored Undos. If greater than 0 Undo will be effective.
int getAvailableUndos(int id=0) const;
int getAvailableUndos(int id = 0) const;
/// Returns a list of the Undo names
std::vector<std::string> getAvailableUndoNames() const;
/// Will UNDO one step, returns False if no undo was done (Undos == 0).
bool undo(int id=0);
bool undo(int id = 0);
/// Returns the number of stored Redos. If greater than 0 Redo will be effective.
int getAvailableRedos(int id=0) const;
int getAvailableRedos(int id = 0) const;
/// Returns a list of the Redo names.
std::vector<std::string> getAvailableRedoNames() const;
/// Will REDO one step, returns False if no redo was done (Redos == 0).
bool redo(int id=0) ;
/// returns true if the document is in an Transaction phase, e.g. currently performing a redo/undo or rollback
bool redo(int id = 0);
/// returns true if the document is in an Transaction phase, e.g. currently performing a
/// redo/undo or rollback
bool isPerformingTransaction() const;
/// \internal add or remove property from a transactional object
void addOrRemovePropertyOfObject(TransactionalObject*, Property *prop, bool add);
void addOrRemovePropertyOfObject(TransactionalObject*, Property* prop, bool add);
//@}
/** @name dependency stuff */
//@{
/// write GraphViz file
void writeDependencyGraphViz(std::ostream &out);
void writeDependencyGraphViz(std::ostream& out);
/// checks if the graph is directed and has no cycles
bool checkOnCycle();
/// get a list of all objects linking to the given object
std::vector<App::DocumentObject*> getInList(const DocumentObject* me) const;
/// Option bit flags used by getDepenencyList()
enum DependencyOption {
enum DependencyOption
{
/// Return topological sorted list
DepSort = 1,
/// Do no include object linked by PropertyXLink, as it can handle external link
@@ -461,14 +479,15 @@ public:
* @param objs: input objects to query for dependency.
* @param options: See DependencyOption
*/
static std::vector<App::DocumentObject*> getDependencyList(
const std::vector<App::DocumentObject*> &objs, int options=0);
static std::vector<App::DocumentObject*>
getDependencyList(const std::vector<App::DocumentObject*>& objs, int options = 0);
std::vector<App::Document*> getDependentDocuments(bool sort=true);
static std::vector<App::Document*> getDependentDocuments(std::vector<App::Document*> docs, bool sort);
std::vector<App::Document*> getDependentDocuments(bool sort = true);
static std::vector<App::Document*> getDependentDocuments(std::vector<App::Document*> docs,
bool sort);
// set Changed
//void setChanged(DocumentObject* change);
// void setChanged(DocumentObject* change);
/// get a list of topological sorted objects (https://en.wikipedia.org/wiki/Topological_sorting)
std::vector<App::DocumentObject*> topologicalSort() const;
/// get all root objects (objects no other one reference too)
@@ -476,8 +495,8 @@ public:
/// get all tree root objects (objects that are at the root of the object tree)
std::vector<App::DocumentObject*> getRootObjectsIgnoreLinks() const;
/// get all possible paths from one object to another following the OutList
std::vector<std::list<App::DocumentObject*> > getPathsByOutList
(const App::DocumentObject* from, const App::DocumentObject* to) const;
std::vector<std::list<App::DocumentObject*>>
getPathsByOutList(const App::DocumentObject* from, const App::DocumentObject* to) const;
//@}
/** Called by a property during save to store its StringHasher
@@ -493,7 +512,7 @@ public:
* of the hasher. If the hasher has not been added before, the object must
* save the hasher by calling StringHasher::Save
*/
std::pair<bool,int> addStringHasher(const StringHasherRef & hasher) const;
std::pair<bool, int> addStringHasher(const StringHasherRef& hasher) const;
/** Called by property to restore its StringHasher
*
@@ -505,7 +524,7 @@ public:
* The caller is responsible for restoring the hasher if the caller is the first
* owner of the hasher, i.e. if addStringHasher() returns true during save.
*/
StringHasherRef getStringHasher(int index=-1) const;
StringHasherRef getStringHasher(int index = -1) const;
/** Return the links to a given object
*
@@ -516,22 +535,32 @@ public:
* @param objs: optional objects to search for, if empty, then all objects
* of this document are searched.
*/
void getLinksTo(std::set<DocumentObject*> &links,
const DocumentObject *obj, int options, int maxCount=0,
const std::vector<DocumentObject*> &objs = {}) const;
void getLinksTo(std::set<DocumentObject*>& links,
const DocumentObject* obj,
int options,
int maxCount = 0,
const std::vector<DocumentObject*>& objs = {}) const;
/// Check if there is any link to the given object
bool hasLinksTo(const DocumentObject *obj) const;
bool hasLinksTo(const DocumentObject* obj) const;
/// Called by objects during restore to ask for recompute
void addRecomputeObject(DocumentObject *obj);
void addRecomputeObject(DocumentObject* obj);
const std::string &getOldLabel() const {return oldLabel;}
const std::string& getOldLabel() const
{
return oldLabel;
}
/// Function called to signal that an object identifier has been renamed
void renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> & paths, const std::function<bool(const App::DocumentObject*)> &selector = [](const App::DocumentObject *) { return true; });
void renameObjectIdentifiers(
const std::map<App::ObjectIdentifier, App::ObjectIdentifier>& paths,
const std::function<bool(const App::DocumentObject*)>& selector =
[](const App::DocumentObject*) {
return true;
});
PyObject *getPyObject() override;
PyObject* getPyObject() override;
std::string getFullName() const override;
@@ -550,23 +579,23 @@ public:
protected:
/// Construction
explicit Document(const char *documentName = "");
explicit Document(const char* documentName = "");
void _removeObject(DocumentObject* pcObject);
void _addObject(DocumentObject* pcObject, const char* pObjectName);
/// checks if a valid transaction is open
void _checkTransaction(DocumentObject* pcDelObj, const Property *What, int line);
void _checkTransaction(DocumentObject* pcDelObj, const Property* What, int line);
void breakDependency(DocumentObject* pcObject, bool clear);
std::vector<App::DocumentObject*> readObjects(Base::XMLReader& reader);
void writeObjects(const std::vector<App::DocumentObject*>&, Base::Writer &writer) const;
void writeObjects(const std::vector<App::DocumentObject*>&, Base::Writer& writer) const;
bool saveToFile(const char* filename) const;
void onBeforeChange(const Property* prop) override;
void onChanged(const Property* prop) override;
/// callback from the Document objects before property will be changed
void onBeforeChangeProperty(const TransactionalObject *Who, const Property *What);
void onBeforeChangeProperty(const TransactionalObject* Who, const Property* What);
/// callback from the Document objects after property was changed
void onChangedProperty(const DocumentObject *Who, const Property *What);
void onChangedProperty(const DocumentObject* Who, const Property* What);
/// helper which Recompute only this feature
/// @return 0 if succeeded, 1 if failed, -1 if aborted by user.
int _recomputeFeature(DocumentObject* Feat);
@@ -574,9 +603,10 @@ protected:
/// refresh the internal dependency graph
void _rebuildDependencyList(
const std::vector<App::DocumentObject*> &objs = std::vector<App::DocumentObject*>());
const std::vector<App::DocumentObject*>& objs = std::vector<App::DocumentObject*>());
std::string getTransientDirectoryName(const std::string& uuid, const std::string& filename) const;
std::string getTransientDirectoryName(const std::string& uuid,
const std::string& filename) const;
/** Open a new command Undo/Redo, an UTF-8 name can be specified
*
@@ -588,18 +618,19 @@ protected:
* This function creates an actual transaction regardless of Application
* AutoTransaction setting.
*/
int _openTransaction(const char* name=nullptr, int id=0);
int _openTransaction(const char* name = nullptr, int id = 0);
/// Internally called by App::Application to commit the Command transaction.
void _commitTransaction(bool notify=false);
void _commitTransaction(bool notify = false);
/// Internally called by App::Application to abort the running transaction.
void _abortTransaction();
private:
// # Data Member of the document +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// # Data Member of the document
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
std::list<Transaction*> mUndoTransactions;
std::map<int,Transaction*> mUndoMap;
std::map<int, Transaction*> mUndoMap;
std::list<Transaction*> mRedoTransactions;
std::map<int,Transaction*> mRedoMap;
std::map<int, Transaction*> mRedoMap;
struct DocumentP* d;
@@ -613,12 +644,13 @@ inline std::vector<T*> Document::getObjectsOfType() const
std::vector<T*> type;
std::vector<App::DocumentObject*> obj = this->getObjectsOfType(T::getClassTypeId());
type.reserve(obj.size());
for (std::vector<App::DocumentObject*>::iterator it = obj.begin(); it != obj.end(); ++it)
type.push_back(static_cast<T*>(*it));
for (auto it : obj) {
type.push_back(static_cast<T*>(it));
}
return type;
}
} //namespace App
} // namespace App
#endif // APP_DOCUMENT_H
#endif // APP_DOCUMENT_H
+468 -346
View File
File diff suppressed because it is too large Load Diff
+216 -124
View File
@@ -46,44 +46,49 @@ class DocumentObjectGroup;
class DocumentObjectPy;
class Expression;
enum ObjectStatus {
// clang-format off
enum ObjectStatus
{
Touch = 0,
Error = 1,
New = 2,
Recompute = 3, // set when the object is currently being recomputed
Recompute = 3, // set when the object is currently being recomputed
Restore = 4,
Remove = 5,
PythonCall = 6,
Destroy = 7,
Enforce = 8,
Recompute2 = 9, // set when the object is being recomputed in the second pass
Recompute2 = 9, // set when the object is being recomputed in the second pass
PartialObject = 10,
PendingRecompute = 11, // set by Document, indicating the object is in recomputation queue
ObjImporting = 13, // Mark the object as importing
NoTouch = 14, // no touch on any property change
GeoExcluded = 15, // mark as a member but not claimed by GeoFeatureGroup
Expand = 16, // indicate the object's tree item expansion status
NoAutoExpand = 17, // disable tree item auto expand on selection for this object
PendingTransactionUpdate = 18, // mark that the object expects a call to onUndoRedoFinished() after transaction is finished.
RecomputeExtension = 19, // mark the object to recompute its extensions
TouchOnColorChange = 20, // inform view provider touch object on color change
Freeze = 21, // do not recompute ever
PendingRecompute = 11, // set by Document, indicating the object is in recomputation queue
ObjImporting = 13, // Mark the object as importing
NoTouch = 14, // no touch on any property change
GeoExcluded = 15, // mark as a member but not claimed by GeoFeatureGroup
Expand = 16, // indicate the object's tree item expansion status
NoAutoExpand = 17, // disable tree item auto expand on selection for this object
PendingTransactionUpdate = 18, // mark that the object expects a call to onUndoRedoFinished() after transaction is finished.
RecomputeExtension = 19, // mark the object to recompute its extensions
TouchOnColorChange = 20, // inform view provider touch object on color change
Freeze = 21, // do not recompute ever
};
// clang-format on
/** Return object for feature execution
*/
*/
class AppExport DocumentObjectExecReturn
{
public:
explicit DocumentObjectExecReturn(const std::string& sWhy, DocumentObject* WhichObject=nullptr)
: Why(sWhy), Which(WhichObject)
{
}
explicit DocumentObjectExecReturn(const char* sWhy, DocumentObject* WhichObject=nullptr)
explicit DocumentObjectExecReturn(const std::string& sWhy,
DocumentObject* WhichObject = nullptr)
: Why(sWhy)
, Which(WhichObject)
{}
explicit DocumentObjectExecReturn(const char* sWhy, DocumentObject* WhichObject = nullptr)
: Which(WhichObject)
{
if (sWhy)
if (sWhy) {
Why = sWhy;
}
}
std::string Why;
@@ -91,7 +96,6 @@ public:
};
/** Base class of all Classes handled in the Document
*/
class AppExport DocumentObject: public App::TransactionalObject
@@ -99,7 +103,6 @@ class AppExport DocumentObject: public App::TransactionalObject
PROPERTY_HEADER_WITH_OVERRIDE(App::DocumentObject);
public:
PropertyString Label;
PropertyString Label2;
PropertyExpressionEngine ExpressionEngine;
@@ -107,15 +110,18 @@ public:
/// Allow control visibility status in App name space
PropertyBool Visibility;
// clang-format off
/// signal before changing a property of this object
boost::signals2::signal<void (const App::DocumentObject&, const App::Property&)> signalBeforeChange;
boost::signals2::signal<void(const App::DocumentObject&, const App::Property&)> signalBeforeChange;
/// signal on changed property of this object
boost::signals2::signal<void (const App::DocumentObject&, const App::Property&)> signalChanged;
boost::signals2::signal<void(const App::DocumentObject&, const App::Property&)> signalChanged;
/// signal on changed property of this object before document scoped signalChangedObject
boost::signals2::signal<void (const App::DocumentObject&, const App::Property&)> signalEarlyChanged;
boost::signals2::signal<void(const App::DocumentObject&, const App::Property&)> signalEarlyChanged;
// clang-format on
/// returns the type name of the ViewProvider
virtual const char* getViewProviderName() const {
virtual const char* getViewProviderName() const
{
return "";
}
/**
@@ -127,7 +133,8 @@ public:
* If not, the view provider will be reverted to the one returned from \ref
* getViewProviderName().
*/
virtual const char *getViewProviderNameOverride() const {
virtual const char* getViewProviderNameOverride() const
{
return getViewProviderName();
}
@@ -138,11 +145,14 @@ public:
/// returns a value that uniquely identifies this DocumentObject.
const char* getDagKey() const;
/// returns the name which is set in the document for this object (not the name property!)
const char *getNameInDocument() const;
const char* getNameInDocument() const;
/// Return the object ID that is unique within its owner document
long getID() const {return _Id;}
long getID() const
{
return _Id;
}
/// returns the name that is safe to be exported to other document
std::string getExportName(bool forced=false) const;
std::string getExportName(bool forced = false) const;
/// Return the object full name of the form DocName#ObjName
std::string getFullName() const override;
/// Return the object full label in the form DocName#ObjName
@@ -150,13 +160,13 @@ public:
bool isAttachedToDocument() const override;
const char* detachFromDocument() override;
/// gets the document in which this Object is handled
App::Document *getDocument() const;
App::Document* getDocument() const;
/** Set the property touched -> changed, cause recomputation in Update()
*/
//@{
/// set this document object touched (cause recomputation on dependent features)
void touch(bool noRecompute=false);
void touch(bool noRecompute = false);
/// test if this document object is touched
bool isTouched() const;
/// Enforce this document object to be recomputed
@@ -164,32 +174,63 @@ public:
/// Test if this document object must be recomputed
bool mustRecompute() const;
/// reset this document object touched
void purgeTouched() {
void purgeTouched()
{
StatusBits.reset(ObjectStatus::Touch);
StatusBits.reset(ObjectStatus::Enforce);
setPropertyStatus(0,false);
setPropertyStatus(0, false);
}
/// set this feature to error
bool isError() const {return StatusBits.test(ObjectStatus::Error);}
bool isValid() const {return !StatusBits.test(ObjectStatus::Error);}
bool isError() const
{
return StatusBits.test(ObjectStatus::Error);
}
bool isValid() const
{
return !StatusBits.test(ObjectStatus::Error);
}
/// remove the error from the object
void purgeError(){StatusBits.reset(ObjectStatus::Error);}
void purgeError()
{
StatusBits.reset(ObjectStatus::Error);
}
/// returns true if this objects is currently recomputing
bool isRecomputing() const {return StatusBits.test(ObjectStatus::Recompute);}
bool isRecomputing() const
{
return StatusBits.test(ObjectStatus::Recompute);
}
/// returns true if this objects is currently restoring from file
bool isRestoring() const {return StatusBits.test(ObjectStatus::Restore);}
bool isRestoring() const
{
return StatusBits.test(ObjectStatus::Restore);
}
/// returns true if this objects is currently removed from the document
bool isRemoving() const {return StatusBits.test(ObjectStatus::Remove);}
bool isRemoving() const
{
return StatusBits.test(ObjectStatus::Remove);
}
/// set this document object freezed (prevent recomputation)
void freeze();
/// set this document object unfreezed (and touch it)
void unfreeze(bool noRecompute=false);
void unfreeze(bool noRecompute = false);
/// returns true if this objects is currently freezed
bool isFreezed() const {return StatusBits.test(ObjectStatus::Freeze);}
bool isFreezed() const
{
return StatusBits.test(ObjectStatus::Freeze);
}
/// return the status bits
unsigned long getStatus() const {return StatusBits.to_ulong();}
bool testStatus(ObjectStatus pos) const {return StatusBits.test(size_t(pos));}
void setStatus(ObjectStatus pos, bool on) {StatusBits.set(size_t(pos), on);}
unsigned long getStatus() const
{
return StatusBits.to_ulong();
}
bool testStatus(ObjectStatus pos) const
{
return StatusBits.test(size_t(pos));
}
void setStatus(ObjectStatus pos, bool on)
{
StatusBits.set(size_t(pos), on);
}
//@}
int isExporting() const;
@@ -205,14 +246,14 @@ public:
* @return -1 if element visibility is not supported, 0 if element is not
* found, 1 if success
*/
virtual int setElementVisible(const char *element, bool visible);
virtual int setElementVisible(const char* element, bool visible);
/** Get sub-element visibility
*
* @return -1 if element visibility is not supported or element not found, 0
* if element is invisible, or else 1
*/
virtual int isElementVisible(const char *element) const;
virtual int isElementVisible(const char* element) const;
/// return true to activate tree view group object handling and element visibility
virtual bool hasChildElement() const;
@@ -225,7 +266,8 @@ public:
*/
//@{
/// OutList options
enum OutListOption {
enum OutListOption
{
/// Do not include link from expression engine
OutListNoExpression = 1,
/// Do not hide any link (i.e. include links with LinkScopeHidden)
@@ -234,9 +276,9 @@ public:
OutListNoXLinked = 4,
};
/// returns a list of objects this object is pointing to by Links
const std::vector<App::DocumentObject*> &getOutList() const;
const std::vector<App::DocumentObject*>& getOutList() const;
std::vector<App::DocumentObject*> getOutList(int option) const;
void getOutList(int option, std::vector<App::DocumentObject*> &res) const;
void getOutList(int option, std::vector<App::DocumentObject*>& res) const;
/// returns a list of objects linked by the property
std::vector<App::DocumentObject*> getOutListOfProperty(App::Property*) const;
@@ -245,15 +287,15 @@ public:
/// clear internal out list cache
void clearOutListCache() const;
/// get all possible paths from this to another object following the OutList
std::vector<std::list<App::DocumentObject*> > getPathsByOutList(App::DocumentObject* to) const;
std::vector<std::list<App::DocumentObject*>> getPathsByOutList(App::DocumentObject* to) const;
#ifdef USE_OLD_DAG
/// get all objects link to this object
std::vector<App::DocumentObject*> getInList(void) const
#else
const std::vector<App::DocumentObject*> &getInList() const;
const std::vector<App::DocumentObject*>& getInList() const;
#endif
/// get all objects link directly or indirectly to this object
std::vector<App::DocumentObject*> getInListRecursive() const;
/// get all objects link directly or indirectly to this object
std::vector<App::DocumentObject*> getInListRecursive() const;
/** Get a set of all objects linking to this object, including possible external parent objects
*
* @param inSet [out]: a set containing all objects linking to this object.
@@ -261,9 +303,11 @@ public:
* @param inList [in, out]: optional pointer to a vector holding the output
* objects, with the furthest linking object ordered last.
*/
void getInListEx(std::set<App::DocumentObject*> &inSet,
bool recursive, std::vector<App::DocumentObject*> *inList=nullptr) const;
/** Return a set of all objects linking to this object, including possible external parent objects
void getInListEx(std::set<App::DocumentObject*>& inSet,
bool recursive,
std::vector<App::DocumentObject*>* inList = nullptr) const;
/** Return a set of all objects linking to this object, including possible external parent
* objects
* @param recursive [in]: whether to obtain recursive in list
*/
std::set<App::DocumentObject*> getInListEx(bool recursive) const;
@@ -296,9 +340,9 @@ public:
* That is, if the return is true, the link is allowed.
*/
bool testIfLinkDAGCompatible(DocumentObject* linkTo) const;
bool testIfLinkDAGCompatible(const std::vector<DocumentObject *> &linksTo) const;
bool testIfLinkDAGCompatible(App::PropertyLinkSubList &linksTo) const;
bool testIfLinkDAGCompatible(App::PropertyLinkSub &linkTo) const;
bool testIfLinkDAGCompatible(const std::vector<DocumentObject*>& linksTo) const;
bool testIfLinkDAGCompatible(App::PropertyLinkSubList& linksTo) const;
bool testIfLinkDAGCompatible(App::PropertyLinkSub& linkTo) const;
/** Return the element map version of the geometry data stored in the given property
*
@@ -309,10 +353,11 @@ public:
*
* @return Return the element map version string.
*/
virtual std::string getElementMapVersion(const App::Property *prop, bool restored=false) const;
virtual std::string getElementMapVersion(const App::Property* prop,
bool restored = false) const;
/// Return true to signal re-generation of geometry element names
virtual bool checkElementMapVersion(const App::Property *prop, const char *ver) const;
virtual bool checkElementMapVersion(const App::Property* prop, const char* ver) const;
public:
/** mustExecute
@@ -332,10 +377,10 @@ public:
*
* @param recursive: set to true to recompute any dependent objects as well
*/
bool recomputeFeature(bool recursive=false);
bool recomputeFeature(bool recursive = false);
/// get the status Message
const char *getStatusString() const;
const char* getStatusString() const;
/** Called in case of losing a link
* Get called by the document when a object got deleted a link property of this
@@ -344,7 +389,7 @@ public:
* additional or different behavior.
*/
virtual void onLostLinkToObject(DocumentObject*);
PyObject *getPyObject() override;
PyObject* getPyObject() override;
/** Get the sub element/object by name
*
@@ -374,8 +419,11 @@ public:
* then it shall return itself. If subname is invalid, then it shall return
* zero.
*/
virtual DocumentObject *getSubObject(const char *subname, PyObject **pyObj=nullptr,
Base::Matrix4D *mat=nullptr, bool transform=true, int depth=0) const;
virtual DocumentObject* getSubObject(const char* subname,
PyObject** pyObj = nullptr,
Base::Matrix4D* mat = nullptr,
bool transform = true,
int depth = 0) const;
/** Return a list of objects referenced by a given subname including this object
* @param subname: the sub name path
@@ -391,7 +439,8 @@ public:
bool flatten = false) const;
/// reason of calling getSubObjects()
enum GSReason {
enum GSReason
{
/// default, mostly for exporting shape objects
GS_DEFAULT,
/// for element selection
@@ -413,10 +462,10 @@ public:
* need special transformation. For example, sub objects of an array type
* of object.
*/
virtual std::vector<std::string> getSubObjects(int reason=0) const;
virtual std::vector<std::string> getSubObjects(int reason = 0) const;
///Obtain top parents and subnames of this object using its InList
std::vector<std::pair<App::DocumentObject*,std::string> > getParents(int depth=0) const;
/// Obtain top parents and subnames of this object using its InList
std::vector<std::pair<App::DocumentObject*, std::string>> getParents(int depth = 0) const;
/// Obtain the first parent group of this object
App::DocumentObject* getFirstParent() const;
@@ -436,20 +485,34 @@ public:
* @return Return the linked object. This function must return itself if the
* it is not a link or the link is invalid.
*/
virtual DocumentObject *getLinkedObject(bool recurse=true,
Base::Matrix4D *mat=nullptr, bool transform=false, int depth=0) const;
virtual DocumentObject* getLinkedObject(bool recurse = true,
Base::Matrix4D* mat = nullptr,
bool transform = false,
int depth = 0) const;
/* Return true to cause PropertyView to show linked object's property */
virtual bool canLinkProperties() const {return true;}
virtual bool canLinkProperties() const
{
return true;
}
/* Return whether this object is a link */
virtual bool isLink() const {return false;};
virtual bool isLink() const
{
return false;
}
/* Return whether this object is a link group */
virtual bool isLinkGroup() const {return false;};
virtual bool isLinkGroup() const
{
return false;
}
/* Return true to bypass duplicate label checking */
virtual bool allowDuplicateLabel() const {return false;}
virtual bool allowDuplicateLabel() const
{
return false;
}
/*** Called to let object itself control relabeling
*
@@ -457,38 +520,50 @@ public:
*
* This function is called before onBeforeChange()
*/
virtual void onBeforeChangeLabel(std::string &newLabel) {(void)newLabel;}
virtual void onBeforeChangeLabel(std::string& newLabel)
{
(void)newLabel;
}
friend class Document;
friend class Transaction;
friend class ObjectExecution;
static DocumentObjectExecReturn *StdReturn;
static DocumentObjectExecReturn* StdReturn;
void Save (Base::Writer &writer) const override;
void Save(Base::Writer& writer) const override;
/* Expression support */
virtual void setExpression(const ObjectIdentifier & path, std::shared_ptr<App::Expression> expr);
virtual void setExpression(const ObjectIdentifier& path, std::shared_ptr<App::Expression> expr);
void clearExpression(const ObjectIdentifier & path);
void clearExpression(const ObjectIdentifier& path);
virtual const PropertyExpressionEngine::ExpressionInfo getExpression(const ObjectIdentifier &path) const;
virtual const PropertyExpressionEngine::ExpressionInfo
getExpression(const ObjectIdentifier& path) const;
virtual void renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> & paths);
virtual void
renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier>& paths);
const std::string & getOldLabel() const { return oldLabel; }
const std::string& getOldLabel() const
{
return oldLabel;
}
const char *getViewProviderNameStored() const {
const char* getViewProviderNameStored() const
{
return _pcViewProviderName.c_str();
}
bool removeDynamicProperty(const char* prop) override;
App::Property* addDynamicProperty(
const char* type, const char* name=nullptr,
const char* group=nullptr, const char* doc=nullptr,
short attr=0, bool ro=false, bool hidden=false) override;
App::Property* addDynamicProperty(const char* type,
const char* name = nullptr,
const char* group = nullptr,
const char* doc = nullptr,
short attr = 0,
bool ro = false,
bool hidden = false) override;
/** Resolve the last document object referenced in the subname
*
@@ -502,9 +577,14 @@ public:
* @return Returns the last referenced document object in the subname. If no
* such object in subname, return pObject.
*/
App::DocumentObject *resolve(const char *subname, App::DocumentObject **parent=nullptr,
std::string *childName=nullptr, const char **subElement=nullptr,
PyObject **pyObj=nullptr, Base::Matrix4D *mat=nullptr, bool transform=true, int depth=0) const;
App::DocumentObject* resolve(const char* subname,
App::DocumentObject** parent = nullptr,
std::string* childName = nullptr,
const char** subElement = nullptr,
PyObject** pyObj = nullptr,
Base::Matrix4D* mat = nullptr,
bool transform = true,
int depth = 0) const;
/** Resolve a link reference that is relative to this object reference
*
@@ -550,8 +630,9 @@ public:
*
* The common parent 'Group' is removed.
*/
App::DocumentObject *resolveRelativeLink(std::string &subname,
App::DocumentObject *&link, std::string &linkSub) const;
App::DocumentObject* resolveRelativeLink(std::string& subname,
App::DocumentObject*& link,
std::string& linkSub) const;
/** Called to adjust link properties to avoid cyclic links
*
@@ -567,8 +648,8 @@ public:
* properties that can hold subnames) to avoid cyclic when added to the
* future parent.
*/
virtual bool adjustRelativeLinks(const std::set<App::DocumentObject*> &inList,
std::set<App::DocumentObject*> *visited=nullptr);
virtual bool adjustRelativeLinks(const std::set<App::DocumentObject*>& inList,
std::set<App::DocumentObject*>* visited = nullptr);
/** allow partial loading of dependent objects
*
@@ -576,9 +657,13 @@ public:
* dependent objects to be partially loaded, i.e. only create, but not
* restored. 2 means this object itself can be partially loaded.
*/
virtual int canLoadPartial() const {return 0;}
virtual int canLoadPartial() const
{
return 0;
}
virtual void onUpdateElementReference(const Property *) {}
virtual void onUpdateElementReference(const Property*)
{}
/** Allow object to redirect a subname path
*
@@ -593,34 +678,34 @@ public:
* item is selected in the tree. Document object can use this function to
* redirect the selection to some other objects.
*/
virtual bool redirectSubName(std::ostringstream &ss,
DocumentObject *topParent, DocumentObject *child) const;
virtual bool
redirectSubName(std::ostringstream& ss, DocumentObject* topParent, DocumentObject* child) const;
/** Special marker to mark the object as hidden
*
* It is used by Gui::ViewProvider::getElementColors(), but exposed here
* for convenience
*/
static const std::string &hiddenMarker();
static const std::string& hiddenMarker();
/// Check if the subname reference ends with hidden marker.
static const char *hasHiddenMarker(const char *subname);
static const char* hasHiddenMarker(const char* subname);
protected:
/// recompute only this object
virtual App::DocumentObjectExecReturn *recompute();
virtual App::DocumentObjectExecReturn* recompute();
/** get called by the document to recompute this feature
* Normally this method get called in the processing of
* Document::recompute().
* In execute() the output properties get recomputed
* with the data from linked objects and objects own
* properties.
*/
virtual App::DocumentObjectExecReturn *execute();
* Normally this method get called in the processing of
* Document::recompute().
* In execute() the output properties get recomputed
* with the data from linked objects and objects own
* properties.
*/
virtual App::DocumentObjectExecReturn* execute();
/**
* Executes the extensions of a document object.
*/
App::DocumentObjectExecReturn *executeExtensions();
App::DocumentObjectExecReturn* executeExtensions();
/** Status bits of the document object
* The first 8 bits are used for the base system the rest can be used in
@@ -638,8 +723,14 @@ protected:
*/
std::bitset<32> StatusBits;
void setError(){StatusBits.set(ObjectStatus::Error);}
void resetError(){StatusBits.reset(ObjectStatus::Error);}
void setError()
{
StatusBits.set(ObjectStatus::Error);
}
void resetError()
{
StatusBits.reset(ObjectStatus::Error);
}
void setDocument(App::Document* doc);
/// get called before the value is changed
@@ -660,39 +751,40 @@ protected:
virtual void unsetupObject();
/// get called when a property status has changed
void onPropertyStatusChanged(const Property &prop, unsigned long oldStatus) override;
void onPropertyStatusChanged(const Property& prop, unsigned long oldStatus) override;
private:
void printInvalidLinks() const;
/// python object of this class and all descendent
protected: // attributes
/// python object of this class and all descendent
protected: // attributes
Py::SmartPtr PythonObject;
/// pointer to the document this object belongs to
App::Document* _pDoc{nullptr};
App::Document* _pDoc {nullptr};
/// Old label; used for renaming expressions
std::string oldLabel;
// pointer to the document name string (for performance)
const std::string *pcNameInDocument{nullptr};
const std::string* pcNameInDocument {nullptr};
private:
// accessed by App::Document to record and restore the correct view provider type
std::string _pcViewProviderName;
// unique identifier (among a document) of this object.
long _Id{0};
long _Id {0};
private:
// Back pointer to all the fathers in a DAG of the document
// this is used by the document (via friend) to have a effective DAG handling
std::vector<App::DocumentObject*> _inList;
mutable std::vector<App::DocumentObject *> _outList;
mutable std::unordered_map<const char *, App::DocumentObject*, CStringHasher, CStringHasher> _outListMap;
mutable std::vector<App::DocumentObject*> _outList;
mutable std::unordered_map<const char*, App::DocumentObject*, CStringHasher, CStringHasher>
_outListMap;
mutable bool _outListCached = false;
};
} //namespace App
} // namespace App
#endif // APP_DOCUMENTOBJECT_H
#endif // APP_DOCUMENTOBJECT_H
+320 -214
View File
@@ -30,7 +30,8 @@
#include <Base/Quantity.h>
#include <Base/Vector3D.h>
namespace App {
namespace App
{
////////////////////////////////////////////////////////////////////////////////////
// Expecting the extended expression is going to be constantly amended (to
@@ -39,67 +40,87 @@ namespace App {
// included by everyone
///////////////////////////////////////////////////////////////////////////////////
struct AppExport Expression::Component {
struct AppExport Expression::Component
{
ObjectIdentifier::Component comp;
Expression* e1;
Expression* e2;
Expression* e3;
explicit Component(const std::string &n);
Component(Expression *e1, Expression *e2, Expression *e3, bool isRange=false);
explicit Component(const ObjectIdentifier::Component &comp);
Component(const Component &other);
explicit Component(const std::string& n);
Component(Expression* e1, Expression* e2, Expression* e3, bool isRange = false);
explicit Component(const ObjectIdentifier::Component& comp);
Component(const Component& other);
~Component();
Component &operator=(const Component &)=delete;
Component& operator=(const Component&) = delete;
void visit(ExpressionVisitor &v);
void visit(ExpressionVisitor& v);
bool isTouched() const;
void toString(std::ostream &ss, bool persistent) const;
Component *copy() const;
Component *eval() const;
void toString(std::ostream& ss, bool persistent) const;
Component* copy() const;
Component* eval() const;
Py::Object get(const Expression *owner, const Py::Object &pyobj) const;
void set(const Expression *owner, Py::Object &pyobj, const Py::Object &value) const;
void del(const Expression *owner, Py::Object &pyobj) const;
Py::Object get(const Expression* owner, const Py::Object& pyobj) const;
void set(const Expression* owner, Py::Object& pyobj, const Py::Object& value) const;
void del(const Expression* owner, Py::Object& pyobj) const;
};
////////////////////////////////////////////////////////////////////////////////////
/**
* Part of an expressions that contains a unit.
*
*/
* Part of an expressions that contains a unit.
*
*/
class AppExport UnitExpression : public Expression {
class AppExport UnitExpression: public Expression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit UnitExpression(const App::DocumentObject *_owner = nullptr, const Base::Quantity & _quantity = Base::Quantity(), const std::string & _unitStr = std::string());
explicit UnitExpression(const App::DocumentObject* _owner = nullptr,
const Base::Quantity& _quantity = Base::Quantity(),
const std::string& _unitStr = std::string());
~UnitExpression() override;
Expression * simplify() const override;
Expression* simplify() const override;
void setUnit(const Base::Quantity &_quantity);
void setUnit(const Base::Quantity& _quantity);
void setQuantity(const Base::Quantity &_quantity);
void setQuantity(const Base::Quantity& _quantity);
double getValue() const { return quantity.getValue(); }
double getValue() const
{
return quantity.getValue();
}
const Base::Unit & getUnit() const { return quantity.getUnit(); }
const Base::Unit& getUnit() const
{
return quantity.getUnit();
}
const Base::Quantity & getQuantity() const { return quantity; }
const Base::Quantity& getQuantity() const
{
return quantity;
}
const std::string getUnitString() const { return unitStr; }
const std::string getUnitString() const
{
return unitStr;
}
double getScaler() const { return quantity.getValue(); }
double getScaler() const
{
return quantity.getValue();
}
protected:
Expression * _copy() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
Expression* _copy() const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
Py::Object _getPyValue() const override;
protected:
mutable PyObject *cache = nullptr;
mutable PyObject* cache = nullptr;
private:
Base::Quantity quantity;
@@ -107,54 +128,65 @@ private:
};
/**
* Class implementing a number with an optional unit
*/
* Class implementing a number with an optional unit
*/
class AppExport NumberExpression : public UnitExpression {
class AppExport NumberExpression: public UnitExpression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit NumberExpression(const App::DocumentObject *_owner = nullptr, const Base::Quantity & quantity = Base::Quantity());
Expression * simplify() const override;
public:
explicit NumberExpression(const App::DocumentObject* _owner = nullptr,
const Base::Quantity& quantity = Base::Quantity());
Expression* simplify() const override;
void negate();
bool isInteger(long *v=nullptr) const;
bool isInteger(long* v = nullptr) const;
protected:
Expression * _copy() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
Expression* _copy() const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
};
class AppExport ConstantExpression : public NumberExpression {
class AppExport ConstantExpression: public NumberExpression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit ConstantExpression(const App::DocumentObject *_owner = nullptr,
const char *_name = "",
const Base::Quantity &_quantity = Base::Quantity());
std::string getName() const { return name; }
public:
explicit ConstantExpression(const App::DocumentObject* _owner = nullptr,
const char* _name = "",
const Base::Quantity& _quantity = Base::Quantity());
std::string getName() const
{
return name;
}
bool isNumber() const;
protected:
Py::Object _getPyValue() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
Expression* _copy() const override;
protected:
const char *name;
const char* name;
};
/**
* Class implementing an infix expression.
*
*/
* Class implementing an infix expression.
*
*/
class AppExport OperatorExpression : public UnitExpression {
class AppExport OperatorExpression: public UnitExpression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
enum Operator {
enum Operator
{
NONE,
ADD,
SUB,
@@ -172,30 +204,42 @@ public:
NEG,
POS
};
explicit OperatorExpression(const App::DocumentObject *_owner = nullptr, Expression * _left = nullptr, Operator _op = NONE, Expression * _right = nullptr);
explicit OperatorExpression(const App::DocumentObject* _owner = nullptr,
Expression* _left = nullptr,
Operator _op = NONE,
Expression* _right = nullptr);
~OperatorExpression() override;
bool isTouched() const override;
Expression * simplify() const override;
Expression* simplify() const override;
int priority() const override;
Operator getOperator() const { return op; }
Operator getOperator() const
{
return op;
}
Expression * getLeft() const { return left; }
Expression* getLeft() const
{
return left;
}
Expression * getRight() const { return right; }
Expression* getRight() const
{
return right;
}
protected:
Expression * _copy() const override;
Expression* _copy() const override;
Py::Object _getPyValue() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
void _visit(ExpressionVisitor & v) override;
void _visit(ExpressionVisitor& v) override;
virtual bool isCommutative() const;
@@ -203,46 +247,53 @@ protected:
virtual bool isRightAssociative() const;
Operator op; /**< Operator working on left and right */
Expression * left; /**< Left operand */
Expression * right; /**< Right operand */
Operator op; /**< Operator working on left and right */
Expression* left; /**< Left operand */
Expression* right; /**< Right operand */
};
class AppExport ConditionalExpression : public Expression {
class AppExport ConditionalExpression: public Expression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit ConditionalExpression(const App::DocumentObject *_owner = nullptr, Expression * _condition = nullptr,Expression * _trueExpr = nullptr, Expression * _falseExpr = nullptr);
explicit ConditionalExpression(const App::DocumentObject* _owner = nullptr,
Expression* _condition = nullptr,
Expression* _trueExpr = nullptr,
Expression* _falseExpr = nullptr);
~ConditionalExpression() override;
bool isTouched() const override;
Expression * simplify() const override;
Expression* simplify() const override;
int priority() const override;
protected:
Expression * _copy() const override;
void _visit(ExpressionVisitor & v) override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
Expression* _copy() const override;
void _visit(ExpressionVisitor& v) override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
Py::Object _getPyValue() const override;
protected:
Expression * condition; /**< Condition */
Expression * trueExpr; /**< Expression if abs(condition) is > 0.5 */
Expression * falseExpr; /**< Expression if abs(condition) is < 0.5 */
Expression* condition; /**< Condition */
Expression* trueExpr; /**< Expression if abs(condition) is > 0.5 */
Expression* falseExpr; /**< Expression if abs(condition) is < 0.5 */
};
/**
* Class implementing various functions, e.g sin, cos, etc.
*
*/
* Class implementing various functions, e.g sin, cos, etc.
*
*/
class AppExport FunctionExpression : public UnitExpression {
class AppExport FunctionExpression: public UnitExpression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
enum Function {
enum Function
{
NONE,
// Normal functions taking one or two arguments
@@ -287,31 +338,32 @@ public:
VSCALEZ,
// Matrix
MINVERT, // invert matrix/placement/rotation
MROTATE, // Rotate matrix/placement/rotation around axis, by rotation object, or by euler angles.
MROTATEX, // Rotate matrix/placement/rotation around x-axis.
MROTATEY, // Rotate matrix/placement/rotation around y-axis.
MROTATEZ, // Rotate matrix/placement/rotation around z-axis.
MSCALE, // matrix scale by vector
MTRANSLATE, // Translate matrix/placement.
MINVERT, // invert matrix/placement/rotation
MROTATE, // Rotate matrix/placement/rotation around axis, by rotation object, or by euler
// angles.
MROTATEX, // Rotate matrix/placement/rotation around x-axis.
MROTATEY, // Rotate matrix/placement/rotation around y-axis.
MROTATEZ, // Rotate matrix/placement/rotation around z-axis.
MSCALE, // matrix scale by vector
MTRANSLATE, // Translate matrix/placement.
// Object creation
CREATE, // Create new object of a given type.
LIST, // Create Python list.
MATRIX, // Create matrix object.
PLACEMENT, // Create placement object.
ROTATION, // Create rotation object.
ROTATIONX, // Create x-axis rotation object.
ROTATIONY, // Create y-axis rotation object.
ROTATIONZ, // Create z-axis rotation object.
STR, // stringify
PARSEQUANT, // parse string quantity
TRANSLATIONM, // Create translation matrix object.
TUPLE, // Create Python tuple.
VECTOR, // Create vector object.
CREATE, // Create new object of a given type.
LIST, // Create Python list.
MATRIX, // Create matrix object.
PLACEMENT, // Create placement object.
ROTATION, // Create rotation object.
ROTATIONX, // Create x-axis rotation object.
ROTATIONY, // Create y-axis rotation object.
ROTATIONZ, // Create z-axis rotation object.
STR, // stringify
PARSEQUANT, // parse string quantity
TRANSLATIONM, // Create translation matrix object.
TUPLE, // Create Python tuple.
VECTOR, // Create vector object.
HIDDENREF, // hidden reference that has no dependency check
HREF, // deprecated alias of HIDDENREF
HIDDENREF, // hidden reference that has no dependency check
HREF, // deprecated alias of HIDDENREF
// Aggregates
AGGREGATES,
@@ -327,219 +379,273 @@ public:
LAST,
};
explicit FunctionExpression(const App::DocumentObject *_owner = nullptr, Function _f = NONE,
std::string &&name = std::string(), std::vector<Expression *> _args = std::vector<Expression*>());
explicit FunctionExpression(const App::DocumentObject* _owner = nullptr,
Function _f = NONE,
std::string&& name = std::string(),
std::vector<Expression*> _args = std::vector<Expression*>());
~FunctionExpression() override;
bool isTouched() const override;
Expression * simplify() const override;
Expression* simplify() const override;
static Py::Object evaluate(const Expression *owner, int type, const std::vector<Expression*> &args);
static Py::Object
evaluate(const Expression* owner, int type, const std::vector<Expression*>& args);
Function getFunction() const {return f;}
const std::vector<Expression*> &getArgs() const {return args;}
Function getFunction() const
{
return f;
}
const std::vector<Expression*>& getArgs() const
{
return args;
}
protected:
static Py::Object evalAggregate(const Expression *owner, int type, const std::vector<Expression*> &args);
static Base::Vector3d evaluateSecondVectorArgument(const Expression *expression, const std::vector<Expression*> &arguments);
static double extractLengthValueArgument(const Expression *expression, const std::vector<Expression*> &arguments, int argumentIndex);
static Base::Vector3d extractVectorArgument(const Expression *expression, const std::vector<Expression*> &arguments, int argumentIndex);
static void initialiseObject(const Py::Object *object, const std::vector<Expression*> &arguments, const unsigned long offset = 0);
static Py::Object transformFirstArgument(
const Expression *expression,
const std::vector<Expression*> &arguments,
const Base::Matrix4D *transformationMatrix);
static Py::Object
evalAggregate(const Expression* owner, int type, const std::vector<Expression*>& args);
static Base::Vector3d evaluateSecondVectorArgument(const Expression* expression,
const std::vector<Expression*>& arguments);
static double extractLengthValueArgument(const Expression* expression,
const std::vector<Expression*>& arguments,
int argumentIndex);
static Base::Vector3d extractVectorArgument(const Expression* expression,
const std::vector<Expression*>& arguments,
int argumentIndex);
static void initialiseObject(const Py::Object* object,
const std::vector<Expression*>& arguments,
const unsigned long offset = 0);
static Py::Object transformFirstArgument(const Expression* expression,
const std::vector<Expression*>& arguments,
const Base::Matrix4D* transformationMatrix);
static Py::Object translationMatrix(double x, double y, double z);
Py::Object _getPyValue() const override;
Expression * _copy() const override;
void _visit(ExpressionVisitor & v) override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
Expression* _copy() const override;
void _visit(ExpressionVisitor& v) override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
Function f; /**< Function to execute */
Function f; /**< Function to execute */
std::string fname;
std::vector<Expression *> args; /** Arguments to function*/
std::vector<Expression*> args; /** Arguments to function*/
};
/**
* Class implementing a reference to a property. If the name is unqualified,
* the owner of the expression is searched. If it is qualified, the document
* that contains the owning document object is searched for other document
* objects to search. Both labels and internal document names are searched.
*
*/
* Class implementing a reference to a property. If the name is unqualified,
* the owner of the expression is searched. If it is qualified, the document
* that contains the owning document object is searched for other document
* objects to search. Both labels and internal document names are searched.
*
*/
class AppExport VariableExpression : public UnitExpression {
class AppExport VariableExpression: public UnitExpression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit VariableExpression(const App::DocumentObject *_owner = nullptr, const ObjectIdentifier& _var = ObjectIdentifier());
explicit VariableExpression(const App::DocumentObject* _owner = nullptr,
const ObjectIdentifier& _var = ObjectIdentifier());
~VariableExpression() override;
bool isTouched() const override;
Expression * simplify() const override;
Expression* simplify() const override;
std::string name() const { return var.getPropertyName(); }
std::string name() const
{
return var.getPropertyName();
}
ObjectIdentifier getPath() const { return var; }
ObjectIdentifier getPath() const
{
return var;
}
void setPath(const ObjectIdentifier & path);
void setPath(const ObjectIdentifier& path);
const App::Property *getProperty() const;
const App::Property* getProperty() const;
void addComponent(Component* component) override;
protected:
Expression * _copy() const override;
Expression* _copy() const override;
Py::Object _getPyValue() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
bool _isIndexable() const override;
void _getIdentifiers(std::map<App::ObjectIdentifier,bool> &) const override;
bool _adjustLinks(const std::set<App::DocumentObject*> &, ExpressionVisitor &) override;
void _importSubNames(const ObjectIdentifier::SubNameMap &) override;
void _updateLabelReference(App::DocumentObject *, const std::string &, const char *) override;
bool _updateElementReference(App::DocumentObject *,bool,ExpressionVisitor &) override;
bool _relabeledDocument(const std::string &, const std::string &, ExpressionVisitor &) override;
bool _renameObjectIdentifier(const std::map<ObjectIdentifier,ObjectIdentifier> &,
const ObjectIdentifier &, ExpressionVisitor &) override;
void _collectReplacement(std::map<ObjectIdentifier,ObjectIdentifier> &,
const App::DocumentObject *parent, App::DocumentObject *oldObj,
App::DocumentObject *newObj) const override;
void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override;
void _offsetCells(int, int, ExpressionVisitor &) override;
void _getIdentifiers(std::map<App::ObjectIdentifier, bool>&) const override;
bool _adjustLinks(const std::set<App::DocumentObject*>&, ExpressionVisitor&) override;
void _importSubNames(const ObjectIdentifier::SubNameMap&) override;
void _updateLabelReference(App::DocumentObject*, const std::string&, const char*) override;
bool _updateElementReference(App::DocumentObject*, bool, ExpressionVisitor&) override;
bool _relabeledDocument(const std::string&, const std::string&, ExpressionVisitor&) override;
bool _renameObjectIdentifier(const std::map<ObjectIdentifier, ObjectIdentifier>&,
const ObjectIdentifier&,
ExpressionVisitor&) override;
void _collectReplacement(std::map<ObjectIdentifier, ObjectIdentifier>&,
const App::DocumentObject* parent,
App::DocumentObject* oldObj,
App::DocumentObject* newObj) const override;
void _moveCells(const CellAddress&, int, int, ExpressionVisitor&) override;
void _offsetCells(int, int, ExpressionVisitor&) override;
protected:
ObjectIdentifier var; /**< Variable name */
};
//////////////////////////////////////////////////////////////////////
class AppExport PyObjectExpression : public Expression {
class AppExport PyObjectExpression: public Expression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit PyObjectExpression(const App::DocumentObject *_owner=nullptr, PyObject *pyobj=nullptr, bool owned=false)
:Expression(_owner)
explicit PyObjectExpression(const App::DocumentObject* _owner = nullptr,
PyObject* pyobj = nullptr,
bool owned = false)
: Expression(_owner)
{
setPyValue(pyobj,owned);
setPyValue(pyobj, owned);
}
~PyObjectExpression() override;
void setPyValue(Py::Object pyobj);
void setPyValue(PyObject *pyobj, bool owned=false);
Expression * simplify() const override { return copy(); }
void setPyValue(PyObject* pyobj, bool owned = false);
Expression* simplify() const override
{
return copy();
}
protected:
Expression* _copy() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
Py::Object _getPyValue() const override;
protected:
PyObject *pyObj = nullptr;
PyObject* pyObj = nullptr;
};
/**
* Class implementing a string. Used to signal either a genuine string or
* a failed evaluation of an expression.
*/
* Class implementing a string. Used to signal either a genuine string or
* a failed evaluation of an expression.
*/
class AppExport StringExpression : public Expression {
class AppExport StringExpression: public Expression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit StringExpression(const App::DocumentObject *_owner = nullptr, const std::string & _text = std::string());
explicit StringExpression(const App::DocumentObject* _owner = nullptr,
const std::string& _text = std::string());
~StringExpression() override;
Expression * simplify() const override;
Expression* simplify() const override;
virtual std::string getText() const
{
return text;
}
virtual std::string getText() const { return text; }
protected:
Expression * _copy() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
Expression* _copy() const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
Py::Object _getPyValue() const override;
bool _isIndexable() const override { return true; }
bool _isIndexable() const override
{
return true;
}
private:
std::string text; /**< Text string */
mutable PyObject *cache = nullptr;
mutable PyObject* cache = nullptr;
};
class AppExport RangeExpression : public App::Expression {
class AppExport RangeExpression: public App::Expression
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
explicit RangeExpression(const App::DocumentObject * _owner = nullptr, const std::string & begin = std::string(), const std::string & end = std::string());
explicit RangeExpression(const App::DocumentObject* _owner = nullptr,
const std::string& begin = std::string(),
const std::string& end = std::string());
~RangeExpression() override = default;
bool isTouched() const override;
App::Expression * simplify() const override;
App::Expression* simplify() const override;
Range getRange() const;
protected:
Expression * _copy() const override;
void _toString(std::ostream &ss, bool persistent, int indent) const override;
Expression* _copy() const override;
void _toString(std::ostream& ss, bool persistent, int indent) const override;
Py::Object _getPyValue() const override;
void _getIdentifiers(std::map<App::ObjectIdentifier,bool> &) const override;
bool _renameObjectIdentifier(const std::map<ObjectIdentifier,ObjectIdentifier> &,
const ObjectIdentifier &, ExpressionVisitor &) override;
void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override;
void _offsetCells(int, int, ExpressionVisitor &) override;
void _getIdentifiers(std::map<App::ObjectIdentifier, bool>&) const override;
bool _renameObjectIdentifier(const std::map<ObjectIdentifier, ObjectIdentifier>&,
const ObjectIdentifier&,
ExpressionVisitor&) override;
void _moveCells(const CellAddress&, int, int, ExpressionVisitor&) override;
void _offsetCells(int, int, ExpressionVisitor&) override;
protected:
std::string begin;
std::string end;
};
namespace ExpressionParser {
AppExport Expression * parse(const App::DocumentObject *owner, const char *buffer);
AppExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer);
AppExport ObjectIdentifier parsePath(const App::DocumentObject *owner, const char* buffer);
AppExport bool isTokenAnIndentifier(const std::string & str);
AppExport bool isTokenAConstant(const std::string & str);
AppExport bool isTokenAUnit(const std::string & str);
AppExport std::vector<std::tuple<int, int, std::string> > tokenize(const std::string & str);
namespace ExpressionParser
{
AppExport Expression* parse(const App::DocumentObject* owner, const char* buffer);
AppExport UnitExpression* parseUnit(const App::DocumentObject* owner, const char* buffer);
AppExport ObjectIdentifier parsePath(const App::DocumentObject* owner, const char* buffer);
AppExport bool isTokenAnIndentifier(const std::string& str);
AppExport bool isTokenAConstant(const std::string& str);
AppExport bool isTokenAUnit(const std::string& str);
AppExport std::vector<std::tuple<int, int, std::string>> tokenize(const std::string& str);
/// Convenient class to mark begin of importing
class AppExport ExpressionImporter {
class AppExport ExpressionImporter
{
public:
explicit ExpressionImporter(Base::XMLReader &reader);
explicit ExpressionImporter(Base::XMLReader& reader);
~ExpressionImporter();
static Base::XMLReader *reader();
static Base::XMLReader* reader();
};
AppExport bool isModuleImported(PyObject *);
AppExport bool isModuleImported(PyObject*);
/**
* @brief The semantic_type class encapsulates the value in the parse tree during parsing.
*/
class semantic_type {
class semantic_type
{
public:
struct {
Base::Quantity scaler;
std::string unitStr;
} quantity;
Expression::Component *component{nullptr};
Expression * expr{nullptr};
ObjectIdentifier path;
std::deque<ObjectIdentifier::Component> components;
long long int ivalue{0};
double fvalue{0};
struct {
const char *name = "";
double fvalue = 0;
} constant;
std::vector<Expression*> arguments;
std::vector<Expression*> list;
std::string string;
std::pair<FunctionExpression::Function,std::string> func;
ObjectIdentifier::String string_or_identifier;
semantic_type() : func({FunctionExpression::NONE, std::string()}) {}
struct
{
Base::Quantity scaler;
std::string unitStr;
} quantity;
Expression::Component* component {nullptr};
Expression* expr {nullptr};
ObjectIdentifier path;
std::deque<ObjectIdentifier::Component> components;
long long int ivalue {0};
double fvalue {0};
struct
{
const char* name = "";
double fvalue = 0;
} constant;
std::vector<Expression*> arguments;
std::vector<Expression*> list;
std::string string;
std::pair<FunctionExpression::Function, std::string> func;
ObjectIdentifier::String string_or_identifier;
semantic_type()
: func({FunctionExpression::NONE, std::string()})
{}
};
#define YYSTYPE semantic_type
@@ -547,8 +653,8 @@ public:
#undef YYTOKENTYPE
#undef YYSTYPE
#undef YYSTYPE_ISDECLARED
}
} // namespace ExpressionParser
}
} // namespace App
#endif //EXPRESSION_PARSER_H
#endif // EXPRESSION_PARSER_H
+27 -26
View File
@@ -44,16 +44,16 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos)
std::vector<std::tuple<int, int, std::string>> result =
ExpressionParser::tokenize(expr.toStdString());
std::vector<std::tuple<int, int, QString>> tokens;
std::transform(result.cbegin(),
result.cend(),
std::back_inserter(tokens),
[&](const std::tuple<int, int, std::string>& item) {
return std::make_tuple(
std::get<0>(item),
QString::fromStdString(expr.toStdString().substr(0, std::get<1>(item))).size(),
QString::fromStdString(std::get<2>(item))
);
});
std::transform(
result.cbegin(),
result.cend(),
std::back_inserter(tokens),
[&](const std::tuple<int, int, std::string>& item) {
return std::make_tuple(
std::get<0>(item),
QString::fromStdString(expr.toStdString().substr(0, std::get<1>(item))).size(),
QString::fromStdString(std::get<2>(item)));
});
return tokens;
};
@@ -63,7 +63,7 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos)
int start = (prefix.size() > 0 && prefix.at(0) == QChar::fromLatin1('=')) ? 1 : 0;
// Tokenize prefix
std::vector<std::tuple<int, int, QString> > tokens = tokenizeExpression(prefix.mid(start));
std::vector<std::tuple<int, int, QString>> tokens = tokenizeExpression(prefix.mid(start));
// No tokens
if (tokens.empty()) {
@@ -78,8 +78,9 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos)
if (std::get<1>(*it) >= pos) {
// Include the immediately followed '.' or '#', because we'll be
// inserting these separators too, in ExpressionCompleteModel::pathFromIndex()
if (it != tokens.begin() && std::get<0>(*it) != '.' && std::get<0>(*it) != '#')
if (it != tokens.begin() && std::get<0>(*it) != '.' && std::get<0>(*it) != '#') {
it = it - 1;
}
tokens.resize(it - tokens.begin() + 1);
prefixEnd = start + std::get<1>(*it) + (int)std::get<2>(*it).size();
break;
@@ -87,8 +88,9 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos)
}
int trim = 0;
if (prefixEnd > pos)
if (prefixEnd > pos) {
trim = prefixEnd - pos;
}
// Extract last tokens that can be rebuilt to a variable
long i = static_cast<long>(tokens.size()) - 1;
@@ -111,9 +113,8 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos)
}
// Not an unclosed string and the last character is a space
if (!stringing && !prefix.isEmpty() &&
prefixEnd > 0 && prefixEnd <= prefix.size() &&
prefix[prefixEnd-1] == QChar(32)) {
if (!stringing && !prefix.isEmpty() && prefixEnd > 0 && prefixEnd <= prefix.size()
&& prefix[prefixEnd - 1] == QChar(32)) {
return {};
}
@@ -121,23 +122,22 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos)
i = static_cast<long>(tokens.size()) - 1;
for (; i >= 0; --i) {
int token = std::get<0>(tokens[i]);
if (token != '.' &&
token != '#' &&
token != ExpressionParser::IDENTIFIER &&
token != ExpressionParser::INTEGER &&
token != ExpressionParser::STRING &&
token != ExpressionParser::UNIT &&
token != ExpressionParser::ONE)
if (token != '.' && token != '#' && token != ExpressionParser::IDENTIFIER
&& token != ExpressionParser::INTEGER && token != ExpressionParser::STRING
&& token != ExpressionParser::UNIT && token != ExpressionParser::ONE) {
break;
}
}
++i;
}
// Set prefix start for use when replacing later
if (i == static_cast<long>(tokens.size()))
if (i == static_cast<long>(tokens.size())) {
prefixStart = prefixEnd;
else
}
else {
prefixStart = start + std::get<1>(tokens[i]);
}
// Build prefix from tokens
while (i < static_cast<long>(tokens.size())) {
@@ -145,8 +145,9 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos)
++i;
}
if (trim && trim < int(completionPrefix.size()))
if (trim && trim < int(completionPrefix.size())) {
completionPrefix.resize(completionPrefix.size() - trim);
}
return completionPrefix;
}
+6 -4
View File
@@ -34,12 +34,14 @@ class AppExport ExpressionTokenizer
public:
QString perform(const QString& text, int pos);
void getPrefixRange(int &start, int &end) const {
void getPrefixRange(int& start, int& end) const
{
start = prefixStart;
end = prefixEnd;
}
void updatePrefixEnd(int end) {
void updatePrefixEnd(int end)
{
prefixEnd = end;
}
@@ -48,6 +50,6 @@ private:
int prefixEnd = 0;
};
}
} // namespace App
#endif //EXPRESSIONTOKENIZER_H
#endif // EXPRESSIONTOKENIZER_H
+63 -43
View File
@@ -25,48 +25,57 @@
#include "Expression.h"
namespace App {
namespace App
{
/**
* @brief The RenameObjectIdentifierExpressionVisitor class is a functor used to visit each node of an expression, and
* possibly rename VariableExpression nodes.
* @brief The RenameObjectIdentifierExpressionVisitor class is a functor used to visit each node of
* an expression, and possibly rename VariableExpression nodes.
*/
template<class P> class RenameObjectIdentifierExpressionVisitor : public ExpressionModifier<P> {
template<class P>
class RenameObjectIdentifierExpressionVisitor: public ExpressionModifier<P>
{
public:
RenameObjectIdentifierExpressionVisitor(
P &_prop,
const std::map<ObjectIdentifier, ObjectIdentifier> &_paths,
const ObjectIdentifier &_owner)
P& _prop,
const std::map<ObjectIdentifier, ObjectIdentifier>& _paths,
const ObjectIdentifier& _owner)
: ExpressionModifier<P>(_prop)
, paths( _paths )
, owner( _owner )
{
}
, paths(_paths)
, owner(_owner)
{}
void visit(Expression &node) override {
this->renameObjectIdentifier(node,paths,owner);
void visit(Expression& node) override
{
this->renameObjectIdentifier(node, paths, owner);
}
private:
const std::map<ObjectIdentifier, ObjectIdentifier> &paths; /**< Map with current and new object identifiers */
const ObjectIdentifier owner; /**< Owner of expression */
const std::map<ObjectIdentifier, ObjectIdentifier>&
paths; /**< Map with current and new object identifiers */
const ObjectIdentifier owner; /**< Owner of expression */
};
template<class P> class UpdateElementReferenceExpressionVisitor : public ExpressionModifier<P> {
template<class P>
class UpdateElementReferenceExpressionVisitor: public ExpressionModifier<P>
{
public:
explicit UpdateElementReferenceExpressionVisitor(P& _prop,
App::DocumentObject* feature = nullptr,
bool reverse = false)
: ExpressionModifier<P>(_prop)
, feature(feature)
, reverse(reverse)
{}
explicit UpdateElementReferenceExpressionVisitor(P & _prop, App::DocumentObject *feature=nullptr, bool reverse=false)
: ExpressionModifier<P>(_prop),feature(feature),reverse(reverse)
void visit(Expression& node) override
{
}
void visit(Expression &node) override {
this->updateElementReference(node,feature,reverse);
this->updateElementReference(node, feature, reverse);
}
private:
App::DocumentObject *feature;
App::DocumentObject* feature;
bool reverse;
};
@@ -74,30 +83,36 @@ private:
// ExpressionModifier, hence not calling aboutToSetValue/hasSetValue().
// By right, modification of document label should not change evaluation result
// of any expression.
class RelabelDocumentExpressionVisitor : public ExpressionVisitor {
class RelabelDocumentExpressionVisitor: public ExpressionVisitor
{
public:
explicit RelabelDocumentExpressionVisitor(const App::Document& doc)
: doc(doc)
{}
explicit RelabelDocumentExpressionVisitor(const App::Document &doc)
: doc(doc)
void visit(Expression& node) override
{
}
void visit(Expression &node) override {
this->relabeledDocument(node,doc.getOldLabel(),doc.Label.getStrValue());
this->relabeledDocument(node, doc.getOldLabel(), doc.Label.getStrValue());
}
private:
const App::Document &doc;
const App::Document& doc;
};
template<class P> class MoveCellsExpressionVisitor : public ExpressionModifier<P> {
template<class P>
class MoveCellsExpressionVisitor: public ExpressionModifier<P>
{
public:
MoveCellsExpressionVisitor(P &prop, const CellAddress &address, int rowCount, int colCount)
: ExpressionModifier<P>(prop),address(address),rowCount(rowCount),colCount(colCount)
MoveCellsExpressionVisitor(P& prop, const CellAddress& address, int rowCount, int colCount)
: ExpressionModifier<P>(prop)
, address(address)
, rowCount(rowCount)
, colCount(colCount)
{}
void visit(Expression &node) override {
this->moveCells(node,address,rowCount,colCount);
void visit(Expression& node) override
{
this->moveCells(node, address, rowCount, colCount);
}
private:
@@ -106,14 +121,19 @@ private:
int colCount;
};
template<class P> class OffsetCellsExpressionVisitor : public ExpressionModifier<P> {
template<class P>
class OffsetCellsExpressionVisitor: public ExpressionModifier<P>
{
public:
OffsetCellsExpressionVisitor(P &prop, int rowOffset, int colOffset)
: ExpressionModifier<P>(prop),rowOffset(rowOffset),colOffset(colOffset)
OffsetCellsExpressionVisitor(P& prop, int rowOffset, int colOffset)
: ExpressionModifier<P>(prop)
, rowOffset(rowOffset)
, colOffset(colOffset)
{}
void visit(Expression &node) override {
this->offsetCells(node,rowOffset,colOffset);
void visit(Expression& node) override
{
this->offsetCells(node, rowOffset, colOffset);
}
private:
@@ -121,6 +141,6 @@ private:
int colOffset;
};
}
} // namespace App
#endif // RENAMEOBJECTIDENTIFIEREXPRESSIONVISITOR_H
#endif // RENAMEOBJECTIDENTIFIEREXPRESSIONVISITOR_H
+118 -75
View File
@@ -38,8 +38,8 @@
#include "Range.h"
#ifdef _MSC_VER
#pragma warning( disable : 4700 )
#pragma warning( disable : 4723 )
#pragma warning(disable : 4700)
#pragma warning(disable : 4723)
#endif
using namespace App;
@@ -47,73 +47,106 @@ using namespace App;
PROPERTY_SOURCE(App::FeatureTest, App::DocumentObject)
const char* enums[]= {"Zero","One","Two","Three","Four",nullptr};
const PropertyIntegerConstraint::Constraints intPercent = {0,100,1};
const PropertyFloatConstraint::Constraints floatPercent = {0.0,100.0,1.0};
const char* enums[] = {"Zero", "One", "Two", "Three", "Four", nullptr};
const PropertyIntegerConstraint::Constraints intPercent = {0, 100, 1};
const PropertyFloatConstraint::Constraints floatPercent = {0.0, 100.0, 1.0};
FeatureTest::FeatureTest()
{
ADD_PROPERTY(Integer,(4711) );
ADD_PROPERTY(Float ,(47.11f) );
ADD_PROPERTY(Bool ,(true) );
ADD_PROPERTY(BoolList,(false));
ADD_PROPERTY(String ,("4711"));
ADD_PROPERTY(Path ,("c:\\temp"));
ADD_PROPERTY(StringList ,("4711"));
// clang-format off
ADD_PROPERTY(Integer, (4711));
ADD_PROPERTY(Float, (47.11f));
ADD_PROPERTY(Bool, (true));
ADD_PROPERTY(BoolList, (false));
ADD_PROPERTY(String, ("4711"));
ADD_PROPERTY(Path, ("c:\\temp"));
ADD_PROPERTY(StringList, ("4711"));
ADD_PROPERTY(Enum ,(4));
Enum.setEnums(enums);
ADD_PROPERTY(ConstraintInt ,(5));
ConstraintInt.setConstraints(&intPercent);
ADD_PROPERTY(ConstraintFloat ,(5.0));
ConstraintFloat.setConstraints(&floatPercent);
ADD_PROPERTY(Enum, (4));
Enum.setEnums(enums);
ADD_PROPERTY(ConstraintInt, (5));
ConstraintInt.setConstraints(&intPercent);
ADD_PROPERTY(ConstraintFloat, (5.0));
ConstraintFloat.setConstraints(&floatPercent);
App::Color c;
App::Material mat(App::Material::GOLD);
ADD_PROPERTY(Colour ,(c) );
ADD_PROPERTY(ColourList ,(c) );
ADD_PROPERTY(Material ,(mat));
ADD_PROPERTY(MaterialList,(mat));
App::Color c;
App::Material mat(App::Material::GOLD);
ADD_PROPERTY(Colour, (c));
ADD_PROPERTY(ColourList, (c));
ADD_PROPERTY(Material, (mat));
ADD_PROPERTY(MaterialList, (mat));
ADD_PROPERTY(Distance,(47.11f) );
ADD_PROPERTY(Angle ,(3.0f) );
ADD_PROPERTY(Distance, (47.11f));
ADD_PROPERTY(Angle, (3.0f));
ADD_PROPERTY(IntegerList,(4711) );
ADD_PROPERTY(FloatList ,(47.11f) );
ADD_PROPERTY(IntegerList, (4711));
ADD_PROPERTY(FloatList, (47.11f));
ADD_PROPERTY(Link ,(nullptr));
ADD_PROPERTY(LinkSub ,(nullptr));
ADD_PROPERTY(LinkList ,(nullptr));
ADD_PROPERTY(LinkSubList,(nullptr));
ADD_PROPERTY(Link, (nullptr));
ADD_PROPERTY(LinkSub, (nullptr));
ADD_PROPERTY(LinkList, (nullptr));
ADD_PROPERTY(LinkSubList, (nullptr));
ADD_PROPERTY(Vector ,(1.0,2.0,3.0));
ADD_PROPERTY(VectorList,(3.0,2.0,1.0));
ADD_PROPERTY(Matrix ,(Base::Matrix4D(1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0)));
ADD_PROPERTY(Placement ,(Base::Placement()));
ADD_PROPERTY(Vector, (1.0, 2.0, 3.0));
ADD_PROPERTY(VectorList, (3.0, 2.0, 1.0));
ADD_PROPERTY(Matrix,
(Base::Matrix4D( 1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0,
13.0, 14.0, 15.0, 16.0)));
ADD_PROPERTY(Placement, (Base::Placement()));
// properties for recompute testing
static const char* group = "Feature Test";
ADD_PROPERTY_TYPE(Source1 ,(nullptr),group,Prop_None,"Source for testing links");
ADD_PROPERTY_TYPE(Source2 ,(nullptr),group,Prop_None,"Source for testing links");
ADD_PROPERTY_TYPE(SourceN ,(nullptr),group,Prop_None,"Source for testing links");
ADD_PROPERTY_TYPE(ExecResult ,("empty"),group,Prop_None,"Result of the execution");
ADD_PROPERTY_TYPE(ExceptionType ,(0),group,Prop_None,"The type of exception the execution method throws");
ADD_PROPERTY_TYPE(ExecCount ,(0),group,Prop_None,"Number of executions");
// properties for recompute testing
static const char* group = "Feature Test";
ADD_PROPERTY_TYPE(Source1, (nullptr), group, Prop_None, "Source for testing links");
ADD_PROPERTY_TYPE(Source2, (nullptr), group, Prop_None, "Source for testing links");
ADD_PROPERTY_TYPE(SourceN, (nullptr), group, Prop_None, "Source for testing links");
ADD_PROPERTY_TYPE(ExecResult, ("empty"), group, Prop_None, "Result of the execution");
ADD_PROPERTY_TYPE(ExceptionType,
(0),
group,
Prop_None,
"The type of exception the execution method throws");
ADD_PROPERTY_TYPE(ExecCount, (0), group, Prop_None, "Number of executions");
// properties with types
ADD_PROPERTY_TYPE(TypeHidden ,(4711),group,Prop_Hidden,"An example property which has the type 'Hidden'" );
ADD_PROPERTY_TYPE(TypeReadOnly,(4711),group,Prop_ReadOnly ,"An example property which has the type 'ReadOnly'" );
ADD_PROPERTY_TYPE(TypeOutput ,(4711),group,Prop_Output ,"An example property which has the type 'Output'" );
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'");
// properties with types
ADD_PROPERTY_TYPE(TypeHidden,
(4711),
group,
Prop_Hidden,
"An example property which has the type 'Hidden'");
ADD_PROPERTY_TYPE(TypeReadOnly,
(4711),
group,
Prop_ReadOnly,
"An example property which has the type 'ReadOnly'");
ADD_PROPERTY_TYPE(TypeOutput,
(4711),
group,
Prop_Output,
"An example property which has the type 'Output'");
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'");
ADD_PROPERTY(QuantityLength,(1.0));
QuantityLength.setUnit(Base::Unit::Length);
ADD_PROPERTY(QuantityOther,(5.0));
QuantityOther.setUnit(Base::Unit(-3,1));
ADD_PROPERTY(QuantityLength, (1.0));
QuantityLength.setUnit(Base::Unit::Length);
ADD_PROPERTY(QuantityOther, (5.0));
QuantityOther.setUnit(Base::Unit(-3, 1));
// clang-format on
}
FeatureTest::~FeatureTest() = default;
@@ -123,7 +156,7 @@ short FeatureTest::mustExecute() const
return DocumentObject::mustExecute();
}
DocumentObjectExecReturn *FeatureTest::execute()
DocumentObjectExecReturn* FeatureTest::execute()
{
// Enum handling
Enumeration enumObj1 = Enum.getEnum();
@@ -159,19 +192,27 @@ DocumentObjectExecReturn *FeatureTest::execute()
enumObj6.setEnums(list);
enumObj6.setValue(list.back());
int *i=nullptr,j;
int *i = nullptr, j;
float f;
void *s;
void* s;
std::string t;
// Code analyzers may complain about some errors. This can be ignored
// because this is done on purpose to test the error handling mechanism
switch(ExceptionType.getValue())
{
case 0: break;
case 1: throw std::runtime_error("Test Exception");
case 2: throw Base::RuntimeError("FeatureTestException::execute(): Testexception");
default: (void)i; (void)j; (void)f; (void)s; (void)t; break;
switch (ExceptionType.getValue()) {
case 0:
break;
case 1:
throw std::runtime_error("Test Exception");
case 2:
throw Base::RuntimeError("FeatureTestException::execute(): Testexception");
default:
(void)i;
(void)j;
(void)f;
(void)s;
(void)t;
break;
}
ExecCount.setValue(ExecCount.getValue() + 1);
@@ -188,12 +229,12 @@ PROPERTY_SOURCE(App::FeatureTestException, App::FeatureTest)
FeatureTestException::FeatureTestException()
{
ADD_PROPERTY(ExceptionType,(Base::Exception::getClassTypeId().getKey()) );
ADD_PROPERTY(ExceptionType, (Base::Exception::getClassTypeId().getKey()));
}
DocumentObjectExecReturn *FeatureTestException::execute()
DocumentObjectExecReturn* FeatureTestException::execute()
{
//ExceptionType;
// ExceptionType;
throw Base::RuntimeError("FeatureTestException::execute(): Testexception ;-)");
return nullptr;
@@ -211,7 +252,7 @@ FeatureTestColumn::FeatureTestColumn()
ADD_PROPERTY_TYPE(Value, (0L), "Test", App::Prop_Output, "");
}
DocumentObjectExecReturn *FeatureTestColumn::execute()
DocumentObjectExecReturn* FeatureTestColumn::execute()
{
Value.setValue(decodeColumn(Column.getStrValue(), Silent.getValue()));
return nullptr;
@@ -229,7 +270,7 @@ FeatureTestRow::FeatureTestRow()
ADD_PROPERTY_TYPE(Value, (0L), "Test", App::Prop_Output, "");
}
DocumentObjectExecReturn *FeatureTestRow::execute()
DocumentObjectExecReturn* FeatureTestRow::execute()
{
Value.setValue(decodeRow(Row.getStrValue(), Silent.getValue()));
return nullptr;
@@ -246,7 +287,7 @@ FeatureTestAbsAddress::FeatureTestAbsAddress()
ADD_PROPERTY_TYPE(Valid, (false), "Test", PropertyType(Prop_Output | Prop_ReadOnly), "");
}
DocumentObjectExecReturn *FeatureTestAbsAddress::execute()
DocumentObjectExecReturn* FeatureTestAbsAddress::execute()
{
CellAddress address;
Valid.setValue(address.parseAbsoluteAddress(Address.getValue()));
@@ -266,7 +307,7 @@ FeatureTestPlacement::FeatureTestPlacement()
ADD_PROPERTY_TYPE(MultRight, (Base::Placement()), "Test", Prop_Output, "");
}
DocumentObjectExecReturn *FeatureTestPlacement::execute()
DocumentObjectExecReturn* FeatureTestPlacement::execute()
{
Base::Placement p1 = Input1.getValue();
Base::Placement q1 = Input1.getValue();
@@ -295,8 +336,9 @@ FeatureTestAttribute::~FeatureTestAttribute()
#if PYCXX_VERSION_MAJOR >= 7
Py::ifPyErrorThrowCxxException();
#else
if (PyErr_Occurred())
if (PyErr_Occurred()) {
throw Py::RuntimeError();
}
#endif
}
catch (Py::RuntimeError& e) {
@@ -308,7 +350,7 @@ FeatureTestAttribute::~FeatureTestAttribute()
}
}
DocumentObjectExecReturn *FeatureTestAttribute::execute()
DocumentObjectExecReturn* FeatureTestAttribute::execute()
{
Base::PyGILStateLocker lock;
try {
@@ -316,8 +358,9 @@ DocumentObjectExecReturn *FeatureTestAttribute::execute()
#if PYCXX_VERSION_MAJOR >= 7
Py::ifPyErrorThrowCxxException();
#else
if (PyErr_Occurred())
if (PyErr_Occurred()) {
throw Py::AttributeError();
}
#endif
}
catch (Py::AttributeError& e) {
+94 -91
View File
@@ -35,107 +35,110 @@ namespace App
{
/// The testing feature
class FeatureTest : public DocumentObject
class FeatureTest: public DocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTest);
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTest);
public:
FeatureTest();
FeatureTest();
~FeatureTest() override;
~FeatureTest() override;
// Standard Properties (PropertyStandard.h)
App::PropertyInteger Integer;
App::PropertyFloat Float;
App::PropertyBool Bool;
App::PropertyBoolList BoolList;
App::PropertyString String;
App::PropertyPath Path;
App::PropertyStringList StringList;
// Standard Properties (PropertyStandard.h)
App::PropertyInteger Integer;
App::PropertyFloat Float;
App::PropertyBool Bool;
App::PropertyBoolList BoolList;
App::PropertyString String;
App::PropertyPath Path;
App::PropertyStringList StringList;
App::PropertyColor Colour;
App::PropertyColorList ColourList;
App::PropertyMaterial Material;
App::PropertyMaterialList MaterialList;
App::PropertyColor Colour;
App::PropertyColorList ColourList;
App::PropertyMaterial Material;
App::PropertyMaterialList MaterialList;
// special types
App::PropertyDistance Distance;
App::PropertyAngle Angle;
// special types
App::PropertyDistance Distance;
App::PropertyAngle Angle;
// Constraint types
App::PropertyEnumeration Enum;
App::PropertyIntegerConstraint ConstraintInt;
App::PropertyFloatConstraint ConstraintFloat;
// Constraint types
App::PropertyEnumeration Enum;
App::PropertyIntegerConstraint ConstraintInt;
App::PropertyFloatConstraint ConstraintFloat;
// Standard Properties (PrppertyStandard.h)
App::PropertyIntegerList IntegerList;
App::PropertyFloatList FloatList;
// Standard Properties (PrppertyStandard.h)
App::PropertyIntegerList IntegerList;
App::PropertyFloatList FloatList;
// Standard Properties (PropertyLinks.h)
App::PropertyLink Link;
App::PropertyLinkSub LinkSub;
App::PropertyLinkList LinkList;
App::PropertyLinkSubList LinkSubList;
// Standard Properties (PropertyLinks.h)
App::PropertyLink Link;
App::PropertyLinkSub LinkSub;
App::PropertyLinkList LinkList;
App::PropertyLinkSubList LinkSubList;
// Standard Properties (PropertyGeo.h)
App::PropertyMatrix Matrix;
App::PropertyVector Vector;
App::PropertyVectorList VectorList;
App::PropertyPlacement Placement;
// Standard Properties (PropertyGeo.h)
App::PropertyMatrix Matrix;
App::PropertyVector Vector;
App::PropertyVectorList VectorList;
App::PropertyPlacement Placement;
// Properties to test the Document::recompute()
App::PropertyLink Source1;
App::PropertyLink Source2;
App::PropertyLinkList SourceN;
App::PropertyString ExecResult;
App::PropertyInteger ExceptionType;
App::PropertyInteger ExecCount;
// Properties to test the Document::recompute()
App::PropertyLink Source1;
App::PropertyLink Source2;
App::PropertyLinkList SourceN;
App::PropertyString ExecResult;
App::PropertyInteger ExceptionType;
App::PropertyInteger ExecCount;
App::PropertyInteger TypeHidden;
App::PropertyInteger TypeReadOnly;
App::PropertyInteger TypeOutput;
App::PropertyInteger TypeAll;
App::PropertyInteger TypeTransient;
App::PropertyInteger TypeNoRecompute;
App::PropertyInteger TypeHidden;
App::PropertyInteger TypeReadOnly;
App::PropertyInteger TypeOutput;
App::PropertyInteger TypeAll;
App::PropertyInteger TypeTransient;
App::PropertyInteger TypeNoRecompute;
App::PropertyQuantity QuantityLength;
App::PropertyQuantity QuantityOther;
//App::PropertyQuantity QuantityMass;
//App::PropertyQuantity QuantityAngle;
App::PropertyQuantity QuantityLength;
App::PropertyQuantity QuantityOther;
// App::PropertyQuantity QuantityMass;
// App::PropertyQuantity QuantityAngle;
/** @name methods override Feature */
//@{
short mustExecute() const override;
/// recalculate the Feature
DocumentObjectExecReturn *execute() override;
/// returns the type name of the ViewProvider
//Hint: Probably it makes sense to have a view provider for unittests (e.g. Gui::ViewProviderTest)
const char* getViewProviderName() const override {
return "Gui::ViewProviderFeature";
}
//@}
/** @name methods override Feature */
//@{
short mustExecute() const override;
/// recalculate the Feature
DocumentObjectExecReturn* execute() override;
/// returns the type name of the ViewProvider
// Hint: Probably it makes sense to have a view provider for unittests (e.g.
// Gui::ViewProviderTest)
const char* getViewProviderName() const override
{
return "Gui::ViewProviderFeature";
}
//@}
};
/// The exception testing feature
class FeatureTestException :public FeatureTest
class FeatureTestException: public FeatureTest
{
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestException);
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestException);
public:
FeatureTestException();
FeatureTestException();
/// this property defines which kind of exceptio the feature throw on you
App::PropertyInteger ExceptionType;
/// this property defines which kind of exceptio the feature throw on you
App::PropertyInteger ExceptionType;
/// recalculate the Feature and throw an exception
DocumentObjectExecReturn *execute() override;
/// returns the type name of the ViewProvider
const char* getViewProviderName() const override {
return "Gui::ViewProviderFeature";
}
/// recalculate the Feature and throw an exception
DocumentObjectExecReturn* execute() override;
/// returns the type name of the ViewProvider
const char* getViewProviderName() const override
{
return "Gui::ViewProviderFeature";
}
};
class FeatureTestColumn : public DocumentObject
class FeatureTestColumn: public DocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestColumn);
@@ -143,17 +146,17 @@ public:
FeatureTestColumn();
// Standard Properties (PropertyStandard.h)
App::PropertyString Column;
App::PropertyBool Silent;
App::PropertyString Column;
App::PropertyBool Silent;
App::PropertyInteger Value;
/** @name methods override Feature */
//@{
DocumentObjectExecReturn *execute() override;
DocumentObjectExecReturn* execute() override;
//@}
};
class FeatureTestRow : public DocumentObject
class FeatureTestRow: public DocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestRow);
@@ -161,29 +164,29 @@ public:
FeatureTestRow();
// Standard Properties (PropertyStandard.h)
App::PropertyString Row;
App::PropertyBool Silent;
App::PropertyString Row;
App::PropertyBool Silent;
App::PropertyInteger Value;
/** @name methods override Feature */
//@{
DocumentObjectExecReturn *execute() override;
DocumentObjectExecReturn* execute() override;
//@}
};
class FeatureTestAbsAddress : public DocumentObject
class FeatureTestAbsAddress: public DocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestAbsAddress);
public:
FeatureTestAbsAddress();
DocumentObjectExecReturn *execute() override;
DocumentObjectExecReturn* execute() override;
App::PropertyString Address;
App::PropertyBool Valid;
};
class FeatureTestPlacement : public DocumentObject
class FeatureTestPlacement: public DocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestPlacement);
@@ -198,24 +201,24 @@ public:
/** @name methods override Feature */
//@{
DocumentObjectExecReturn *execute() override;
DocumentObjectExecReturn* execute() override;
//@}
};
class FeatureTestAttribute : public DocumentObject
class FeatureTestAttribute: public DocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestAttribute);
public:
FeatureTestAttribute();
~FeatureTestAttribute() override;
DocumentObjectExecReturn *execute() override;
DocumentObjectExecReturn* execute() override;
App::PropertyPythonObject Object;
App::PropertyString Attribute;
};
} //namespace App
} // namespace App
#endif // APP_FEATURETEST_H
#endif // APP_FEATURETEST_H
+62 -43
View File
@@ -47,12 +47,12 @@ PROPERTY_SOURCE(App::GeoFeature, App::DocumentObject)
GeoFeature::GeoFeature()
{
ADD_PROPERTY_TYPE(Placement,(Base::Placement()),nullptr,Prop_NoRecompute,nullptr);
ADD_PROPERTY_TYPE(Placement, (Base::Placement()), nullptr, Prop_NoRecompute, nullptr);
}
GeoFeature::~GeoFeature() = default;
void GeoFeature::transformPlacement(const Base::Placement &transform)
void GeoFeature::transformPlacement(const Base::Placement& transform)
{
Base::Placement plm = this->Placement.getValue();
plm = transform * plm;
@@ -66,7 +66,7 @@ Base::Placement GeoFeature::globalPlacement() const
auto ext = group->getExtensionByType<GeoFeatureGroupExtension>();
return ext->globalGroupPlacement() * Placement.getValue();
}
return Placement.getValue();
return Placement.getValue();
}
const PropertyComplexGeoData* GeoFeature::getPropertyOfGeometry() const
@@ -78,22 +78,22 @@ PyObject* GeoFeature::getPyObject()
{
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new GeoFeaturePy(this),true);
PythonObject = Py::Object(new GeoFeaturePy(this), true);
}
return Py::new_reference_to(PythonObject);
}
ElementNamePair
GeoFeature::getElementName(const char *name, ElementNameType type) const
ElementNamePair GeoFeature::getElementName(const char* name, ElementNameType type) const
{
(void)type;
if(!name)
if (!name) {
return {};
}
auto prop = getPropertyOfGeometry();
if (!prop) {
return ElementNamePair("",name);
return ElementNamePair("", name);
}
auto geo = prop->getComplexData();
@@ -104,8 +104,8 @@ GeoFeature::getElementName(const char *name, ElementNameType type) const
return _getElementName(name, geo->getElementName(name));
}
ElementNamePair
GeoFeature::_getElementName(const char* name, const Data::MappedElement& mapped) const
ElementNamePair GeoFeature::_getElementName(const char* name,
const Data::MappedElement& mapped) const
{
ElementNamePair ret;
if (mapped.index && mapped.name) {
@@ -123,9 +123,9 @@ GeoFeature::_getElementName(const char* name, const Data::MappedElement& mapped)
// missing reference
std::ostringstream ss;
ss << Data::MISSING_PREFIX << dot + 1;
return ElementNamePair(name, ss.str().c_str() );
return ElementNamePair(name, ss.str().c_str());
}
return ElementNamePair(name,"");
return ElementNamePair(name, "");
}
else {
std::string oldName;
@@ -134,53 +134,70 @@ GeoFeature::_getElementName(const char* name, const Data::MappedElement& mapped)
}
}
DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subname,
ElementNamePair &elementName, bool append,
ElementNameType type, const DocumentObject *filter,
const char **_element, GeoFeature **geoFeature)
DocumentObject* GeoFeature::resolveElement(DocumentObject* obj,
const char* subname,
ElementNamePair& elementName,
bool append,
ElementNameType type,
const DocumentObject* filter,
const char** _element,
GeoFeature** geoFeature)
{
elementName.newName.clear();
elementName.oldName.clear();
if(!obj || !obj->isAttachedToDocument())
if (!obj || !obj->isAttachedToDocument()) {
return nullptr;
if(!subname)
}
if (!subname) {
subname = "";
const char *element = Data::findElementName(subname);
if(_element) *_element = element;
}
const char* element = Data::findElementName(subname);
if (_element) {
*_element = element;
}
auto sobj = obj->getSubObject(std::string(subname, element).c_str());
if(!sobj)
if (!sobj) {
return nullptr;
}
auto linked = sobj->getLinkedObject(true);
auto geo = Base::freecad_dynamic_cast<GeoFeature>(linked);
if(!geo && linked) {
if (!geo && linked) {
auto ext = linked->getExtensionByType<LinkBaseExtension>(true);
if(ext)
if (ext) {
geo = Base::freecad_dynamic_cast<GeoFeature>(ext->getTrueLinkedObject(true));
}
}
if(geoFeature)
if (geoFeature) {
*geoFeature = geo;
if(filter && geo!=filter)
}
if (filter && geo != filter) {
return nullptr;
if(!element || !element[0]) {
if(append)
}
if (!element || !element[0]) {
if (append) {
elementName.oldName = Data::oldElementName(subname);
}
return sobj;
}
if(!geo || hasHiddenMarker(element)) {
if(!append)
if (!geo || hasHiddenMarker(element)) {
if (!append) {
elementName.oldName = element;
else
}
else {
elementName.oldName = Data::oldElementName(subname);
}
return sobj;
}
if(!append)
elementName = geo->getElementName(element,type);
else{
const auto &names = geo->getElementName(element,type);
std::string prefix(subname,element-subname);
if(!names.newName.empty())
if (!append) {
elementName = geo->getElementName(element, type);
}
else {
const auto& names = geo->getElementName(element, type);
std::string prefix(subname, element - subname);
if (!names.newName.empty()) {
elementName.newName = prefix + names.newName;
}
elementName.oldName = prefix + names.oldName;
}
return sobj;
@@ -264,12 +281,12 @@ std::vector<const char*> GeoFeature::getElementTypes(bool /*all*/) const
return prop->getComplexData()->getElementTypes();
}
std::vector<Data::IndexedName>
GeoFeature::getHigherElements(const char *element, bool silent) const
std::vector<Data::IndexedName> GeoFeature::getHigherElements(const char* element, bool silent) const
{
auto prop = getPropertyOfGeometry();
if (!prop)
if (!prop) {
return {};
}
return prop->getComplexData()->getHigherElements(element, silent);
}
@@ -284,8 +301,8 @@ Base::Placement GeoFeature::getPlacementFromProp(App::DocumentObject* obj, const
}
Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj,
App::DocumentObject* rootObj,
const std::string& sub)
App::DocumentObject* rootObj,
const std::string& sub)
{
if (!targetObj || !rootObj || sub.empty()) {
return Base::Placement();
@@ -295,7 +312,9 @@ Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj,
App::Document* doc = rootObj->getDocument();
Base::Placement plc = getPlacementFromProp(rootObj, "Placement");
if (targetObj == rootObj) return plc;
if (targetObj == rootObj) {
return plc;
}
for (auto& name : names) {
App::DocumentObject* obj = doc->getObject(name.c_str());
@@ -319,7 +338,7 @@ Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj,
}
Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj,
App::PropertyXLinkSub* prop)
App::PropertyXLinkSub* prop)
{
if (!targetObj || !prop) {
return Base::Placement();
+45 -33
View File
@@ -36,7 +36,7 @@ namespace App
/** Base class of all geometric document objects.
*/
class AppExport GeoFeature : public App::DocumentObject
class AppExport GeoFeature: public App::DocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(App::GeoFeature);
@@ -54,7 +54,7 @@ public:
* was only called by alignment task (Edit->Alignment)
* @param transform (input).
*/
virtual void transformPlacement(const Base::Placement &transform);
virtual void transformPlacement(const Base::Placement& transform);
/**
* This method returns the main property of a geometric object that holds
* the actual geometry. For a part object this is the Shape property, for
@@ -68,14 +68,15 @@ public:
*/
PyObject* getPyObject() override;
/// Specify the type of element name to return when calling getElementName()
enum ElementNameType {
/// Specify the type of element name to return when calling getElementName()
enum ElementNameType
{
/// Normal usage
Normal=0,
Normal = 0,
/// For importing
Import=1,
Import = 1,
/// For exporting
Export=2,
Export = 2,
};
/** Return the new and old style sub-element name
@@ -86,12 +87,13 @@ public:
* @return a struct with the newName and oldName. New element name may be empty.
*/
virtual ElementNamePair getElementName( // NOLINT(google-default-arguments)
const char *name, ElementNameType type=Normal) const;
const char* name,
ElementNameType type = Normal) const;
/** Resolve both the new and old style element name
*
* @param obj: top parent object
* @param subname: subname reference
* @param subname: subname reference
* @param elementName: output of a pair(newElementName,oldElementName)
* @param append: Whether to include subname prefix into the returned
* element name
@@ -102,22 +104,26 @@ public:
*
* @return Return the owner object of the element
*/
static DocumentObject *resolveElement(App::DocumentObject *obj,
const char *subname, ElementNamePair &elementName,
bool append=false, ElementNameType type=Normal,
const DocumentObject *filter=nullptr,const char **element=nullptr, GeoFeature **geo=nullptr);
static DocumentObject* resolveElement(App::DocumentObject* obj,
const char* subname,
ElementNamePair& elementName,
bool append = false,
ElementNameType type = Normal,
const DocumentObject* filter = nullptr,
const char** element = nullptr,
GeoFeature** geo = nullptr);
/**
* @brief Deprecated. Calculates the placement in the global reference coordinate system
*
*
* Deprecated: This does not handle App::Links correctly. Use getGlobalPlacement() instead.
* In FreeCAD the GeoFeature placement describes the local placement of the object in its parent
* coordinate system. This is however not always the same as the global reference system. If the
* object is in a GeoFeatureGroup, hence in another local coordinate system, the Placement
* property does only give the local transformation. This function can be used to calculate the
* placement of the object in the global reference coordinate system taking all stacked local
* property does only give the local transformation. This function can be used to calculate the
* placement of the object in the global reference coordinate system taking all stacked local
* systems into account.
*
*
* @return Base::Placement The transformation from the global reference coordinate system
*/
Base::Placement globalPlacement() const;
@@ -148,7 +154,8 @@ public:
*
* @return bool whether or not a direction is found.
*/
virtual bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname = nullptr) const;
virtual bool getCameraAlignmentDirection(Base::Vector3d& direction,
const char* subname = nullptr) const;
/** Search sub element using internal cached geometry
*
* @param element: element name
@@ -164,36 +171,41 @@ public:
* code may call this function to search for the new element name that
* reference to the same geometry of the old element.
*/
virtual const std::vector<std::string>& searchElementCache(const std::string &element,
Data::SearchOptions options = Data::SearchOption::CheckGeometry,
double tol = 1e-7,
double atol = 1e-10) const;
virtual const std::vector<std::string>&
searchElementCache(const std::string& element,
Data::SearchOptions options = Data::SearchOption::CheckGeometry,
double tol = 1e-7,
double atol = 1e-10) const;
static bool hasMissingElement(const char *subname);
static bool hasMissingElement(const char* subname);
/// Return the object that owns the shape that contains the give element name
virtual DocumentObject *getElementOwner(const Data::MappedName & /*name*/) const
{return nullptr;}
virtual DocumentObject* getElementOwner(const Data::MappedName& /*name*/) const
{
return nullptr;
}
virtual std::vector<const char *> getElementTypes(bool all=true) const;
virtual std::vector<const char*> getElementTypes(bool all = true) const;
/// Return the higher level element names of the given element
virtual std::vector<Data::IndexedName> getHigherElements(const char *name, bool silent=false) const;
virtual std::vector<Data::IndexedName> getHigherElements(const char* name,
bool silent = false) const;
static Base::Placement getPlacementFromProp(DocumentObject* obj, const char* propName);
static Base::Placement getGlobalPlacement(DocumentObject* targetObj, DocumentObject* rootObj, const std::string& sub);
static Base::Placement
getGlobalPlacement(DocumentObject* targetObj, DocumentObject* rootObj, const std::string& sub);
static Base::Placement getGlobalPlacement(DocumentObject* targetObj, PropertyXLinkSub* prop);
protected:
void onChanged(const Property* prop) override;
// void onDocumentRestored() override;
// void onDocumentRestored() override;
void updateElementReference();
protected:
ElementNamePair _getElementName(const char* name,
const Data::MappedElement& mapped) const;
ElementNamePair _getElementName(const char* name, const Data::MappedElement& mapped) const;
};
} //namespace App
} // namespace App
#endif // APP_GEOFEATURE_H
#endif // APP_GEOFEATURE_H
+1256 -893
View File
File diff suppressed because it is too large Load Diff
+401 -285
View File
@@ -33,22 +33,23 @@
#include "PropertyLinks.h"
//FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro
// FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
#define LINK_THROW(_type,_msg) do{\
if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))\
FC_ERR(_msg);\
throw _type(_msg);\
}while(0)
#define LINK_THROW(_type, _msg) \
do { \
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) \
FC_ERR(_msg); \
throw _type(_msg); \
} while (0)
namespace App
{
class AppExport LinkBaseExtension : public App::DocumentObjectExtension
class AppExport LinkBaseExtension: public App::DocumentObjectExtension
{
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::LinkExtension);
using inherited = App::DocumentObjectExtension;
@@ -59,9 +60,10 @@ public:
PropertyBool _LinkTouched;
PropertyInteger _LinkOwner;
PropertyLinkList _ChildCache; // cache for plain group expansion
PropertyLinkList _ChildCache; // cache for plain group expansion
enum {
enum
{
LinkModeNone,
LinkModeAutoDelete,
LinkModeAutoLink,
@@ -76,267 +78,365 @@ public:
*/
//@{
#define LINK_PARAM_LINK_PLACEMENT(...) \
(LinkPlacement, Base::Placement, App::PropertyPlacement, Base::Placement(), "Link placement", ##__VA_ARGS__)
#define LINK_PARAM_LINK_PLACEMENT(...) \
(LinkPlacement, \
Base::Placement, \
App::PropertyPlacement, \
Base::Placement(), \
"Link placement", \
##__VA_ARGS__)
#define LINK_PARAM_PLACEMENT(...) \
(Placement, Base::Placement, App::PropertyPlacement, Base::Placement(), \
"Alias to LinkPlacement to make the link object compatibale with other objects", ##__VA_ARGS__)
#define LINK_PARAM_PLACEMENT(...) \
(Placement, \
Base::Placement, \
App::PropertyPlacement, \
Base::Placement(), \
"Alias to LinkPlacement to make the link object compatibale with other objects", \
##__VA_ARGS__)
#define LINK_PARAM_OBJECT(...) \
#define LINK_PARAM_OBJECT(...) \
(LinkedObject, App::DocumentObject*, App::PropertyLink, 0, "Linked object", ##__VA_ARGS__)
#define LINK_PARAM_TRANSFORM(...) \
(LinkTransform, bool, App::PropertyBool, false, \
"Set to false to override linked object's placement", ##__VA_ARGS__)
#define LINK_PARAM_TRANSFORM(...) \
(LinkTransform, \
bool, \
App::PropertyBool, \
false, \
"Set to false to override linked object's placement", \
##__VA_ARGS__)
#define LINK_PARAM_CLAIM_CHILD(...) \
(LinkClaimChild, bool, App::PropertyBool, false, \
"Claim the linked object as a child", ##__VA_ARGS__)
#define LINK_PARAM_CLAIM_CHILD(...) \
(LinkClaimChild, \
bool, \
App::PropertyBool, \
false, \
"Claim the linked object as a child", \
##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE(...) \
(LinkCopyOnChange, long, App::PropertyEnumeration, ((long)0), \
"Disabled: disable copy on change\n"\
"Enabled: enable copy linked object on change of any of its properties marked as CopyOnChange\n"\
"Owned: indicate the linked object has been copied and is own owned by the link. And the\n"\
" the link will try to sync any change of the original linked object back to the copy.",\
##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE(...) \
(LinkCopyOnChange, \
long, \
App::PropertyEnumeration, \
((long)0), \
"Disabled: disable copy on change\n" \
"Enabled: enable copy linked object on change of any of its properties marked as " \
"CopyOnChange\n" \
"Owned: indicate the linked object has been copied and is own owned by the link. And the\n" \
" the link will try to sync any change of the original linked object back to the " \
"copy.", \
##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE_SOURCE(...) \
(LinkCopyOnChangeSource, App::DocumentObject*, App::PropertyLink, 0, "The copy on change source object", ##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE_SOURCE(...) \
(LinkCopyOnChangeSource, \
App::DocumentObject*, \
App::PropertyLink, \
0, \
"The copy on change source object", \
##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE_GROUP(...) \
(LinkCopyOnChangeGroup, App::DocumentObject*, App::PropertyLink, 0, \
"Linked to a internal group object for holding on change copies", ##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE_GROUP(...) \
(LinkCopyOnChangeGroup, \
App::DocumentObject*, \
App::PropertyLink, \
0, \
"Linked to a internal group object for holding on change copies", \
##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE_TOUCHED(...) \
(LinkCopyOnChangeTouched, bool, App::PropertyBool, 0, "Indicating the copy on change source object has been changed", ##__VA_ARGS__)
#define LINK_PARAM_COPY_ON_CHANGE_TOUCHED(...) \
(LinkCopyOnChangeTouched, \
bool, \
App::PropertyBool, \
0, \
"Indicating the copy on change source object has been changed", \
##__VA_ARGS__)
#define LINK_PARAM_SCALE(...) \
#define LINK_PARAM_SCALE(...) \
(Scale, double, App::PropertyFloat, 1.0, "Scale factor", ##__VA_ARGS__)
#define LINK_PARAM_SCALE_VECTOR(...) \
(ScaleVector, Base::Vector3d, App::PropertyVector, Base::Vector3d(1,1,1), "Scale factors", ##__VA_ARGS__)
#define LINK_PARAM_SCALE_VECTOR(...) \
(ScaleVector, \
Base::Vector3d, \
App::PropertyVector, \
Base::Vector3d(1, 1, 1), \
"Scale factors", \
##__VA_ARGS__)
#define LINK_PARAM_PLACEMENTS(...) \
(PlacementList, std::vector<Base::Placement>, App::PropertyPlacementList, std::vector<Base::Placement>(),\
"The placement for each link element", ##__VA_ARGS__)
#define LINK_PARAM_PLACEMENTS(...) \
(PlacementList, \
std::vector<Base::Placement>, \
App::PropertyPlacementList, \
std::vector<Base::Placement>(), \
"The placement for each link element", \
##__VA_ARGS__)
#define LINK_PARAM_SCALES(...) \
(ScaleList, std::vector<Base::Vector3d>, App::PropertyVectorList, std::vector<Base::Vector3d>(),\
"The scale factors for each link element", ##__VA_ARGS__)
#define LINK_PARAM_SCALES(...) \
(ScaleList, \
std::vector<Base::Vector3d>, \
App::PropertyVectorList, \
std::vector<Base::Vector3d>(), \
"The scale factors for each link element", \
##__VA_ARGS__)
#define LINK_PARAM_VISIBILITIES(...) \
(VisibilityList, boost::dynamic_bitset<>, App::PropertyBoolList, boost::dynamic_bitset<>(),\
"The visibility state of each link element", ##__VA_ARGS__)
#define LINK_PARAM_VISIBILITIES(...) \
(VisibilityList, \
boost::dynamic_bitset<>, \
App::PropertyBoolList, \
boost::dynamic_bitset<>(), \
"The visibility state of each link element", \
##__VA_ARGS__)
#define LINK_PARAM_COUNT(...) \
#define LINK_PARAM_COUNT(...) \
(ElementCount, int, App::PropertyInteger, 0, "Link element count", ##__VA_ARGS__)
#define LINK_PARAM_ELEMENTS(...) \
(ElementList, std::vector<App::DocumentObject*>, App::PropertyLinkList, std::vector<App::DocumentObject*>(),\
"The link element object list", ##__VA_ARGS__)
#define LINK_PARAM_ELEMENTS(...) \
(ElementList, \
std::vector<App::DocumentObject*>, \
App::PropertyLinkList, \
std::vector<App::DocumentObject*>(), \
"The link element object list", \
##__VA_ARGS__)
#define LINK_PARAM_SHOW_ELEMENT(...) \
#define LINK_PARAM_SHOW_ELEMENT(...) \
(ShowElement, bool, App::PropertyBool, true, "Enable link element list", ##__VA_ARGS__)
#define LINK_PARAM_MODE(...) \
#define LINK_PARAM_MODE(...) \
(LinkMode, long, App::PropertyEnumeration, ((long)0), "Link group mode", ##__VA_ARGS__)
#define LINK_PARAM_LINK_EXECUTE(...) \
(LinkExecute, const char*, App::PropertyString, (""),\
"Link execute function. Default to 'appLinkExecute'. 'None' to disable.", ##__VA_ARGS__)
#define LINK_PARAM_LINK_EXECUTE(...) \
(LinkExecute, \
const char*, \
App::PropertyString, \
(""), \
"Link execute function. Default to 'appLinkExecute'. 'None' to disable.", \
##__VA_ARGS__)
#define LINK_PARAM_COLORED_ELEMENTS(...) \
(ColoredElements, App::DocumentObject*, App::PropertyLinkSubHidden, \
0, "Link colored elements", ##__VA_ARGS__)
#define LINK_PARAM_COLORED_ELEMENTS(...) \
(ColoredElements, \
App::DocumentObject*, \
App::PropertyLinkSubHidden, \
0, \
"Link colored elements", \
##__VA_ARGS__)
#define LINK_PARAM(_param) (LINK_PARAM_##_param())
#define LINK_PNAME(_param) BOOST_PP_TUPLE_ELEM(0,_param)
#define LINK_PTYPE(_param) BOOST_PP_TUPLE_ELEM(1,_param)
#define LINK_PPTYPE(_param) BOOST_PP_TUPLE_ELEM(2,_param)
#define LINK_PDEF(_param) BOOST_PP_TUPLE_ELEM(3,_param)
#define LINK_PDOC(_param) BOOST_PP_TUPLE_ELEM(4,_param)
#define LINK_PNAME(_param) BOOST_PP_TUPLE_ELEM(0, _param)
#define LINK_PTYPE(_param) BOOST_PP_TUPLE_ELEM(1, _param)
#define LINK_PPTYPE(_param) BOOST_PP_TUPLE_ELEM(2, _param)
#define LINK_PDEF(_param) BOOST_PP_TUPLE_ELEM(3, _param)
#define LINK_PDOC(_param) BOOST_PP_TUPLE_ELEM(4, _param)
#define LINK_PINDEX(_param) BOOST_PP_CAT(Prop,LINK_PNAME(_param))
#define LINK_PINDEX(_param) BOOST_PP_CAT(Prop, LINK_PNAME(_param))
//@}
#define LINK_PARAMS \
LINK_PARAM(PLACEMENT)\
LINK_PARAM(LINK_PLACEMENT)\
LINK_PARAM(OBJECT)\
LINK_PARAM(CLAIM_CHILD)\
LINK_PARAM(TRANSFORM)\
LINK_PARAM(SCALE)\
LINK_PARAM(SCALE_VECTOR)\
LINK_PARAM(PLACEMENTS)\
LINK_PARAM(SCALES)\
LINK_PARAM(VISIBILITIES)\
LINK_PARAM(COUNT)\
LINK_PARAM(ELEMENTS)\
LINK_PARAM(SHOW_ELEMENT)\
LINK_PARAM(MODE)\
LINK_PARAM(LINK_EXECUTE)\
LINK_PARAM(COLORED_ELEMENTS)\
LINK_PARAM(COPY_ON_CHANGE)\
LINK_PARAM(COPY_ON_CHANGE_SOURCE)\
LINK_PARAM(COPY_ON_CHANGE_GROUP)\
LINK_PARAM(COPY_ON_CHANGE_TOUCHED)\
#define LINK_PARAMS \
LINK_PARAM(PLACEMENT) \
LINK_PARAM(LINK_PLACEMENT) \
LINK_PARAM(OBJECT) \
LINK_PARAM(CLAIM_CHILD) \
LINK_PARAM(TRANSFORM) \
LINK_PARAM(SCALE) \
LINK_PARAM(SCALE_VECTOR) \
LINK_PARAM(PLACEMENTS) \
LINK_PARAM(SCALES) \
LINK_PARAM(VISIBILITIES) \
LINK_PARAM(COUNT) \
LINK_PARAM(ELEMENTS) \
LINK_PARAM(SHOW_ELEMENT) \
LINK_PARAM(MODE) \
LINK_PARAM(LINK_EXECUTE) \
LINK_PARAM(COLORED_ELEMENTS) \
LINK_PARAM(COPY_ON_CHANGE) \
LINK_PARAM(COPY_ON_CHANGE_SOURCE) \
LINK_PARAM(COPY_ON_CHANGE_GROUP) \
LINK_PARAM(COPY_ON_CHANGE_TOUCHED)
enum PropIndex {
#define LINK_PINDEX_DEFINE(_1,_2,_param) LINK_PINDEX(_param),
enum PropIndex
{
#define LINK_PINDEX_DEFINE(_1, _2, _param) LINK_PINDEX(_param),
// defines Prop##Name enumeration value
BOOST_PP_SEQ_FOR_EACH(LINK_PINDEX_DEFINE,_,LINK_PARAMS)
PropMax
BOOST_PP_SEQ_FOR_EACH(LINK_PINDEX_DEFINE, _, LINK_PARAMS) PropMax
};
virtual void setProperty(int idx, Property *prop);
Property *getProperty(int idx);
Property *getProperty(const char *);
virtual void setProperty(int idx, Property* prop);
Property* getProperty(int idx);
Property* getProperty(const char*);
struct PropInfo {
struct PropInfo
{
int index;
const char *name;
const char* name;
Base::Type type;
const char *doc;
const char* doc;
PropInfo(int index, const char *name,Base::Type type,const char *doc)
: index(index), name(name), type(type), doc(doc)
PropInfo(int index, const char* name, Base::Type type, const char* doc)
: index(index)
, name(name)
, type(type)
, doc(doc)
{}
PropInfo() : index(0), name(nullptr), doc(nullptr) {}
PropInfo()
: index(0)
, name(nullptr)
, doc(nullptr)
{}
};
#define LINK_PROP_INFO(_1,_var,_param) \
_var.push_back(PropInfo(BOOST_PP_CAT(Prop,LINK_PNAME(_param)),\
BOOST_PP_STRINGIZE(LINK_PNAME(_param)),\
LINK_PPTYPE(_param)::getClassTypeId(), \
LINK_PDOC(_param)));
#define LINK_PROP_INFO(_1, _var, _param) \
_var.push_back(PropInfo(BOOST_PP_CAT(Prop, LINK_PNAME(_param)), \
BOOST_PP_STRINGIZE(LINK_PNAME(_param)), \
LINK_PPTYPE(_param)::getClassTypeId(), \
LINK_PDOC(_param)));
virtual const std::vector<PropInfo> &getPropertyInfo() const;
virtual const std::vector<PropInfo>& getPropertyInfo() const;
using PropInfoMap = std::map<std::string, PropInfo>;
virtual const PropInfoMap &getPropertyInfoMap() const;
virtual const PropInfoMap& getPropertyInfoMap() const;
enum LinkCopyOnChangeType {
enum LinkCopyOnChangeType
{
CopyOnChangeDisabled = 0,
CopyOnChangeEnabled = 1,
CopyOnChangeOwned = 2,
CopyOnChangeTracking = 3
};
#define LINK_PROP_GET(_1,_2,_param) \
LINK_PTYPE(_param) BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Value)) () const {\
auto prop = props[LINK_PINDEX(_param)];\
if(!prop) return LINK_PDEF(_param);\
return static_cast<const LINK_PPTYPE(_param) *>(prop)->getValue();\
}\
const LINK_PPTYPE(_param) *BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property)) () const {\
auto prop = props[LINK_PINDEX(_param)];\
return static_cast<const LINK_PPTYPE(_param) *>(prop);\
}\
LINK_PPTYPE(_param) *BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property)) () {\
auto prop = props[LINK_PINDEX(_param)];\
return static_cast<LINK_PPTYPE(_param) *>(prop);\
}\
#define LINK_PROP_GET(_1, _2, _param) \
LINK_PTYPE(_param) BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Value))() const \
{ \
auto prop = props[LINK_PINDEX(_param)]; \
if (!prop) \
return LINK_PDEF(_param); \
return static_cast<const LINK_PPTYPE(_param)*>(prop)->getValue(); \
} \
const LINK_PPTYPE(_param) * BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property))() const \
{ \
auto prop = props[LINK_PINDEX(_param)]; \
return static_cast<const LINK_PPTYPE(_param)*>(prop); \
} \
LINK_PPTYPE(_param) * BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property))() \
{ \
auto prop = props[LINK_PINDEX(_param)]; \
return static_cast<LINK_PPTYPE(_param)*>(prop); \
}
// defines get##Name##Property() and get##Name##Value() accessor
BOOST_PP_SEQ_FOR_EACH(LINK_PROP_GET,_,LINK_PARAMS)
BOOST_PP_SEQ_FOR_EACH(LINK_PROP_GET, _, LINK_PARAMS)
PropertyLinkList *_getElementListProperty() const;
const std::vector<App::DocumentObject*> &_getElementListValue() const;
PropertyLinkList* _getElementListProperty() const;
const std::vector<App::DocumentObject*>& _getElementListValue() const;
PropertyBool *_getShowElementProperty() const;
PropertyBool* _getShowElementProperty() const;
bool _getShowElementValue() const;
PropertyInteger *_getElementCountProperty() const;
PropertyInteger* _getElementCountProperty() const;
int _getElementCountValue() const;
std::vector<DocumentObject*> getLinkedChildren(bool filter=true) const;
std::vector<DocumentObject*> getLinkedChildren(bool filter = true) const;
const char *flattenSubname(const char *subname) const;
void expandSubname(std::string &subname) const;
const char* flattenSubname(const char* subname) const;
void expandSubname(std::string& subname) const;
DocumentObject *getLink(int depth=0) const;
DocumentObject* getLink(int depth = 0) const;
Base::Matrix4D getTransform(bool transform) const;
Base::Vector3d getScaleVector() const;
App::GroupExtension *linkedPlainGroup() const;
App::GroupExtension* linkedPlainGroup() const;
bool linkTransform() const;
const char *getSubName() const {
const char* getSubName() const
{
parseSubName();
return !mySubName.empty()?mySubName.c_str():nullptr;
return !mySubName.empty() ? mySubName.c_str() : nullptr;
}
const std::vector<std::string> &getSubElements() const {
const std::vector<std::string>& getSubElements() const
{
parseSubName();
return mySubElements;
}
bool extensionGetSubObject(DocumentObject *&ret, const char *subname,
PyObject **pyObj=nullptr, Base::Matrix4D *mat=nullptr, bool transform=false, int depth=0) const override;
bool extensionGetSubObject(DocumentObject*& ret,
const char* subname,
PyObject** pyObj = nullptr,
Base::Matrix4D* mat = nullptr,
bool transform = false,
int depth = 0) const override;
bool extensionGetSubObjects(std::vector<std::string>&ret, int reason) const override;
bool extensionGetSubObjects(std::vector<std::string>& ret, int reason) const override;
bool extensionGetLinkedObject(DocumentObject *&ret,
bool recurse, Base::Matrix4D *mat, bool transform, int depth) const override;
bool extensionGetLinkedObject(DocumentObject*& ret,
bool recurse,
Base::Matrix4D* mat,
bool transform,
int depth) const override;
App::DocumentObjectExecReturn *extensionExecute() override;
App::DocumentObjectExecReturn* extensionExecute() override;
short extensionMustExecute() override;
void extensionOnChanged(const Property* p) override;
void onExtendedUnsetupObject () override;
void onExtendedUnsetupObject() override;
void onExtendedDocumentRestored() override;
int extensionSetElementVisible(const char *, bool) override;
int extensionIsElementVisible(const char *) override;
int extensionSetElementVisible(const char*, bool) override;
int extensionIsElementVisible(const char*) override;
bool extensionHasChildElement() const override;
PyObject* getExtensionPyObject() override;
Property *extensionGetPropertyByName(const char* name) const override;
Property* extensionGetPropertyByName(const char* name) const override;
static int getArrayIndex(const char *subname, const char **psubname=nullptr);
int getElementIndex(const char *subname, const char **psubname=nullptr) const;
void elementNameFromIndex(int idx, std::ostream &ss) const;
static int getArrayIndex(const char* subname, const char** psubname = nullptr);
int getElementIndex(const char* subname, const char** psubname = nullptr) const;
void elementNameFromIndex(int idx, std::ostream& ss) const;
DocumentObject *getContainer();
const DocumentObject *getContainer() const;
DocumentObject* getContainer();
const DocumentObject* getContainer() const;
void setLink(int index, DocumentObject *obj, const char *subname=nullptr,
const std::vector<std::string> &subs = std::vector<std::string>());
void setLink(int index,
DocumentObject* obj,
const char* subname = nullptr,
const std::vector<std::string>& subs = std::vector<std::string>());
DocumentObject *getTrueLinkedObject(bool recurse,
Base::Matrix4D *mat=nullptr,int depth=0, bool noElement=false) const;
DocumentObject* getTrueLinkedObject(bool recurse,
Base::Matrix4D* mat = nullptr,
int depth = 0,
bool noElement = false) const;
using LinkPropMap = std::map<const Property*,std::pair<LinkBaseExtension*,int> >;
using LinkPropMap = std::map<const Property*, std::pair<LinkBaseExtension*, int>>;
bool hasPlacement() const {
bool hasPlacement() const
{
return getLinkPlacementProperty() || getPlacementProperty();
}
void cacheChildLabel(int enable=-1) const;
void cacheChildLabel(int enable = -1) const;
static bool setupCopyOnChange(App::DocumentObject *obj, App::DocumentObject *linked,
std::vector<boost::signals2::scoped_connection> *copyOnChangeConns, bool checkExisting);
static bool
setupCopyOnChange(App::DocumentObject* obj,
App::DocumentObject* linked,
std::vector<boost::signals2::scoped_connection>* copyOnChangeConns,
bool checkExisting);
static bool isCopyOnChangeProperty(App::DocumentObject *obj, const Property &prop);
static bool isCopyOnChangeProperty(App::DocumentObject* obj, const Property& prop);
void syncCopyOnChange();
/** Options used in setOnChangeCopyObject()
* Multiple options can be combined by bitwise or operator
*/
enum class OnChangeCopyOptions {
enum class OnChangeCopyOptions
{
/// No options set
None = 0,
/// If set, then exclude the input from object list to copy on change, or else, include the input object.
/// If set, then exclude the input from object list to copy on change, or else, include the
/// input object.
Exclude = 1,
/// If set , then apply the setting to all links to the input object, or else, apply only to this link.
/// If set , then apply the setting to all links to the input object, or else, apply only to
/// this link.
ApplyAll = 2,
};
@@ -344,53 +444,55 @@ public:
* @param obj: input object
* @param options: control options. @sa OnChangeCopyOptions.
*/
void setOnChangeCopyObject(App::DocumentObject *obj, OnChangeCopyOptions options);
void setOnChangeCopyObject(App::DocumentObject* obj, OnChangeCopyOptions options);
std::vector<App::DocumentObject *> getOnChangeCopyObjects(
std::vector<App::DocumentObject *> *excludes = nullptr,
App::DocumentObject *src = nullptr);
std::vector<App::DocumentObject*>
getOnChangeCopyObjects(std::vector<App::DocumentObject*>* excludes = nullptr,
App::DocumentObject* src = nullptr);
bool isLinkedToConfigurableObject() const;
void monitorOnChangeCopyObjects(const std::vector<App::DocumentObject*> &objs);
void monitorOnChangeCopyObjects(const std::vector<App::DocumentObject*>& objs);
/// Check if the linked object is a copy on change
bool isLinkMutated() const;
protected:
void _handleChangedPropertyName(Base::XMLReader &reader,
const char * TypeName, const char *PropName);
void
_handleChangedPropertyName(Base::XMLReader& reader, const char* TypeName, const char* PropName);
void parseSubName() const;
void update(App::DocumentObject *parent, const Property *prop);
void checkCopyOnChange(App::DocumentObject *parent, const App::Property &prop);
void setupCopyOnChange(App::DocumentObject *parent, bool checkSource = false);
App::DocumentObject *makeCopyOnChange();
void update(App::DocumentObject* parent, const Property* prop);
void checkCopyOnChange(App::DocumentObject* parent, const App::Property& prop);
void setupCopyOnChange(App::DocumentObject* parent, bool checkSource = false);
App::DocumentObject* makeCopyOnChange();
void syncElementList();
void detachElement(App::DocumentObject *obj);
void detachElement(App::DocumentObject* obj);
void detachElements();
void checkGeoElementMap(const App::DocumentObject *obj,
const App::DocumentObject *linked, PyObject **pyObj, const char *postfix) const;
void checkGeoElementMap(const App::DocumentObject* obj,
const App::DocumentObject* linked,
PyObject** pyObj,
const char* postfix) const;
void updateGroup();
void slotChangedPlainGroup(const App::DocumentObject &, const App::Property &);
void slotChangedPlainGroup(const App::DocumentObject&, const App::Property&);
protected:
std::vector<Property *> props;
std::vector<Property*> props;
std::unordered_set<const App::DocumentObject*> myHiddenElements;
mutable std::vector<std::string> mySubElements;
mutable std::string mySubName;
std::unordered_map<const App::DocumentObject*,
boost::signals2::scoped_connection> plainGroupConns;
std::unordered_map<const App::DocumentObject*, boost::signals2::scoped_connection>
plainGroupConns;
long prevLinkedObjectID = 0;
mutable std::unordered_map<std::string,int> myLabelCache; // for label based subname lookup
mutable bool enableLabelCache{false};
bool hasOldSubElement{false};
mutable std::unordered_map<std::string, int> myLabelCache; // for label based subname lookup
mutable bool enableLabelCache {false};
bool hasOldSubElement {false};
std::vector<boost::signals2::scoped_connection> copyOnChangeConns;
std::vector<boost::signals2::scoped_connection> copyOnChangeSrcConns;
bool hasCopyOnChange{true};
bool hasCopyOnChange {true};
mutable bool checkingProperty = false;
bool pauseCopyOnChange = false;
@@ -404,7 +506,7 @@ using LinkBaseExtensionPython = ExtensionPythonT<LinkBaseExtension>;
///////////////////////////////////////////////////////////////////////////
class AppExport LinkExtension : public LinkBaseExtension
class AppExport LinkExtension: public LinkBaseExtension
{
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::LinkExtension);
using inherited = LinkBaseExtension;
@@ -428,36 +530,36 @@ public:
*/
//@{
#define LINK_ENAME(_param) BOOST_PP_TUPLE_ELEM(5,_param)
#define LINK_ETYPE(_param) BOOST_PP_TUPLE_ELEM(6,_param)
#define LINK_EPTYPE(_param) BOOST_PP_TUPLE_ELEM(7,_param)
#define LINK_EGROUP(_param) BOOST_PP_TUPLE_ELEM(8,_param)
#define LINK_ENAME(_param) BOOST_PP_TUPLE_ELEM(5, _param)
#define LINK_ETYPE(_param) BOOST_PP_TUPLE_ELEM(6, _param)
#define LINK_EPTYPE(_param) BOOST_PP_TUPLE_ELEM(7, _param)
#define LINK_EGROUP(_param) BOOST_PP_TUPLE_ELEM(8, _param)
#define _LINK_PROP_ADD(_add_property, _param) \
_add_property(BOOST_PP_STRINGIZE(LINK_ENAME(_param)),LINK_ENAME(_param),\
(LINK_PDEF(_param)),LINK_EGROUP(_param),LINK_EPTYPE(_param),LINK_PDOC(_param));\
setProperty(LINK_PINDEX(_param),&LINK_ENAME(_param));
#define _LINK_PROP_ADD(_add_property, _param) \
_add_property(BOOST_PP_STRINGIZE(LINK_ENAME(_param)), \
LINK_ENAME(_param), \
(LINK_PDEF(_param)), \
LINK_EGROUP(_param), \
LINK_EPTYPE(_param), \
LINK_PDOC(_param)); \
setProperty(LINK_PINDEX(_param), &LINK_ENAME(_param));
#define LINK_PROP_ADD(_1,_2,_param) \
_LINK_PROP_ADD(_ADD_PROPERTY_TYPE,_param);
#define LINK_PROP_ADD(_1, _2, _param) _LINK_PROP_ADD(_ADD_PROPERTY_TYPE, _param);
#define LINK_PROP_ADD_EXTENSION(_1,_2,_param) \
_LINK_PROP_ADD(_EXTENSION_ADD_PROPERTY_TYPE,_param);
#define LINK_PROP_ADD_EXTENSION(_1, _2, _param) \
_LINK_PROP_ADD(_EXTENSION_ADD_PROPERTY_TYPE, _param);
#define LINK_PROPS_ADD(_seq) \
BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD,_,_seq)
#define LINK_PROPS_ADD(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD, _, _seq)
#define LINK_PROPS_ADD_EXTENSION(_seq) \
BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD_EXTENSION,_,_seq)
#define LINK_PROPS_ADD_EXTENSION(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD_EXTENSION, _, _seq)
#define _LINK_PROP_SET(_1,_2,_param) \
setProperty(LINK_PINDEX(_param),&LINK_ENAME(_param));
#define _LINK_PROP_SET(_1, _2, _param) setProperty(LINK_PINDEX(_param), &LINK_ENAME(_param));
#define LINK_PROPS_SET(_seq) BOOST_PP_SEQ_FOR_EACH(_LINK_PROP_SET,_,_seq)
#define LINK_PROPS_SET(_seq) BOOST_PP_SEQ_FOR_EACH(_LINK_PROP_SET, _, _seq)
/// Helper for defining default extended parameter
#define _LINK_PARAM_EXT(_name,_type,_ptype,_def,_doc,...) \
((_name,_type,_ptype,_def,_doc,_name,_ptype,App::Prop_None," Link"))
#define _LINK_PARAM_EXT(_name, _type, _ptype, _def, _doc, ...) \
((_name, _type, _ptype, _def, _doc, _name, _ptype, App::Prop_None, " Link"))
/** Define default extended parameter
* It simply reuses Name as Property_Name, Property_Type as
@@ -466,44 +568,46 @@ public:
#define LINK_PARAM_EXT(_param) BOOST_PP_EXPAND(_LINK_PARAM_EXT LINK_PARAM_##_param())
/// Helper for extended parameter with app property type
#define _LINK_PARAM_EXT_ATYPE(_name,_type,_ptype,_def,_doc,_atype) \
((_name,_type,_ptype,_def,_doc,_name,_ptype,_atype," Link"))
#define _LINK_PARAM_EXT_ATYPE(_name, _type, _ptype, _def, _doc, _atype) \
((_name, _type, _ptype, _def, _doc, _name, _ptype, _atype, " Link"))
/// Define extended parameter with app property type
#define LINK_PARAM_EXT_ATYPE(_param,_atype) \
#define LINK_PARAM_EXT_ATYPE(_param, _atype) \
BOOST_PP_EXPAND(_LINK_PARAM_EXT_ATYPE LINK_PARAM_##_param(_atype))
/// Helper for extended parameter with derived property type
#define _LINK_PARAM_EXT_TYPE(_name,_type,_ptype,_def,_doc,_dtype) \
((_name,_type,_ptype,_def,_doc,_name,_dtype,App::Prop_None," Link"))
#define _LINK_PARAM_EXT_TYPE(_name, _type, _ptype, _def, _doc, _dtype) \
((_name, _type, _ptype, _def, _doc, _name, _dtype, App::Prop_None, " Link"))
/// Define extended parameter with derived property type
#define LINK_PARAM_EXT_TYPE(_param,_dtype) \
#define LINK_PARAM_EXT_TYPE(_param, _dtype) \
BOOST_PP_EXPAND(_LINK_PARAM_EXT_TYPE LINK_PARAM_##_param(_dtype))
/// Helper for extended parameter with a different property name
#define _LINK_PARAM_EXT_NAME(_name,_type,_ptype,_def,_doc,_pname) \
((_name,_type,_ptype,_def,_doc,_pname,_ptype,App::Prop_None," Link"))
#define _LINK_PARAM_EXT_NAME(_name, _type, _ptype, _def, _doc, _pname) \
((_name, _type, _ptype, _def, _doc, _pname, _ptype, App::Prop_None, " Link"))
/// Define extended parameter with a different property name
#define LINK_PARAM_EXT_NAME(_param,_pname) BOOST_PP_EXPAND(_LINK_PARAM_EXT_NAME LINK_PARAM_##_param(_pname))
#define LINK_PARAM_EXT_NAME(_param, _pname) \
BOOST_PP_EXPAND(_LINK_PARAM_EXT_NAME LINK_PARAM_##_param(_pname))
//@}
#define LINK_PARAMS_EXT \
LINK_PARAM_EXT(SCALE)\
LINK_PARAM_EXT_ATYPE(SCALE_VECTOR,App::Prop_Hidden)\
LINK_PARAM_EXT(SCALES)\
LINK_PARAM_EXT(VISIBILITIES)\
LINK_PARAM_EXT(PLACEMENTS)\
#define LINK_PARAMS_EXT \
LINK_PARAM_EXT(SCALE) \
LINK_PARAM_EXT_ATYPE(SCALE_VECTOR, App::Prop_Hidden) \
LINK_PARAM_EXT(SCALES) \
LINK_PARAM_EXT(VISIBILITIES) \
LINK_PARAM_EXT(PLACEMENTS) \
LINK_PARAM_EXT(ELEMENTS)
#define LINK_PROP_DEFINE(_1,_2,_param) LINK_ETYPE(_param) LINK_ENAME(_param);
#define LINK_PROPS_DEFINE(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_DEFINE,_,_seq)
#define LINK_PROP_DEFINE(_1, _2, _param) LINK_ETYPE(_param) LINK_ENAME(_param);
#define LINK_PROPS_DEFINE(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_DEFINE, _, _seq)
// defines the actual properties
LINK_PROPS_DEFINE(LINK_PARAMS_EXT)
void onExtendedDocumentRestored() override {
void onExtendedDocumentRestored() override
{
LINK_PROPS_SET(LINK_PARAMS_EXT);
inherited::onExtendedDocumentRestored();
}
@@ -515,44 +619,47 @@ using LinkExtensionPython = ExtensionPythonT<LinkExtension>;
///////////////////////////////////////////////////////////////////////////
class AppExport Link : public App::DocumentObject, public App::LinkExtension
class AppExport Link: public App::DocumentObject, public App::LinkExtension
{
PROPERTY_HEADER_WITH_EXTENSIONS(App::Link);
using inherited = App::DocumentObject;
public:
#define LINK_PARAMS_LINK \
LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink)\
LINK_PARAM_EXT(CLAIM_CHILD)\
LINK_PARAM_EXT(TRANSFORM)\
LINK_PARAM_EXT(LINK_PLACEMENT)\
LINK_PARAM_EXT(PLACEMENT)\
LINK_PARAM_EXT(SHOW_ELEMENT)\
LINK_PARAM_EXT_TYPE(COUNT,App::PropertyIntegerConstraint)\
LINK_PARAM_EXT(LINK_EXECUTE)\
LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS,App::Prop_Hidden)\
LINK_PARAM_EXT(COPY_ON_CHANGE)\
LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink)\
LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP)\
LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)\
public:
#define LINK_PARAMS_LINK \
LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink) \
LINK_PARAM_EXT(CLAIM_CHILD) \
LINK_PARAM_EXT(TRANSFORM) \
LINK_PARAM_EXT(LINK_PLACEMENT) \
LINK_PARAM_EXT(PLACEMENT) \
LINK_PARAM_EXT(SHOW_ELEMENT) \
LINK_PARAM_EXT_TYPE(COUNT, App::PropertyIntegerConstraint) \
LINK_PARAM_EXT(LINK_EXECUTE) \
LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS, App::Prop_Hidden) \
LINK_PARAM_EXT(COPY_ON_CHANGE) \
LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink) \
LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP) \
LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)
LINK_PROPS_DEFINE(LINK_PARAMS_LINK)
Link();
const char* getViewProviderName() const override{
const char* getViewProviderName() const override
{
return "Gui::ViewProviderLink";
}
void onDocumentRestored() override {
void onDocumentRestored() override
{
LINK_PROPS_SET(LINK_PARAMS_LINK);
inherited::onDocumentRestored();
}
void handleChangedPropertyName(Base::XMLReader &reader,
const char * TypeName, const char *PropName) override
void handleChangedPropertyName(Base::XMLReader& reader,
const char* TypeName,
const char* PropName) override
{
_handleChangedPropertyName(reader,TypeName,PropName);
_handleChangedPropertyName(reader, TypeName, PropName);
}
bool canLinkProperties() const override;
@@ -566,42 +673,46 @@ using LinkPython = App::FeaturePythonT<Link>;
///////////////////////////////////////////////////////////////////////////
class AppExport LinkElement : public App::DocumentObject, public App::LinkBaseExtension {
class AppExport LinkElement: public App::DocumentObject, public App::LinkBaseExtension
{
PROPERTY_HEADER_WITH_EXTENSIONS(App::LinkElement);
using inherited = App::DocumentObject;
public:
#define LINK_PARAMS_ELEMENT \
LINK_PARAM_EXT(SCALE)\
LINK_PARAM_EXT_ATYPE(SCALE_VECTOR,App::Prop_Hidden)\
LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink)\
LINK_PARAM_EXT(TRANSFORM) \
LINK_PARAM_EXT(LINK_PLACEMENT)\
LINK_PARAM_EXT(PLACEMENT)\
LINK_PARAM_EXT(COPY_ON_CHANGE)\
LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink)\
LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP)\
LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)\
public:
#define LINK_PARAMS_ELEMENT \
LINK_PARAM_EXT(SCALE) \
LINK_PARAM_EXT_ATYPE(SCALE_VECTOR, App::Prop_Hidden) \
LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink) \
LINK_PARAM_EXT(TRANSFORM) \
LINK_PARAM_EXT(LINK_PLACEMENT) \
LINK_PARAM_EXT(PLACEMENT) \
LINK_PARAM_EXT(COPY_ON_CHANGE) \
LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink) \
LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP) \
LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)
// defines the actual properties
LINK_PROPS_DEFINE(LINK_PARAMS_ELEMENT)
LinkElement();
const char* getViewProviderName() const override{
const char* getViewProviderName() const override
{
return "Gui::ViewProviderLink";
}
void onDocumentRestored() override {
void onDocumentRestored() override
{
LINK_PROPS_SET(LINK_PARAMS_ELEMENT);
inherited::onDocumentRestored();
}
bool canDelete() const;
void handleChangedPropertyName(Base::XMLReader &reader,
const char * TypeName, const char *PropName) override
void handleChangedPropertyName(Base::XMLReader& reader,
const char* TypeName,
const char* PropName) override
{
_handleChangedPropertyName(reader,TypeName,PropName);
_handleChangedPropertyName(reader, TypeName, PropName);
}
bool isLink() const override;
@@ -613,28 +724,31 @@ using LinkElementPython = App::FeaturePythonT<LinkElement>;
///////////////////////////////////////////////////////////////////////////
class AppExport LinkGroup : public App::DocumentObject, public App::LinkBaseExtension {
class AppExport LinkGroup: public App::DocumentObject, public App::LinkBaseExtension
{
PROPERTY_HEADER_WITH_EXTENSIONS(App::LinkGroup);
using inherited = App::DocumentObject;
public:
#define LINK_PARAMS_GROUP \
LINK_PARAM_EXT(ELEMENTS)\
LINK_PARAM_EXT(PLACEMENT)\
LINK_PARAM_EXT(VISIBILITIES)\
LINK_PARAM_EXT(MODE)\
LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS,App::Prop_Hidden)
public:
#define LINK_PARAMS_GROUP \
LINK_PARAM_EXT(ELEMENTS) \
LINK_PARAM_EXT(PLACEMENT) \
LINK_PARAM_EXT(VISIBILITIES) \
LINK_PARAM_EXT(MODE) \
LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS, App::Prop_Hidden)
// defines the actual properties
LINK_PROPS_DEFINE(LINK_PARAMS_GROUP)
LinkGroup();
const char* getViewProviderName() const override{
const char* getViewProviderName() const override
{
return "Gui::ViewProviderLink";
}
void onDocumentRestored() override {
void onDocumentRestored() override
{
LINK_PROPS_SET(LINK_PARAMS_GROUP);
inherited::onDocumentRestored();
}
@@ -642,7 +756,7 @@ public:
using LinkGroupPython = App::FeaturePythonT<LinkGroup>;
} //namespace App
} // namespace App
ENABLE_BITMASK_OPERATORS(App::Link::OnChangeCopyOptions)
@@ -651,7 +765,8 @@ import LinkParams
LinkParams.declare()
]]]*/
namespace App {
namespace App
{
/** Convenient class to obtain App::Link related parameters
* The parameters are under group "User parameter:BaseApp/Preferences/Link"
@@ -682,7 +797,8 @@ namespace App {
* void LinkParams:on<parameter_name>Changed()
* @endcode
*/
class AppExport LinkParams {
class AppExport LinkParams
{
public:
static ParameterGrp::handle getHandle();
@@ -691,21 +807,21 @@ public:
///
/// Stores the last user choice of whether to apply CopyOnChange setup to all link
/// that links to the same configurable object
static const bool & getCopyOnChangeApplyToAll();
static const bool & defaultCopyOnChangeApplyToAll();
static const bool& getCopyOnChangeApplyToAll();
static const bool& defaultCopyOnChangeApplyToAll();
static void removeCopyOnChangeApplyToAll();
static void setCopyOnChangeApplyToAll(const bool &v);
static const char *docCopyOnChangeApplyToAll();
static void setCopyOnChangeApplyToAll(const bool& v);
static const char* docCopyOnChangeApplyToAll();
//@}
// Auto generated code. See class document of LinkParams.
};
} // namespace App
} // namespace App
//[[[end]]]
#if defined(__clang__)
# pragma clang diagnostic pop
#pragma clang diagnostic pop
#endif
#endif // APP_LINK_H
#endif // APP_LINK_H
+143 -104
View File
@@ -23,7 +23,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
#include <sstream>
#endif
#include "DocumentObjectPy.h"
@@ -40,155 +40,167 @@ std::string LinkBaseExtensionPy::representation() const
return str.str();
}
using PropTmpMap = std::map<std::string, std::pair<int,Property*> >;
using PropTmpMap = std::map<std::string, std::pair<int, Property*>>;
using PropMap = std::map<std::string, Property*>;
static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap &infoMap,
const PropMap &propMap, PyObject *key, PyObject *value)
static bool getProperty(PropTmpMap& props,
const LinkBaseExtension::PropInfoMap& infoMap,
const PropMap& propMap,
PyObject* key,
PyObject* value)
{
std::ostringstream str;
if(!PyUnicode_Check(key)) {
if (!PyUnicode_Check(key)) {
PyErr_SetString(PyExc_TypeError, "key must be a unicode string");
return false;
}
const char *keyStr = PyUnicode_AsUTF8(key);
const char* keyStr = PyUnicode_AsUTF8(key);
auto it = infoMap.find(keyStr);
if(it == infoMap.end()){
if (it == infoMap.end()) {
str << "unknown key '" << keyStr << "'";
PyErr_SetString(PyExc_KeyError, str.str().c_str());
return false;
}
const char *valStr = nullptr;
if(key == value)
const char* valStr = nullptr;
if (key == value) {
valStr = keyStr;
else if (value!=Py_None) {
if(!PyUnicode_Check(value)) {
}
else if (value != Py_None) {
if (!PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be unicode string");
return false;
}
valStr = PyUnicode_AsUTF8(value);
}
App::Property *prop = nullptr;
auto &info = it->second;
if(valStr) {
App::Property* prop = nullptr;
auto& info = it->second;
if (valStr) {
auto pIt = propMap.find(valStr);
if(pIt == propMap.end()) {
if (pIt == propMap.end()) {
str << "cannot find property '" << valStr << "'";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return false;
}
prop = pIt->second;
if(!prop->isDerivedFrom(info.type)) {
str << "expect property '" << keyStr << "(" << valStr
<< ") to be derived from '" << info.type.getName()
<< "', instead of '" << prop->getTypeId().getName() << "'";
if (!prop->isDerivedFrom(info.type)) {
str << "expect property '" << keyStr << "(" << valStr << ") to be derived from '"
<< info.type.getName() << "', instead of '" << prop->getTypeId().getName() << "'";
PyErr_SetString(PyExc_TypeError, str.str().c_str());
}
}
props[keyStr] = std::make_pair(info.index,prop);
props[keyStr] = std::make_pair(info.index, prop);
return true;
}
PyObject* LinkBaseExtensionPy::configLinkProperty(PyObject *args, PyObject *keywds) {
PyObject* LinkBaseExtensionPy::configLinkProperty(PyObject* args, PyObject* keywds)
{
auto ext = getLinkBaseExtensionPtr();
const auto &info = ext->getPropertyInfoMap();
const auto& info = ext->getPropertyInfoMap();
PropMap propMap;
ext->getExtendedContainer()->getPropertyMap(propMap);
PropTmpMap props;
if(args && PyTuple_Check(args)) {
for(Py_ssize_t pos=0;pos<PyTuple_GET_SIZE(args);++pos) {
auto key = PyTuple_GET_ITEM(args,pos);
if(!getProperty(props,info,propMap,key,key))
if (args && PyTuple_Check(args)) {
for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
auto key = PyTuple_GET_ITEM(args, pos);
if (!getProperty(props, info, propMap, key, key)) {
return nullptr;
}
}
}
if(keywds && PyDict_Check(keywds)) {
if (keywds && PyDict_Check(keywds)) {
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(keywds, &pos, &key, &value)) {
if(!getProperty(props,info,propMap,key,value))
if (!getProperty(props, info, propMap, key, value)) {
return nullptr;
}
}
}
for(auto &v : props)
ext->setProperty(v.second.first,v.second.second);
for (auto& v : props) {
ext->setProperty(v.second.first, v.second.second);
}
Py_Return;
}
PyObject* LinkBaseExtensionPy::getLinkExtProperty(PyObject *args)
PyObject* LinkBaseExtensionPy::getLinkExtProperty(PyObject* args)
{
const char *name;
if(!PyArg_ParseTuple(args,"s",&name))
const char* name;
if (!PyArg_ParseTuple(args, "s", &name)) {
return nullptr;
}
auto prop = getLinkBaseExtensionPtr()->getProperty(name);
if(!prop) {
if (!prop) {
PyErr_SetString(PyExc_AttributeError, "unknown property name");
return nullptr;
}
return prop->getPyObject();
}
PyObject* LinkBaseExtensionPy::getLinkExtPropertyName(PyObject *args) {
const char *name;
if(!PyArg_ParseTuple(args,"s",&name))
PyObject* LinkBaseExtensionPy::getLinkExtPropertyName(PyObject* args)
{
const char* name;
if (!PyArg_ParseTuple(args, "s", &name)) {
return nullptr;
}
auto prop = getLinkBaseExtensionPtr()->getProperty(name);
if(!prop) {
if (!prop) {
PyErr_SetString(PyExc_AttributeError, "unknown property name");
return nullptr;
}
auto container = getLinkBaseExtensionPtr()->getExtendedContainer();
if(!container) {
if (!container) {
PyErr_SetString(PyExc_RuntimeError, "no extended container");
return nullptr;
}
name = container->getPropertyName(prop);
if(!name) {
if (!name) {
PyErr_SetString(PyExc_RuntimeError, "cannot find property name");
return nullptr;
}
return Py::new_reference_to(Py::String(name));
}
PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject *args)
PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject* args)
{
auto ext = getLinkBaseExtensionPtr();
const auto &infos = ext->getPropertyInfo();
const auto& infos = ext->getPropertyInfo();
if(PyArg_ParseTuple(args,"")) {
if (PyArg_ParseTuple(args, "")) {
Py::Tuple ret(infos.size());
int i=0;
for(const auto &info : infos) {
ret.setItem(i++,Py::TupleN(Py::String(info.name),
Py::String(info.type.getName()),Py::String(info.doc)));
int i = 0;
for (const auto& info : infos) {
ret.setItem(i++,
Py::TupleN(Py::String(info.name),
Py::String(info.type.getName()),
Py::String(info.doc)));
}
return Py::new_reference_to(ret);
}
short index = 0;
if(PyArg_ParseTuple(args,"h",&index)) {
if(index<0 || index>=(int)infos.size()) {
if (PyArg_ParseTuple(args, "h", &index)) {
if (index < 0 || index >= (int)infos.size()) {
PyErr_SetString(PyExc_ValueError, "index out of range");
return nullptr;
}
Py::TupleN ret(Py::String(infos[index].name),
Py::String(infos[index].type.getName()),Py::String(infos[index].doc));
Py::String(infos[index].type.getName()),
Py::String(infos[index].doc));
return Py::new_reference_to(ret);
}
char *name;
if(PyArg_ParseTuple(args,"s",&name)) {
for(const auto & info : infos) {
if(strcmp(info.name,name)==0) {
Py::TupleN ret(Py::String(info.type.getName()),
Py::String(info.doc));
char* name;
if (PyArg_ParseTuple(args, "s", &name)) {
for (const auto& info : infos) {
if (strcmp(info.name, name) == 0) {
Py::TupleN ret(Py::String(info.type.getName()), Py::String(info.doc));
return Py::new_reference_to(ret);
}
}
@@ -200,101 +212,128 @@ PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject *args)
return nullptr;
}
void parseLink(LinkBaseExtension *ext, int index, PyObject *value) {
App::DocumentObject *obj = nullptr;
void parseLink(LinkBaseExtension* ext, int index, PyObject* value)
{
App::DocumentObject* obj = nullptr;
PropertyStringList subs;
PropertyString sub;
if(value!=Py_None) {
if(PyObject_TypeCheck(value,&DocumentObjectPy::Type)) {
if (value != Py_None) {
if (PyObject_TypeCheck(value, &DocumentObjectPy::Type)) {
obj = static_cast<DocumentObjectPy*>(value)->getDocumentObjectPtr();
}else if(!PySequence_Check(value))
}
else if (!PySequence_Check(value)) {
throw Base::TypeError("Expects type of DocumentObject or sequence");
else{
}
else {
Py::Sequence seq(value);
if(seq[0].ptr() != Py_None) {
if(!PyObject_TypeCheck(seq[0].ptr(),&DocumentObjectPy::Type))
throw Base::TypeError("Expects the first argument to be DocumentObject in sequence");
if (seq[0].ptr() != Py_None) {
if (!PyObject_TypeCheck(seq[0].ptr(), &DocumentObjectPy::Type)) {
throw Base::TypeError(
"Expects the first argument to be DocumentObject in sequence");
}
obj = static_cast<DocumentObjectPy*>(seq[0].ptr())->getDocumentObjectPtr();
if(seq.size()>1) {
if (seq.size() > 1) {
sub.setPyObject(seq[1].ptr());
if(seq.size()>2)
if (seq.size() > 2) {
subs.setPyObject(seq[2].ptr());
}
}
}
}
}
ext->setLink(index,obj,sub.getValue(),subs.getValue());
ext->setLink(index, obj, sub.getValue(), subs.getValue());
}
PyObject* LinkBaseExtensionPy::setLink(PyObject *_args)
PyObject* LinkBaseExtensionPy::setLink(PyObject* _args)
{
Py::Sequence args(_args);
PY_TRY {
PY_TRY
{
auto ext = getLinkBaseExtensionPtr();
PyObject *pcObj = args.size()?args[0].ptr():Py_None;
if(pcObj == Py_None) {
ext->setLink(-1,nullptr);
}else if(PyDict_Check(pcObj)) {
PyObject* pcObj = args.size() ? args[0].ptr() : Py_None;
if (pcObj == Py_None) {
ext->setLink(-1, nullptr);
}
else if (PyDict_Check(pcObj)) {
PyObject *key, *value;
Py_ssize_t pos = 0;
while(PyDict_Next(pcObj, &pos, &key, &value))
parseLink(ext,Py::Int(key),value);
}else if(PySequence_Check(pcObj)) {
ext->setLink(-1,nullptr);
while (PyDict_Next(pcObj, &pos, &key, &value)) {
parseLink(ext, Py::Int(key), value);
}
}
else if (PySequence_Check(pcObj)) {
ext->setLink(-1, nullptr);
Py::Sequence seq(pcObj);
for(Py_ssize_t i=0;i<seq.size();++i)
parseLink(ext,i,seq[i].ptr());
}else
parseLink(ext,-1,_args);
for (Py_ssize_t i = 0; i < seq.size(); ++i) {
parseLink(ext, i, seq[i].ptr());
}
}
else {
parseLink(ext, -1, _args);
}
Py_Return;
}PY_CATCH
}
PY_CATCH
}
PyObject* LinkBaseExtensionPy::cacheChildLabel(PyObject *args) {
PyObject *enable = Py_True;
if(!PyArg_ParseTuple(args,"|O",&enable))
PyObject* LinkBaseExtensionPy::cacheChildLabel(PyObject* args)
{
PyObject* enable = Py_True;
if (!PyArg_ParseTuple(args, "|O", &enable)) {
return nullptr;
PY_TRY {
}
PY_TRY
{
getLinkBaseExtensionPtr()->cacheChildLabel(Base::asBoolean(enable) ? -1 : 0);
Py_Return;
}PY_CATCH;
}
PY_CATCH;
}
PyObject* LinkBaseExtensionPy::flattenSubname(PyObject *args) {
const char *subname;
if(!PyArg_ParseTuple(args,"s",&subname))
PyObject* LinkBaseExtensionPy::flattenSubname(PyObject* args)
{
const char* subname;
if (!PyArg_ParseTuple(args, "s", &subname)) {
return nullptr;
PY_TRY {
return Py::new_reference_to(Py::String(
getLinkBaseExtensionPtr()->flattenSubname(subname)));
}PY_CATCH;
}
PY_TRY
{
return Py::new_reference_to(Py::String(getLinkBaseExtensionPtr()->flattenSubname(subname)));
}
PY_CATCH;
}
PyObject* LinkBaseExtensionPy::expandSubname(PyObject *args) {
const char *subname;
if(!PyArg_ParseTuple(args,"s",&subname))
PyObject* LinkBaseExtensionPy::expandSubname(PyObject* args)
{
const char* subname;
if (!PyArg_ParseTuple(args, "s", &subname)) {
return nullptr;
PY_TRY {
}
PY_TRY
{
std::string sub(subname);
getLinkBaseExtensionPtr()->expandSubname(sub);
return Py::new_reference_to(Py::String(sub));
}PY_CATCH;
}
PY_CATCH;
}
Py::List LinkBaseExtensionPy::getLinkedChildren() const {
Py::List LinkBaseExtensionPy::getLinkedChildren() const
{
Py::List ret;
for(auto o : getLinkBaseExtensionPtr()->getLinkedChildren(true))
for (auto o : getLinkBaseExtensionPtr()->getLinkedChildren(true)) {
ret.append(Py::asObject(o->getPyObject()));
}
return ret;
}
PyObject *LinkBaseExtensionPy::getCustomAttributes(const char* /*attr*/) const
PyObject* LinkBaseExtensionPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int LinkBaseExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject * /*obj*/)
int LinkBaseExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}
+15 -9
View File
@@ -4,27 +4,33 @@ from os import sys, path
# Actual code generation is done in Base/param_utils.py.
# The following code is to import param_util.py without needing __init__.py in Base directory
sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'Base'))
sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), "Base"))
import params_utils
from params_utils import ParamBool, ParamInt, ParamString, ParamUInt, ParamFloat
NameSpace = 'App'
ClassName = 'LinkParams'
ParamPath = 'User parameter:BaseApp/Preferences/Link'
ClassDoc = 'Convenient class to obtain App::Link related parameters'
HeaderFile = 'Link.h'
SourceFile = 'Link.cpp'
NameSpace = "App"
ClassName = "LinkParams"
ParamPath = "User parameter:BaseApp/Preferences/Link"
ClassDoc = "Convenient class to obtain App::Link related parameters"
HeaderFile = "Link.h"
SourceFile = "Link.cpp"
Params = [
ParamBool('CopyOnChangeApplyToAll', True, '''\
ParamBool(
"CopyOnChangeApplyToAll",
True,
"""\
Stores the last user choice of whether to apply CopyOnChange setup to all link
that links to the same configurable object'''),
that links to the same configurable object""",
),
]
def declare():
params_utils.declare_begin(sys.modules[__name__], header=False)
params_utils.declare_end(sys.modules[__name__])
def define():
params_utils.define(sys.modules[__name__], header=False)
+7 -7
View File
@@ -150,17 +150,17 @@ struct AppExport Dependency
explicit Dependency(std::string pkg);
explicit Dependency(const XERCES_CPP_NAMESPACE::DOMElement* elem);
std::string package; //< Required: must exactly match the contents of the "name" element in the
//referenced package's package.xml file.
// referenced package's package.xml file.
std::string version_lt; //< Optional: The dependency to the package is restricted to versions
//less than the stated version number.
// less than the stated version number.
std::string version_lte; //< Optional: The dependency to the package is restricted to versions
//less or equal than the stated version number.
// less or equal than the stated version number.
std::string version_eq; //< Optional: The dependency to the package is restricted to a version
//equal than the stated version number.
// equal than the stated version number.
std::string version_gte; //< Optional: The dependency to the package is restricted to versions
//greater or equal than the stated version number.
// greater or equal than the stated version number.
std::string version_gt; //< Optional: The dependency to the package is restricted to versions
//greater than the stated version number.
// greater than the stated version number.
std::string condition; //< Optional: Conditional expression as documented in REP149.
bool optional; //< Optional: Whether this dependency is considered "optional"
DependencyType dependencyType; //< Optional: defaults to "automatic"
@@ -238,7 +238,7 @@ public:
std::vector<Meta::License>
license() const; //< Must be at least one, and most licenses require including a license file.
std::vector<Meta::Url> url() const; //< Any number of URLs may be specified, but at least one
//repository URL must be included at the package level.
// repository URL must be included at the package level.
std::vector<Meta::Contact>
author() const; //< Any number of authors may be specified, and email addresses are optional.
std::vector<Meta::Dependency>
File diff suppressed because it is too large Load Diff
+296 -180
View File
@@ -34,7 +34,8 @@
#include "ElementNamingUtils.h"
namespace Py {
namespace Py
{
class Object;
}
namespace App
@@ -43,12 +44,14 @@ namespace App
using any = boost::any;
template<class T>
inline const T &any_cast(const boost::any &value) {
inline const T& any_cast(const boost::any& value)
{
return boost::any_cast<const T&>(value);
}
template<class T>
inline T &any_cast(boost::any &value) {
inline T& any_cast(boost::any& value)
{
return boost::any_cast<T&>(value);
}
@@ -58,48 +61,49 @@ class PropertyContainer;
class DocumentObject;
class ExpressionVisitor;
AppExport std::string quote(const std::string &input, bool toPython=false);
AppExport std::string quote(const std::string& input, bool toPython = false);
// Unfortunately VS2013 does not support default move constructor, so we have
// to implement them manually
#define FC_DEFAULT_CTORS(_t) \
_t(const _t &) = default;\
_t &operator=(const _t &) = default;\
_t(_t &&other) { *this = std::move(other); }\
_t &operator=(_t &&other)
#define FC_DEFAULT_CTORS(_t) \
_t(const _t&) = default; \
_t& operator=(const _t&) = default; \
_t(_t&& other) \
{ \
*this = std::move(other); \
} \
_t& operator=(_t&& other)
class AppExport ObjectIdentifier {
class AppExport ObjectIdentifier
{
public:
class AppExport DocumentMapper {
class AppExport DocumentMapper
{
public:
explicit DocumentMapper(const std::map<std::string,std::string> &);
explicit DocumentMapper(const std::map<std::string, std::string>&);
~DocumentMapper();
};
class String {
class String
{
friend class ObjectIdentifier;
public:
String(const std::string& s = "", bool _isRealString = false, bool _forceIdentifier = false)
: str(s)
, isString(_isRealString)
, forceIdentifier(_forceIdentifier)
{} // explicit bombs
String(const std::string &s = "",
bool _isRealString = false,
bool _forceIdentifier = false)
: str(s),
isString(_isRealString),
forceIdentifier(_forceIdentifier)
{}//explicit bombs
explicit String(std::string &&s,
bool _isRealString = false,
bool _forceIdentifier = false)
: str(std::move(s)),
isString(_isRealString),
forceIdentifier(_forceIdentifier)
explicit String(std::string&& s, bool _isRealString = false, bool _forceIdentifier = false)
: str(std::move(s))
, isString(_isRealString)
, forceIdentifier(_forceIdentifier)
{}
FC_DEFAULT_CTORS(String) {
FC_DEFAULT_CTORS(String)
{
str = std::move(other.str);
isString = other.isString;
forceIdentifier = other.forceIdentifier;
@@ -109,40 +113,70 @@ public:
// Accessors
/** Returns the string */
const std::string &getString() const { return str; }
const std::string& getString() const
{
return str;
}
/** Return true is string need to be quoted */
bool isRealString() const { return isString; }
bool isRealString() const
{
return isString;
}
bool isForceIdentifier() const { return forceIdentifier; }
bool isForceIdentifier() const
{
return forceIdentifier;
}
/** Returns a possibly quoted string */
std::string toString(bool toPython=false) const;
std::string toString(bool toPython = false) const;
// Operators
explicit operator std::string() const { return str; }
explicit operator std::string() const
{
return str;
}
explicit operator const char *() const { return str.c_str(); }
explicit operator const char*() const
{
return str.c_str();
}
bool operator==(const String & other) const { return str == other.str; }
bool operator==(const String& other) const
{
return str == other.str;
}
bool operator!=(const String & other) const { return str != other.str; }
bool operator!=(const String& other) const
{
return str != other.str;
}
bool operator>=(const String & other) const { return str >= other.str; }
bool operator>=(const String& other) const
{
return str >= other.str;
}
bool operator<(const String & other) const { return str < other.str; }
bool operator<(const String& other) const
{
return str < other.str;
}
bool operator>(const String & other) const { return str > other.str; }
bool operator>(const String& other) const
{
return str > other.str;
}
void checkImport(const App::DocumentObject* owner,
const App::DocumentObject* obj = nullptr,
String* objName = nullptr);
void checkImport(const App::DocumentObject *owner,
const App::DocumentObject *obj=nullptr, String *objName=nullptr);
private:
std::string str;
bool isString;
bool forceIdentifier;
};
/**
@@ -151,21 +185,22 @@ public:
* a single entry, and array, or a map to other sub-fields.
*/
class AppExport Component {
class AppExport Component
{
private:
enum typeEnum {
enum typeEnum
{
SIMPLE,
MAP,
ARRAY,
RANGE,
} ;
};
public:
// Constructors
FC_DEFAULT_CTORS(Component) {
FC_DEFAULT_CTORS(Component)
{
name = std::move(other.name);
type = other.type;
begin = other.begin;
@@ -174,98 +209,147 @@ public:
return *this;
}
Component(const String &_name = String(), typeEnum _type=SIMPLE,
int begin=INT_MAX, int end=INT_MAX, int step=1);//explicit bombs
Component(String &&_name, typeEnum _type=SIMPLE,
int begin=INT_MAX, int end=INT_MAX, int step=1);//explicit bombs
Component(const String& _name = String(),
typeEnum _type = SIMPLE,
int begin = INT_MAX,
int end = INT_MAX,
int step = 1); // explicit bombs
Component(String&& _name,
typeEnum _type = SIMPLE,
int begin = INT_MAX,
int end = INT_MAX,
int step = 1); // explicit bombs
static Component SimpleComponent(const char * _component);
static Component SimpleComponent(const char* _component);
static Component SimpleComponent(const String & _component);
static Component SimpleComponent(String &&_component);
static Component SimpleComponent(const String& _component);
static Component SimpleComponent(String&& _component);
static Component ArrayComponent(int _index);
static Component RangeComponent(int _begin, int _end = INT_MAX, int _step=1);
static Component RangeComponent(int _begin, int _end = INT_MAX, int _step = 1);
static Component MapComponent(const String &_key);
static Component MapComponent(String &&_key);
static Component MapComponent(const String& _key);
static Component MapComponent(String&& _key);
// Type queries
bool isSimple() const { return type == SIMPLE; }
bool isSimple() const
{
return type == SIMPLE;
}
bool isMap() const { return type == MAP; }
bool isMap() const
{
return type == MAP;
}
bool isArray() const { return type == ARRAY; }
bool isArray() const
{
return type == ARRAY;
}
bool isRange() const { return type == RANGE; }
bool isRange() const
{
return type == RANGE;
}
// Accessors
void toString(std::ostream &ss, bool toPython=false) const;
void toString(std::ostream& ss, bool toPython = false) const;
const std::string &getName() const { return name.getString(); }
const std::string& getName() const
{
return name.getString();
}
int getIndex() const {return begin;}
int getIndex() const
{
return begin;
}
size_t getIndex(size_t count) const;
int getBegin() const { return begin; }
int getEnd() const { return end; }
int getStep() const { return step; }
int getBegin() const
{
return begin;
}
int getEnd() const
{
return end;
}
int getStep() const
{
return step;
}
// Operators
bool operator==(const Component & other) const;
bool operator<(const Component & other) const;
bool operator==(const Component& other) const;
bool operator<(const Component& other) const;
Py::Object get(const Py::Object &pyobj) const;
void set(Py::Object &pyobj, const Py::Object &value) const;
void del(Py::Object &pyobj) const;
Py::Object get(const Py::Object& pyobj) const;
void set(Py::Object& pyobj, const Py::Object& value) const;
void del(Py::Object& pyobj) const;
private:
String name;
typeEnum type;
int begin;
int end;
int step;
friend class ObjectIdentifier;
};
static Component SimpleComponent(const char * _component)
{return Component::SimpleComponent(_component);}
static Component SimpleComponent(const char* _component)
{
return Component::SimpleComponent(_component);
}
static Component SimpleComponent(const String & _component)
{return Component::SimpleComponent(_component);}
static Component SimpleComponent(const String& _component)
{
return Component::SimpleComponent(_component);
}
static Component SimpleComponent(String &&_component)
{return Component::SimpleComponent(std::move(_component));}
static Component SimpleComponent(String&& _component)
{
return Component::SimpleComponent(std::move(_component));
}
static Component SimpleComponent(const std::string _component)
{return Component::SimpleComponent(_component.c_str());}
static Component SimpleComponent(const std::string _component)
{
return Component::SimpleComponent(_component.c_str());
}
static Component ArrayComponent(int _index)
{return Component::ArrayComponent(_index); }
{
return Component::ArrayComponent(_index);
}
static Component RangeComponent(int _begin, int _end = INT_MAX, int _step=1)
{return Component::RangeComponent(_begin,_end,_step);}
static Component RangeComponent(int _begin, int _end = INT_MAX, int _step = 1)
{
return Component::RangeComponent(_begin, _end, _step);
}
static Component MapComponent(const String &_key)
{return Component::MapComponent(_key);}
static Component MapComponent(const String& _key)
{
return Component::MapComponent(_key);
}
static Component MapComponent(String &&_key)
{return Component::MapComponent(_key);}
static Component MapComponent(String&& _key)
{
return Component::MapComponent(_key);
}
explicit ObjectIdentifier(const App::PropertyContainer * _owner = nullptr,
const std::string & property = std::string(), int index=INT_MAX);
explicit ObjectIdentifier(const App::PropertyContainer* _owner = nullptr,
const std::string& property = std::string(),
int index = INT_MAX);
ObjectIdentifier(const App::PropertyContainer * _owner, bool localProperty);
ObjectIdentifier(const App::PropertyContainer* _owner, bool localProperty);
ObjectIdentifier(const App::Property & prop, int index=INT_MAX);//explicit bombs
ObjectIdentifier(const App::Property& prop, int index = INT_MAX); // explicit bombs
FC_DEFAULT_CTORS(ObjectIdentifier) {
FC_DEFAULT_CTORS(ObjectIdentifier)
{
owner = other.owner;
documentName = std::move(other.documentName);
documentObjectName = std::move(other.documentObjectName);
@@ -282,16 +366,21 @@ public:
virtual ~ObjectIdentifier() = default;
App::DocumentObject *getOwner() const { return owner; }
App::DocumentObject* getOwner() const
{
return owner;
}
// Components
void addComponent(const Component &c) {
void addComponent(const Component& c)
{
components.push_back(c);
_cache.clear();
}
// Components
void addComponent(Component &&c) {
void addComponent(Component&& c)
{
components.push_back(std::move(c));
_cache.clear();
}
@@ -299,23 +388,29 @@ public:
std::string getPropertyName() const;
template<typename C>
void addComponents(const C &cs) { components.insert(components.end(), cs.begin(), cs.end()); }
void addComponents(const C& cs)
{
components.insert(components.end(), cs.begin(), cs.end());
}
const Component & getPropertyComponent(int i, int *idx=nullptr) const;
const Component& getPropertyComponent(int i, int* idx = nullptr) const;
void setComponent(int idx, Component &&comp);
void setComponent(int idx, const Component &comp);
void setComponent(int idx, Component&& comp);
void setComponent(int idx, const Component& comp);
std::vector<Component> getPropertyComponents() const;
const std::vector<Component> &getComponents() const { return components; }
const std::vector<Component>& getComponents() const
{
return components;
}
std::string getSubPathStr(bool toPython=false) const;
std::string getSubPathStr(bool toPython = false) const;
int numComponents() const;
int numSubComponents() const;
const std::string &toString() const;
const std::string& toString() const;
std::string toPersistentString() const;
@@ -323,37 +418,46 @@ public:
bool isTouched() const;
App::Property *getProperty(int *ptype=nullptr) const;
App::Property* getProperty(int* ptype = nullptr) const;
App::ObjectIdentifier canonicalPath() const;
// Document-centric functions
void setDocumentName(String &&name, bool force = false);
void setDocumentName(String&& name, bool force = false);
String getDocumentName() const;
void setDocumentObjectName(String &&name, bool force = false,
String &&subname = String(), bool checkImport=false);
void setDocumentObjectName(String&& name,
bool force = false,
String&& subname = String(),
bool checkImport = false);
void setDocumentObjectName(const App::DocumentObject *obj, bool force = false,
String &&subname = String(), bool checkImport=false);
void setDocumentObjectName(const App::DocumentObject* obj,
bool force = false,
String&& subname = String(),
bool checkImport = false);
bool hasDocumentObjectName(bool forced=false) const;
bool hasDocumentObjectName(bool forced = false) const;
bool isLocalProperty() const { return localProperty; }
bool isLocalProperty() const
{
return localProperty;
}
String getDocumentObjectName() const;
const std::string &getSubObjectName(bool newStyle) const;
const std::string &getSubObjectName() const;
const std::string& getSubObjectName(bool newStyle) const;
const std::string& getSubObjectName() const;
using SubNameMap = std::map<std::pair<App::DocumentObject*,std::string>,std::string>;
void importSubNames(const SubNameMap &subNameMap);
using SubNameMap = std::map<std::pair<App::DocumentObject*, std::string>, std::string>;
void importSubNames(const SubNameMap& subNameMap);
bool updateLabelReference(App::DocumentObject *, const std::string &, const char *);
bool updateLabelReference(App::DocumentObject*, const std::string&, const char*);
bool relabeledDocument(ExpressionVisitor &v, const std::string &oldLabel, const std::string &newLabel);
bool relabeledDocument(ExpressionVisitor& v,
const std::string& oldLabel,
const std::string& newLabel);
/** Type for storing dependency of an ObjectIdentifier
*
@@ -365,7 +469,7 @@ public:
* the property may not exist at the time this ObjectIdentifier is
* constructed.
*/
using Dependencies = std::map<App::DocumentObject *, std::set<std::string> >;
using Dependencies = std::map<App::DocumentObject*, std::set<std::string>>;
/** Get dependencies of this object identifier
*
@@ -377,7 +481,7 @@ public:
* first referred object dependency. Or else, all object and property
* dependencies will be returned.
*/
Dependencies getDep(bool needProps, std::vector<std::string> *labels=nullptr) const;
Dependencies getDep(bool needProps, std::vector<std::string>* labels = nullptr) const;
/** Get dependencies of this object identifier
*
@@ -390,104 +494,112 @@ public:
* first referred object dependency. Or else, all object and property
* dependencies will be returned.
*/
void getDep(Dependencies &deps, bool needProps, std::vector<std::string> *labels=nullptr) const;
void
getDep(Dependencies& deps, bool needProps, std::vector<std::string>* labels = nullptr) const;
/// Returns all label references
void getDepLabels(std::vector<std::string> &labels) const;
void getDepLabels(std::vector<std::string>& labels) const;
App::Document *getDocument(String name = String(), bool *ambiguous=nullptr) const;
App::Document* getDocument(String name = String(), bool* ambiguous = nullptr) const;
App::DocumentObject *getDocumentObject() const;
App::DocumentObject* getDocumentObject() const;
std::vector<std::string> getStringList() const;
App::ObjectIdentifier relativeTo(const App::ObjectIdentifier & other) const;
App::ObjectIdentifier relativeTo(const App::ObjectIdentifier& other) const;
bool replaceObject(ObjectIdentifier &res, const App::DocumentObject *parent,
App::DocumentObject *oldObj, App::DocumentObject *newObj) const;
bool replaceObject(ObjectIdentifier& res,
const App::DocumentObject* parent,
App::DocumentObject* oldObj,
App::DocumentObject* newObj) const;
// Operators
App::ObjectIdentifier & operator<<(const Component & value);
App::ObjectIdentifier & operator<<(Component &&value);
App::ObjectIdentifier& operator<<(const Component& value);
App::ObjectIdentifier& operator<<(Component&& value);
bool operator==(const ObjectIdentifier & other) const;
bool operator==(const ObjectIdentifier& other) const;
bool operator!=(const ObjectIdentifier & other) const;
bool operator!=(const ObjectIdentifier& other) const;
bool operator<(const ObjectIdentifier &other) const;
bool operator<(const ObjectIdentifier& other) const;
// Getter
App::any getValue(bool pathValue=false, bool *isPseudoProperty=nullptr) const;
App::any getValue(bool pathValue = false, bool* isPseudoProperty = nullptr) const;
Py::Object getPyValue(bool pathValue=false, bool *isPseudoProperty=nullptr) const;
Py::Object getPyValue(bool pathValue = false, bool* isPseudoProperty = nullptr) const;
// Setter: is const because it does not alter the object state,
// but does have an aiding effect.
void setValue(const App::any & value) const;
void setValue(const App::any& value) const;
// Static functions
static ObjectIdentifier parse(const App::DocumentObject *docObj, const std::string & str);
static ObjectIdentifier parse(const App::DocumentObject* docObj, const std::string& str);
std::string resolveErrorString() const;
bool adjustLinks(ExpressionVisitor &v, const std::set<App::DocumentObject *> &inList);
bool adjustLinks(ExpressionVisitor& v, const std::set<App::DocumentObject*>& inList);
bool updateElementReference(ExpressionVisitor &v, App::DocumentObject *feature=nullptr, bool reverse=false);
bool updateElementReference(ExpressionVisitor& v,
App::DocumentObject* feature = nullptr,
bool reverse = false);
void resolveAmbiguity();
bool verify(const App::Property &prop, bool silent=false) const;
bool verify(const App::Property& prop, bool silent = false) const;
std::size_t hash() const;
protected:
struct ResolveResults
{
struct ResolveResults {
explicit ResolveResults(const ObjectIdentifier& oi);
explicit ResolveResults(const ObjectIdentifier & oi);
int propertyIndex{0};
App::Document * resolvedDocument{nullptr};
int propertyIndex {0};
App::Document* resolvedDocument {nullptr};
String resolvedDocumentName;
App::DocumentObject * resolvedDocumentObject{nullptr};
App::DocumentObject* resolvedDocumentObject {nullptr};
String resolvedDocumentObjectName;
String subObjectName;
App::DocumentObject * resolvedSubObject{nullptr};
App::Property * resolvedProperty{nullptr};
App::DocumentObject* resolvedSubObject {nullptr};
App::Property* resolvedProperty {nullptr};
std::string propertyName;
int propertyType{0};
int propertyType {0};
std::bitset<32> flags;
std::string resolveErrorString() const;
void getProperty(const ObjectIdentifier &oi);
void getProperty(const ObjectIdentifier& oi);
};
friend struct ResolveResults;
App::Property *resolveProperty(const App::DocumentObject *obj,
const char *propertyName, App::DocumentObject *&sobj,int &ptype) const;
App::Property* resolveProperty(const App::DocumentObject* obj,
const char* propertyName,
App::DocumentObject*& sobj,
int& ptype) const;
void getSubPathStr(std::ostream &ss, const ResolveResults &result, bool toPython=false) const;
void getSubPathStr(std::ostream& ss, const ResolveResults& result, bool toPython = false) const;
Py::Object access(const ResolveResults &rs,
Py::Object *value=nullptr, Dependencies *deps=nullptr) const;
Py::Object access(const ResolveResults& rs,
Py::Object* value = nullptr,
Dependencies* deps = nullptr) const;
void resolve(ResolveResults & results) const;
void resolveAmbiguity(ResolveResults &results);
void resolve(ResolveResults& results) const;
void resolveAmbiguity(ResolveResults& results);
static App::DocumentObject *getDocumentObject(
const App::Document *doc, const String &name, std::bitset<32> &flags);
static App::DocumentObject*
getDocumentObject(const App::Document* doc, const String& name, std::bitset<32>& flags);
void getDepLabels(const ResolveResults &result, std::vector<std::string> &labels) const;
void getDepLabels(const ResolveResults& result, std::vector<std::string>& labels) const;
App::DocumentObject * owner;
String documentName;
String documentObjectName;
String subObjectName;
App::DocumentObject* owner;
String documentName;
String documentObjectName;
String subObjectName;
ElementNamePair shadowSub;
std::vector<Component> components;
bool documentNameSet;
@@ -495,35 +607,39 @@ protected:
bool localProperty;
private:
std::string _cache; // Cached string represstation of this identifier
std::size_t _hash; // Cached hash of this string
std::string _cache; // Cached string represstation of this identifier
std::size_t _hash; // Cached hash of this string
};
inline std::size_t hash_value(const App::ObjectIdentifier & path) {
inline std::size_t hash_value(const App::ObjectIdentifier& path)
{
return path.hash();
}
/** Helper function to convert Python object to/from App::any
*
* WARNING! Must hold Python global interpreter lock before calling these
* functions
*/
*
* WARNING! Must hold Python global interpreter lock before calling these
* functions
*/
//@{
App::any AppExport pyObjectToAny(Py::Object pyobj, bool check=true);
Py::Object AppExport pyObjectFromAny(const App::any &value);
App::any AppExport pyObjectToAny(Py::Object pyobj, bool check = true);
Py::Object AppExport pyObjectFromAny(const App::any& value);
//@}
}
} // namespace App
namespace std {
namespace std
{
template<>
struct hash<App::ObjectIdentifier> {
struct hash<App::ObjectIdentifier>
{
using argument_type = App::ObjectIdentifier;
using result_type = std::size_t;
inline result_type operator()(argument_type const& s) const {
inline result_type operator()(argument_type const& s) const
{
return s.hash();
}
};
}
} // namespace std
#endif
+100 -68
View File
@@ -45,7 +45,7 @@ using namespace App;
// Property
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TYPESYSTEM_SOURCE_ABSTRACT(App::Property , Base::Persistence)
TYPESYSTEM_SOURCE_ABSTRACT(App::Property, Base::Persistence)
//**************************************************************************
// Construction/Destruction
@@ -54,9 +54,8 @@ static std::atomic<int64_t> _PropID;
// Here is the implementation! Description should take place in the header file!
Property::Property()
: _id(++_PropID)
{
}
: _id(++_PropID)
{}
Property::~Property() = default;
@@ -75,16 +74,21 @@ bool Property::isValidName(const char* name)
return name && name[0] != '\0';
}
std::string Property::getFullName() const {
std::string Property::getFullName() const
{
std::string name;
if(myName) {
if(father)
if (myName) {
if (father) {
name = father->getFullName() + ".";
else
}
else {
name = "?.";
}
name += myName;
}else
}
else {
return "?";
}
return name;
}
@@ -116,9 +120,11 @@ std::string Property::getFileName(const char* postfix, const char* prefix) const
short Property::getType() const
{
short type = 0;
#define GET_PTYPE(_name) do {\
if(testStatus(App::Property::Prop##_name)) type|=Prop_##_name;\
}while(0)
#define GET_PTYPE(_name) \
do { \
if (testStatus(App::Property::Prop##_name)) \
type |= Prop_##_name; \
} while (0)
GET_PTYPE(ReadOnly);
GET_PTYPE(Hidden);
GET_PTYPE(Output);
@@ -128,10 +134,13 @@ short Property::getType() const
return type;
}
void Property::syncType(unsigned type) {
#define SYNC_PTYPE(_name) do{\
if(type & Prop_##_name) StatusBits.set((size_t)Prop##_name);\
}while(0)
void Property::syncType(unsigned type)
{
#define SYNC_PTYPE(_name) \
do { \
if (type & Prop_##_name) \
StatusBits.set((size_t)Prop##_name); \
} while (0)
SYNC_PTYPE(ReadOnly);
SYNC_PTYPE(Transient);
SYNC_PTYPE(Hidden);
@@ -150,32 +159,33 @@ const char* Property::getDocumentation() const
return father->getPropertyDocumentation(this);
}
void Property::setContainer(PropertyContainer *Father)
void Property::setContainer(PropertyContainer* Father)
{
father = Father;
}
void Property::setPathValue(const ObjectIdentifier &path, const boost::any &value)
void Property::setPathValue(const ObjectIdentifier& path, const boost::any& value)
{
path.setValue(value);
}
const boost::any Property::getPathValue(const ObjectIdentifier &path) const
const boost::any Property::getPathValue(const ObjectIdentifier& path) const
{
return path.getValue();
}
void Property::getPaths(std::vector<ObjectIdentifier> &paths) const
void Property::getPaths(std::vector<ObjectIdentifier>& paths) const
{
paths.emplace_back(getContainer(), getName());
}
ObjectIdentifier Property::canonicalPath(const ObjectIdentifier &p) const
ObjectIdentifier Property::canonicalPath(const ObjectIdentifier& p) const
{
return p;
}
namespace App {
namespace App
{
/*!
* \brief The PropertyCleaner struct
* Make deleting dynamic property safer by postponing its destruction.
@@ -186,43 +196,51 @@ namespace App {
* removed property, and only deleting them when no onChanged() call is
* active.
*/
struct PropertyCleaner {
explicit PropertyCleaner(Property *p)
struct PropertyCleaner
{
explicit PropertyCleaner(Property* p)
: prop(p)
{
++_PropCleanerCounter;
}
~PropertyCleaner() {
if(--_PropCleanerCounter)
~PropertyCleaner()
{
if (--_PropCleanerCounter) {
return;
}
bool found = false;
while (!_RemovedProps.empty()) {
auto p = _RemovedProps.back();
_RemovedProps.pop_back();
if(p != prop)
if (p != prop) {
delete p;
else
}
else {
found = true;
}
}
if (found)
if (found) {
_RemovedProps.push_back(prop);
}
}
static void add(Property *prop) {
static void add(Property* prop)
{
_RemovedProps.push_back(prop);
}
Property *prop;
Property* prop;
static std::vector<Property*> _RemovedProps;
static int _PropCleanerCounter;
};
}
} // namespace App
std::vector<Property*> PropertyCleaner::_RemovedProps;
int PropertyCleaner::_PropCleanerCounter = 0;
void Property::destroy(Property *p) {
void Property::destroy(Property* p)
{
if (p) {
// Is it necessary to nullify the container? May cause crash if any
// onChanged() caller assumes a non-null container.
@@ -253,8 +271,8 @@ void Property::hasSetValue()
PropertyCleaner guard(this);
if (father) {
father->onChanged(this);
if(!testStatus(Busy)) {
Base::BitsetLocker<decltype(StatusBits)> guard(StatusBits,Busy);
if (!testStatus(Busy)) {
Base::BitsetLocker<decltype(StatusBits)> guard(StatusBits, Busy);
signalChanged(*this);
}
}
@@ -263,16 +281,17 @@ void Property::hasSetValue()
void Property::aboutToSetValue()
{
if (father)
if (father) {
father->onBeforeChange(this);
}
}
void Property::verifyPath(const ObjectIdentifier &p) const
void Property::verifyPath(const ObjectIdentifier& p) const
{
p.verify(*this);
}
Property *Property::Copy() const
Property* Property::Copy() const
{
// have to be reimplemented by a subclass!
assert(0);
@@ -285,7 +304,8 @@ void Property::Paste(const Property& /*from*/)
assert(0);
}
void Property::setStatusValue(unsigned long status) {
void Property::setStatusValue(unsigned long status)
{
// clang-format off
static const unsigned long mask =
(1<<PropDynamic)
@@ -303,26 +323,31 @@ void Property::setStatusValue(unsigned long status) {
unsigned long oldStatus = StatusBits.to_ulong();
StatusBits = decltype(StatusBits)(status);
if(father) {
static unsigned long _signalMask = (1<<ReadOnly) | (1<<Hidden);
if((status & _signalMask) != (oldStatus & _signalMask))
father->onPropertyStatusChanged(*this,oldStatus);
if (father) {
static unsigned long _signalMask = (1 << ReadOnly) | (1 << Hidden);
if ((status & _signalMask) != (oldStatus & _signalMask)) {
father->onPropertyStatusChanged(*this, oldStatus);
}
}
}
void Property::setStatus(Status pos, bool on) {
void Property::setStatus(Status pos, bool on)
{
auto bits = StatusBits;
bits.set(pos,on);
bits.set(pos, on);
setStatusValue(bits.to_ulong());
}
bool Property::isSame(const Property &other) const {
if(&other == this)
bool Property::isSame(const Property& other) const
{
if (&other == this) {
return true;
if(other.getTypeId() != getTypeId() || getMemSize() != other.getMemSize())
}
if (other.getTypeId() != getTypeId() || getMemSize() != other.getMemSize()) {
return false;
}
Base::StringWriter writer,writer2;
Base::StringWriter writer, writer2;
Save(writer);
other.Save(writer2);
return writer.getString() == writer2.getString();
@@ -333,9 +358,10 @@ bool Property::isSame(const Property &other) const {
// PropertyListsBase
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void PropertyListsBase::_setPyObject(PyObject *value) {
void PropertyListsBase::_setPyObject(PyObject* value)
{
std::vector<int> indices;
std::vector<PyObject *> vals;
std::vector<PyObject*> vals;
Py::Object pySeq;
if (PyDict_Check(value)) {
@@ -344,42 +370,48 @@ void PropertyListsBase::_setPyObject(PyObject *value) {
vals.reserve(size);
indices.reserve(size);
int listSize = getSize();
for(auto it=dict.begin();it!=dict.end();++it) {
const auto &item = *it;
PyObject *key = item.first.ptr();
if(!PyLong_Check(key))
for (auto it = dict.begin(); it != dict.end(); ++it) {
const auto& item = *it;
PyObject* key = item.first.ptr();
if (!PyLong_Check(key)) {
throw Base::TypeError("expect key type to be integer");
}
long idx = PyLong_AsLong(key);
if(idx<-1 || idx>listSize)
if (idx < -1 || idx > listSize) {
throw Base::ValueError("index out of bound");
if(idx==-1 || idx==listSize) {
}
if (idx == -1 || idx == listSize) {
idx = listSize;
++listSize;
}
indices.push_back(idx);
vals.push_back(item.second.ptr());
}
} else {
if (PySequence_Check(value))
}
else {
if (PySequence_Check(value)) {
pySeq = value;
}
else {
PyObject *iter = PyObject_GetIter(value);
if(iter) {
Py::Object pyIter(iter,true);
pySeq = Py::asObject(PySequence_Fast(iter,""));
} else {
PyObject* iter = PyObject_GetIter(value);
if (iter) {
Py::Object pyIter(iter, true);
pySeq = Py::asObject(PySequence_Fast(iter, ""));
}
else {
PyErr_Clear();
vals.push_back(value);
}
}
if(!pySeq.isNone()) {
if (!pySeq.isNone()) {
Py::Sequence seq(pySeq);
vals.reserve(seq.size());
for(auto it=seq.begin();it!=seq.end();++it)
for (auto it = seq.begin(); it != seq.end(); ++it) {
vals.push_back((*it).ptr());
}
}
}
setPyValues(vals,indices);
setPyValues(vals, indices);
}
@@ -388,4 +420,4 @@ void PropertyListsBase::_setPyObject(PyObject *value) {
// PropertyLists
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLists , App::Property)
TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLists, App::Property)
+195 -122
View File
@@ -33,7 +33,8 @@
#include <FCGlobal.h>
#include "ElementNamingUtils.h"
namespace Py {
namespace Py
{
class Object;
}
@@ -52,33 +53,34 @@ class ObjectIdentifier;
* possible properties. It is also possible to define user properties
* and use them in the framework...
*/
class AppExport Property : public Base::Persistence
class AppExport Property: public Base::Persistence
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
enum Status
{
Touched = 0, // touched property
Immutable = 1, // can't modify property
ReadOnly = 2, // for property editor
Hidden = 3, // for property editor
Transient = 4, // for property container save
MaterialEdit = 5, // to turn ON PropertyMaterial edit
NoMaterialListEdit = 6, // to turn OFF PropertyMaterialList edit
Output = 7, // same effect as Prop_Output
LockDynamic = 8, // prevent being removed from dynamic property
NoModify = 9, // prevent causing Gui::Document::setModified()
PartialTrigger = 10, // allow change in partial doc
NoRecompute = 11, // touch owner for recompute on property change
Single = 12, // for save/load of floating point numbers
Ordered = 13, // for PropertyLists whether the order of the elements is
// relevant for the container using it
EvalOnRestore = 14, // In case of expression binding, evaluate the
// expression on restore and touch the object on value change.
Busy = 15, // internal use to avoid recursive signaling
CopyOnChange = 16, // for Link to copy the linked object on change of the property with this flag
UserEdit = 17, // cause property editor to create button for user defined editing
Touched = 0, // touched property
Immutable = 1, // can't modify property
ReadOnly = 2, // for property editor
Hidden = 3, // for property editor
Transient = 4, // for property container save
MaterialEdit = 5, // to turn ON PropertyMaterial edit
NoMaterialListEdit = 6, // to turn OFF PropertyMaterialList edit
Output = 7, // same effect as Prop_Output
LockDynamic = 8, // prevent being removed from dynamic property
NoModify = 9, // prevent causing Gui::Document::setModified()
PartialTrigger = 10, // allow change in partial doc
NoRecompute = 11, // touch owner for recompute on property change
Single = 12, // for save/load of floating point numbers
Ordered = 13, // for PropertyLists whether the order of the elements is
// relevant for the container using it
EvalOnRestore = 14, // In case of expression binding, evaluate the
// expression on restore and touch the object on value change.
Busy = 15, // internal use to avoid recursive signaling
CopyOnChange =
16, // for Link to copy the linked object on change of the property with this flag
UserEdit = 17, // cause property editor to create button for user defined editing
// The following bits are corresponding to PropertyType set when the
// property added. These types are meant to be static, and cannot be
@@ -86,26 +88,26 @@ public:
// required in PropertyContainer::getPropertyType()
//
PropStaticBegin = 21,
PropDynamic = 21, // indicating the property is dynamically added
PropNoPersist = 22, // corresponding to Prop_NoPersist
PropNoRecompute = 23, // corresponding to Prop_NoRecompute
PropReadOnly = 24, // corresponding to Prop_ReadOnly
PropTransient= 25, // corresponding to Prop_Transient
PropHidden = 26, // corresponding to Prop_Hidden
PropOutput = 27, // corresponding to Prop_Output
PropDynamic = 21, // indicating the property is dynamically added
PropNoPersist = 22, // corresponding to Prop_NoPersist
PropNoRecompute = 23, // corresponding to Prop_NoRecompute
PropReadOnly = 24, // corresponding to Prop_ReadOnly
PropTransient = 25, // corresponding to Prop_Transient
PropHidden = 26, // corresponding to Prop_Hidden
PropOutput = 27, // corresponding to Prop_Output
PropStaticEnd = 28,
User1 = 28, // user-defined status
User2 = 29, // user-defined status
User3 = 30, // user-defined status
User4 = 31 // user-defined status
User1 = 28, // user-defined status
User2 = 29, // user-defined status
User3 = 30, // user-defined status
User4 = 31 // user-defined status
};
Property();
~Property() override;
/// For safe deleting of a dynamic property
static void destroy(Property *p);
static void destroy(Property* p);
/** This method is used to get the size of objects
* It is not meant to have the exact size, it is more or less an estimation
@@ -113,7 +115,8 @@ public:
* This method is defined in Base::Persistence
* @see Base::Persistence
*/
unsigned int getMemSize () const override {
unsigned int getMemSize() const override
{
// you have to implement this method in all property classes!
return sizeof(father) + sizeof(StatusBits);
}
@@ -136,7 +139,10 @@ public:
std::string getFullName() const;
/// Get the class name of the associated property editor item
virtual const char* getEditorName() const { return ""; }
virtual const char* getEditorName() const
{
return "";
}
/// Get the type of the property in the container
short getType() const;
@@ -148,27 +154,31 @@ public:
const char* getDocumentation() const;
/// Is called by the framework to set the father (container)
void setContainer(PropertyContainer *Father);
void setContainer(PropertyContainer* Father);
/// Get a pointer to the PropertyContainer derived class the property belongs to
PropertyContainer *getContainer() const {return father;}
PropertyContainer* getContainer() const
{
return father;
}
/// Set value of property
virtual void setPathValue(const App::ObjectIdentifier & path, const boost::any & value);
virtual void setPathValue(const App::ObjectIdentifier& path, const boost::any& value);
/// Get value of property
virtual const boost::any getPathValue(const App::ObjectIdentifier & path) const;
virtual const boost::any getPathValue(const App::ObjectIdentifier& path) const;
/// Get Python value of property
virtual bool getPyPathValue(const App::ObjectIdentifier &, Py::Object &) const {
virtual bool getPyPathValue(const App::ObjectIdentifier&, Py::Object&) const
{
return false;
}
/// Convert p to a canonical representation of it
virtual App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier & p) const;
virtual App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier& p) const;
/// Get valid paths for this property; used by auto completer
virtual void getPaths(std::vector<App::ObjectIdentifier> & paths) const;
virtual void getPaths(std::vector<App::ObjectIdentifier>& paths) const;
/** Called at the beginning of Document::afterRestore()
*
@@ -190,7 +200,8 @@ public:
* with existing documents. PropertyExpressionEngine can now auto adjust
* external references without any problem.
*/
virtual void afterRestore() {}
virtual void afterRestore()
{}
/** Called before calling DocumentObject::onDocumentRestored()
*
@@ -199,7 +210,8 @@ public:
* is assumed ready. So, unlike Property::afterRestore(), this function is
* called on objects with dependency order.
*/
virtual void onContainerRestored() {}
virtual void onContainerRestored()
{}
/** Property status handling
*/
@@ -207,50 +219,59 @@ public:
/// Set the property touched
void touch();
/// Test if this property is touched
inline bool isTouched() const {
inline bool isTouched() const
{
return StatusBits.test(Touched);
}
/// Reset this property touched
inline void purgeTouched() {
inline void purgeTouched()
{
StatusBits.reset(Touched);
}
/// return the status bits
inline unsigned long getStatus() const {
inline unsigned long getStatus() const
{
return StatusBits.to_ulong();
}
inline bool testStatus(Status pos) const {
inline bool testStatus(Status pos) const
{
return StatusBits.test(static_cast<size_t>(pos));
}
void setStatus(Status pos, bool on);
void setStatusValue(unsigned long status);
///Sets property editable/grayed out in property editor
/// Sets property editable/grayed out in property editor
void setReadOnly(bool readOnly);
inline bool isReadOnly() const {
inline bool isReadOnly() const
{
return testStatus(App::Property::ReadOnly);
}
/// Sets precision of properties using floating point
/// numbers to single, the default is double.
void setSinglePrecision(bool single) {
void setSinglePrecision(bool single)
{
setStatus(App::Property::Single, single);
}
/// Gets precision of properties using floating point numbers
inline bool isSinglePrecision() const {
inline bool isSinglePrecision() const
{
return testStatus(App::Property::Single);
}
//@}
/// Returns a new copy of the property (mainly for Undo/Redo and transactions)
virtual Property *Copy() const = 0;
virtual Property* Copy() const = 0;
/// Paste the value from the property (mainly for Undo/Redo and transactions)
virtual void Paste(const Property &from) = 0;
virtual void Paste(const Property& from) = 0;
/// Called when a child property has changed value
virtual void hasSetChildValue(Property &) {}
virtual void hasSetChildValue(Property&)
{}
/// Called before a child property changing value
virtual void aboutToSetChildValue(Property &) {}
virtual void aboutToSetChildValue(Property&)
{}
/// Compare if this property has the same content as the given one
virtual bool isSame(const Property &other) const;
virtual bool isSame(const Property& other) const;
/** Return a unique ID for the property
*
@@ -258,11 +279,15 @@ public:
* internal counter. The intention of the ID is to be used as a key for
* mapping, instead of using the raw pointer. Because, it is possible for
* the runtime memory allocator to reuse just deleted memory, which will
* cause hard to debug problem if use pointer as key.
* cause hard to debug problem if use pointer as key.
*/
int64_t getID() const {return _id;}
int64_t getID() const
{
return _id;
}
virtual void beforeSave() const {}
virtual void beforeSave() const
{}
friend class PropertyContainer;
friend struct PropertyData;
@@ -287,31 +312,32 @@ protected:
virtual void aboutToSetValue();
/// Verify a path for the current property
virtual void verifyPath(const App::ObjectIdentifier & p) const;
virtual void verifyPath(const App::ObjectIdentifier& p) const;
/// Return a file name suitable for saving this property
std::string getFileName(const char *postfix=0, const char *prefix=0) const;
std::string getFileName(const char* postfix = 0, const char* prefix = 0) const;
public:
// forbidden
Property(const Property&) = delete;
Property& operator = (const Property&) = delete;
Property& operator=(const Property&) = delete;
private:
// Sync status with Property_Type
void syncType(unsigned type);
private:
PropertyContainer *father{nullptr};
const char *myName{nullptr};
PropertyContainer* father {nullptr};
const char* myName {nullptr};
int64_t _id;
public:
boost::signals2::signal<void (const App::Property&)> signalChanged;
boost::signals2::signal<void(const App::Property&)> signalChanged;
};
/** A template class that is used to inhibit multiple nested calls to aboutToSetValue/hasSetValue for properties.
/** A template class that is used to inhibit multiple nested calls to aboutToSetValue/hasSetValue
* for properties.
*
* A template class that is used to inhibit multiple nested calls to
* aboutToSetValue/hasSetValue for properties, and only invoke it on change and
@@ -338,12 +364,15 @@ public:
* you can manually call AtomicPropertyChange::tryInvoke(). If the condition is
* satisfied, it will call hasSetValue() that allows exception propagation.
*/
template<class P> class AtomicPropertyChangeInterface {
template<class P>
class AtomicPropertyChangeInterface
{
protected:
AtomicPropertyChangeInterface() = default;
public:
class AtomicPropertyChange {
class AtomicPropertyChange
{
public:
/** Constructor
*
@@ -352,10 +381,13 @@ public:
* hasn't been marked before, and calls its
* aboutToSetValue().
*/
explicit AtomicPropertyChange(P & prop, bool markChange=true) : mProp(prop) {
explicit AtomicPropertyChange(P& prop, bool markChange = true)
: mProp(prop)
{
mProp.signalCounter++;
if (markChange)
if (markChange) {
aboutToChange();
}
}
/** Mark the property as changed
@@ -363,7 +395,8 @@ public:
* It will mark the property as changed only if it has been marked
* before, and only then will it call the property's aboutToSetValue().
*/
void aboutToChange() {
void aboutToChange()
{
if (!mProp.hasChanged) {
mProp.hasChanged = true;
mProp.aboutToSetValue();
@@ -376,7 +409,8 @@ public:
* of the class in current call stack, it will call property's
* hasSetValue()
*/
~AtomicPropertyChange() {
~AtomicPropertyChange()
{
// Signal counter == 1? meaning we are the last one. Invoke
// hasSetValue() before decrease counter to prevent recursive call
// triggered by another AtomicPropertyChange created inside
@@ -385,13 +419,17 @@ public:
// Must make sure to not throw in a destructor
try {
mProp.hasSetValue();
} catch(Base::Exception &e) {
}
catch (Base::Exception& e) {
e.ReportException();
} catch(...) {}
}
catch (...) {
}
mProp.hasChanged = false;
}
if (mProp.signalCounter>0)
if (mProp.signalCounter > 0) {
mProp.signalCounter--;
}
}
/** Check and invoke property's hasSetValue()
@@ -401,22 +439,24 @@ public:
*/
// Destructor cannot throw. So we provide this function to allow error
// propagation.
void tryInvoke() {
if (mProp.signalCounter==1 && mProp.hasChanged) {
void tryInvoke()
{
if (mProp.signalCounter == 1 && mProp.hasChanged) {
mProp.hasSetValue();
if (mProp.signalCounter>0)
if (mProp.signalCounter > 0) {
--mProp.signalCounter;
}
mProp.hasChanged = false;
}
}
private:
P & mProp; /**< Referenced to property we work on */
P& mProp; /**< Referenced to property we work on */
};
protected:
int signalCounter{0}; /**< Counter for invoking transaction start/stop */
bool hasChanged{false};
int signalCounter {0}; /**< Counter for invoking transaction start/stop */
bool hasChanged {false};
};
@@ -429,25 +469,28 @@ protected:
class AppExport PropertyListsBase
{
public:
virtual void setSize(int newSize)=0;
virtual int getSize() const =0;
virtual void setSize(int newSize) = 0;
virtual int getSize() const = 0;
const std::set<int> &getTouchList() const {
const std::set<int>& getTouchList() const
{
return _touchList;
}
void clearTouchList() {
void clearTouchList()
{
_touchList.clear();
}
protected:
virtual void setPyValues(const std::vector<PyObject*> &vals, const std::vector<int> &indices) {
virtual void setPyValues(const std::vector<PyObject*>& vals, const std::vector<int>& indices)
{
(void)vals;
(void)indices;
throw Base::NotImplementedError("not implemented");
}
void _setPyObject(PyObject *);
void _setPyObject(PyObject*);
protected:
std::set<int> _touchList;
@@ -458,111 +501,141 @@ protected:
* multiple values, not only a single value.
* All property types which may contain more than one value inherits this class.
*/
class AppExport PropertyLists : public Property, public PropertyListsBase
class AppExport PropertyLists: public Property, public PropertyListsBase
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
void setPyObject(PyObject *obj) override {
void setPyObject(PyObject* obj) override
{
_setPyObject(obj);
}
// if the order of the elements in the list relevant?
// if yes, certain operations, like restoring must make sure that the
// order is kept despite errors.
inline void setOrderRelevant(bool on) { this->setStatus(Status::Ordered,on); }
inline bool isOrderRelevant() const { return this->testStatus(Status::Ordered);}
inline void setOrderRelevant(bool on)
{
this->setStatus(Status::Ordered, on);
}
inline bool isOrderRelevant() const
{
return this->testStatus(Status::Ordered);
}
};
/** Helper class to implement PropertyLists */
template<class T, class ListT = std::vector<T>, class ParentT = PropertyLists >
class PropertyListsT: public ParentT
, public AtomicPropertyChangeInterface<PropertyListsT<T,ListT,ParentT> >
template<class T, class ListT = std::vector<T>, class ParentT = PropertyLists>
class PropertyListsT: public ParentT,
public AtomicPropertyChangeInterface<PropertyListsT<T, ListT, ParentT>>
{
public:
using const_reference = typename ListT::const_reference;
using list_type = ListT;
using parent_type = ParentT;
using atomic_change = typename AtomicPropertyChangeInterface<
PropertyListsT<T,ListT,ParentT> >::AtomicPropertyChange;
PropertyListsT<T, ListT, ParentT>>::AtomicPropertyChange;
friend atomic_change;
virtual void setSize(int newSize, const_reference def) {
_lValueList.resize(newSize,def);
virtual void setSize(int newSize, const_reference def)
{
_lValueList.resize(newSize, def);
}
void setSize(int newSize) override {
void setSize(int newSize) override
{
_lValueList.resize(newSize);
}
int getSize() const override {
int getSize() const override
{
return static_cast<int>(_lValueList.size());
}
void setValue(const_reference value) {
void setValue(const_reference value)
{
ListT vals;
vals.resize(1,value);
vals.resize(1, value);
setValues(vals);
}
virtual void setValues(const ListT &newValues = ListT()) {
virtual void setValues(const ListT& newValues = ListT())
{
atomic_change guard(*this);
this->_touchList.clear();
this->_lValueList = newValues;
guard.tryInvoke();
}
void setValue(const ListT &newValues = ListT()) {
void setValue(const ListT& newValues = ListT())
{
setValues(newValues);
}
const ListT &getValues() const{return _lValueList;}
const ListT& getValues() const
{
return _lValueList;
}
// alias to getValues
const ListT &getValue() const{return getValues();}
const ListT& getValue() const
{
return getValues();
}
const_reference operator[] (int idx) const {return _lValueList[idx];}
const_reference operator[](int idx) const
{
return _lValueList[idx];
}
bool isSame(const Property &other) const override {
if (&other == this)
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
return this->getTypeId() == other.getTypeId()
&& this->getValue() == static_cast<decltype(this)>(&other)->getValue();
}
void setPyObject(PyObject *value) override {
void setPyObject(PyObject* value) override
{
try {
setValue(getPyValue(value));
return;
}catch(...){}
}
catch (...) {
}
parent_type::setPyObject(value);
}
virtual void set1Value(int index, const_reference value) {
virtual void set1Value(int index, const_reference value)
{
int size = getSize();
if (index<-1 || index>size)
if (index < -1 || index > size) {
throw Base::RuntimeError("index out of bound");
}
atomic_change guard(*this);
if (index==-1 || index == size) {
if (index == -1 || index == size) {
index = size;
setSize(index+1,value);
} else
setSize(index + 1, value);
}
else {
_lValueList[index] = value;
}
this->_touchList.insert(index);
guard.tryInvoke();
}
protected:
void setPyValues(const std::vector<PyObject*>& vals, const std::vector<int>& indices) override
{
if (indices.empty()) {
ListT values {};
values.reserve(vals.size());
for (auto *valsContent : vals) {
for (auto* valsContent : vals) {
values.push_back(getPyValue(valsContent));
}
setValues(std::move(values));
@@ -584,6 +657,6 @@ protected:
ListT _lValueList;
};
} // namespace App
} // namespace App
#endif // APP_PROPERTY_H
#endif // APP_PROPERTY_H
+60 -60
View File
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
Name="PropertyContainerPy"
TwinPointer="PropertyContainer"
Twin="PropertyContainer"
Include="App/PropertyContainer.h"
Namespace="App"
FatherInclude="Base/PersistencePy.h"
<PythonExport
Father="PersistencePy"
Name="PropertyContainerPy"
TwinPointer="PropertyContainer"
Twin="PropertyContainer"
Include="App/PropertyContainer.h"
Namespace="App"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
DisableNotify="true">
<Documentation>
@@ -16,14 +16,14 @@
</Documentation>
<Methode Name="getPropertyByName">
<Documentation>
<UserDocu>getPropertyByName(name, checkOwner=0) -> object or Tuple
<UserDocu>getPropertyByName(name, checkOwner=0) -> object or Tuple
Returns the value of a named property. Note that the returned property may not
always belong to this container (e.g. from a linked object).
always belong to this container (e.g. from a linked object).
name : str
name : str
Name of the property.
checkOwner : int
checkOwner : int
0: just return the property.
1: raise exception if not found or the property does not belong to this container.
2: return a tuple (owner, propertyValue).</UserDocu>
@@ -31,44 +31,44 @@ checkOwner : int
</Methode>
<Methode Name="getPropertyTouchList">
<Documentation>
<UserDocu>getPropertyTouchList(name) -> tuple
<UserDocu>getPropertyTouchList(name) -> tuple
Returns a list of index of touched values for list type properties.
Returns a list of index of touched values for list type properties.
name : str
name : str
Property name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getTypeOfProperty">
<Documentation>
<UserDocu>getTypeOfProperty(name) -> list
<UserDocu>getTypeOfProperty(name) -> list
Returns the type of a named property. This can be a list conformed by elements in
(Hidden, NoRecompute, NoPersist, Output, ReadOnly, Transient).
(Hidden, NoRecompute, NoPersist, Output, ReadOnly, Transient).
name : str
name : str
Property name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getTypeIdOfProperty">
<Documentation>
<UserDocu>getTypeIdOfProperty(name) -> str
<UserDocu>getTypeIdOfProperty(name) -> str
Returns the C++ class name of a named property.
Returns the C++ class name of a named property.
name : str
name : str
Property name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="setEditorMode">
<Documentation>
<UserDocu>setEditorMode(name, type) -> None
<UserDocu>setEditorMode(name, type) -> None
Set the behaviour of the property in the property editor.
Set the behaviour of the property in the property editor.
name : str
name : str
Property name.
type : int, sequence of str
type : int, sequence of str
Property type.
0: default behaviour. 1: item is ready-only. 2: item is hidden. 3: item is hidden and read-only.
If sequence, the available items are 'ReadOnly' and 'Hidden'.</UserDocu>
@@ -76,121 +76,121 @@ type : int, sequence of str
</Methode>
<Methode Name="getEditorMode">
<Documentation>
<UserDocu>getEditorMode(name) -> list
<UserDocu>getEditorMode(name) -> list
Get the behaviour of the property in the property editor.
It returns a list of strings with the current mode. If the list is empty there are no
special restrictions.
If the list contains 'ReadOnly' then the item appears in the property editor but is
disabled.
If the list contains 'Hidden' then the item even doesn't appear in the property editor.
If the list contains 'Hidden' then the item even doesn't appear in the property editor.
name : str
name : str
Property name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getGroupOfProperty">
<Documentation>
<UserDocu>getGroupOfProperty(name) -> str
<UserDocu>getGroupOfProperty(name) -> str
Returns the name of the group which the property belongs to in this class.
The properties are sorted in different named groups for convenience.
The properties are sorted in different named groups for convenience.
name : str
name : str
Property name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="setGroupOfProperty">
<Documentation>
<UserDocu>setGroupOfProperty(name, group) -> None
<UserDocu>setGroupOfProperty(name, group) -> None
Set the name of the group of a dynamic property.
Set the name of the group of a dynamic property.
name : str
name : str
Property name.
group : str
group : str
Group name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="setPropertyStatus">
<Documentation>
<UserDocu>setPropertyStatus(name, val) -> None
<UserDocu>setPropertyStatus(name, val) -> None
Set property status.
Set property status.
name : str
name : str
Property name.
val : int, str, sequence of str or int
val : int, str, sequence of str or int
Call getPropertyStatus() to get a list of supported text value.
If the text start with '-' or the integer value is negative, then the status is cleared.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getPropertyStatus">
<Documentation>
<UserDocu>getPropertyStatus(name='') -> list
<UserDocu>getPropertyStatus(name='') -> list
Get property status.
Get property status.
name : str
name : str
Property name. If empty, returns a list of supported text names of the status.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getDocumentationOfProperty">
<Documentation>
<UserDocu>getDocumentationOfProperty(name) -> str
<UserDocu>getDocumentationOfProperty(name) -> str
Returns the documentation string of the property of this class.
Returns the documentation string of the property of this class.
name : str
name : str
Property name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="setDocumentationOfProperty">
<Documentation>
<UserDocu>setDocumentationOfProperty(name, docstring) -> None
<UserDocu>setDocumentationOfProperty(name, docstring) -> None
Set the documentation string of a dynamic property of this class.
Set the documentation string of a dynamic property of this class.
name : str
name : str
Property name.
docstring : str
docstring : str
Documentation string.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getEnumerationsOfProperty">
<Documentation>
<UserDocu>getEnumerationsOfProperty(name) -> list or None
<UserDocu>getEnumerationsOfProperty(name) -> list or None
Return all enumeration strings of the property of this class or None if not a
PropertyEnumeration.
PropertyEnumeration.
name : str
name : str
Property name.</UserDocu>
</Documentation>
</Methode>
<Methode Name="dumpPropertyContent" Keyword="true" Const="true">
<Documentation>
<UserDocu>dumpPropertyContent(Property, Compression=3) -> bytearray
<UserDocu>dumpPropertyContent(Property, Compression=3) -> bytearray
Dumps the content of the property, both the XML representation and the additional
data files required, into a byte representation.
data files required, into a byte representation.
Property : str
Property : str
Property Name.
Compression : int
Compression : int
Set the data compression level in the range [0, 9]. Set to 0 for no compression.</UserDocu>
</Documentation>
</Methode>
<Methode Name="restorePropertyContent">
<Documentation>
<UserDocu>restorePropertyContent(name, obj) -> None
<UserDocu>restorePropertyContent(name, obj) -> None
Restore the content of the object from a byte representation as stored by `dumpPropertyContent`.
It could be restored from any Python object implementing the buffer protocol.
It could be restored from any Python object implementing the buffer protocol.
name : str
name : str
Property name.
obj : buffer
obj : buffer
Object with buffer protocol support.</UserDocu>
</Documentation>
</Methode>
+208 -152
View File
@@ -24,7 +24,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
#include <sstream>
#endif
#include "PropertyContainer.h"
@@ -49,12 +49,13 @@ std::string PropertyContainerPy::representation() const
return {"<property container>"};
}
PyObject* PropertyContainerPy::getPropertyByName(PyObject *args)
PyObject* PropertyContainerPy::getPropertyByName(PyObject* args)
{
char *pstr;
int checkOwner=0;
if (!PyArg_ParseTuple(args, "s|i", &pstr, &checkOwner))
char* pstr {};
int checkOwner = 0;
if (!PyArg_ParseTuple(args, "s|i", &pstr, &checkOwner)) {
return nullptr;
}
if (checkOwner < 0 || checkOwner > 2) {
PyErr_SetString(PyExc_ValueError, "'checkOwner' expected in the range [0, 2]");
@@ -67,76 +68,87 @@ PyObject* PropertyContainerPy::getPropertyByName(PyObject *args)
return nullptr;
}
if (!checkOwner || (checkOwner==1 && prop->getContainer()==getPropertyContainerPtr()))
if (!checkOwner || (checkOwner == 1 && prop->getContainer() == getPropertyContainerPtr())) {
return prop->getPyObject();
}
Py::TupleN res(Py::asObject(prop->getContainer()->getPyObject()), Py::asObject(prop->getPyObject()));
Py::TupleN res(Py::asObject(prop->getContainer()->getPyObject()),
Py::asObject(prop->getPyObject()));
return Py::new_reference_to(res);
}
PyObject* PropertyContainerPy::getPropertyTouchList(PyObject *args)
PyObject* PropertyContainerPy::getPropertyTouchList(PyObject* args)
{
char *pstr;
if (!PyArg_ParseTuple(args, "s", &pstr))
char* pstr {};
if (!PyArg_ParseTuple(args, "s", &pstr)) {
return nullptr;
}
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (prop && prop->isDerivedFrom(PropertyLists::getClassTypeId())) {
const auto &touched = static_cast<PropertyLists*>(prop)->getTouchList();
const auto& touched = static_cast<PropertyLists*>(prop)->getTouchList();
Py::Tuple ret(touched.size());
int i=0;
for(int idx : touched)
ret.setItem(i++,Py::Long(idx));
int i = 0;
for (int idx : touched) {
ret.setItem(i++, Py::Long(idx));
}
return Py::new_reference_to(ret);
}
else if (!prop) {
PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr);
return nullptr;
}
else {
PyErr_Format(PyExc_AttributeError, "Property '%s' is not of list type", pstr);
return nullptr;
}
}
PyObject* PropertyContainerPy::getTypeOfProperty(PyObject *args)
{
Py::List ret;
char *pstr;
if (!PyArg_ParseTuple(args, "s", &pstr))
return nullptr;
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (!prop) {
PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr);
return nullptr;
}
short Type = prop->getType();
if (Type & Prop_ReadOnly)
PyErr_Format(PyExc_AttributeError, "Property '%s' is not of list type", pstr);
return nullptr;
}
PyObject* PropertyContainerPy::getTypeOfProperty(PyObject* args)
{
Py::List ret;
char* pstr {};
if (!PyArg_ParseTuple(args, "s", &pstr)) {
return nullptr;
}
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (!prop) {
PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr);
return nullptr;
}
short Type = prop->getType();
if (Type & Prop_ReadOnly) {
ret.append(Py::String("ReadOnly"));
if (Type & Prop_Transient)
}
if (Type & Prop_Transient) {
ret.append(Py::String("Transient"));
if (Type & Prop_Hidden)
}
if (Type & Prop_Hidden) {
ret.append(Py::String("Hidden"));
if (Type & Prop_Output)
}
if (Type & Prop_Output) {
ret.append(Py::String("Output"));
if (Type & Prop_NoRecompute)
}
if (Type & Prop_NoRecompute) {
ret.append(Py::String("NoRecompute"));
if (Type & Prop_NoPersist)
}
if (Type & Prop_NoPersist) {
ret.append(Py::String("NoPersist"));
}
return Py::new_reference_to(ret);
}
PyObject* PropertyContainerPy::getTypeIdOfProperty(PyObject *args)
PyObject* PropertyContainerPy::getTypeIdOfProperty(PyObject* args)
{
char *pstr;
if (!PyArg_ParseTuple(args, "s", &pstr))
char* pstr {};
if (!PyArg_ParseTuple(args, "s", &pstr)) {
return nullptr;
}
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (!prop) {
PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr);
return nullptr;
@@ -146,10 +158,10 @@ PyObject* PropertyContainerPy::getTypeIdOfProperty(PyObject *args)
return Py::new_reference_to(str);
}
PyObject* PropertyContainerPy::setEditorMode(PyObject *args)
PyObject* PropertyContainerPy::setEditorMode(PyObject* args)
{
char* name;
short type;
char* name {};
short type {};
if (PyArg_ParseTuple(args, "sh", &name, &type)) {
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name);
if (!prop) {
@@ -166,7 +178,7 @@ PyObject* PropertyContainerPy::setEditorMode(PyObject *args)
}
PyErr_Clear();
PyObject *iter;
PyObject* iter {};
if (PyArg_ParseTuple(args, "sO", &name, &iter)) {
if (PyTuple_Check(iter) || PyList_Check(iter)) {
Py::Sequence seq(iter);
@@ -180,12 +192,14 @@ PyObject* PropertyContainerPy::setEditorMode(PyObject *args)
std::bitset<32> status(prop->getStatus());
status.reset(Property::ReadOnly);
status.reset(Property::Hidden);
for (Py::Sequence::iterator it = seq.begin();it!=seq.end();++it) {
for (Py::Sequence::iterator it = seq.begin(); it != seq.end(); ++it) {
std::string str = static_cast<std::string>(Py::String(*it));
if (str == "ReadOnly")
if (str == "ReadOnly") {
status.set(Property::ReadOnly);
else if (str == "Hidden")
}
else if (str == "Hidden") {
status.set(Property::Hidden);
}
}
prop->setStatusValue(status.to_ulong());
@@ -193,13 +207,15 @@ PyObject* PropertyContainerPy::setEditorMode(PyObject *args)
}
}
PyErr_SetString(PyExc_TypeError, "First argument must be str, second can be int, list or tuple");
PyErr_SetString(PyExc_TypeError,
"First argument must be str, second can be int, list or tuple");
return nullptr;
}
static const std::map<std::string, int> &getStatusMap() {
static std::map<std::string,int> statusMap;
if(statusMap.empty()) {
static const std::map<std::string, int>& getStatusMap()
{
static std::map<std::string, int> statusMap;
if (statusMap.empty()) {
statusMap["Immutable"] = Property::Immutable;
statusMap["ReadOnly"] = Property::ReadOnly;
statusMap["Hidden"] = Property::Hidden;
@@ -217,12 +233,13 @@ static const std::map<std::string, int> &getStatusMap() {
return statusMap;
}
PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args)
PyObject* PropertyContainerPy::setPropertyStatus(PyObject* args)
{
char* name {};
PyObject* pyValue {};
if (!PyArg_ParseTuple(args, "sO", &name, &pyValue))
if (!PyArg_ParseTuple(args, "sO", &name, &pyValue)) {
return nullptr;
}
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name);
if (!prop) {
@@ -247,7 +264,7 @@ PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args)
for (const auto& item : items) {
bool value = true;
if (item.isString()) {
const auto &statusMap = getStatusMap();
const auto& statusMap = getStatusMap();
auto v = static_cast<std::string>(Py::String(item));
if (v.size() > 1 && v[0] == '-') {
value = false;
@@ -288,17 +305,19 @@ PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args)
Py_Return;
}
PyObject* PropertyContainerPy::getPropertyStatus(PyObject *args)
PyObject* PropertyContainerPy::getPropertyStatus(PyObject* args)
{
const char* name = "";
if (!PyArg_ParseTuple(args, "|s", &name))
if (!PyArg_ParseTuple(args, "|s", &name)) {
return nullptr;
}
Py::List ret;
const auto &statusMap = getStatusMap();
const auto& statusMap = getStatusMap();
if (!name[0]) {
for(auto &v : statusMap)
for (auto& v : statusMap) {
ret.append(Py::String(v.first.c_str()));
}
}
else {
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name);
@@ -308,32 +327,37 @@ PyObject* PropertyContainerPy::getPropertyStatus(PyObject *args)
}
auto linkProp = Base::freecad_dynamic_cast<App::PropertyLinkBase>(prop);
if (linkProp && linkProp->testFlag(App::PropertyLinkBase::LinkAllowPartial))
if (linkProp && linkProp->testFlag(App::PropertyLinkBase::LinkAllowPartial)) {
ret.append(Py::String("AllowPartial"));
}
std::bitset<32> bits(prop->getStatus());
for(size_t i=1; i<bits.size(); ++i) {
if(!bits[i]) continue;
for (size_t i = 1; i < bits.size(); ++i) {
if (!bits[i]) {
continue;
}
bool found = false;
for(auto &v : statusMap) {
if(v.second == static_cast<int>(i)) {
for (auto& v : statusMap) {
if (v.second == static_cast<int>(i)) {
ret.append(Py::String(v.first.c_str()));
found = true;
break;
}
}
if (!found)
if (!found) {
ret.append(Py::Int(static_cast<long>(i)));
}
}
}
return Py::new_reference_to(ret);
}
PyObject* PropertyContainerPy::getEditorMode(PyObject *args)
PyObject* PropertyContainerPy::getEditorMode(PyObject* args)
{
char* name;
if (!PyArg_ParseTuple(args, "s", &name))
char* name {};
if (!PyArg_ParseTuple(args, "s", &name)) {
return nullptr;
}
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name);
if (!prop) {
@@ -343,20 +367,23 @@ PyObject* PropertyContainerPy::getEditorMode(PyObject *args)
Py::List ret;
if (prop) {
short Type = prop->getType();
if ((prop->testStatus(Property::ReadOnly)) || (Type & Prop_ReadOnly))
short Type = prop->getType();
if ((prop->testStatus(Property::ReadOnly)) || (Type & Prop_ReadOnly)) {
ret.append(Py::String("ReadOnly"));
if ((prop->testStatus(Property::Hidden)) || (Type & Prop_Hidden))
}
if ((prop->testStatus(Property::Hidden)) || (Type & Prop_Hidden)) {
ret.append(Py::String("Hidden"));
}
}
return Py::new_reference_to(ret);
}
PyObject* PropertyContainerPy::getGroupOfProperty(PyObject *args)
PyObject* PropertyContainerPy::getGroupOfProperty(PyObject* args)
{
char *pstr;
if (!PyArg_ParseTuple(args, "s", &pstr))
char* pstr {};
if (!PyArg_ParseTuple(args, "s", &pstr)) {
return nullptr;
}
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (!prop) {
@@ -365,37 +392,44 @@ PyObject* PropertyContainerPy::getGroupOfProperty(PyObject *args)
}
const char* Group = getPropertyContainerPtr()->getPropertyGroup(prop);
if (Group)
if (Group) {
return Py::new_reference_to(Py::String(Group));
else
}
else {
return Py::new_reference_to(Py::String(""));
}
}
PyObject* PropertyContainerPy::setGroupOfProperty(PyObject *args)
PyObject* PropertyContainerPy::setGroupOfProperty(PyObject* args)
{
char *pstr;
char *group;
if (!PyArg_ParseTuple(args, "ss", &pstr, &group))
char* pstr {};
char* group {};
if (!PyArg_ParseTuple(args, "ss", &pstr, &group)) {
return nullptr;
}
PY_TRY {
PY_TRY
{
Property* prop = getPropertyContainerPtr()->getDynamicPropertyByName(pstr);
if (!prop) {
PyErr_Format(PyExc_AttributeError, "Property container has no dynamic property '%s'", pstr);
PyErr_Format(PyExc_AttributeError,
"Property container has no dynamic property '%s'",
pstr);
return nullptr;
}
prop->getContainer()->changeDynamicProperty(prop,group,nullptr);
prop->getContainer()->changeDynamicProperty(prop, group, nullptr);
Py_Return;
}
PY_CATCH
}
PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args)
PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject* args)
{
char *pstr;
if (!PyArg_ParseTuple(args, "s", &pstr))
char* pstr {};
if (!PyArg_ParseTuple(args, "s", &pstr)) {
return nullptr;
}
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (!prop) {
@@ -404,36 +438,43 @@ PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args)
}
const char* docstr = getPropertyContainerPtr()->getPropertyDocumentation(prop);
if (docstr)
if (docstr) {
return Py::new_reference_to(Py::String(docstr));
else
}
else {
return Py::new_reference_to(Py::String(""));
}
}
PyObject* PropertyContainerPy::setDocumentationOfProperty(PyObject *args)
PyObject* PropertyContainerPy::setDocumentationOfProperty(PyObject* args)
{
char *pstr;
char *doc;
if (!PyArg_ParseTuple(args, "ss", &pstr, &doc))
char* pstr {};
char* doc {};
if (!PyArg_ParseTuple(args, "ss", &pstr, &doc)) {
return nullptr;
}
PY_TRY {
PY_TRY
{
Property* prop = getPropertyContainerPtr()->getDynamicPropertyByName(pstr);
if (!prop) {
PyErr_Format(PyExc_AttributeError, "Property container has no dynamic property '%s'", pstr);
PyErr_Format(PyExc_AttributeError,
"Property container has no dynamic property '%s'",
pstr);
return nullptr;
}
prop->getContainer()->changeDynamicProperty(prop,nullptr,doc);
prop->getContainer()->changeDynamicProperty(prop, nullptr, doc);
Py_Return;
}
PY_CATCH
}
PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args)
PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject* args)
{
char *pstr;
if (!PyArg_ParseTuple(args, "s", &pstr))
char* pstr {};
if (!PyArg_ParseTuple(args, "s", &pstr)) {
return nullptr;
}
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (!prop) {
@@ -441,13 +482,14 @@ PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args)
return nullptr;
}
PropertyEnumeration *enumProp = dynamic_cast<PropertyEnumeration*>(prop);
if (!enumProp)
PropertyEnumeration* enumProp = dynamic_cast<PropertyEnumeration*>(prop);
if (!enumProp) {
Py_Return;
}
std::vector<std::string> enumerations = enumProp->getEnumVector();
Py::List ret;
for (const auto & it : enumerations) {
for (const auto& it : enumerations) {
ret.append(Py::String(it));
}
return Py::new_reference_to(ret);
@@ -456,24 +498,30 @@ PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args)
Py::List PropertyContainerPy::getPropertiesList() const
{
Py::List ret;
std::map<std::string,Property*> Map;
std::map<std::string, Property*> Map;
getPropertyContainerPtr()->getPropertyMap(Map);
for (std::map<std::string,Property*>::const_iterator It=Map.begin(); It!=Map.end(); ++It)
ret.append(Py::String(It->first));
for (const auto& It : Map) {
ret.append(Py::String(It.first));
}
return ret;
}
PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwds)
PyObject* PropertyContainerPy::dumpPropertyContent(PyObject* args, PyObject* kwds)
{
int compression = 3;
const char* property;
static const std::array<const char *, 3> kwds_def {"Property", "Compression", nullptr};
const char* property {};
static const std::array<const char*, 3> kwds_def {"Property", "Compression", nullptr};
PyErr_Clear();
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "s|i", kwds_def, &property, &compression)) {
if (!Base::Wrapped_ParseTupleAndKeywords(args,
kwds,
"s|i",
kwds_def,
&property,
&compression)) {
return nullptr;
}
@@ -483,35 +531,36 @@ PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwd
return nullptr;
}
//setup the stream. the in flag is needed to make "read" work
std::stringstream stream(std::stringstream::out | std::stringstream::in | std::stringstream::binary);
// setup the stream. the in flag is needed to make "read" work
std::stringstream stream(std::stringstream::out | std::stringstream::in
| std::stringstream::binary);
try {
prop->dumpToStream(stream, compression);
}
catch (...) {
PyErr_SetString(PyExc_IOError, "Unable to parse content into binary representation");
return nullptr;
PyErr_SetString(PyExc_IOError, "Unable to parse content into binary representation");
return nullptr;
}
//build the byte array with correct size
if (!stream.seekp(0, stream.end)) {
// build the byte array with correct size
if (!stream.seekp(0, std::stringstream::end)) {
PyErr_SetString(PyExc_IOError, "Unable to find end of stream");
return nullptr;
}
std::stringstream::pos_type offset = stream.tellp();
if (!stream.seekg(0, stream.beg)) {
if (!stream.seekg(0, std::stringstream::beg)) {
PyErr_SetString(PyExc_IOError, "Unable to find begin of stream");
return nullptr;
}
PyObject* ba = PyByteArray_FromStringAndSize(nullptr, offset);
//use the buffer protocol to access the underlying array and write into it
// use the buffer protocol to access the underlying array and write into it
Py_buffer buf = Py_buffer();
PyObject_GetBuffer(ba, &buf, PyBUF_WRITABLE);
try {
if(!stream.read((char*)buf.buf, offset)) {
if (!stream.read((char*)buf.buf, offset)) {
PyErr_SetString(PyExc_IOError, "Error copying data into byte array");
return nullptr;
}
@@ -526,12 +575,13 @@ PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwd
return ba;
}
PyObject* PropertyContainerPy::restorePropertyContent(PyObject *args)
PyObject* PropertyContainerPy::restorePropertyContent(PyObject* args)
{
PyObject* buffer;
char* property;
if( !PyArg_ParseTuple(args, "sO", &property, &buffer) )
PyObject* buffer {};
char* property {};
if (!PyArg_ParseTuple(args, "sO", &property, &buffer)) {
return nullptr;
}
Property* prop = getPropertyContainerPtr()->getPropertyByName(property);
if (!prop) {
@@ -539,28 +589,29 @@ PyObject* PropertyContainerPy::restorePropertyContent(PyObject *args)
return nullptr;
}
//check if it really is a buffer
if( !PyObject_CheckBuffer(buffer) ) {
// check if it really is a buffer
if (!PyObject_CheckBuffer(buffer)) {
PyErr_SetString(PyExc_TypeError, "Must be a buffer object");
return nullptr;
}
Py_buffer buf;
if(PyObject_GetBuffer(buffer, &buf, PyBUF_SIMPLE) < 0)
if (PyObject_GetBuffer(buffer, &buf, PyBUF_SIMPLE) < 0) {
return nullptr;
}
if(!PyBuffer_IsContiguous(&buf, 'C')) {
if (!PyBuffer_IsContiguous(&buf, 'C')) {
PyErr_SetString(PyExc_TypeError, "Buffer must be contiguous");
return nullptr;
}
//check if it really is a buffer
// check if it really is a buffer
try {
using Device = boost::iostreams::basic_array_source<char>;
boost::iostreams::stream<Device> stream((char*)buf.buf, buf.len);
prop->restoreFromStream(stream);
}
catch(...) {
catch (...) {
PyErr_SetString(PyExc_IOError, "Unable to restore content");
return nullptr;
}
@@ -568,13 +619,13 @@ PyObject* PropertyContainerPy::restorePropertyContent(PyObject *args)
Py_Return;
}
PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const
PyObject* PropertyContainerPy::getCustomAttributes(const char* attr) const
{
// search in PropertyList
if(FC_LOG_INSTANCE.level()>FC_LOGLEVEL_TRACE) {
if (FC_LOG_INSTANCE.level() > FC_LOGLEVEL_TRACE) {
FC_TRACE("Get property " << attr);
}
Property *prop = getPropertyContainerPtr()->getPropertyByName(attr);
Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
if (prop) {
PyObject* pyobj = prop->getPyObject();
if (!pyobj && PyErr_Occurred()) {
@@ -583,44 +634,49 @@ PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const
}
return pyobj;
}
else if (Base::streq(attr, "__dict__")) {
if (Base::streq(attr, "__dict__")) {
// get the properties to the C++ PropertyContainer class
std::map<std::string,App::Property*> Map;
std::map<std::string, App::Property*> Map;
getPropertyContainerPtr()->getPropertyMap(Map);
Py::Dict dict;
for (const auto & it : Map) {
for (const auto& it : Map) {
dict.setItem(it.first, Py::String(""));
}
return Py::new_reference_to(dict);
}
///FIXME: For v0.20: Do not use stuff from Part module here!
else if(Base::streq(attr,"Shape") && getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
/// FIXME: For v0.20: Do not use stuff from Part module here!
if (Base::streq(attr, "Shape")
&& getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
// Special treatment of Shape property
static PyObject *_getShape = nullptr;
if(!_getShape) {
static PyObject* _getShape = nullptr;
if (!_getShape) {
_getShape = Py_None;
PyObject *mod = PyImport_ImportModule("Part");
if(!mod) {
PyObject* mod = PyImport_ImportModule("Part");
if (!mod) {
PyErr_Clear();
} else {
}
else {
Py::Object pyMod = Py::asObject(mod);
if(pyMod.hasAttr("getShape"))
if (pyMod.hasAttr("getShape")) {
_getShape = Py::new_reference_to(pyMod.getAttr("getShape"));
}
}
}
if(_getShape != Py_None) {
if (_getShape != Py_None) {
Py::Tuple args(1);
args.setItem(0,Py::Object(const_cast<PropertyContainerPy*>(this)));
args.setItem(0, Py::Object(const_cast<PropertyContainerPy*>(this)));
auto res = PyObject_CallObject(_getShape, args.ptr());
if(!res)
if (!res) {
PyErr_Clear();
}
else {
Py::Object pyres(res,true);
if(pyres.hasAttr("isNull")) {
Py::Object pyres(res, true);
if (pyres.hasAttr("isNull")) {
Py::Callable func(pyres.getAttr("isNull"));
if(!func.apply().isTrue())
if (!func.apply().isTrue()) {
return Py::new_reference_to(res);
}
}
}
}
@@ -629,13 +685,13 @@ PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const
return nullptr;
}
int PropertyContainerPy::setCustomAttributes(const char* attr, PyObject *obj)
int PropertyContainerPy::setCustomAttributes(const char* attr, PyObject* obj)
{
// search in PropertyList
Property *prop = getPropertyContainerPtr()->getPropertyByName(attr);
Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
if (prop) {
// Read-only attributes must not be set over its Python interface
if(prop->testStatus(Property::Immutable)) {
if (prop->testStatus(Property::Immutable)) {
std::stringstream s;
s << "Object attribute '" << attr << "' is read-only";
throw Py::AttributeError(s.str());
File diff suppressed because it is too large Load Diff
+92 -70
View File
@@ -31,12 +31,14 @@
#include <App/PropertyLinks.h>
#include <set>
namespace Base {
namespace Base
{
class Writer;
class XMLReader;
}
} // namespace Base
namespace App {
namespace App
{
class DocumentObject;
class DocumentObjectExecReturn;
@@ -44,84 +46,96 @@ class ObjectIdentifier;
class Expression;
using ExpressionPtr = std::unique_ptr<Expression>;
class AppExport PropertyExpressionContainer : public App::PropertyXLinkContainer
class AppExport PropertyExpressionContainer: public App::PropertyXLinkContainer
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
PropertyExpressionContainer();
~PropertyExpressionContainer() override;
virtual std::map<App::ObjectIdentifier, const App::Expression*> getExpressions() const = 0;
virtual void setExpressions(std::map<App::ObjectIdentifier, App::ExpressionPtr> &&exprs) = 0;
virtual void setExpressions(std::map<App::ObjectIdentifier, App::ExpressionPtr>&& exprs) = 0;
protected:
virtual void onRelabeledDocument(const App::Document &doc) = 0;
virtual void onRelabeledDocument(const App::Document& doc) = 0;
private:
static void slotRelabelDocument(const App::Document &doc);
static void slotRelabelDocument(const App::Document& doc);
};
class AppExport PropertyExpressionEngine : public App::PropertyExpressionContainer,
private App::AtomicPropertyChangeInterface<PropertyExpressionEngine>
class AppExport PropertyExpressionEngine
: public App::PropertyExpressionContainer,
private App::AtomicPropertyChangeInterface<PropertyExpressionEngine>
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
void updateElementReference(
App::DocumentObject *feature, bool reverse=false, bool notify=false) override;
void updateElementReference(App::DocumentObject* feature,
bool reverse = false,
bool notify = false) override;
bool referenceChanged() const override;
bool adjustLink(const std::set<App::DocumentObject *> &inList) override;
Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override;
Property *CopyOnLabelChange(App::DocumentObject *obj,
const std::string &ref, const char *newLabel) const override;
Property *CopyOnLinkReplace(const App::DocumentObject *parent,
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override;
bool adjustLink(const std::set<App::DocumentObject*>& inList) override;
Property*
CopyOnImportExternal(const std::map<std::string, std::string>& nameMap) const override;
Property* CopyOnLabelChange(App::DocumentObject* obj,
const std::string& ref,
const char* newLabel) const override;
Property* CopyOnLinkReplace(const App::DocumentObject* parent,
App::DocumentObject* oldObj,
App::DocumentObject* newObj) const override;
using ValidatorFunc = std::function<std::string (const App::ObjectIdentifier & path, std::shared_ptr<const App::Expression> expr)>;
using ValidatorFunc = std::function<std::string(const App::ObjectIdentifier& path,
std::shared_ptr<const App::Expression> expr)>;
/**
* @brief The ExpressionInfo struct encapsulates an expression.
*/
struct ExpressionInfo {
struct ExpressionInfo
{
std::shared_ptr<App::Expression> expression; /**< The actual expression tree */
bool busy;
explicit ExpressionInfo(std::shared_ptr<App::Expression> expression = std::shared_ptr<App::Expression>()) {
explicit ExpressionInfo(
std::shared_ptr<App::Expression> expression = std::shared_ptr<App::Expression>())
{
this->expression = expression;
this->busy = false;
}
ExpressionInfo(const ExpressionInfo &) = default;
ExpressionInfo(const ExpressionInfo&) = default;
ExpressionInfo & operator=(const ExpressionInfo &) = default;
ExpressionInfo& operator=(const ExpressionInfo&) = default;
};
PropertyExpressionEngine();
~PropertyExpressionEngine() override;
unsigned int getMemSize () const override;
unsigned int getMemSize() const override;
std::map<App::ObjectIdentifier, const App::Expression*> getExpressions() const override;
void setExpressions(std::map<App::ObjectIdentifier, App::ExpressionPtr> &&exprs) override;
void onRelabeledDocument(const App::Document &doc) override;
void setExpressions(std::map<App::ObjectIdentifier, App::ExpressionPtr>&& exprs) override;
void onRelabeledDocument(const App::Document& doc) override;
void setValue() { } // Dummy
void setValue()
{} // Dummy
Property *Copy() const override;
Property* Copy() const override;
void Paste(const Property &from) override;
void Paste(const Property& from) override;
void Save (Base::Writer & writer) const override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader &reader) override;
void Restore(Base::XMLReader& reader) override;
void setValue(const App::ObjectIdentifier &path, std::shared_ptr<App::Expression> expr);
void setValue(const App::ObjectIdentifier& path, std::shared_ptr<App::Expression> expr);
const boost::any getPathValue(const App::ObjectIdentifier & path) const override;
const boost::any getPathValue(const App::ObjectIdentifier& path) const override;
/// Execute options
enum ExecuteOption {
enum ExecuteOption
{
/// Execute all expression
ExecuteAll,
/// Execute only output property bindings
@@ -135,67 +149,74 @@ public:
*
* @param option: execution option, see ExecuteOption.
*/
DocumentObjectExecReturn * execute(ExecuteOption option=ExecuteAll, bool *touched=nullptr);
DocumentObjectExecReturn* execute(ExecuteOption option = ExecuteAll, bool* touched = nullptr);
void getPathsToDocumentObject(DocumentObject*, std::vector<App::ObjectIdentifier> & paths) const;
void getPathsToDocumentObject(DocumentObject*, std::vector<App::ObjectIdentifier>& paths) const;
bool depsAreTouched() const;
/* Expression validator */
void setValidator(ValidatorFunc f) { validator = f; }
void setValidator(ValidatorFunc f)
{
validator = f;
}
std::string validateExpression(const App::ObjectIdentifier & path, std::shared_ptr<const App::Expression> expr) const;
std::string validateExpression(const App::ObjectIdentifier& path,
std::shared_ptr<const App::Expression> expr) const;
void renameExpressions(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> &paths);
void renameExpressions(const std::map<App::ObjectIdentifier, App::ObjectIdentifier>& paths);
void renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> & paths);
void
renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier>& paths);
App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier &p) const override;
App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier& p) const override;
size_t numExpressions() const;
///signal called when an expression was changed
boost::signals2::signal<void (const App::ObjectIdentifier &)> expressionChanged;
/// signal called when an expression was changed
boost::signals2::signal<void(const App::ObjectIdentifier&)> expressionChanged;
void afterRestore() override;
void onContainerRestored() override;
void getLinksTo(std::vector<App::ObjectIdentifier> &identifiers,
App::DocumentObject *obj,
const char *subname=nullptr,
bool all=false) const override;
void getLinksTo(std::vector<App::ObjectIdentifier>& identifiers,
App::DocumentObject* obj,
const char* subname = nullptr,
bool all = false) const override;
/* Python interface */
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
protected:
void hasSetValue() override;
private:
using DiGraph = boost::adjacency_list< boost::listS, boost::vecS, boost::directedS >;
using DiGraph = boost::adjacency_list<boost::listS, boost::vecS, boost::directedS>;
using Edge = std::pair<int, int>;
// Note: use std::map instead of unordered_map to keep the binding order stable
#if defined(FC_OS_MACOSX) || defined(FC_OS_BSD) || defined(_LIBCPP_VERSION)
// Note: use std::map instead of unordered_map to keep the binding order stable
#if defined(FC_OS_MACOSX) || defined(FC_OS_BSD) || defined(_LIBCPP_VERSION)
using ExpressionMap = std::map<App::ObjectIdentifier, ExpressionInfo>;
#else
#else
using ExpressionMap = std::map<const App::ObjectIdentifier, ExpressionInfo>;
#endif
#endif
std::vector<App::ObjectIdentifier> computeEvaluationOrder(ExecuteOption option);
void buildGraphStructures(const App::ObjectIdentifier &path,
const std::shared_ptr<Expression> expression, boost::unordered_map<App::ObjectIdentifier, int> &nodes,
boost::unordered_map<int, App::ObjectIdentifier> &revNodes, std::vector<Edge> &edges) const;
void buildGraphStructures(const App::ObjectIdentifier& path,
const std::shared_ptr<Expression> expression,
boost::unordered_map<App::ObjectIdentifier, int>& nodes,
boost::unordered_map<int, App::ObjectIdentifier>& revNodes,
std::vector<Edge>& edges) const;
void buildGraph(const ExpressionMap &exprs,
boost::unordered_map<int, App::ObjectIdentifier> &revNodes,
DiGraph &g, ExecuteOption option=ExecuteAll) const;
void buildGraph(const ExpressionMap& exprs,
boost::unordered_map<int, App::ObjectIdentifier>& revNodes,
DiGraph& g,
ExecuteOption option = ExecuteAll) const;
void slotChangedObject(const App::DocumentObject &obj, const App::Property &prop);
void slotChangedProperty(const App::DocumentObject &obj, const App::Property &prop);
void updateHiddenReference(const std::string &key);
void slotChangedObject(const App::DocumentObject& obj, const App::Property& prop);
void slotChangedProperty(const App::DocumentObject& obj, const App::Property& prop);
void updateHiddenReference(const std::string& key);
bool running = false; /**< Boolean used to avoid loops */
bool restoring = false;
@@ -204,21 +225,22 @@ private:
ValidatorFunc validator; /**< Valdiator functor */
struct RestoredExpression {
struct RestoredExpression
{
std::string path;
std::string expr;
std::string comment;
};
/**< Expressions are read from file to this map first before they are validated and inserted into the actual map */
std::unique_ptr<std::vector<RestoredExpression> > restoredExpressions;
/**< Expressions are read from file to this map first before they are validated and inserted
* into the actual map */
std::unique_ptr<std::vector<RestoredExpression>> restoredExpressions;
struct Private;
std::unique_ptr<Private> pimpl;
friend class AtomicPropertyChange;
};
}
} // namespace App
#endif // EXPRESSIONENGINE_H
#endif // EXPRESSIONENGINE_H
+70 -67
View File
@@ -41,12 +41,11 @@ using namespace Base;
using namespace std;
//**************************************************************************
// PropertyFileIncluded
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TYPESYSTEM_SOURCE(App::PropertyFileIncluded , App::Property)
TYPESYSTEM_SOURCE(App::PropertyFileIncluded, App::Property)
PropertyFileIncluded::PropertyFileIncluded() = default;
@@ -78,7 +77,7 @@ void PropertyFileIncluded::aboutToSetValue()
std::string PropertyFileIncluded::getDocTransientPath() const
{
std::string path;
PropertyContainer *co = getContainer();
PropertyContainer* co = getContainer();
if (co->isDerivedFrom(DocumentObject::getClassTypeId())) {
path = static_cast<DocumentObject*>(co)->getDocument()->TransientDir.getValue();
std::replace(path.begin(), path.end(), '\\', '/');
@@ -86,7 +85,8 @@ std::string PropertyFileIncluded::getDocTransientPath() const
return path;
}
std::string PropertyFileIncluded::getUniqueFileName(const std::string& path, const std::string& filename) const
std::string PropertyFileIncluded::getUniqueFileName(const std::string& path,
const std::string& filename) const
{
Base::Uuid uuid;
Base::FileInfo fi(path + "/" + filename);
@@ -99,8 +99,8 @@ std::string PropertyFileIncluded::getUniqueFileName(const std::string& path, con
std::string PropertyFileIncluded::getExchangeTempFile() const
{
return Base::FileInfo::getTempFileName(Base::FileInfo
(getValue()).fileName().c_str(), getDocTransientPath().c_str());
return Base::FileInfo::getTempFileName(Base::FileInfo(getValue()).fileName().c_str(),
getDocTransientPath().c_str());
}
std::string PropertyFileIncluded::getOriginalFileName() const
@@ -111,8 +111,9 @@ std::string PropertyFileIncluded::getOriginalFileName() const
void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
{
if (sFile && sFile[0] != '\0') {
if (_cValue == sFile)
if (_cValue == sFile) {
throw Base::FileSystemError("Not possible to set the same file!");
}
// keep the path to the original file
_OriginalName = sFile;
@@ -126,7 +127,7 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
throw Base::FileSystemError(str.str());
}
aboutToSetValue(); // undo/redo by moving the file away with temp name
aboutToSetValue(); // undo/redo by moving the file away with temp name
// remove old file (if not moved by undo)
Base::FileInfo value(_cValue);
@@ -144,16 +145,16 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
std::string dir = pathTrans;
std::string fnp = fi.fileNamePure();
std::string ext = fi.extension();
int i=0;
int i = 0;
do {
i++;
std::stringstream str;
str << dir << "/" << fnp << i;
if (!ext.empty())
if (!ext.empty()) {
str << "." << ext;
}
fi.setFile(str.str());
}
while (fi.exists());
} while (fi.exists());
_cValue = fi.filePath();
_BaseFileName = fi.fileName();
@@ -189,7 +190,7 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
Base::FileInfo dst(_cValue);
dst.setPermissions(Base::FileInfo::ReadOnly);
}
// otherwise copy from origin location
// otherwise copy from origin location
else {
// if file already exists in transient dir make a new unique name
Base::FileInfo fi(_cValue);
@@ -198,16 +199,16 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
std::string dir = fi.dirPath();
std::string fnp = fi.fileNamePure();
std::string ext = fi.extension();
int i=0;
int i = 0;
do {
i++;
std::stringstream str;
str << dir << "/" << fnp << i;
if (!ext.empty())
if (!ext.empty()) {
str << "." << ext;
}
fi.setFile(str.str());
}
while (fi.exists());
} while (fi.exists());
_cValue = fi.filePath();
_BaseFileName = fi.fileName();
@@ -231,40 +232,41 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
const char* PropertyFileIncluded::getValue() const
{
return _cValue.c_str();
return _cValue.c_str();
}
PyObject *PropertyFileIncluded::getPyObject()
PyObject* PropertyFileIncluded::getPyObject()
{
PyObject *p = PyUnicode_DecodeUTF8(_cValue.c_str(),_cValue.size(),nullptr);
PyObject* p = PyUnicode_DecodeUTF8(_cValue.c_str(), _cValue.size(), nullptr);
if (!p) {
throw Base::UnicodeError("PropertyFileIncluded: UTF-8 conversion failure");
}
return p;
}
namespace App {
namespace App
{
const char* getNameFromFile(PyObject* value)
{
const char* string = nullptr;
PyObject *oname = PyObject_GetAttrString (value, "name");
PyObject* oname = PyObject_GetAttrString(value, "name");
if (oname) {
if (PyUnicode_Check (oname)) {
string = PyUnicode_AsUTF8 (oname);
if (PyUnicode_Check(oname)) {
string = PyUnicode_AsUTF8(oname);
}
else if (PyBytes_Check (oname)) {
string = PyBytes_AsString (oname);
else if (PyBytes_Check(oname)) {
string = PyBytes_AsString(oname);
}
Py_DECREF (oname);
Py_DECREF(oname);
}
if (!string)
if (!string) {
throw Base::TypeError("Unable to get filename");
}
return string;
}
bool isIOFile(PyObject* file)
{
PyObject* io = PyImport_ImportModule("io");
@@ -274,9 +276,9 @@ bool isIOFile(PyObject* file)
Py_DECREF(io);
return isFile;
}
}
} // namespace App
void PropertyFileIncluded::setPyObject(PyObject *value)
void PropertyFileIncluded::setPyObject(PyObject* value)
{
if (PyUnicode_Check(value)) {
std::string string = PyUnicode_AsUTF8(value);
@@ -286,15 +288,16 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
std::string string = PyBytes_AsString(value);
setValue(string.c_str());
}
else if (isIOFile(value)){
else if (isIOFile(value)) {
std::string string = getNameFromFile(value);
setValue(string.c_str());
}
else if (PyTuple_Check(value)) {
if (PyTuple_Size(value) != 2)
throw Base::TypeError("Tuple needs size of (filePath,newFileName)");
PyObject* file = PyTuple_GetItem(value,0);
PyObject* name = PyTuple_GetItem(value,1);
if (PyTuple_Size(value) != 2) {
throw Base::TypeError("Tuple needs size of (filePath,newFileName)");
}
PyObject* file = PyTuple_GetItem(value, 0);
PyObject* name = PyTuple_GetItem(value, 1);
// decoding file
std::string fileStr;
@@ -330,7 +333,7 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
throw Base::TypeError(error);
}
setValue(fileStr.c_str(),nameStr.c_str());
setValue(fileStr.c_str(), nameStr.c_str());
}
else if (PyDict_Check(value)) {
Py::Dict dict(value);
@@ -349,39 +352,40 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
}
}
void PropertyFileIncluded::Save (Base::Writer &writer) const
void PropertyFileIncluded::Save(Base::Writer& writer) const
{
// when saving a document under a new file name the transient directory
// name changes and thus the stored file name doesn't work any more.
if (!_cValue.empty() && !Base::FileInfo(_cValue).exists()) {
Base::FileInfo fi(getDocTransientPath() + "/" + _BaseFileName);
if (fi.exists())
if (fi.exists()) {
_cValue = fi.filePath();
}
}
if (writer.isForceXML()) {
if (!_cValue.empty()) {
Base::FileInfo file(_cValue.c_str());
writer.Stream() << writer.ind() << "<FileIncluded data=\""
<< file.fileName() << "\">" << std::endl;
writer.Stream() << writer.ind() << "<FileIncluded data=\"" << file.fileName() << "\">"
<< std::endl;
// write the file in the XML stream
writer.incInd();
writer.insertBinFile(_cValue.c_str());
writer.decInd();
writer.Stream() << writer.ind() <<"</FileIncluded>" << endl;
writer.Stream() << writer.ind() << "</FileIncluded>" << endl;
}
else {
writer.Stream() << writer.ind() << "<FileIncluded data=\"\"/>" << std::endl;
}
}
else {
// instead initiate an extra file
// instead initiate an extra file
if (!_cValue.empty()) {
Base::FileInfo file(_cValue.c_str());
std::string filename = writer.addFile(file.fileName().c_str(), this);
filename = encodeAttribute(filename);
writer.Stream() << writer.ind() << "<FileIncluded file=\""
<< filename << "\"/>" << std::endl;
writer.Stream() << writer.ind() << "<FileIncluded file=\"" << filename << "\"/>"
<< std::endl;
}
else {
writer.Stream() << writer.ind() << "<FileIncluded file=\"\"/>" << std::endl;
@@ -389,14 +393,14 @@ void PropertyFileIncluded::Save (Base::Writer &writer) const
}
}
void PropertyFileIncluded::Restore(Base::XMLReader &reader)
void PropertyFileIncluded::Restore(Base::XMLReader& reader)
{
reader.readElement("FileIncluded");
if (reader.hasAttribute("file")) {
string file (reader.getAttribute("file") );
string file(reader.getAttribute("file"));
if (!file.empty()) {
// initiate a file read
reader.addFile(file.c_str(),this);
reader.addFile(file.c_str(), this);
// is in the document transient path
aboutToSetValue();
_cValue = getDocTransientPath() + "/" + file;
@@ -406,7 +410,7 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader)
}
// section is XML stream
else if (reader.hasAttribute("data")) {
string file (reader.getAttribute("data") );
string file(reader.getAttribute("data"));
if (!file.empty()) {
// is in the document transient path
aboutToSetValue();
@@ -422,7 +426,7 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader)
}
}
void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
void PropertyFileIncluded::SaveDocFile(Base::Writer& writer) const
{
Base::ifstream from(Base::FileInfo(_cValue.c_str()), std::ios::in | std::ios::binary);
if (!from) {
@@ -440,7 +444,7 @@ void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
}
}
void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
void PropertyFileIncluded::RestoreDocFile(Base::Reader& reader)
{
Base::FileInfo fi(_cValue.c_str());
if (fi.exists() && !fi.isWritable()) {
@@ -469,7 +473,7 @@ void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
hasSetValue();
}
Property *PropertyFileIncluded::Copy() const
Property* PropertyFileIncluded::Copy() const
{
std::unique_ptr<PropertyFileIncluded> prop(new PropertyFileIncluded());
@@ -486,8 +490,8 @@ Property *PropertyFileIncluded::Copy() const
if (!done) {
std::stringstream str;
str << "PropertyFileIncluded::Copy(): "
<< "Renaming the file '" << file.filePath() << "' to '"
<< newName.filePath() << "' failed.";
<< "Renaming the file '" << file.filePath() << "' to '" << newName.filePath()
<< "' failed.";
throw Base::FileSystemError(str.str());
}
}
@@ -497,14 +501,14 @@ Property *PropertyFileIncluded::Copy() const
if (!done) {
std::stringstream str;
str << "PropertyFileIncluded::Copy(): "
<< "Copying the file '" << file.filePath() << "' to '"
<< newName.filePath() << "' failed.";
<< "Copying the file '" << file.filePath() << "' to '" << newName.filePath()
<< "' failed.";
throw Base::FileSystemError(str.str());
}
}
// remember the new name for the Undo
Base::Console().Log("Copy '%s' to '%s'\n",_cValue.c_str(),newName.filePath().c_str());
Base::Console().Log("Copy '%s' to '%s'\n", _cValue.c_str(), newName.filePath().c_str());
prop->_cValue = newName.filePath().c_str();
// make backup files writable to avoid copying them again on undo/redo
@@ -514,10 +518,10 @@ Property *PropertyFileIncluded::Copy() const
return prop.release();
}
void PropertyFileIncluded::Paste(const Property &from)
void PropertyFileIncluded::Paste(const Property& from)
{
aboutToSetValue();
const PropertyFileIncluded &prop = dynamic_cast<const PropertyFileIncluded&>(from);
const PropertyFileIncluded& prop = dynamic_cast<const PropertyFileIncluded&>(from);
// make sure that source and destination file are different
if (_cValue != prop._cValue) {
// delete old file (if still there)
@@ -540,8 +544,8 @@ void PropertyFileIncluded::Paste(const Property &from)
if (!fiSrc.renameFile(fiDst.filePath().c_str())) {
std::stringstream str;
str << "PropertyFileIncluded::Paste(): "
<< "Renaming the file '" << fiSrc.filePath() << "' to '"
<< fiDst.filePath() << "' failed.";
<< "Renaming the file '" << fiSrc.filePath() << "' to '" << fiDst.filePath()
<< "' failed.";
throw Base::FileSystemError(str.str());
}
}
@@ -549,8 +553,8 @@ void PropertyFileIncluded::Paste(const Property &from)
if (!fiSrc.copyTo(fiDst.filePath().c_str())) {
std::stringstream str;
str << "PropertyFileIncluded::Paste(): "
<< "Copying the file '" << fiSrc.filePath() << "' to '"
<< fiDst.filePath() << "' failed.";
<< "Copying the file '" << fiSrc.filePath() << "' to '" << fiDst.filePath()
<< "' failed.";
throw Base::FileSystemError(str.str());
}
}
@@ -569,7 +573,7 @@ void PropertyFileIncluded::Paste(const Property &from)
hasSetValue();
}
unsigned int PropertyFileIncluded::getMemSize () const
unsigned int PropertyFileIncluded::getMemSize() const
{
unsigned int mem = Property::getMemSize();
mem += _cValue.size();
@@ -591,7 +595,7 @@ std::string PropertyFileIncluded::getFilter() const
// PropertyFile
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TYPESYSTEM_SOURCE(App::PropertyFile , App::PropertyString)
TYPESYSTEM_SOURCE(App::PropertyFile, App::PropertyString)
PropertyFile::PropertyFile()
{
@@ -610,7 +614,7 @@ std::string PropertyFile::getFilter() const
return m_filter;
}
void PropertyFile::setPyObject(PyObject *value)
void PropertyFile::setPyObject(PyObject* value)
{
if (PyDict_Check(value)) {
Py::Dict dict(value);
@@ -626,4 +630,3 @@ void PropertyFile::setPyObject(PyObject *value)
PropertyString::setPyObject(value);
}
}
+49 -39
View File
@@ -29,7 +29,8 @@
#include "PropertyStandard.h"
namespace Base {
namespace Base
{
class Writer;
}
@@ -37,9 +38,9 @@ namespace App
{
/** File properties
* This property holds a file name
*/
class AppExport PropertyFile : public PropertyString
* This property holds a file name
*/
class AppExport PropertyFile: public PropertyString
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -48,9 +49,11 @@ public:
~PropertyFile() override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyFileItem"; }
{
return "Gui::PropertyEditor::PropertyFileItem";
}
void setPyObject(PyObject *) override;
void setPyObject(PyObject*) override;
virtual void setFilter(const std::string filter);
virtual std::string getFilter() const;
@@ -59,20 +62,20 @@ private:
};
/** File include properties
* This property doesn't only save the file name like PropertyFile
* it also includes the file itself into the document. The file
* doesn't get loaded into memory, it gets copied from the document
* archive into the document transient directory. There it is accessible for
* the algorithms. You get the transient path through getDocTransientPath()
* It's allowed to read the file, it's not allowed to write the file
* directly in the transient path! That would undermine the Undo/Redo
* framework. It's only allowed to use setValue() to change the file.
* If you give a file name outside the transient dir to setValue() it
* will copy the file. If you give a file name in the transient path it
* will just rename and use the same file. You can use getExchangeTempFile() to
* get a file name in the transient dir to write a new file version.
* This property doesn't only save the file name like PropertyFile
* it also includes the file itself into the document. The file
* doesn't get loaded into memory, it gets copied from the document
* archive into the document transient directory. There it is accessible for
* the algorithms. You get the transient path through getDocTransientPath()
* It's allowed to read the file, it's not allowed to write the file
* directly in the transient path! That would undermine the Undo/Redo
* framework. It's only allowed to use setValue() to change the file.
* If you give a file name outside the transient dir to setValue() it
* will copy the file. If you give a file name in the transient path it
* will just rename and use the same file. You can use getExchangeTempFile() to
* get a file name in the transient dir to write a new file version.
*/
class AppExport PropertyFileIncluded : public Property
class AppExport PropertyFileIncluded: public Property
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -80,27 +83,31 @@ public:
PropertyFileIncluded();
~PropertyFileIncluded() override;
void setValue(const char* sFile, const char* sName=nullptr);
void setValue(const char* sFile, const char* sName = nullptr);
const char* getValue() const;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyTransientFileItem"; }
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
{
return "Gui::PropertyEditor::PropertyTransientFileItem";
}
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
void SaveDocFile (Base::Writer &writer) const override;
void RestoreDocFile(Base::Reader &reader) override;
void SaveDocFile(Base::Writer& writer) const override;
void RestoreDocFile(Base::Reader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
bool isSame(const Property &other) const override {
if (&other == this)
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
return getTypeId() == other.getTypeId()
&& _BaseFileName == static_cast<decltype(this)>(&other)->_BaseFileName
&& _OriginalName == static_cast<decltype(this)>(&other)->_OriginalName
@@ -108,14 +115,17 @@ public:
}
/** get a temp file name in the transient path of the document.
* Using this file for new Version of the file and set
* this file with setValue() is the fastest way to change
* the File.
*/
* Using this file for new Version of the file and set
* this file with setValue() is the fastest way to change
* the File.
*/
std::string getExchangeTempFile() const;
std::string getOriginalFileName() const;
bool isEmpty() const {return _cValue.empty();}
bool isEmpty() const
{
return _cValue.empty();
}
void setFilter(std::string filter);
std::string getFilter() const;
@@ -136,6 +146,6 @@ private:
};
} // namespace App
} // namespace App
#endif // APP_PROPERTFILE_H
#endif // APP_PROPERTFILE_H
+293 -245
View File
File diff suppressed because it is too large Load Diff
+124 -102
View File
@@ -34,11 +34,13 @@
#include <FCGlobal.h>
namespace Base {
namespace Base
{
class Writer;
}
namespace Data {
namespace Data
{
class ComplexGeoData;
}
@@ -47,7 +49,6 @@ namespace App
class Placement;
/** Vector properties
* This is the father of all properties handling Integers.
*/
@@ -70,43 +71,48 @@ public:
/** Sets the property
*/
void setValue(const Base::Vector3d &vec);
void setValue(const Base::Vector3d& vec);
void setValue(double x, double y, double z);
/// Get valid paths for this property; used by auto completer
void getPaths(std::vector<ObjectIdentifier> &paths) const override;
void getPaths(std::vector<ObjectIdentifier>& paths) const override;
/** This method returns a string representation of the property
*/
const Base::Vector3d &getValue() const;
const char* getEditorName() const override {
const Base::Vector3d& getValue() const;
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyVectorItem";
}
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override {
unsigned int getMemSize() const override
{
return sizeof(Base::Vector3d);
}
const boost::any getPathValue(const ObjectIdentifier &path) const override;
const boost::any getPathValue(const ObjectIdentifier& path) const override;
bool getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const override;
bool getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const override;
virtual Base::Unit getUnit() const {
virtual Base::Unit getUnit() const
{
return {};
}
bool isSame(const Property &other) const override {
if (&other == this)
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
return getTypeId() == other.getTypeId()
&& getValue() == dynamic_cast<decltype(this)>(&other)->getValue();
}
@@ -133,11 +139,13 @@ public:
*/
~PropertyVectorDistance() override;
Base::Unit getUnit() const override {
Base::Unit getUnit() const override
{
return Base::Unit::Length;
}
const char* getEditorName() const override {
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyVectorDistanceItem";
}
};
@@ -159,11 +167,13 @@ public:
*/
~PropertyPosition() override;
Base::Unit getUnit() const override {
Base::Unit getUnit() const override
{
return Base::Unit::Length;
}
const char* getEditorName() const override {
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyPositionItem";
}
};
@@ -185,11 +195,13 @@ public:
*/
~PropertyDirection() override;
Base::Unit getUnit() const override {
Base::Unit getUnit() const override
{
return Base::Unit::Length;
}
const char* getEditorName() const override {
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyDirectionItem";
}
};
@@ -216,24 +228,25 @@ public:
void setValue(double x, double y, double z);
using inherited::setValue;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
void SaveDocFile (Base::Writer &writer) const override;
void RestoreDocFile(Base::Reader &reader) override;
void SaveDocFile(Base::Writer& writer) const override;
void RestoreDocFile(Base::Reader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override;
const char* getEditorName() const override {
unsigned int getMemSize() const override;
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyVectorListItem";
}
protected:
Base::Vector3d getPyValue(PyObject *) const override;
Base::Vector3d getPyValue(PyObject*) const override;
};
/// Property representing a 4x4 matrix
@@ -259,31 +272,35 @@ public:
/** Sets the property
*/
void setValue(const Base::Matrix4D &mat);
void setValue(const Base::Matrix4D& mat);
/** This method returns a string representation of the property
*/
const Base::Matrix4D &getValue() const;
const char* getEditorName() const override {
const Base::Matrix4D& getValue() const;
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyMatrixItem";
}
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override {
unsigned int getMemSize() const override
{
return sizeof(Base::Matrix4D);
}
bool isSame(const Property &other) const override {
if (&other == this)
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
@@ -315,49 +332,52 @@ public:
/** Sets the property
*/
void setValue(const Base::Placement &pos);
void setValue(const Base::Placement& pos);
/** Sets property only if changed
* @param pos: input placement
* @param tol: position tolerance
* @param atol: angular tolerance
*/
bool setValueIfChanged(const Base::Placement &pos,
double tol=1e-7, double atol=1e-12);
bool setValueIfChanged(const Base::Placement& pos, double tol = 1e-7, double atol = 1e-12);
/** This method returns a string representation of the property
*/
const Base::Placement &getValue() const;
const Base::Placement& getValue() const;
/// Get valid paths for this property; used by auto completer
void getPaths(std::vector<ObjectIdentifier> &paths) const override;
void getPaths(std::vector<ObjectIdentifier>& paths) const override;
void setPathValue(const ObjectIdentifier &path, const boost::any &value) override;
void setPathValue(const ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const ObjectIdentifier &path) const override;
const boost::any getPathValue(const ObjectIdentifier& path) const override;
bool getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const override;
bool getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const override;
const char* getEditorName() const override {
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyPlacementItem";
}
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override {
unsigned int getMemSize() const override
{
return sizeof(Base::Placement);
}
bool isSame(const Property &other) const override {
if (&other == this)
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
@@ -371,7 +391,7 @@ private:
/** the general Link Property
* Main Purpose of this property is to Link Objects and Features in a document.
*/
class AppExport PropertyPlacementLink : public PropertyLink
class AppExport PropertyPlacementLink: public PropertyLink
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -390,10 +410,10 @@ public:
/** This method returns the linked DocumentObject
*/
App::Placement * getPlacementObject() const;
App::Placement* getPlacementObject() const;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
};
@@ -409,21 +429,21 @@ public:
~PropertyPlacementList() override;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
void SaveDocFile (Base::Writer &writer) const override;
void RestoreDocFile(Base::Reader &reader) override;
void SaveDocFile(Base::Writer& writer) const override;
void RestoreDocFile(Base::Reader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override;
unsigned int getMemSize() const override;
protected:
Base::Placement getPyValue(PyObject *) const override;
Base::Placement getPyValue(PyObject* item) const override;
};
@@ -431,7 +451,7 @@ protected:
/*!
* Encapsulates a Base::Rotation in a Property
*/
class AppExport PropertyRotation : public Property
class AppExport PropertyRotation: public Property
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -450,42 +470,44 @@ public:
/** Sets the property
*/
void setValue(const Base::Rotation &rot);
void setValue(const Base::Rotation& rot);
/** Sets property only if changed
* @param pos: input placement
* @param tol: position tolerance
* @param atol: angular tolerance
*/
bool setValueIfChanged(const Base::Rotation &rot, double atol=1e-12);
bool setValueIfChanged(const Base::Rotation& rot, double atol = 1e-12);
/** This method returns a string representation of the property
*/
const Base::Rotation &getValue() const;
const Base::Rotation& getValue() const;
/// Get valid paths for this property; used by auto completer
void getPaths(std::vector<ObjectIdentifier> &paths) const override;
void getPaths(std::vector<ObjectIdentifier>& paths) const override;
void setPathValue(const ObjectIdentifier &path, const boost::any &value) override;
void setPathValue(const ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const ObjectIdentifier &path) const override;
const boost::any getPathValue(const ObjectIdentifier& path) const override;
bool getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const override;
bool getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const override;
const char* getEditorName() const override {
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyRotationItem";
}
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override {
unsigned int getMemSize() const override
{
return sizeof(Base::Placement);
}
@@ -497,7 +519,7 @@ private:
/** The base class for all basic geometry properties.
* @author Werner Mayer
*/
class AppExport PropertyGeometry : public App::Property
class AppExport PropertyGeometry: public App::Property
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -512,7 +534,7 @@ public:
/// Get the placement of the geometry
virtual Base::Matrix4D getTransform() const = 0;
/// Applies a transformation on the real geometric data type
virtual void transformGeometry(const Base::Matrix4D &rclMat) = 0;
virtual void transformGeometry(const Base::Matrix4D& rclMat) = 0;
/// Retrieve bounding box information
virtual Base::BoundBox3d getBoundingBox() const = 0;
//@}
@@ -521,7 +543,7 @@ public:
/** The base class for all complex data properties.
* @author Werner Mayer
*/
class AppExport PropertyComplexGeoData : public App::PropertyGeometry
class AppExport PropertyComplexGeoData: public App::PropertyGeometry
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -532,7 +554,7 @@ public:
/** @name Modification */
//@{
/// Applies a transformation on the real geometric data type
void transformGeometry(const Base::Matrix4D &rclMat) override = 0;
void transformGeometry(const Base::Matrix4D& rclMat) override = 0;
//@}
/** @name Getting basic geometric entities */
@@ -546,15 +568,15 @@ public:
* @param persisted: if true, return the restored element map version. Or
* else, return the current element map version
*/
virtual std::string getElementMapVersion(bool restored=false) const;
virtual std::string getElementMapVersion(bool restored = false) const;
/// Return true to signal element map version change
virtual bool checkElementMapVersion(const char * ver) const;
virtual bool checkElementMapVersion(const char* ver) const;
void afterRestore() override;
};
} // namespace App
} // namespace App
#endif // APP_PROPERTYGEO_H
#endif // APP_PROPERTYGEO_H
+2356 -1674
View File
File diff suppressed because it is too large Load Diff
+591 -403
View File
File diff suppressed because it is too large Load Diff
+99 -90
View File
@@ -39,7 +39,7 @@
using namespace App;
TYPESYSTEM_SOURCE(App::PropertyPythonObject , App::Property)
TYPESYSTEM_SOURCE(App::PropertyPythonObject, App::Property)
PropertyPythonObject::PropertyPythonObject() = default;
@@ -51,11 +51,11 @@ PropertyPythonObject::~PropertyPythonObject()
this->object = Py::Object();
}
void PropertyPythonObject::setValue(Py::Object o)
void PropertyPythonObject::setValue(const Py::Object& py)
{
Base::PyGILStateLocker lock;
aboutToSetValue();
this->object = o;
this->object = py;
hasSetValue();
}
@@ -64,12 +64,12 @@ Py::Object PropertyPythonObject::getValue() const
return object;
}
PyObject *PropertyPythonObject::getPyObject()
PyObject* PropertyPythonObject::getPyObject()
{
return Py::new_reference_to(this->object);
}
void PropertyPythonObject::setPyObject(PyObject * obj)
void PropertyPythonObject::setPyObject(PyObject* obj)
{
Base::PyGILStateLocker lock;
aboutToSetValue();
@@ -82,9 +82,10 @@ std::string PropertyPythonObject::toString() const
std::string repr;
Base::PyGILStateLocker lock;
try {
Py::Module pickle(PyImport_ImportModule("json"),true);
if (pickle.isNull())
Py::Module pickle(PyImport_ImportModule("json"), true);
if (pickle.isNull()) {
throw Py::Exception();
}
Py::Callable method(pickle.getAttr(std::string("dumps")));
Py::Object dump;
if (this->object.hasAttr("dumps")) {
@@ -95,10 +96,9 @@ std::string PropertyPythonObject::toString() const
// support add-ons that use the old method names
else if (this->object.hasAttr("__getstate__")
#if PY_VERSION_HEX >= 0x030b0000
&& this->object.getAttr("__getstate__").hasAttr("__func__")
&& this->object.getAttr("__getstate__").hasAttr("__func__")
#endif
)
{
) {
Py::Tuple args;
Py::Callable state(this->object.getAttr("__getstate__"));
dump = state.apply(args);
@@ -118,8 +118,9 @@ std::string PropertyPythonObject::toString() const
}
catch (Py::Exception&) {
Py::String typestr(this->object.type().str());
Base::Console().Error("PropertyPythonObject::toString(): failed for %s\n", typestr.as_string().c_str());
Base::PyException e; // extract the Python error text
Base::Console().Error("PropertyPythonObject::toString(): failed for %s\n",
typestr.as_string().c_str());
Base::PyException e; // extract the Python error text
e.ReportException();
}
@@ -130,11 +131,13 @@ void PropertyPythonObject::fromString(const std::string& repr)
{
Base::PyGILStateLocker lock;
try {
if (repr.empty())
if (repr.empty()) {
return;
Py::Module pickle(PyImport_ImportModule("json"),true);
if (pickle.isNull())
}
Py::Module pickle(PyImport_ImportModule("json"), true);
if (pickle.isNull()) {
throw Py::Exception();
}
Py::Callable method(pickle.getAttr(std::string("loads")));
Py::Tuple args(1);
args.setItem(0, Py::String(repr));
@@ -149,10 +152,9 @@ void PropertyPythonObject::fromString(const std::string& repr)
// support add-ons that use the old method names
else if (this->object.hasAttr("__setstate__")
#if PY_VERSION_HEX >= 0x030b0000
&& this->object.getAttr("__setstate__").hasAttr("__func__")
&& this->object.getAttr("__setstate__").hasAttr("__func__")
#endif
)
{
) {
Py::Tuple args(1);
args.setItem(0, res);
Py::Callable state(this->object.getAttr("__setstate__"));
@@ -168,7 +170,7 @@ void PropertyPythonObject::fromString(const std::string& repr)
}
}
catch (Py::Exception&) {
Base::PyException e; // extract the Python error text
Base::PyException e; // extract the Python error text
e.ReportException();
}
}
@@ -194,7 +196,7 @@ void PropertyPythonObject::loadPickle(const std::string& str)
}
}
catch (Py::Exception&) {
Base::PyException e; // extract the Python error text
Base::PyException e; // extract the Python error text
e.ReportException();
}
}
@@ -203,18 +205,24 @@ std::string PropertyPythonObject::encodeValue(const std::string& str) const
{
std::string tmp;
for (char it : str) {
if (it == '<')
if (it == '<') {
tmp += "&lt;";
else if (it == '"')
}
else if (it == '"') {
tmp += "&quot;";
else if (it == '&')
}
else if (it == '&') {
tmp += "&amp;";
else if (it == '>')
}
else if (it == '>') {
tmp += "&gt";
else if (it == '\n')
}
else if (it == '\n') {
tmp += "\\n";
else
}
else {
tmp += it;
}
}
return tmp;
@@ -230,14 +238,15 @@ std::string PropertyPythonObject::decodeValue(const std::string& str) const
tmp += '\n';
}
}
else
else {
tmp += *it;
}
}
return tmp;
}
void PropertyPythonObject::saveObject(Base::Writer &writer) const
void PropertyPythonObject::saveObject(Base::Writer& writer) const
{
Base::PyGILStateLocker lock;
try {
@@ -258,19 +267,19 @@ void PropertyPythonObject::saveObject(Base::Writer &writer) const
}
}
void PropertyPythonObject::restoreObject(Base::XMLReader &reader)
void PropertyPythonObject::restoreObject(Base::XMLReader& reader)
{
Base::PyGILStateLocker lock;
try {
PropertyContainer* parent = this->getContainer();
if (reader.hasAttribute("object")) {
if (strcmp(reader.getAttribute("object"),"yes") == 0) {
if (strcmp(reader.getAttribute("object"), "yes") == 0) {
Py::Object obj = Py::asObject(parent->getPyObject());
this->object.setAttr("__object__", obj);
}
}
if (reader.hasAttribute("vobject")) {
if (strcmp(reader.getAttribute("vobject"),"yes") == 0) {
if (strcmp(reader.getAttribute("vobject"), "yes") == 0) {
Py::Object obj = Py::asObject(parent->getPyObject());
this->object.setAttr("__vobject__", obj);
}
@@ -280,65 +289,57 @@ void PropertyPythonObject::restoreObject(Base::XMLReader &reader)
e.clear();
}
catch (const Base::Exception& e) {
Base::Console().Error("%s\n",e.what());
Base::Console().Error("%s\n", e.what());
}
catch (...) {
Base::Console().Error("Critical error in PropertyPythonObject::restoreObject\n");
}
}
void PropertyPythonObject::Save (Base::Writer &writer) const
void PropertyPythonObject::Save(Base::Writer& writer) const
{
//if (writer.isForceXML()) {
std::string repr = this->toString();
repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size());
std::string val = /*encodeValue*/(repr);
writer.Stream() << writer.ind() << "<Python value=\"" << val
<< R"(" encoded="yes")";
std::string repr = this->toString();
repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size());
std::string val = /*encodeValue*/ (repr);
writer.Stream() << writer.ind() << "<Python value=\"" << val << R"(" encoded="yes")";
Base::PyGILStateLocker lock;
try {
if (this->object.hasAttr("__module__") && this->object.hasAttr("__class__")) {
Py::String mod(this->object.getAttr("__module__"));
Py::Object cls(this->object.getAttr("__class__"));
if (cls.hasAttr("__name__")) {
Py::String name(cls.getAttr("__name__"));
writer.Stream() << " module=\"" << (std::string)mod << "\""
<< " class=\"" << (std::string)name << "\"";
}
}
else {
writer.Stream() << " json=\"yes\"";
Base::PyGILStateLocker lock;
try {
if (this->object.hasAttr("__module__") && this->object.hasAttr("__class__")) {
Py::String mod(this->object.getAttr("__module__"));
Py::Object cls(this->object.getAttr("__class__"));
if (cls.hasAttr("__name__")) {
Py::String name(cls.getAttr("__name__"));
writer.Stream() << " module=\"" << (std::string)mod << "\""
<< " class=\"" << (std::string)name << "\"";
}
}
catch (Py::Exception&) {
Base::PyException e; // extract the Python error text
e.ReportException();
else {
writer.Stream() << " json=\"yes\"";
}
}
catch (Py::Exception&) {
Base::PyException e; // extract the Python error text
e.ReportException();
}
saveObject(writer);
writer.Stream() << "/>" << std::endl;
//}
//else {
// writer.Stream() << writer.ind() << "<Python file=\"" <<
// writer.addFile("pickle", this) << "\"/>" << std::endl;
//}
saveObject(writer);
writer.Stream() << "/>" << std::endl;
}
void PropertyPythonObject::Restore(Base::XMLReader &reader)
void PropertyPythonObject::Restore(Base::XMLReader& reader)
{
reader.readElement("Python");
if (reader.hasAttribute("file")) {
std::string file(reader.getAttribute("file"));
reader.addFile(file.c_str(),this);
reader.addFile(file.c_str(), this);
}
else {
bool load_json=false;
bool load_pickle=false;
bool load_failed=false;
bool load_json = false;
bool load_pickle = false;
bool load_failed = false;
std::string buffer = reader.getAttribute("value");
if (reader.hasAttribute("encoded") &&
strcmp(reader.getAttribute("encoded"),"yes") == 0) {
if (reader.hasAttribute("encoded") && strcmp(reader.getAttribute("encoded"), "yes") == 0) {
buffer = Base::base64_decode(buffer);
}
else {
@@ -353,14 +354,15 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader)
start = buffer.begin();
end = buffer.end();
if (reader.hasAttribute("module") && reader.hasAttribute("class")) {
Py::Module mod(PyImport_ImportModule(reader.getAttribute("module")),true);
if (mod.isNull())
Py::Module mod(PyImport_ImportModule(reader.getAttribute("module")), true);
if (mod.isNull()) {
throw Py::Exception();
}
PyObject* cls = mod.getAttr(reader.getAttribute("class")).ptr();
if (!cls) {
std::stringstream s;
s << "Module " << reader.getAttribute("module")
<< " has no class " << reader.getAttribute("class");
s << "Module " << reader.getAttribute("module") << " has no class "
<< reader.getAttribute("class");
throw Py::AttributeError(s.str());
}
if (PyType_Check(cls)) {
@@ -374,9 +376,10 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader)
else if (boost::regex_search(start, end, what, pickle)) {
std::string name = std::string(what[1].first, what[1].second);
std::string type = std::string(what[2].first, what[2].second);
Py::Module mod(PyImport_ImportModule(name.c_str()),true);
if (mod.isNull())
Py::Module mod(PyImport_ImportModule(name.c_str()), true);
if (mod.isNull()) {
throw Py::Exception();
}
this->object = PyObject_CallObject(mod.getAttr(type).ptr(), nullptr);
load_pickle = true;
buffer = std::string(what[2].second, end);
@@ -386,57 +389,63 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader)
}
}
catch (Py::Exception&) {
Base::PyException e; // extract the Python error text
Base::PyException e; // extract the Python error text
e.ReportException();
this->object = Py::None();
load_failed = true;
}
aboutToSetValue();
if (load_json)
if (load_json) {
this->fromString(buffer);
else if (load_pickle)
}
else if (load_pickle) {
this->loadPickle(buffer);
else if (!load_failed)
Base::Console().Warning("PropertyPythonObject::Restore: unsupported serialisation: %s\n", buffer.c_str());
}
else if (!load_failed) {
Base::Console().Warning(
"PropertyPythonObject::Restore: unsupported serialisation: %s\n",
buffer.c_str());
}
restoreObject(reader);
hasSetValue();
}
}
void PropertyPythonObject::SaveDocFile (Base::Writer &writer) const
void PropertyPythonObject::SaveDocFile(Base::Writer& writer) const
{
std::string buffer = this->toString();
for (char it : buffer)
for (char it : buffer) {
writer.Stream().put(it);
}
}
void PropertyPythonObject::RestoreDocFile(Base::Reader &reader)
void PropertyPythonObject::RestoreDocFile(Base::Reader& reader)
{
aboutToSetValue();
std::string buffer;
char c;
while (reader.get(c)) {
buffer.push_back(c);
char ch {};
while (reader.get(ch)) {
buffer.push_back(ch);
}
this->fromString(buffer);
hasSetValue();
}
unsigned int PropertyPythonObject::getMemSize () const
unsigned int PropertyPythonObject::getMemSize() const
{
return sizeof(Py::Object);
}
Property *PropertyPythonObject::Copy() const
Property* PropertyPythonObject::Copy() const
{
PropertyPythonObject *p = new PropertyPythonObject();
PropertyPythonObject* p = new PropertyPythonObject();
Base::PyGILStateLocker lock;
p->object = this->object;
return p;
}
void PropertyPythonObject::Paste(const Property &from)
void PropertyPythonObject::Paste(const Property& from)
{
if (from.is<PropertyPythonObject>()) {
Base::PyGILStateLocker lock;
+18 -17
View File
@@ -30,10 +30,11 @@
#include "Property.h"
namespace Base {
namespace Base
{
class Writer;
class XMLReader;
}
} // namespace Base
namespace App
{
@@ -42,7 +43,7 @@ namespace App
* PropertyPythonObject is used to manage Py::Object instances as properties.
* @author Werner Mayer
*/
class AppExport PropertyPythonObject : public Property
class AppExport PropertyPythonObject: public Property
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -50,29 +51,29 @@ public:
PropertyPythonObject();
~PropertyPythonObject() override;
void setValue(Py::Object);
void setValue(const Py::Object& py);
Py::Object getValue() const;
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject* obj) override;
/** Use Python's pickle module to save the object */
void Save (Base::Writer &writer) const override;
void Save(Base::Writer& writer) const override;
/** Use Python's pickle module to restore the object */
void Restore(Base::XMLReader &reader) override;
void SaveDocFile (Base::Writer &writer) const override;
void RestoreDocFile(Base::Reader &reader) override;
void Restore(Base::XMLReader& reader) override;
void SaveDocFile(Base::Writer& writer) const override;
void RestoreDocFile(Base::Reader& reader) override;
unsigned int getMemSize () const override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize() const override;
Property* Copy() const override;
void Paste(const Property& from) override;
std::string toString() const;
void fromString(const std::string&);
private:
void saveObject(Base::Writer &writer) const;
void restoreObject(Base::XMLReader &reader);
void saveObject(Base::Writer& writer) const;
void restoreObject(Base::XMLReader& reader);
std::string encodeValue(const std::string& str) const;
std::string decodeValue(const std::string& str) const;
void loadPickle(const std::string& str);
@@ -80,6 +81,6 @@ private:
};
} // namespace App
} // namespace App
#endif // APP_PROPERTYPYTHONOBJECT_H
#endif // APP_PROPERTYPYTHONOBJECT_H
File diff suppressed because it is too large Load Diff
+294 -208
View File
@@ -37,11 +37,12 @@
#include "Material.h"
namespace Base {
namespace Base
{
class InputStream;
class OutputStream;
class Writer;
}
} // namespace Base
namespace App
@@ -65,23 +66,33 @@ public:
/** This method returns a string representation of the property
*/
long getValue() const;
const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyIntegerItem"; }
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyIntegerItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override{return sizeof(long);}
unsigned int getMemSize() const override
{
return sizeof(long);
}
void setPathValue(const App::ObjectIdentifier & path, const boost::any & value) override;
const boost::any getPathValue(const App::ObjectIdentifier & /*path*/) const override { return _lValue; }
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const App::ObjectIdentifier& /*path*/) const override
{
return _lValue;
}
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -101,36 +112,39 @@ class AppExport PropertyPath: public Property
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
PropertyPath();
~PropertyPath() override;
/** Sets the property
*/
void setValue(const boost::filesystem::path &);
void setValue(const boost::filesystem::path&);
/** Sets the property
*/
void setValue(const char *);
void setValue(const char*);
/** This method returns a string representation of the property
*/
const boost::filesystem::path &getValue() const;
const boost::filesystem::path& getValue() const;
const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyPathItem"; }
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyPathItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override;
unsigned int getMemSize() const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -152,7 +166,7 @@ public:
PropertyEnumeration();
/// Obvious constructor
explicit PropertyEnumeration(const Enumeration &e);
explicit PropertyEnumeration(const Enumeration& e);
/// destructor
~PropertyEnumeration() override;
@@ -173,7 +187,7 @@ public:
/** setting the enumeration string as vector of strings
* This makes the enumeration custom.
*/
void setEnums(const std::vector<std::string> &Enums);
void setEnums(const std::vector<std::string>& Enums);
/** set the enum by a string
* is slower than setValue(long). Use long if possible
@@ -187,7 +201,7 @@ public:
void setValue(long);
/// Setter using Enumeration
void setValue(const Enumeration &source);
void setValue(const Enumeration& source);
/// Returns current value of the enumeration as an integer
long getValue() const;
@@ -199,16 +213,16 @@ public:
bool isPartOf(const char* value) const;
/// get the value as string
const char * getValueAsString() const;
const char* getValueAsString() const;
/// Returns Enumeration object
const Enumeration &getEnum() const;
const Enumeration& getEnum() const;
/// get all possible enum values as vector of strings
std::vector<std::string> getEnumVector() const;
/// set enum values as vector of strings
void setEnumVector(const std::vector<std::string> &);
void setEnumVector(const std::vector<std::string>&);
/// get the pointer to the enum list
bool hasEnums() const;
@@ -216,24 +230,31 @@ public:
bool isValid() const;
//@}
const char* getEditorName() const override { return _editorTypeName.c_str(); }
void setEditorName(const char* name) { _editorTypeName = name; }
const char* getEditorName() const override
{
return _editorTypeName.c_str();
}
void setEditorName(const char* name)
{
_editorTypeName = name;
}
PyObject * getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save(Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property * Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
void setPathValue(const App::ObjectIdentifier & path, const boost::any & value) override;
virtual bool setPyPathValue(const App::ObjectIdentifier & path, const Py::Object &value);
const boost::any getPathValue(const App::ObjectIdentifier & /*path*/) const override;
bool getPyPathValue(const ObjectIdentifier &path, Py::Object &r) const override;
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
virtual bool setPyPathValue(const App::ObjectIdentifier& path, const Py::Object& value);
const boost::any getPathValue(const App::ObjectIdentifier& /*path*/) const override;
bool getPyPathValue(const ObjectIdentifier& path, Py::Object& r) const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -266,22 +287,21 @@ public:
/// Constraint methods
//@{
/// the boundary struct
struct Constraints {
struct Constraints
{
long LowerBound, UpperBound, StepSize;
Constraints()
: LowerBound(0)
, UpperBound(0)
, StepSize(0)
, candelete(false)
{
}
{}
Constraints(long l, long u, long s)
: LowerBound(l)
, UpperBound(u)
, StepSize(s)
, candelete(false)
{
}
{}
~Constraints() = default;
void setDeletable(bool on)
{
@@ -291,6 +311,7 @@ public:
{
return candelete;
}
private:
bool candelete;
};
@@ -304,18 +325,21 @@ public:
*/
void setConstraints(const Constraints* sConstraint);
/// get the constraint struct
const Constraints* getConstraints() const;
const Constraints* getConstraints() const;
//@}
long getMinimum() const;
long getMaximum() const;
long getStepSize() const;
const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyIntegerConstraintItem"; }
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyIntegerConstraintItem";
}
void setPyObject(PyObject* py) override;
protected:
const Constraints* _ConstStruct{nullptr};
const Constraints* _ConstStruct {nullptr};
};
/** Percent property
@@ -357,19 +381,21 @@ public:
~PropertyIntegerList() override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyIntegerListItem"; }
{
return "Gui::PropertyEditor::PropertyIntegerListItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
protected:
long getPyValue(PyObject *item) const override;
long getPyValue(PyObject* item) const override;
};
/** Integer list properties
@@ -396,30 +422,41 @@ public:
/** Sets the property
*/
void setValue(long);
void setValue(){;}
void setValue()
{
;
}
void addValue (long value){_lValueSet.insert(value);}
void setValues (const std::set<long>& values);
void addValue(long value)
{
_lValueSet.insert(value);
}
void setValues(const std::set<long>& values);
const std::set<long> &getValues() const{return _lValueSet;}
const std::set<long>& getValues() const
{
return _lValueSet;
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
return getTypeId() == other.getTypeId()
&& getValues() == static_cast<decltype(this)>(&other)->getValues();
}
private:
std::set<long> _lValueSet;
};
@@ -433,7 +470,6 @@ class AppExport PropertyMap: public Property
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
@@ -450,31 +486,40 @@ public:
/** Sets the property
*/
void setValue(){}
void setValue(const std::string& key,const std::string& value);
void setValues(const std::map<std::string,std::string>&);
void setValue()
{}
void setValue(const std::string& key, const std::string& value);
void setValues(const std::map<std::string, std::string>&);
/// index operator
const std::string& operator[] (const std::string& key) const ;
const std::string& operator[](const std::string& key) const;
void set1Value (const std::string& key, const std::string& value){_lValueList.operator[] (key) = value;}
void set1Value(const std::string& key, const std::string& value)
{
_lValueList.operator[](key) = value;
}
const std::map<std::string,std::string> &getValues() const{return _lValueList;}
const std::map<std::string, std::string>& getValues() const
{
return _lValueList;
}
//virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyStringListItem"; }
// virtual const char* getEditorName(void) const { return
// "Gui::PropertyEditor::PropertyStringListItem"; }
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override;
unsigned int getMemSize() const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -483,11 +528,10 @@ public:
}
private:
std::map<std::string,std::string> _lValueList;
std::map<std::string, std::string> _lValueList;
};
/** Float properties
* This is the father of all properties handling floats.
* Use this type only in rare cases. Mostly you want to
@@ -515,23 +559,30 @@ public:
void setValue(double lValue);
double getValue() const;
const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyFloatItem"; }
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyFloatItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override{return sizeof(double);}
unsigned int getMemSize() const override
{
return sizeof(double);
}
void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override;
const boost::any getPathValue(const App::ObjectIdentifier &path) const override;
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const App::ObjectIdentifier& path) const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -554,7 +605,6 @@ class AppExport PropertyFloatConstraint: public PropertyFloat
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/** Value Constructor
* Construct with explicit Values
*/
@@ -570,22 +620,21 @@ public:
/// Constraint methods
//@{
/// the boundary struct
struct Constraints {
struct Constraints
{
double LowerBound, UpperBound, StepSize;
Constraints()
: LowerBound(0)
, UpperBound(0)
, StepSize(0)
, candelete(false)
{
}
{}
Constraints(double l, double u, double s)
: LowerBound(l)
, UpperBound(u)
, StepSize(s)
, candelete(false)
{
}
{}
~Constraints() = default;
void setDeletable(bool on)
{
@@ -595,6 +644,7 @@ public:
{
return candelete;
}
private:
bool candelete;
};
@@ -608,7 +658,7 @@ public:
*/
void setConstraints(const Constraints* sConstrain);
/// get the constraint struct
const Constraints* getConstraints() const;
const Constraints* getConstraints() const;
//@}
double getMinimum() const;
@@ -616,12 +666,14 @@ public:
double getStepSize() const;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyFloatConstraintItem"; }
{
return "Gui::PropertyEditor::PropertyFloatConstraintItem";
}
void setPyObject(PyObject* py) override;
protected:
const Constraints* _ConstStruct{nullptr};
const Constraints* _ConstStruct {nullptr};
};
@@ -633,11 +685,14 @@ protected:
class AppExport PropertyPrecision: public PropertyFloatConstraint
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
PropertyPrecision();
~PropertyPrecision() override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyPrecisionItem"; }
{
return "Gui::PropertyEditor::PropertyPrecisionItem";
}
};
@@ -646,7 +701,6 @@ class AppExport PropertyFloatList: public PropertyListsT<double>
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
@@ -660,22 +714,24 @@ public:
~PropertyFloatList() override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyFloatListItem"; }
{
return "Gui::PropertyEditor::PropertyFloatListItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
void SaveDocFile (Base::Writer &writer) const override;
void RestoreDocFile(Base::Reader &reader) override;
void SaveDocFile(Base::Writer& writer) const override;
void RestoreDocFile(Base::Reader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
protected:
double getPyValue(PyObject *item) const override;
double getPyValue(PyObject* item) const override;
};
@@ -687,7 +743,6 @@ class AppExport PropertyString: public Property
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
@@ -701,27 +756,36 @@ public:
~PropertyString() override;
virtual void setValue(const char* sString);
void setValue(const std::string &sString);
void setValue(const std::string& sString);
const char* getValue() const;
const std::string& getStrValue() const
{ return _cValue; }
bool isEmpty(){return _cValue.empty();}
{
return _cValue;
}
bool isEmpty()
{
return _cValue.empty();
}
const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyStringItem"; }
PyObject *getPyObject() override;
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyStringItem";
}
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override;
const boost::any getPathValue(const App::ObjectIdentifier &path) const override;
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const App::ObjectIdentifier& path) const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -741,7 +805,6 @@ class AppExport PropertyUUID: public Property
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
@@ -755,24 +818,26 @@ public:
~PropertyUUID() override;
void setValue(const Base::Uuid &);
void setValue(const Base::Uuid&);
void setValue(const char* sString);
void setValue(const std::string &sString);
void setValue(const std::string& sString);
const std::string& getValueStr() const;
const Base::Uuid& getValue() const;
//virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyStringItem"; }
PyObject *getPyObject() override;
// virtual const char* getEditorName(void) const { return
// "Gui::PropertyEditor::PropertyStringItem"; }
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -787,7 +852,7 @@ private:
/** Property handling with font names.
*/
class AppExport PropertyFont : public PropertyString
class AppExport PropertyFont: public PropertyString
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -795,9 +860,12 @@ public:
PropertyFont();
~PropertyFont() override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyFontItem"; }
{
return "Gui::PropertyEditor::PropertyFontItem";
}
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -812,7 +880,6 @@ class AppExport PropertyStringList: public PropertyListsT<std::string>
using inherited = PropertyListsT<std::string>;
public:
/**
* A constructor.
* A more elaborate description of the constructor.
@@ -829,31 +896,32 @@ public:
using inherited::setValues;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyStringListItem"; }
{
return "Gui::PropertyEditor::PropertyStringListItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override;
unsigned int getMemSize() const override;
protected:
std::string getPyValue(PyObject *item) const override;
std::string getPyValue(PyObject* item) const override;
};
/** Bool properties
* This is the father of all properties handling booleans.
*/
class AppExport PropertyBool : public Property
class AppExport PropertyBool: public Property
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
@@ -869,23 +937,30 @@ public:
void setValue(bool lValue);
bool getValue() const;
const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyBoolItem"; }
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyBoolItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override{return sizeof(bool);}
unsigned int getMemSize() const override
{
return sizeof(bool);
}
void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override;
const boost::any getPathValue(const App::ObjectIdentifier &path) const override;
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const App::ObjectIdentifier& path) const override;
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -900,24 +975,24 @@ private:
/** Bool list properties
*
*/
class AppExport PropertyBoolList : public PropertyListsT<bool,boost::dynamic_bitset<> >
class AppExport PropertyBoolList: public PropertyListsT<bool, boost::dynamic_bitset<>>
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
using inherited = PropertyListsT<bool, boost::dynamic_bitset<> >;
using inherited = PropertyListsT<bool, boost::dynamic_bitset<>>;
public:
PropertyBoolList();
~PropertyBoolList() override;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
protected:
bool getPyValue(PyObject* py) const override;
@@ -927,7 +1002,7 @@ protected:
/** Color properties
* This is the father of all properties handling colors.
*/
class AppExport PropertyColor : public Property
class AppExport PropertyColor: public Property
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -946,28 +1021,35 @@ public:
/** Sets the property
*/
void setValue(const Color &col);
void setValue(float r, float g, float b, float a=0.0F);
void setValue(const Color& col);
void setValue(float r, float g, float b, float a = 0.0F);
void setValue(uint32_t rgba);
/** This method returns a string representation of the property
*/
const Color &getValue() const;
const Color& getValue() const;
const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyColorItem"; }
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyColorItem";
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setPyObject(PyObject* py) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize () const override{return sizeof(Color);}
unsigned int getMemSize() const override
{
return sizeof(Color);
}
bool isSame(const Property &other) const override {
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
@@ -984,7 +1066,6 @@ class AppExport PropertyColorList: public PropertyListsT<Color>
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
@@ -997,17 +1078,17 @@ public:
*/
~PropertyColorList() override;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
void SaveDocFile (Base::Writer &writer) const override;
void RestoreDocFile(Base::Reader &reader) override;
void SaveDocFile(Base::Writer& writer) const override;
void RestoreDocFile(Base::Reader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
protected:
Color getPyValue(PyObject* py) const override;
@@ -1118,7 +1199,8 @@ public:
{
PropertyListsT<Material>::setValue(materials);
}
void setValues(const std::vector<App::Material>& newValues = std::vector<App::Material>()) override;
void
setValues(const std::vector<App::Material>& newValues = std::vector<App::Material>()) override;
void setValue(const Material& mat);
void setValue(int index, const Material& mat);
@@ -1196,7 +1278,8 @@ protected:
Material getPyValue(PyObject* py) const override;
private:
enum Format {
enum Format
{
Version_0,
Version_1,
Version_2,
@@ -1206,7 +1289,7 @@ private:
void RestoreDocFileV0(uint32_t count, Base::Reader& reader);
void RestoreDocFileV3(Base::Reader& reader);
void writeString(Base::OutputStream& str, const std::string &value) const;
void writeString(Base::OutputStream& str, const std::string& value) const;
void readString(Base::InputStream& str, std::string& value);
void verifyIndex(int index) const;
@@ -1222,21 +1305,24 @@ private:
* In Python, this property can be assigned a type string to create a dynamic FreeCAD
* object, and then read back as the Python binding of the newly created object.
*/
class AppExport PropertyPersistentObject: public PropertyString {
class AppExport PropertyPersistentObject: public PropertyString
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
using inherited = PropertyString;
public:
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void setValue(const char* type) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override;
Property* Copy() const override;
void Paste(const Property& from) override;
unsigned int getMemSize() const override;
std::shared_ptr<Base::Persistence> getObject() const {
std::shared_ptr<Base::Persistence> getObject() const
{
return _pObject;
}
@@ -1244,6 +1330,6 @@ protected:
std::shared_ptr<Base::Persistence> _pObject;
};
} // namespace App
} // namespace App
#endif // APP_PROPERTYSTANDARD_H
#endif // APP_PROPERTYSTANDARD_H
+44 -34
View File
@@ -22,7 +22,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cfloat>
#include <cfloat>
#endif
#include <Base/QuantityPy.h>
@@ -37,8 +37,8 @@ using namespace Base;
using namespace std;
const PropertyQuantityConstraint::Constraints LengthStandard = {0.0,DBL_MAX,1.0};
const PropertyQuantityConstraint::Constraints AngleStandard = {-360,360,1.0};
const PropertyQuantityConstraint::Constraints LengthStandard = {0.0, DBL_MAX, 1.0};
const PropertyQuantityConstraint::Constraints AngleStandard = {-360, 360, 1.0};
//**************************************************************************
// PropertyQuantity
@@ -48,7 +48,7 @@ TYPESYSTEM_SOURCE(App::PropertyQuantity, App::PropertyFloat)
Base::Quantity PropertyQuantity::getQuantityValue() const
{
return Quantity(_dValue,_Unit);
return Quantity(_dValue, _Unit);
}
const char* PropertyQuantity::getEditorName() const
@@ -56,24 +56,26 @@ const char* PropertyQuantity::getEditorName() const
return "Gui::PropertyEditor::PropertyUnitItem";
}
PyObject *PropertyQuantity::getPyObject()
PyObject* PropertyQuantity::getPyObject()
{
return new QuantityPy (new Quantity(_dValue,_Unit));
return new QuantityPy(new Quantity(_dValue, _Unit));
}
Base::Quantity PropertyQuantity::createQuantityFromPy(PyObject *value)
Base::Quantity PropertyQuantity::createQuantityFromPy(PyObject* value)
{
Base::Quantity quant;
if (PyUnicode_Check(value)){
if (PyUnicode_Check(value)) {
quant = Quantity::parse(QString::fromUtf8(PyUnicode_AsUTF8(value)));
}
else if (PyFloat_Check(value))
quant = Quantity(PyFloat_AsDouble(value),_Unit);
else if (PyLong_Check(value))
quant = Quantity(double(PyLong_AsLong(value)),_Unit);
else if (PyFloat_Check(value)) {
quant = Quantity(PyFloat_AsDouble(value), _Unit);
}
else if (PyLong_Check(value)) {
quant = Quantity(double(PyLong_AsLong(value)), _Unit);
}
else if (PyObject_TypeCheck(value, &(QuantityPy::Type))) {
Base::QuantityPy *pcObject = static_cast<Base::QuantityPy*>(value);
Base::QuantityPy* pcObject = static_cast<Base::QuantityPy*>(value);
quant = *(pcObject->getQuantityPtr());
}
else {
@@ -85,45 +87,47 @@ Base::Quantity PropertyQuantity::createQuantityFromPy(PyObject *value)
return quant;
}
void PropertyQuantity::setPyObject(PyObject *value)
void PropertyQuantity::setPyObject(PyObject* value)
{
// Set the unit if Unit object supplied, else check the unit
// and set the value
if (PyObject_TypeCheck(value, &(UnitPy::Type))) {
Base::UnitPy *pcObject = static_cast<Base::UnitPy*>(value);
Base::UnitPy* pcObject = static_cast<Base::UnitPy*>(value);
Base::Unit unit = *(pcObject->getUnitPtr());
aboutToSetValue();
_Unit = unit;
hasSetValue();
}
else {
Base::Quantity quant= createQuantityFromPy(value);
Base::Quantity quant = createQuantityFromPy(value);
Unit unit = quant.getUnit();
if (unit.isEmpty()){
if (unit.isEmpty()) {
PropertyFloat::setValue(quant.getValue());
return;
}
if (unit != _Unit)
if (unit != _Unit) {
throw Base::UnitsMismatchError("Not matching Unit!");
}
PropertyFloat::setValue(quant.getValue());
}
}
void PropertyQuantity::setPathValue(const ObjectIdentifier & /*path*/, const boost::any &value)
void PropertyQuantity::setPathValue(const ObjectIdentifier& /*path*/, const boost::any& value)
{
auto q = App::anyToQuantity(value);
aboutToSetValue();
if(!q.getUnit().isEmpty())
if (!q.getUnit().isEmpty()) {
_Unit = q.getUnit();
_dValue=q.getValue();
}
_dValue = q.getValue();
setValue(q.getValue());
}
const boost::any PropertyQuantity::getPathValue(const ObjectIdentifier & /*path*/) const
const boost::any PropertyQuantity::getPathValue(const ObjectIdentifier& /*path*/) const
{
return Quantity(_dValue, _Unit);
}
@@ -145,55 +149,61 @@ const char* PropertyQuantityConstraint::getEditorName() const
return "Gui::PropertyEditor::PropertyUnitConstraintItem";
}
const PropertyQuantityConstraint::Constraints* PropertyQuantityConstraint::getConstraints() const
const PropertyQuantityConstraint::Constraints* PropertyQuantityConstraint::getConstraints() const
{
return _ConstStruct;
}
double PropertyQuantityConstraint::getMinimum() const
{
if (_ConstStruct)
if (_ConstStruct) {
return _ConstStruct->LowerBound;
}
return std::numeric_limits<double>::min();
}
double PropertyQuantityConstraint::getMaximum() const
{
if (_ConstStruct)
if (_ConstStruct) {
return _ConstStruct->UpperBound;
}
return std::numeric_limits<double>::max();
}
double PropertyQuantityConstraint::getStepSize() const
{
if (_ConstStruct)
if (_ConstStruct) {
return _ConstStruct->StepSize;
}
return 1.0;
}
void PropertyQuantityConstraint::setPyObject(PyObject *value)
void PropertyQuantityConstraint::setPyObject(PyObject* value)
{
Base::Quantity quant= createQuantityFromPy(value);
Base::Quantity quant = createQuantityFromPy(value);
Unit unit = quant.getUnit();
double temp = quant.getValue();
if (_ConstStruct) {
if (temp > _ConstStruct->UpperBound)
if (temp > _ConstStruct->UpperBound) {
temp = _ConstStruct->UpperBound;
else if (temp < _ConstStruct->LowerBound)
}
else if (temp < _ConstStruct->LowerBound) {
temp = _ConstStruct->LowerBound;
}
}
quant.setValue(temp);
if (unit.isEmpty()){
PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method
if (unit.isEmpty()) {
PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method
return;
}
if (unit != _Unit)
if (unit != _Unit) {
throw Base::UnitsMismatchError("Not matching Unit!");
}
PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method
PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method
}
// ------------------------------------------------------
+43 -24
View File
@@ -29,7 +29,8 @@
#include "PropertyStandard.h"
namespace Base {
namespace Base
{
class Writer;
}
@@ -39,7 +40,7 @@ namespace App
/** Float with Unit property
* This is a property for float with a predefined Unit associated.
*/
class AppExport PropertyQuantity : public PropertyFloat
class AppExport PropertyQuantity: public PropertyFloat
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -51,35 +52,49 @@ public:
const char* getEditorName() const override;
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
void setUnit(const Base::Unit &u) {_Unit = u;}
const Base::Unit &getUnit() const {return _Unit;}
void setUnit(const Base::Unit& u)
{
_Unit = u;
}
const Base::Unit& getUnit() const
{
return _Unit;
}
void setValue(double lValue) { PropertyFloat::setValue(lValue); }
double getValue() const { return PropertyFloat::getValue(); }
void setValue(double lValue)
{
PropertyFloat::setValue(lValue);
}
double getValue() const
{
return PropertyFloat::getValue();
}
void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override;
const boost::any getPathValue(const App::ObjectIdentifier &path) const override;
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const App::ObjectIdentifier& path) const override;
bool isSame(const Property &other) const override {
if (&other == this)
bool isSame(const Property& other) const override
{
if (&other == this) {
return true;
}
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue()
&& _Unit == static_cast<decltype(this)>(&other)->_Unit;
}
protected:
Base::Quantity createQuantityFromPy(PyObject *value);
Base::Quantity createQuantityFromPy(PyObject* value);
Base::Unit _Unit;
};
/** Float with Unit property
* This is a property for float with a predefined Unit associated.
*/
class AppExport PropertyQuantityConstraint : public PropertyQuantity
class AppExport PropertyQuantityConstraint: public PropertyQuantity
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -90,7 +105,8 @@ public:
/// Constraint methods
//@{
/// the boundary struct
struct Constraints {
struct Constraints
{
double LowerBound, UpperBound, StepSize;
};
/** setting the boundaries
@@ -103,7 +119,7 @@ public:
*/
void setConstraints(const Constraints* sConstrain);
/// get the constraint struct
const Constraints* getConstraints() const;
const Constraints* getConstraints() const;
//@}
double getMinimum() const;
@@ -111,10 +127,10 @@ public:
double getStepSize() const;
const char* getEditorName() const override;
void setPyObject(PyObject *) override;
void setPyObject(PyObject*) override;
private:
const Constraints* _ConstStruct{nullptr};
const Constraints* _ConstStruct {nullptr};
};
// ------------------------------------------------------
@@ -158,7 +174,10 @@ class AppExport PropertyAngle: public PropertyQuantityConstraint
public:
PropertyAngle();
~PropertyAngle() override = default;
const char *getEditorName() const override { return "Gui::PropertyEditor::PropertyAngleItem"; }
const char* getEditorName() const override
{
return "Gui::PropertyEditor::PropertyAngleItem";
}
};
/** Area property
@@ -425,7 +444,7 @@ public:
/** InverseVolume property
* This is a property for representing the reciprocal of volume. It is basically a float
* property. which must not be negative. On the Gui it has a quantity like 1/m^3.
* property. which must not be negative. On the Gui it has a quantity like 1/m^3.
*/
class AppExport PropertyInverseVolume: public PropertyQuantity
{
@@ -514,11 +533,11 @@ public:
~PropertyMagneticFluxDensity() override = default;
};
/** Magnetization property
/** Magnetization property
* This is a property for representing magnetizations. It is basically a float
* property. On the Gui it has a quantity like A/m.
*/
class AppExport PropertyMagnetization: public PropertyQuantity
class AppExport PropertyMagnetization: public PropertyQuantity
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -852,6 +871,6 @@ public:
~PropertyYoungsModulus() override = default;
};
}// namespace App
} // namespace App
#endif// APP_PROPERTYUNITS_H
#endif // APP_PROPERTYUNITS_H
+2 -2
View File
@@ -154,8 +154,8 @@ struct DocumentP
Path tmp);
std::vector<App::DocumentObject*>
topologicalSort(const std::vector<App::DocumentObject*>& objects) const;
static std::vector<App::DocumentObject*> partialTopologicalSort(
const std::vector<App::DocumentObject*>& objects);
static std::vector<App::DocumentObject*>
partialTopologicalSort(const std::vector<App::DocumentObject*>& objects);
static void checkStringHasher(const Base::XMLReader& reader);
};