diff --git a/src/App/Color.cpp b/src/App/Color.cpp index cfc5c59bfd..0d2d93e165 100644 --- a/src/App/Color.cpp +++ b/src/App/Color.cpp @@ -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; diff --git a/src/App/Color.h b/src/App/Color.h index 3697c437d7..c03a4fc11f 100644 --- a/src/App/Color.h +++ b/src/App/Color.h @@ -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 static uint32_t asPackedRGBA(const T& color) { - color_traits ct{color}; + color_traits ct {color}; return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8) | ct.alpha(); } @@ -162,7 +162,7 @@ public: template static uint32_t asPackedRGB(const T& color) { - color_traits ct{color}; + color_traits ct {color}; return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8); } @@ -179,7 +179,7 @@ public: template void setValue(const T& q) { - color_traits ct{q}; + color_traits ct {q}; set(ct.redF(), ct.greenF(), ct.blueF()); } /** diff --git a/src/App/ColorModel.cpp b/src/App/ColorModel.cpp index 2bd3a306e8..80e778c244 100644 --- a/src/App/ColorModel.cpp +++ b/src/App/ColorModel.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -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(ctColors / (colorModel.getCountColors() - 1), ctColors - 1); + std::size_t usStep = + std::min(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 ColorGradient::getColorModelNames() const { std::vector 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; diff --git a/src/App/ColorModel.h b/src/App/ColorModel.h index 5ca292642a..8a5a897b3f 100644 --- a/src/App/ColorModel.h +++ b/src/App/ColorModel.h @@ -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; -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 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 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(std::max(int(fConstant + fAscent * fVal), 0), int(ctColors - 1))); + return std::size_t( + std::min(std::max(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 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 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 colorFields; std::deque names; std::deque values; - bool outsideGrayed{false}; + bool outsideGrayed {false}; }; -inline Color ColorLegend::getColor (float fVal) const +inline Color ColorLegend::getColor(float fVal) const { std::deque::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::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 diff --git a/src/App/ComplexGeoData.cpp b/src/App/ComplexGeoData.cpp index 3e11b6f050..e8d50030a4 100644 --- a/src/App/ComplexGeoData.cpp +++ b/src/App/ComplexGeoData.cpp @@ -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()); } return elementMap(flush); - } void ComplexGeoData::flushElementMap() const @@ -656,12 +656,13 @@ unsigned int ComplexGeoData::getMemSize() const return 0; } -std::vector ComplexGeoData::getHigherElements(const char *, bool) const +std::vector ComplexGeoData::getHigherElements(const char*, bool) const { return {}; } -void ComplexGeoData::setMappedChildElements(const std::vector & children) +void ComplexGeoData::setMappedChildElements( + const std::vector& 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; } } diff --git a/src/App/ComplexGeoData.h b/src/App/ComplexGeoData.h index 07d3a65587..995b797944 100644 --- a/src/App/ComplexGeoData.h +++ b/src/App/ComplexGeoData.h @@ -37,7 +37,7 @@ #include "StringHasher.h" #ifdef __GNUC__ -# include +#include #endif @@ -45,16 +45,18 @@ namespace Base { class Placement; class Rotation; -template class BoundBox3;// NOLINT +template +class BoundBox3; // NOLINT using BoundBox3d = BoundBox3; -} +} // 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 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 points; std::vector facets; }; @@ -105,26 +117,24 @@ public: * List of different sub-element types * its NOT a list of the sub-elements itself */ - virtual std::vector getElementTypes() const=0; - virtual unsigned long countSubElements(const char* Type) const=0; + virtual std::vector 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 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 &Points, - std::vector &lines) const; + virtual void getLinesFromSubElement(const Segment*, + std::vector& Points, + std::vector& lines) const; /** Get faces from segment */ - virtual void getFacesFromSubElement( - const Segment*, - std::vector &Points, - std::vector &PointNormals, - std::vector &faces) const; + virtual void getFacesFromSubElement(const Segment*, + std::vector& Points, + std::vector& PointNormals, + std::vector& 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 &Points, - std::vector &Normals, - double Accuracy, uint16_t flags=0) const; + virtual void getPoints(std::vector& Points, + std::vector& Normals, + double Accuracy, + uint16_t flags = 0) const; /** Get lines from object with given accuracy */ - virtual void getLines(std::vector &Points,std::vector &lines, - double Accuracy, uint16_t flags=0) const; + virtual void getLines(std::vector& Points, + std::vector& lines, + double Accuracy, + uint16_t flags = 0) const; /** Get faces from object with given accuracy */ - virtual void getFaces(std::vector &Points,std::vector &faces, - double Accuracy, uint16_t flags=0) const; + virtual void getFaces(std::vector& Points, + std::vector& 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 > - getElementMappedNames(const IndexedName & element, bool needUnmapped=false) const; + std::vector> + 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 *history=nullptr) const { - if ( _elementMap != nullptr ) { + long getElementHistory(const MappedName& name, + MappedName* original = nullptr, + std::vector* history = nullptr) const + { + if (_elementMap != nullptr) { return _elementMap->getElementHistory(name, Tag, original, history); } return 0; }; - void setMappedChildElements(const std::vector & children); + void setMappedChildElements(const std::vector& children); std::vector 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 getElementMap() const; /// Set the entire element map - void setElementMap(const std::vector &elements); + void setElementMap(const std::vector& 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 getHigherElements(const char *name, bool silent=false) const; + virtual std::vector 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(vec.x), static_cast(vec.y), static_cast(vec.z)); + // clang-format on } /// from local to outside template inline std::vector transformPointsToOutside(const std::vector& input) const { + // clang-format off std::vector 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(vec.x), - static_cast(vec.y), - static_cast(vec.z)); - }); + std::transform(input.cbegin(), input.cend(), std::back_inserter(output), + [&mat](const Vec& vec) { + return mat * Base::Vector3d(static_cast(vec.x), + static_cast(vec.y), + static_cast(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(vec.x), - static_cast(vec.y), - static_cast(vec.z)); + static_cast(vec.y), + static_cast(vec.z)); + // clang-format on } template std::vector transformVectorsToOutside(const std::vector& input) const { + // clang-format off std::vector 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(vec.x), - static_cast(vec.y), - static_cast(vec.z)); - }); + std::transform(input.cbegin(), input.cend(), std::back_inserter(output), + [&mat](const Vec& vec) { + return mat * Base::Vector3d(static_cast(vec.x), + static_cast(vec.y), + static_cast(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(tmp.y), static_cast(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(vec.x), static_cast(vec.y), static_cast(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 diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 11ee02c522..aef283502b 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -58,9 +58,9 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include +#include +#include +#include #endif #include @@ -72,7 +72,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include #include #include -#endif //USE_OLD_DAG +#endif // USE_OLD_DAG #include #include @@ -128,12 +128,13 @@ using namespace boost; using namespace zipios; #if FC_DEBUG -# define FC_LOGFEATUREUPDATE +#define FC_LOGFEATUREUPDATE #endif namespace fs = boost::filesystem; -namespace App { +namespace App +{ static bool globalIsRestoring; static bool globalIsRelabeling; @@ -163,7 +164,7 @@ DocumentP::DocumentP() UndoMaxStackSize = 20; } -} // namespace App +} // namespace App PROPERTY_SOURCE(App::Document, App::PropertyContainer) @@ -177,19 +178,19 @@ void Document::setStatus(Status pos, bool on) d->StatusBits.set((size_t)pos, on); } -//bool _has_cycle_dfs(const DependencyList & g, vertex_t u, default_color_type * color) +// bool _has_cycle_dfs(const DependencyList & g, vertex_t u, default_color_type * color) //{ -// color[u] = gray_color; -// graph_traits < DependencyList >::adjacency_iterator vi, vi_end; -// for (tie(vi, vi_end) = adjacent_vertices(u, g); vi != vi_end; ++vi) -// if (color[*vi] == white_color) -// if (has_cycle_dfs(g, *vi, color)) -// return true; // cycle detected, return immediately -// else if (color[*vi] == gray_color) // *vi is an ancestor! -// return true; -// color[u] = black_color; -// return false; -//} +// color[u] = gray_color; +// graph_traits < DependencyList >::adjacency_iterator vi, vi_end; +// for (tie(vi, vi_end) = adjacent_vertices(u, g); vi != vi_end; ++vi) +// if (color[*vi] == white_color) +// if (has_cycle_dfs(g, *vi, color)) +// return true; // cycle detected, return immediately +// else if (color[*vi] == gray_color) // *vi is an ancestor! +// return true; +// color[u] = black_color; +// return false; +// } bool Document::checkOnCycle() { @@ -207,48 +208,51 @@ bool Document::checkOnCycle() bool Document::undo(int id) { if (d->iUndoMode) { - if(id) { + if (id) { auto it = mUndoMap.find(id); - if(it == mUndoMap.end()) + if (it == mUndoMap.end()) { return false; - if(it->second != d->activeUndoTransaction) { - while(!mUndoTransactions.empty() && mUndoTransactions.back()!=it->second) + } + if (it->second != d->activeUndoTransaction) { + while (!mUndoTransactions.empty() && mUndoTransactions.back() != it->second) { undo(0); + } } } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { _commitTransaction(true); - if (mUndoTransactions.empty()) + } + if (mUndoTransactions.empty()) { return false; + } // redo d->activeUndoTransaction = new Transaction(mUndoTransactions.back()->getID()); d->activeUndoTransaction->Name = mUndoTransactions.back()->Name; { - Base::FlagToggler flag(d->undoing); - // applying the undo - mUndoTransactions.back()->apply(*this,false); + Base::FlagToggler flag(d->undoing); + // applying the undo + mUndoTransactions.back()->apply(*this, false); - // save the redo - mRedoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; - mRedoTransactions.push_back(d->activeUndoTransaction); - d->activeUndoTransaction = nullptr; - - mUndoMap.erase(mUndoTransactions.back()->getID()); - delete mUndoTransactions.back(); - mUndoTransactions.pop_back(); + // save the redo + mRedoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; + mRedoTransactions.push_back(d->activeUndoTransaction); + d->activeUndoTransaction = nullptr; + mUndoMap.erase(mUndoTransactions.back()->getID()); + delete mUndoTransactions.back(); + mUndoTransactions.pop_back(); } - for(auto & obj : d->objectArray) { - if(obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { + for (auto& obj : d->objectArray) { + if (obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { obj->onUndoRedoFinished(); - obj->setStatus(ObjectStatus::PendingTransactionUpdate,false); + obj->setStatus(ObjectStatus::PendingTransactionUpdate, false); } } - signalUndo(*this); // now signal the undo + signalUndo(*this); // now signal the undo return true; } @@ -259,18 +263,21 @@ bool Document::undo(int id) bool Document::redo(int id) { if (d->iUndoMode) { - if(id) { + if (id) { auto it = mRedoMap.find(id); - if(it == mRedoMap.end()) + if (it == mRedoMap.end()) { return false; - while(!mRedoTransactions.empty() && mRedoTransactions.back()!=it->second) + } + while (!mRedoTransactions.empty() && mRedoTransactions.back() != it->second) { redo(0); + } } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { _commitTransaction(true); + } - assert(mRedoTransactions.size()!=0); + assert(mRedoTransactions.size() != 0); // undo d->activeUndoTransaction = new Transaction(mRedoTransactions.back()->getID()); @@ -278,22 +285,22 @@ bool Document::redo(int id) // do the redo { - Base::FlagToggler flag(d->undoing); - mRedoTransactions.back()->apply(*this,true); + Base::FlagToggler flag(d->undoing); + mRedoTransactions.back()->apply(*this, true); - mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; - mUndoTransactions.push_back(d->activeUndoTransaction); - d->activeUndoTransaction = nullptr; + mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; + mUndoTransactions.push_back(d->activeUndoTransaction); + d->activeUndoTransaction = nullptr; - mRedoMap.erase(mRedoTransactions.back()->getID()); - delete mRedoTransactions.back(); - mRedoTransactions.pop_back(); + mRedoMap.erase(mRedoTransactions.back()->getID()); + delete mRedoTransactions.back(); + mRedoTransactions.pop_back(); } - for(auto & obj : d->objectArray) { - if(obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { + for (auto& obj : d->objectArray) { + if (obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { obj->onUndoRedoFinished(); - obj->setStatus(ObjectStatus::PendingTransactionUpdate,false); + obj->setStatus(ObjectStatus::PendingTransactionUpdate, false); } } @@ -304,20 +311,23 @@ bool Document::redo(int id) return false; } -void Document::addOrRemovePropertyOfObject(TransactionalObject* obj, Property *prop, bool add) +void Document::addOrRemovePropertyOfObject(TransactionalObject* obj, Property* prop, bool add) { - if (!prop || !obj || !obj->isAttachedToDocument()) + if (!prop || !obj || !obj->isAttachedToDocument()) { return; - if(d->iUndoMode && !isPerformingTransaction() && !d->activeUndoTransaction) { - if(!testStatus(Restoring) || testStatus(Importing)) { - int tid=0; - const char *name = GetApplication().getActiveTransaction(&tid); - if(name && tid>0) - _openTransaction(name,tid); + } + if (d->iUndoMode && !isPerformingTransaction() && !d->activeUndoTransaction) { + if (!testStatus(Restoring) || testStatus(Importing)) { + int tid = 0; + const char* name = GetApplication().getActiveTransaction(&tid); + if (name && tid > 0) { + _openTransaction(name, tid); + } } } - if (d->activeUndoTransaction && !d->rollback) + if (d->activeUndoTransaction && !d->rollback) { d->activeUndoTransaction->addOrRemoveProperty(obj, prop, add); + } } bool Document::isPerformingTransaction() const @@ -328,36 +338,46 @@ bool Document::isPerformingTransaction() const std::vector Document::getAvailableUndoNames() const { std::vector vList; - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { vList.push_back(d->activeUndoTransaction->Name); - for (std::list::const_reverse_iterator It=mUndoTransactions.rbegin();It!=mUndoTransactions.rend();++It) + } + for (std::list::const_reverse_iterator It = mUndoTransactions.rbegin(); + It != mUndoTransactions.rend(); + ++It) { vList.push_back((**It).Name); + } return vList; } std::vector Document::getAvailableRedoNames() const { std::vector vList; - for (std::list::const_reverse_iterator It=mRedoTransactions.rbegin();It!=mRedoTransactions.rend();++It) + for (std::list::const_reverse_iterator It = mRedoTransactions.rbegin(); + It != mRedoTransactions.rend(); + ++It) { vList.push_back((**It).Name); + } return vList; } -void Document::openTransaction(const char* name) { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) +void Document::openTransaction(const char* name) +{ + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot open transaction while transacting"); + } return; } - GetApplication().setActiveTransaction(name?name:""); + GetApplication().setActiveTransaction(name ? name : ""); } int Document::_openTransaction(const char* name, int id) { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot open transaction while transacting"); + } return 0; } @@ -366,80 +386,89 @@ int Document::_openTransaction(const char* name, int id) // clearing the redo transactions and will cause // a double deletion of some transaction and thus // a segmentation fault - if (d->opentransaction) + if (d->opentransaction) { return 0; + } Base::FlagToggler<> flag(d->opentransaction); - if(id && mUndoMap.find(id)!=mUndoMap.end()) + if (id && mUndoMap.find(id) != mUndoMap.end()) { throw Base::RuntimeError("invalid transaction id"); - if (d->activeUndoTransaction) + } + if (d->activeUndoTransaction) { _commitTransaction(true); + } _clearRedos(); d->activeUndoTransaction = new Transaction(id); - if (!name) + if (!name) { name = ""; + } d->activeUndoTransaction->Name = name; mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; id = d->activeUndoTransaction->getID(); signalOpenTransaction(*this, name); - auto &app = GetApplication(); + auto& app = GetApplication(); auto activeDoc = app.getActiveDocument(); - if(activeDoc && - activeDoc!=this && - !activeDoc->hasPendingTransaction()) - { + if (activeDoc && activeDoc != this && !activeDoc->hasPendingTransaction()) { std::string aname("-> "); aname += d->activeUndoTransaction->Name; FC_LOG("auto transaction " << getName() << " -> " << activeDoc->getName()); - activeDoc->_openTransaction(aname.c_str(),id); + activeDoc->_openTransaction(aname.c_str(), id); } return id; } return 0; } -void Document::renameTransaction(const char *name, int id) { - if(name && d->activeUndoTransaction && d->activeUndoTransaction->getID()==id) { - if(boost::starts_with(d->activeUndoTransaction->Name, "-> ")) +void Document::renameTransaction(const char* name, int id) +{ + if (name && d->activeUndoTransaction && d->activeUndoTransaction->getID() == id) { + if (boost::starts_with(d->activeUndoTransaction->Name, "-> ")) { d->activeUndoTransaction->Name.resize(3); - else + } + else { d->activeUndoTransaction->Name.clear(); + } d->activeUndoTransaction->Name += name; } } -void Document::_checkTransaction(DocumentObject* pcDelObj, const Property *What, int line) +void Document::_checkTransaction(DocumentObject* pcDelObj, const Property* What, int line) { // if the undo is active but no transaction open, open one! if (d->iUndoMode && !isPerformingTransaction()) { if (!d->activeUndoTransaction) { - if(!testStatus(Restoring) || testStatus(Importing)) { - int tid=0; - const char *name = GetApplication().getActiveTransaction(&tid); - if(name && tid>0) { + if (!testStatus(Restoring) || testStatus(Importing)) { + int tid = 0; + const char* name = GetApplication().getActiveTransaction(&tid); + if (name && tid > 0) { bool ignore = false; - if(What && What->testStatus(Property::NoModify)) + if (What && What->testStatus(Property::NoModify)) { ignore = true; - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - if(What) - FC_LOG((ignore?"ignore":"auto") << " transaction (" - << line << ") '" << What->getFullName()); - else - FC_LOG((ignore?"ignore":"auto") <<" transaction (" - << line << ") '" << name << "' in " << getName()); } - if(!ignore) - _openTransaction(name,tid); + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + if (What) { + FC_LOG((ignore ? "ignore" : "auto") + << " transaction (" << line << ") '" << What->getFullName()); + } + else { + FC_LOG((ignore ? "ignore" : "auto") << " transaction (" << line << ") '" + << name << "' in " << getName()); + } + } + if (!ignore) { + _openTransaction(name, tid); + } return; } } - if(!pcDelObj) + if (!pcDelObj) { return; - // When the object is going to be deleted we have to check if it has already been added to - // the undo transactions + } + // When the object is going to be deleted we have to check if it has already been added + // to the undo transactions std::list::iterator it; for (it = mUndoTransactions.begin(); it != mUndoTransactions.end(); ++it) { if ((*it)->hasObject(pcDelObj)) { @@ -453,7 +482,7 @@ void Document::_checkTransaction(DocumentObject* pcDelObj, const Property *What, void Document::_clearRedos() { - if(isPerformingTransaction() || d->committing) { + if (isPerformingTransaction() || d->committing) { FC_ERR("Cannot clear redo while transacting"); return; } @@ -465,22 +494,26 @@ void Document::_clearRedos() } } -void Document::commitTransaction() { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) +void Document::commitTransaction() +{ + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot commit transaction while transacting"); + } return; } - if (d->activeUndoTransaction) - GetApplication().closeActiveTransaction(false,d->activeUndoTransaction->getID()); + if (d->activeUndoTransaction) { + GetApplication().closeActiveTransaction(false, d->activeUndoTransaction->getID()); + } } void Document::_commitTransaction(bool notify) { if (isPerformingTransaction()) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot commit transaction while transacting"); + } return; } else if (d->committing) { @@ -490,12 +523,12 @@ void Document::_commitTransaction(bool notify) if (d->activeUndoTransaction) { Base::FlagToggler<> flag(d->committing); - Application::TransactionSignaller signaller(false,true); + Application::TransactionSignaller signaller(false, true); int id = d->activeUndoTransaction->getID(); mUndoTransactions.push_back(d->activeUndoTransaction); d->activeUndoTransaction = nullptr; // check the stack for the limits - if(mUndoTransactions.size() > d->UndoMaxStackSize){ + if (mUndoTransactions.size() > d->UndoMaxStackSize) { mUndoMap.erase(mUndoTransactions.front()->getID()); delete mUndoTransactions.front(); mUndoTransactions.pop_front(); @@ -503,34 +536,39 @@ void Document::_commitTransaction(bool notify) signalCommitTransaction(*this); // closeActiveTransaction() may call again _commitTransaction() - if (notify) - GetApplication().closeActiveTransaction(false,id); + if (notify) { + GetApplication().closeActiveTransaction(false, id); + } } } -void Document::abortTransaction() { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) +void Document::abortTransaction() +{ + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot abort transaction while transacting"); + } return; } - if (d->activeUndoTransaction) - GetApplication().closeActiveTransaction(true,d->activeUndoTransaction->getID()); + if (d->activeUndoTransaction) { + GetApplication().closeActiveTransaction(true, d->activeUndoTransaction->getID()); + } } void Document::_abortTransaction() { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot abort transaction while transacting"); + } } if (d->activeUndoTransaction) { Base::FlagToggler flag(d->rollback); - Application::TransactionSignaller signaller(true,true); + Application::TransactionSignaller signaller(true, true); // applying the so far made changes - d->activeUndoTransaction->apply(*this,false); + d->activeUndoTransaction->apply(*this, false); // destroy the undo mUndoMap.erase(d->activeUndoTransaction->getID()); @@ -542,30 +580,37 @@ void Document::_abortTransaction() bool Document::hasPendingTransaction() const { - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { return true; - else + } + else { return false; + } } -int Document::getTransactionID(bool undo, unsigned pos) const { - if(undo) { - if(d->activeUndoTransaction) { - if(pos == 0) +int Document::getTransactionID(bool undo, unsigned pos) const +{ + if (undo) { + if (d->activeUndoTransaction) { + if (pos == 0) { return d->activeUndoTransaction->getID(); + } --pos; } - if(pos>=mUndoTransactions.size()) + if (pos >= mUndoTransactions.size()) { return 0; + } auto rit = mUndoTransactions.rbegin(); - for(;pos;++rit,--pos) + for (; pos; ++rit, --pos) { continue; + } return (*rit)->getID(); } - if(pos>=mRedoTransactions.size()) + if (pos >= mRedoTransactions.size()) { return 0; + } auto rit = mRedoTransactions.rbegin(); - for(;pos;++rit,--pos){} + for (; pos; ++rit, --pos) {} return (*rit)->getID(); } @@ -592,12 +637,12 @@ void Document::clearDocument() if (!d->objectArray.empty()) { GetApplication().signalDeleteDocument(*this); d->clearDocument(); - GetApplication().signalNewDocument(*this,false); + GetApplication().signalNewDocument(*this, false); } Base::FlagToggler<> flag(globalIsRestoring, false); - setStatus(Document::PartialDoc,false); + setStatus(Document::PartialDoc, false); d->clearRecomputeLog(); d->objectArray.clear(); @@ -609,13 +654,14 @@ void Document::clearDocument() void Document::clearUndos() { - if(isPerformingTransaction() || d->committing) { + if (isPerformingTransaction() || d->committing) { FC_ERR("Cannot clear undos while transacting"); return; } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { _commitTransaction(true); + } mUndoMap.clear(); @@ -629,57 +675,65 @@ void Document::clearUndos() delete mUndoTransactions.front(); mUndoTransactions.pop_front(); } - //while (!mUndoTransactions.empty()) { - // delete mUndoTransactions.back(); - // mUndoTransactions.pop_back(); - //} + // while (!mUndoTransactions.empty()) { + // delete mUndoTransactions.back(); + // mUndoTransactions.pop_back(); + // } _clearRedos(); } int Document::getAvailableUndos(int id) const { - if(id) { + if (id) { auto it = mUndoMap.find(id); - if(it == mUndoMap.end()) + if (it == mUndoMap.end()) { return 0; + } int i = 0; - if(d->activeUndoTransaction) { + if (d->activeUndoTransaction) { ++i; - if(d->activeUndoTransaction->getID()==id) + if (d->activeUndoTransaction->getID() == id) { return i; + } } auto rit = mUndoTransactions.rbegin(); - for(;rit!=mUndoTransactions.rend()&&*rit!=it->second;++rit) + for (; rit != mUndoTransactions.rend() && *rit != it->second; ++rit) { ++i; - assert(rit!=mUndoTransactions.rend()); - return i+1; + } + assert(rit != mUndoTransactions.rend()); + return i + 1; } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { return static_cast(mUndoTransactions.size() + 1); - else + } + else { return static_cast(mUndoTransactions.size()); + } } int Document::getAvailableRedos(int id) const { - if(id) { + if (id) { auto it = mRedoMap.find(id); - if(it == mRedoMap.end()) + if (it == mRedoMap.end()) { return 0; + } int i = 0; - for(auto rit=mRedoTransactions.rbegin();*rit!=it->second;++rit) + for (auto rit = mRedoTransactions.rbegin(); *rit != it->second; ++rit) { ++i; - assert(i<(int)mRedoTransactions.size()); - return i+1; + } + assert(i < (int)mRedoTransactions.size()); + return i + 1; } return static_cast(mRedoTransactions.size()); } void Document::setUndoMode(int iMode) { - if (d->iUndoMode && !iMode) + if (d->iUndoMode && !iMode) { clearUndos(); + } d->iUndoMode = iMode; } @@ -689,7 +743,7 @@ int Document::getUndoMode() const return d->iUndoMode; } -unsigned int Document::getUndoMemSize () const +unsigned int Document::getUndoMemSize() const { return d->UndoMemSize; } @@ -701,18 +755,19 @@ void Document::setUndoLimit(unsigned int UndoMemSize) void Document::setMaxUndoStackSize(unsigned int UndoMaxStackSize) { - d->UndoMaxStackSize = UndoMaxStackSize; + d->UndoMaxStackSize = UndoMaxStackSize; } -unsigned int Document::getMaxUndoStackSize()const +unsigned int Document::getMaxUndoStackSize() const { return d->UndoMaxStackSize; } void Document::onBeforeChange(const Property* prop) { - if(prop == &Label) + if (prop == &Label) { oldLabel = Label.getValue(); + } signalBeforeChange(*this, *prop); } @@ -724,26 +779,35 @@ void Document::onChanged(const Property* prop) if (prop == &Label) { Base::FlagToggler<> flag(globalIsRelabeling); App::GetApplication().signalRelabelDocument(*this); - } else if(prop == &ShowHidden) { + } + else if (prop == &ShowHidden) { App::GetApplication().signalShowHidden(*this); - } else if (prop == &Uid) { - std::string new_dir = getTransientDirectoryName(this->Uid.getValueStr(),this->FileName.getStrValue()); + } + else if (prop == &Uid) { + std::string new_dir = + getTransientDirectoryName(this->Uid.getValueStr(), this->FileName.getStrValue()); std::string old_dir = this->TransientDir.getStrValue(); Base::FileInfo TransDirNew(new_dir); Base::FileInfo TransDirOld(old_dir); // this directory should not exist if (!TransDirNew.exists()) { if (TransDirOld.exists()) { - if (!TransDirOld.renameFile(new_dir.c_str())) - Base::Console().Warning("Failed to rename '%s' to '%s'\n", old_dir.c_str(), new_dir.c_str()); - else + if (!TransDirOld.renameFile(new_dir.c_str())) { + Base::Console().Warning("Failed to rename '%s' to '%s'\n", + old_dir.c_str(), + new_dir.c_str()); + } + else { this->TransientDir.setValue(new_dir); + } } else { - if (!TransDirNew.createDirectories()) + if (!TransDirNew.createDirectories()) { Base::Console().Warning("Failed to create '%s'\n", new_dir.c_str()); - else + } + else { this->TransientDir.setValue(new_dir); + } } } // when reloading an existing document the transient directory doesn't change @@ -753,31 +817,36 @@ void Document::onChanged(const Property* prop) std::string uuid = this->Uid.getValueStr(); Base::Uuid id; Base::Console().Warning("Document with the UUID '%s' already exists, change to '%s'\n", - uuid.c_str(), id.getValue().c_str()); + uuid.c_str(), + id.getValue().c_str()); // recursive call of onChanged() this->Uid.setValue(id); } - } else if(prop == &UseHasher) { - for(auto obj : d->objectArray) { + } + else if (prop == &UseHasher) { + for (auto obj : d->objectArray) { auto geofeature = dynamic_cast(obj); - if(geofeature && geofeature->getPropertyOfGeometry()) + if (geofeature && geofeature->getPropertyOfGeometry()) { geofeature->enforceRecompute(); + } } } } -void Document::onBeforeChangeProperty(const TransactionalObject *Who, const Property *What) +void Document::onBeforeChangeProperty(const TransactionalObject* Who, const Property* What) { - if(Who->isDerivedFrom(App::DocumentObject::getClassTypeId())) + if (Who->isDerivedFrom(App::DocumentObject::getClassTypeId())) { signalBeforeChangeObject(*static_cast(Who), *What); - if(!d->rollback && !globalIsRelabeling) { + } + if (!d->rollback && !globalIsRelabeling) { _checkTransaction(nullptr, What, __LINE__); - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectChange(Who, What); + } } } -void Document::onChangedProperty(const DocumentObject *Who, const Property *What) +void Document::onChangedProperty(const DocumentObject* Who, const Property* What) { signalChangedObject(*Who, *What); } @@ -821,8 +890,11 @@ Document::Document(const char* documentName) PropertyType(Prop_Transient | Prop_ReadOnly), "The path to the file where the document is saved to"); ADD_PROPERTY_TYPE(CreatedBy, (Author.c_str()), 0, Prop_None, "The creator of the document"); - ADD_PROPERTY_TYPE( - CreationDate, (CreationDateString.c_str()), 0, Prop_ReadOnly, "Date of creation"); + ADD_PROPERTY_TYPE(CreationDate, + (CreationDateString.c_str()), + 0, + Prop_ReadOnly, + "Date of creation"); ADD_PROPERTY_TYPE(LastModifiedBy, (""), 0, Prop_None, 0); ADD_PROPERTY_TYPE(LastModifiedDate, ("Unknown"), 0, Prop_ReadOnly, "Date of last modification"); ADD_PROPERTY_TYPE(Company, @@ -840,7 +912,8 @@ Document::Document(const char* documentName) } UnitSystem.setEnums(enumValsAsVector); // Get the preferences/General unit system as the default for a new document - ParameterGrp::handle hGrpu = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units"); + ParameterGrp::handle hGrpu = + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units"); UnitSystem.setValue(hGrpu->GetInt("UserSchema", 0)); ADD_PROPERTY_TYPE(Comment, (""), 0, Prop_None, "Additional tag to save a comment"); ADD_PROPERTY_TYPE(Meta, (), 0, Prop_None, "Map with additional meta information"); @@ -863,15 +936,21 @@ Document::Document(const char* documentName) licenseUrl = (paramGrp->GetASCII("prefLicenseUrl", url)); } ADD_PROPERTY_TYPE(License, (name), 0, Prop_None, "License string of the Item"); - ADD_PROPERTY_TYPE( - LicenseURL, (licenseUrl.c_str()), 0, Prop_None, "URL to the license text/contract"); + ADD_PROPERTY_TYPE(LicenseURL, + (licenseUrl.c_str()), + 0, + Prop_None, + "URL to the license text/contract"); ADD_PROPERTY_TYPE(ShowHidden, (false), 0, PropertyType(Prop_None), "Whether to show hidden object items in the tree view"); - ADD_PROPERTY_TYPE(UseHasher,(true), 0,PropertyType(Prop_Hidden), - "Whether to use hasher on topological naming"); + ADD_PROPERTY_TYPE(UseHasher, + (true), + 0, + PropertyType(Prop_Hidden), + "Whether to use hasher on topological naming"); // this creates and sets 'TransientDir' in onChanged() ADD_PROPERTY_TYPE(TransientDir, @@ -879,8 +958,11 @@ Document::Document(const char* documentName) 0, PropertyType(Prop_Transient | Prop_ReadOnly), "Transient directory, where the files live while the document is open"); - ADD_PROPERTY_TYPE( - Tip, (nullptr), 0, PropertyType(Prop_Transient), "Link of the tip object of the document"); + ADD_PROPERTY_TYPE(Tip, + (nullptr), + 0, + PropertyType(Prop_Transient), + "Link of the tip object of the document"); ADD_PROPERTY_TYPE(TipName, (""), 0, @@ -892,7 +974,7 @@ Document::Document(const char* documentName) Document::~Document() { #ifdef FC_LOGUPDATECHAIN - Console().Log("-App::Document: %s %p\n",getName(), this); + Console().Log("-App::Document: %s %p\n", getName(), this); #endif try { @@ -902,7 +984,7 @@ Document::~Document() } #ifdef FC_LOGUPDATECHAIN - Console().Log("-Delete Features of %s \n",getName()); + Console().Log("-Delete Features of %s \n", getName()); #endif d->clearDocument(); @@ -928,22 +1010,19 @@ Document::~Document() delete d; } -std::string Document::getTransientDirectoryName(const std::string& uuid, const std::string& filename) const +std::string Document::getTransientDirectoryName(const std::string& uuid, + const std::string& filename) const { // Create a directory name of the form: {ExeName}_Doc_{UUID}_{HASH}_{PID} std::stringstream out; QCryptographicHash hash(QCryptographicHash::Sha1); -#if QT_VERSION < QT_VERSION_CHECK(6,3,0) +#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0) hash.addData(filename.c_str(), filename.size()); #else hash.addData(QByteArrayView(filename.c_str(), filename.size())); #endif - out << App::Application::getUserCachePath() << App::Application::getExecutableName() - << "_Doc_" - << uuid - << "_" - << hash.result().toHex().left(6).constData() - << "_" + out << App::Application::getUserCachePath() << App::Application::getExecutableName() << "_Doc_" + << uuid << "_" << hash.result().toHex().left(6).constData() << "_" << App::Application::applicationPid(); return out.str(); } @@ -952,7 +1031,7 @@ std::string Document::getTransientDirectoryName(const std::string& uuid, const s // Exported functions //-------------------------------------------------------------------------- -void Document::Save (Base::Writer &writer) const +void Document::Save(Base::Writer& writer) const { d->hashers.clear(); addStringHasher(d->Hasher); @@ -960,9 +1039,8 @@ void Document::Save (Base::Writer &writer) const writer.Stream() << R"(\n"; + << App::Application::Config()["BuildRevision"] << "\" FileVersion=\"" + << writer.getFileVersion() << "\" StringHasher=\"1\">\n"; writer.incInd(); @@ -983,25 +1061,27 @@ void Document::Save (Base::Writer &writer) const writer.Stream() << "" << endl; } -void Document::Restore(Base::XMLReader &reader) +void Document::Restore(Base::XMLReader& reader) { - int i,Cnt; + int i, Cnt; d->hashers.clear(); d->touchedObjs.clear(); addStringHasher(d->Hasher); - setStatus(Document::PartialDoc,false); + setStatus(Document::PartialDoc, false); reader.readElement("Document"); long scheme = reader.getAttributeAsInteger("SchemaVersion"); reader.DocumentSchema = scheme; if (reader.hasAttribute("ProgramVersion")) { reader.ProgramVersion = reader.getAttribute("ProgramVersion"); - } else { + } + else { reader.ProgramVersion = "pre-0.14"; } if (reader.hasAttribute("FileVersion")) { reader.FileVersion = reader.getAttributeAsUnsigned("FileVersion"); - } else { + } + else { reader.FileVersion = 0; } @@ -1022,7 +1102,8 @@ void Document::Restore(Base::XMLReader &reader) std::string FilePath = FileName.getValue(); std::string DocLabel = Label.getValue(); - // read the Document Properties, when reading in Uid the transient directory gets renamed automatically + // read the Document Properties, when reading in Uid the transient directory gets renamed + // automatically PropertyContainer::Restore(reader); // We must restore the correct 'FileName' property again because the stored @@ -1031,18 +1112,18 @@ void Document::Restore(Base::XMLReader &reader) Label.setValue(DocLabel.c_str()); // SchemeVersion "2" - if ( scheme == 2 ) { + if (scheme == 2) { // read the feature types reader.readElement("Features"); Cnt = reader.getAttributeAsInteger("Count"); - for (i=0 ;isetStatus(ObjectStatus::Restore, true); pObj->Restore(reader); pObj->setStatus(ObjectStatus::Restore, false); @@ -1063,8 +1144,8 @@ void Document::Restore(Base::XMLReader &reader) reader.readEndElement("Feature"); } reader.readEndElement("FeatureData"); - } // SchemeVersion "3" or higher - else if ( scheme >= 3 ) { + } // SchemeVersion "3" or higher + else if (scheme >= 3) { // read the feature types readObjects(reader); @@ -1087,33 +1168,41 @@ void DocumentP::checkStringHasher(const Base::XMLReader& reader) } } -std::pair Document::addStringHasher(const StringHasherRef & hasher) const { - if (!hasher) +std::pair Document::addStringHasher(const StringHasherRef& hasher) const +{ + if (!hasher) { return std::make_pair(false, 0); - auto ret = d->hashers.left.insert(HasherMap::left_map::value_type(hasher,(int)d->hashers.size())); - if (ret.second) + } + auto ret = + d->hashers.left.insert(HasherMap::left_map::value_type(hasher, (int)d->hashers.size())); + if (ret.second) { hasher->clearMarks(); - return std::make_pair(ret.second,ret.first->second); + } + return std::make_pair(ret.second, ret.first->second); } -StringHasherRef Document::getStringHasher(int idx) const { +StringHasherRef Document::getStringHasher(int idx) const +{ StringHasherRef hasher; - if(idx<0) { - if(UseHasher.getValue()) { + if (idx < 0) { + if (UseHasher.getValue()) { return d->Hasher; } return hasher; } auto it = d->hashers.right.find(idx); - if(it == d->hashers.right.end()) { + if (it == d->hashers.right.end()) { hasher = new StringHasher; - d->hashers.right.insert(HasherMap::right_map::value_type(idx,hasher)); - }else + d->hashers.right.insert(HasherMap::right_map::value_type(idx, hasher)); + } + else { hasher = it->second; + } return hasher; } -struct DocExportStatus { +struct DocExportStatus +{ Document::ExportStatus status; std::set objs; }; @@ -1121,14 +1210,17 @@ struct DocExportStatus { static DocExportStatus _ExportStatus; // Exception-safe exporting status setter -class DocumentExporting { +class DocumentExporting +{ public: - explicit DocumentExporting(const std::vector &objs) { + explicit DocumentExporting(const std::vector& objs) + { _ExportStatus.status = Document::Exporting; - _ExportStatus.objs.insert(objs.begin(),objs.end()); + _ExportStatus.objs.insert(objs.begin(), objs.end()); } - ~DocumentExporting() { + ~DocumentExporting() + { _ExportStatus.status = Document::NotExporting; _ExportStatus.objs.clear(); } @@ -1139,26 +1231,32 @@ public: // at the same time. I see no benefits in distinguish which documents are // exporting, so just use a static variable for global status. But the // implementation can easily be changed here if necessary. -Document::ExportStatus Document::isExporting(const App::DocumentObject *obj) const { - if(_ExportStatus.status!=Document::NotExporting && - (!obj || _ExportStatus.objs.find(obj)!=_ExportStatus.objs.end())) +Document::ExportStatus Document::isExporting(const App::DocumentObject* obj) const +{ + if (_ExportStatus.status != Document::NotExporting + && (!obj || _ExportStatus.objs.find(obj) != _ExportStatus.objs.end())) { return _ExportStatus.status; + } return Document::NotExporting; } -void Document::exportObjects(const std::vector& obj, std::ostream& out) { +void Document::exportObjects(const std::vector& obj, std::ostream& out) +{ DocumentExporting exporting(obj); d->hashers.clear(); - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - for(auto o : obj) { - if(o && o->isAttachedToDocument()) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + for (auto o : obj) { + if (o && o->isAttachedToDocument()) { FC_LOG("exporting " << o->getFullName()); if (!o->getPropertyByName("_ObjectUUID")) { - auto prop = static_cast(o->addDynamicProperty( - "App::PropertyUUID", "_ObjectUUID", nullptr, nullptr, - Prop_Output | Prop_Hidden)); + auto prop = static_cast( + o->addDynamicProperty("App::PropertyUUID", + "_ObjectUUID", + nullptr, + nullptr, + Prop_Output | Prop_Hidden)); prop->setValue(Base::Uuid::createUuid()); } } @@ -1171,8 +1269,8 @@ void Document::exportObjects(const std::vector& obj, std:: writer.Stream() << R"()" << endl; + << App::Application::Config()["BuildRevision"] << R"(" FileVersion="1">)" + << endl; // Add this block to have the same layout as for normal documents writer.Stream() << "" << endl; writer.Stream() << "" << endl; @@ -1197,37 +1295,41 @@ void Document::exportObjects(const std::vector& obj, std:: #define FC_ELEMENT_OBJECT_DEP "Dep" void Document::writeObjects(const std::vector& obj, - Base::Writer &writer) const + Base::Writer& writer) const { // writing the features types - writer.incInd(); // indentation for 'Objects count' + writer.incInd(); // indentation for 'Objects count' writer.Stream() << writer.ind() << "" << endl; - writer.incInd(); // indentation for 'Object type' + writer.incInd(); // indentation for 'Object type' - if(!isExporting(nullptr)) { - for(auto o : obj) { - const auto &outList = o->getOutList(DocumentObject::OutListNoHidden - | DocumentObject::OutListNoXLinked); + if (!isExporting(nullptr)) { + for (auto o : obj) { + const auto& outList = + o->getOutList(DocumentObject::OutListNoHidden | DocumentObject::OutListNoXLinked); writer.Stream() << writer.ind() - << "<" FC_ELEMENT_OBJECT_DEPS " " FC_ATTR_DEP_OBJ_NAME "=\"" - << o->getNameInDocument() << "\" " FC_ATTR_DEP_COUNT "=\"" << outList.size(); - if(outList.empty()) { + << "<" FC_ELEMENT_OBJECT_DEPS " " FC_ATTR_DEP_OBJ_NAME "=\"" + << o->getNameInDocument() << "\" " FC_ATTR_DEP_COUNT "=\"" + << outList.size(); + if (outList.empty()) { writer.Stream() << "\"/>" << endl; continue; } int partial = o->canLoadPartial(); - if(partial>0) + if (partial > 0) { writer.Stream() << "\" " FC_ATTR_DEP_ALLOW_PARTIAL << "=\"" << partial; + } writer.Stream() << "\">" << endl; writer.incInd(); - for(auto dep : outList) { - auto name = dep?dep->getNameInDocument():""; - writer.Stream() << writer.ind() << "<" FC_ELEMENT_OBJECT_DEP " " - FC_ATTR_DEP_OBJ_NAME "=\"" << (name?name:"") << "\"/>" << endl; + for (auto dep : outList) { + auto name = dep ? dep->getNameInDocument() : ""; + writer.Stream() << writer.ind() + << "<" FC_ELEMENT_OBJECT_DEP " " FC_ATTR_DEP_OBJ_NAME "=\"" + << (name ? name : "") << "\"/>" << endl; } writer.decInd(); writer.Stream() << writer.ind() << "" << endl; @@ -1237,23 +1339,26 @@ void Document::writeObjects(const std::vector& obj, std::vector::const_iterator it; for (it = obj.begin(); it != obj.end(); ++it) { writer.Stream() << writer.ind() << "getTypeId().getName() << "\" " - << "name=\"" << (*it)->getExportName() << "\" " - << "id=\"" << (*it)->getID() << "\" "; + << "type=\"" << (*it)->getTypeId().getName() << "\" " + << "name=\"" << (*it)->getExportName() << "\" " + << "id=\"" << (*it)->getID() << "\" "; // Only write out custom view provider types std::string viewType = (*it)->getViewProviderNameStored(); - if (viewType != (*it)->getViewProviderName()) + if (viewType != (*it)->getViewProviderName()) { writer.Stream() << "ViewType=\"" << viewType << "\" "; + } // See DocumentObjectPy::getState - if ((*it)->testStatus(ObjectStatus::Touch)) + if ((*it)->testStatus(ObjectStatus::Touch)) { writer.Stream() << "Touched=\"1\" "; + } if ((*it)->testStatus(ObjectStatus::Error)) { writer.Stream() << "Invalid=\"1\" "; auto desc = getErrorDescription(*it); - if(desc) + if (desc) { writer.Stream() << "Error=\"" << Property::encodeAttribute(desc) << "\" "; + } } writer.Stream() << "/>" << endl; } @@ -1262,62 +1367,67 @@ void Document::writeObjects(const std::vector& obj, writer.Stream() << writer.ind() << "" << endl; // writing the features itself - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; - writer.incInd(); // indentation for 'Object name' + writer.incInd(); // indentation for 'Object name' for (it = obj.begin(); it != obj.end(); ++it) { writer.Stream() << writer.ind() << "getExportName() << "\""; - if((*it)->hasExtensions()) + if ((*it)->hasExtensions()) { writer.Stream() << " Extensions=\"True\""; + } writer.Stream() << ">" << endl; (*it)->Save(writer); writer.Stream() << writer.ind() << "" << endl; } - writer.decInd(); // indentation for 'Object name' + writer.decInd(); // indentation for 'Object name' writer.Stream() << writer.ind() << "" << endl; writer.decInd(); // indentation for 'Objects count' } -struct DepInfo { +struct DepInfo +{ std::unordered_set deps; int canLoadPartial = 0; }; -static void _loadDeps(const std::string &name, - std::unordered_map &objs, - const std::unordered_map &deps) +static void _loadDeps(const std::string& name, + std::unordered_map& objs, + const std::unordered_map& deps) { auto it = deps.find(name); - if(it == deps.end()) { - objs.emplace(name,true); + if (it == deps.end()) { + objs.emplace(name, true); return; } - if(it->second.canLoadPartial) { - if(it->second.canLoadPartial == 1) { + if (it->second.canLoadPartial) { + if (it->second.canLoadPartial == 1) { // canLoadPartial==1 means all its children will be created but not // restored, i.e. exists as if newly created object, and therefore no // need to load dependency of the children - for(auto &dep : it->second.deps) - objs.emplace(dep,false); - objs.emplace(name,true); - }else - objs.emplace(name,false); + for (auto& dep : it->second.deps) { + objs.emplace(dep, false); + } + objs.emplace(name, true); + } + else { + objs.emplace(name, false); + } return; } objs[name] = true; // If cannot load partial, then recurse to load all children dependency - for(auto &dep : it->second.deps) { + for (auto& dep : it->second.deps) { auto it = objs.find(dep); - if(it!=objs.end() && it->second) + if (it != objs.end() && it->second) { continue; - _loadDeps(dep,objs,deps); + } + _loadDeps(dep, objs, deps); } } -std::vector -Document::readObjects(Base::XMLReader& reader) +std::vector Document::readObjects(Base::XMLReader& reader) { d->touchedObjs.clear(); bool keepDigits = testStatus(Document::KeepTrailingDigits); @@ -1329,65 +1439,75 @@ Document::readObjects(Base::XMLReader& reader) reader.readElement("Objects"); int Cnt = reader.getAttributeAsInteger("Count"); - if(!reader.hasAttribute(FC_ATTR_DEPENDENCIES)) + if (!reader.hasAttribute(FC_ATTR_DEPENDENCIES)) { d->partialLoadObjects.clear(); - else if(!d->partialLoadObjects.empty()) { - std::unordered_map deps; - for (int i=0 ;ipartialLoadObjects.empty()) { + std::unordered_map deps; + for (int i = 0; i < Cnt; i++) { reader.readElement(FC_ELEMENT_OBJECT_DEPS); int dcount = reader.getAttributeAsInteger(FC_ATTR_DEP_COUNT); - if(!dcount) + if (!dcount) { continue; - auto &info = deps[reader.getAttribute(FC_ATTR_DEP_OBJ_NAME)]; - if(reader.hasAttribute(FC_ATTR_DEP_ALLOW_PARTIAL)) + } + auto& info = deps[reader.getAttribute(FC_ATTR_DEP_OBJ_NAME)]; + if (reader.hasAttribute(FC_ATTR_DEP_ALLOW_PARTIAL)) { info.canLoadPartial = reader.getAttributeAsInteger(FC_ATTR_DEP_ALLOW_PARTIAL); - for(int j=0;j objs; objs.reserve(d->partialLoadObjects.size()); - for(auto &v : d->partialLoadObjects) + for (auto& v : d->partialLoadObjects) { objs.emplace_back(v.first.c_str()); - for(auto &name : objs) - _loadDeps(name,d->partialLoadObjects,deps); - if(Cnt > (int)d->partialLoadObjects.size()) - setStatus(Document::PartialDoc,true); + } + for (auto& name : objs) { + _loadDeps(name, d->partialLoadObjects, deps); + } + if (Cnt > (int)d->partialLoadObjects.size()) { + setStatus(Document::PartialDoc, true); + } else { - for(auto &v : d->partialLoadObjects) { - if(!v.second) { - setStatus(Document::PartialDoc,true); + for (auto& v : d->partialLoadObjects) { + if (!v.second) { + setStatus(Document::PartialDoc, true); break; } } - if(!testStatus(Document::PartialDoc)) + if (!testStatus(Document::PartialDoc)) { d->partialLoadObjects.clear(); + } } } long lastId = 0; - for (int i=0 ;ipartialLoadObjects.empty()) { + if (!d->partialLoadObjects.empty()) { auto it = d->partialLoadObjects.find(name); - if(it == d->partialLoadObjects.end()) + if (it == d->partialLoadObjects.end()) { continue; + } partial = !it->second; } - if(!testStatus(Status::Importing) && reader.hasAttribute("id")) { + if (!testStatus(Status::Importing) && reader.hasAttribute("id")) { // if not importing, then temporary reset lastObjectId and make the // following addObject() generate the correct id for this object. - d->lastObjectId = reader.getAttributeAsInteger("id")-1; + d->lastObjectId = reader.getAttributeAsInteger("id") - 1; } // To prevent duplicate name when export/import of objects from @@ -1399,22 +1519,26 @@ Document::readObjects(Base::XMLReader& reader) // correctly unmap the names. auto pos = name.find('@'); std::string _obj_name; - const char *obj_name; - if(pos!=std::string::npos) { - _obj_name = name.substr(0,pos); + const char* obj_name; + if (pos != std::string::npos) { + _obj_name = name.substr(0, pos); obj_name = _obj_name.c_str(); - }else + } + else { obj_name = name.c_str(); + } try { // Use name from XML as is and do NOT remove trailing digits because // otherwise we may cause a dependency to itself // Example: Object 'Cut001' references object 'Cut' and removing the // digits we make an object 'Cut' referencing itself. - App::DocumentObject* obj = addObject(type.c_str(), obj_name, /*isNew=*/ false, viewType.c_str(), partial); + App::DocumentObject* obj = + addObject(type.c_str(), obj_name, /*isNew=*/false, viewType.c_str(), partial); if (obj) { - if(lastId < obj->_Id) + if (lastId < obj->_Id) { lastId = obj->_Id; + } objs.push_back(obj); // use this name for the later access because an object with // the given name may already exist @@ -1422,13 +1546,16 @@ Document::readObjects(Base::XMLReader& reader) // restore touch/error status flags if (reader.hasAttribute("Touched")) { - if(reader.getAttributeAsInteger("Touched") != 0) + if (reader.getAttributeAsInteger("Touched") != 0) { d->touchedObjs.insert(obj); + } } if (reader.hasAttribute("Invalid")) { - obj->setStatus(ObjectStatus::Error, reader.getAttributeAsInteger("Invalid") != 0); - if(obj->isError() && reader.hasAttribute("Error")) - d->addRecomputeLog(reader.getAttribute("Error"),obj); + obj->setStatus(ObjectStatus::Error, + reader.getAttributeAsInteger("Invalid") != 0); + if (obj->isError() && reader.hasAttribute("Error")) { + d->addRecomputeLog(reader.getAttribute("Error"), obj); + } } } } @@ -1436,8 +1563,9 @@ Document::readObjects(Base::XMLReader& reader) Base::Console().Error("Cannot create object '%s': (%s)\n", name.c_str(), e.what()); } } - if(!testStatus(Status::Importing)) + if (!testStatus(Status::Importing)) { d->lastObjectId = lastId; + } reader.readEndElement("Objects"); setStatus(Document::KeepTrailingDigits, keepDigits); @@ -1446,11 +1574,13 @@ Document::readObjects(Base::XMLReader& reader) reader.clearPartialRestoreDocumentObject(); reader.readElement("ObjectData"); Cnt = reader.getAttributeAsInteger("Count"); - for (int i=0 ;itestStatus(App::PartialObject)) { // check if this feature has been registered + if (pObj + && !pObj->testStatus( + App::PartialObject)) { // check if this feature has been registered pObj->setStatus(ObjectStatus::Restore, true); try { FC_TRACE("restoring " << pObj->getFullName()); @@ -1458,26 +1588,28 @@ Document::readObjects(Base::XMLReader& reader) } // Try to continue only for certain exception types if not handled // by the feature type. For all other exception types abort the process. - catch (const Base::UnicodeError &e) { + catch (const Base::UnicodeError& e) { e.ReportException(); } - catch (const Base::ValueError &e) { + catch (const Base::ValueError& e) { e.ReportException(); } - catch (const Base::IndexError &e) { + catch (const Base::IndexError& e) { e.ReportException(); } - catch (const Base::RuntimeError &e) { + catch (const Base::RuntimeError& e) { e.ReportException(); } - catch (const Base::XMLAttributeError &e) { + catch (const Base::XMLAttributeError& e) { e.ReportException(); } pObj->setStatus(ObjectStatus::Restore, false); if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestoreInDocumentObject)) { - Base::Console().Error("Object \"%s\" was subject to a partial restore. As a result geometry may have changed or be incomplete.\n",name.c_str()); + Base::Console().Error("Object \"%s\" was subject to a partial restore. As a result " + "geometry may have changed or be incomplete.\n", + name.c_str()); reader.clearPartialRestoreDocumentObject(); } } @@ -1488,16 +1620,16 @@ Document::readObjects(Base::XMLReader& reader) return objs; } -void Document::addRecomputeObject(DocumentObject *obj) { - if(testStatus(Status::Restoring) && obj) { +void Document::addRecomputeObject(DocumentObject* obj) +{ + if (testStatus(Status::Restoring) && obj) { setStatus(Status::RecomputeOnRestore, true); d->touchedObjs.insert(obj); obj->touch(); } } -std::vector -Document::importObjects(Base::XMLReader& reader) +std::vector Document::importObjects(Base::XMLReader& reader) { d->hashers.clear(); Base::FlagToggler<> flag(globalIsRestoring, false); @@ -1509,31 +1641,37 @@ Document::importObjects(Base::XMLReader& reader) reader.DocumentSchema = scheme; if (reader.hasAttribute("ProgramVersion")) { reader.ProgramVersion = reader.getAttribute("ProgramVersion"); - } else { + } + else { reader.ProgramVersion = "pre-0.14"; } if (reader.hasAttribute("FileVersion")) { reader.FileVersion = reader.getAttributeAsUnsigned("FileVersion"); - } else { + } + else { reader.FileVersion = 0; } std::vector objs = readObjects(reader); - for(auto o : objs) { - if(o && o->isAttachedToDocument()) { - o->setStatus(App::ObjImporting,true); + for (auto o : objs) { + if (o && o->isAttachedToDocument()) { + o->setStatus(App::ObjImporting, true); FC_LOG("importing " << o->getFullName()); - if (auto propUUID = Base::freecad_dynamic_cast( - o->getPropertyByName("_ObjectUUID"))) - { - auto propSource = Base::freecad_dynamic_cast( - o->getPropertyByName("_SourceUUID")); - if (!propSource) - propSource = static_cast(o->addDynamicProperty( - "App::PropertyUUID", "_SourceUUID", nullptr, nullptr, - Prop_Output | Prop_Hidden)); - if (propSource) + if (auto propUUID = + Base::freecad_dynamic_cast(o->getPropertyByName("_ObjectUUID"))) { + auto propSource = + Base::freecad_dynamic_cast(o->getPropertyByName("_SourceUUID")); + if (!propSource) { + propSource = static_cast( + o->addDynamicProperty("App::PropertyUUID", + "_SourceUUID", + nullptr, + nullptr, + Prop_Output | Prop_Hidden)); + } + if (propSource) { propSource->setValue(propUUID->getValue()); + } propUUID->setValue(Base::Uuid::createUuid()); } } @@ -1542,27 +1680,29 @@ Document::importObjects(Base::XMLReader& reader) reader.readEndElement("Document"); signalImportObjects(objs, reader); - afterRestore(objs,true); + afterRestore(objs, true); signalFinishImportObjects(objs); - for(auto o : objs) { - if(o && o->isAttachedToDocument()) - o->setStatus(App::ObjImporting,false); + for (auto o : objs) { + if (o && o->isAttachedToDocument()) { + o->setStatus(App::ObjImporting, false); + } } d->hashers.clear(); return objs; } -unsigned int Document::getMemSize () const +unsigned int Document::getMemSize() const { unsigned int size = 0; // size of the DocObjects in the document std::vector::const_iterator it; - for (it = d->objectArray.begin(); it != d->objectArray.end(); ++it) + for (it = d->objectArray.begin(); it != d->objectArray.end(); ++it) { size += (*it)->getMemSize(); + } size += d->Hasher->getMemSize(); @@ -1575,20 +1715,23 @@ unsigned int Document::getMemSize () const return size; } -static std::string checkFileName(const char *file) { +static std::string checkFileName(const char* file) +{ std::string fn(file); // Append extension if missing. This option is added for security reason, so // that the user won't accidentally overwrite other file that may be critical. - if(App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("CheckExtension",true)) - { - const char *ext = strrchr(file,'.'); - if(!ext || !boost::iequals(ext+1,"fcstd")) { - if(ext && ext[1] == 0) + if (App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("CheckExtension", true)) { + const char* ext = strrchr(file, '.'); + if (!ext || !boost::iequals(ext + 1, "fcstd")) { + if (ext && ext[1] == 0) { fn += "FCStd"; - else + } + else { fn += ".FCStd"; + } } } return fn; @@ -1601,7 +1744,7 @@ bool Document::saveAs(const char* _file) if (this->FileName.getStrValue() != file) { this->FileName.setValue(file); this->Label.setValue(fi.fileNamePure()); - this->Uid.touch(); // this forces a rename of the transient directory + this->Uid.touch(); // this forces a rename of the transient directory } return save(); @@ -1618,9 +1761,9 @@ bool Document::saveCopy(const char* _file) const } // Save the document under the name it has been opened -bool Document::save () +bool Document::save() { - if(testStatus(Document::PartialDoc)) { + if (testStatus(Document::PartialDoc)) { FC_ERR("Partial loaded document '" << Label.getValue() << "' cannot be saved"); // TODO We don't make this a fatal error and return 'true' to make it possible to // save other documents that depends on this partial opened document. We need better @@ -1637,11 +1780,15 @@ bool Document::save () std::string LastModifiedDateString = Base::Tools::currentDateTimeString(); LastModifiedDate.setValue(LastModifiedDateString.c_str()); // set author if needed - bool saveAuthor = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("prefSetAuthorOnSave",false); + bool saveAuthor = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("prefSetAuthorOnSave", false); if (saveAuthor) { - std::string Author = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetASCII("prefAuthor",""); + std::string Author = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetASCII("prefAuthor", ""); LastModifiedBy.setValue(Author.c_str()); } @@ -1651,46 +1798,56 @@ bool Document::save () return false; } -namespace App { +namespace App +{ // Helper class to handle different backup policies -class BackupPolicy { +class BackupPolicy +{ public: - enum Policy { + enum Policy + { Standard, TimeStamp }; - BackupPolicy() { + BackupPolicy() + { policy = Standard; numberOfFiles = 1; useFCBakExtension = true; saveBackupDateFormat = "%Y%m%d-%H%M%S"; } ~BackupPolicy() = default; - void setPolicy(Policy p) { + void setPolicy(Policy p) + { policy = p; } - void setNumberOfFiles(int count) { + void setNumberOfFiles(int count) + { numberOfFiles = count; } - void useBackupExtension(bool on) { + void useBackupExtension(bool on) + { useFCBakExtension = on; } - void setDateFormat(const std::string& fmt) { + void setDateFormat(const std::string& fmt) + { saveBackupDateFormat = fmt; } - void apply(const std::string& sourcename, const std::string& targetname) { + void apply(const std::string& sourcename, const std::string& targetname) + { switch (policy) { - case Standard: - applyStandard(sourcename, targetname); - break; - case TimeStamp: - applyTimeStamp(sourcename, targetname); - break; + case Standard: + applyStandard(sourcename, targetname); + break; + case TimeStamp: + applyTimeStamp(sourcename, targetname); + break; } } private: - void applyStandard(const std::string& sourcename, const std::string& targetname) { + void applyStandard(const std::string& sourcename, const std::string& targetname) + { // if saving the project data succeeded rename to the actual file name Base::FileInfo fi(targetname); if (fi.exists()) { @@ -1702,12 +1859,12 @@ private: std::vector files = di.getDirectoryContent(); for (const Base::FileInfo& it : files) { std::string file = it.fileName(); - if (file.substr(0,fn.length()) == fn) { + if (file.substr(0, fn.length()) == fn) { // starts with the same file name std::string suf(file.substr(fn.length())); if (!suf.empty()) { std::string::size_type nPos = suf.find_first_not_of("0123456789"); - if (nPos==std::string::npos) { + if (nPos == std::string::npos) { // store all backup files backup.push_back(it); nSuff = std::max(nSuff, std::atol(suf.c_str())); @@ -1720,8 +1877,9 @@ private: // delete the oldest backup file we found Base::FileInfo del = backup.front(); for (const Base::FileInfo& it : backup) { - if (it.lastModified() < del.lastModified()) + if (it.lastModified() < del.lastModified()) { del = it; + } } del.deleteFile(); @@ -1734,8 +1892,9 @@ private: fn = str.str(); } - if (!fi.renameFile(fn.c_str())) + if (!fi.renameFile(fn.c_str())) { Base::Console().Warning("Cannot rename project file to backup file\n"); + } } else { fi.deleteFile(); @@ -1744,17 +1903,18 @@ private: Base::FileInfo tmp(sourcename); if (!tmp.renameFile(targetname.c_str())) { - throw Base::FileException( - "Cannot rename tmp save file to project file", Base::FileInfo(targetname)); + throw Base::FileException("Cannot rename tmp save file to project file", + Base::FileInfo(targetname)); } } - void applyTimeStamp(const std::string& sourcename, const std::string& targetname) { + void applyTimeStamp(const std::string& sourcename, const std::string& targetname) + { Base::FileInfo fi(targetname); std::string fn = sourcename; std::string ext = fi.extension(); - std::string bn; // full path with no extension but with "." - std::string pbn; // base name of the project + "." + std::string bn; // full path with no extension but with "." + std::string pbn; // base name of the project + "." if (!ext.empty()) { bn = fi.filePath().substr(0, fi.filePath().length() - ext.length()); pbn = fi.fileName().substr(0, fi.fileName().length() - ext.length()); @@ -1764,7 +1924,7 @@ private: pbn = fi.fileName() + "."; } - bool backupManagementError = false; // Note error and report at the end + bool backupManagementError = false; // Note error and report at the end if (fi.exists()) { if (numberOfFiles > 0) { // replace . by - in format to avoid . between base name and extension @@ -1780,25 +1940,30 @@ private: std::string file = it.fileName(); std::string fext = it.extension(); std::string fextUp = fext; - std::transform(fextUp.begin(), fextUp.end(), fextUp.begin(),(int (*)(int))toupper); + std::transform(fextUp.begin(), + fextUp.end(), + fextUp.begin(), + (int (*)(int))toupper); // re-enforcing identification of the backup file - // old case : the name starts with the full name of the project and follows with numbers - if ((startsWith(file, fn) && - (file.length() > fn.length()) && - checkDigits(file.substr(fn.length()))) || - // .FCBak case : The bame starts with the base name of the project + "." - // + complement with no "." + ".FCBak" - ((fextUp == "FCBAK") && startsWith(file, pbn) && - (checkValidComplement(file, pbn, fext)))) { + // old case : the name starts with the full name of the project and + // follows with numbers + if ((startsWith(file, fn) && (file.length() > fn.length()) + && checkDigits(file.substr(fn.length()))) + || + // .FCBak case : The bame starts with the base name of the project + + // "." + // + complement with no "." + ".FCBak" + ((fextUp == "FCBAK") && startsWith(file, pbn) + && (checkValidComplement(file, pbn, fext)))) { backup.push_back(it); } } } if (!backup.empty() && (int)backup.size() >= numberOfFiles) { - std::sort (backup.begin(), backup.end(), fileComparisonByDate); + std::sort(backup.begin(), backup.end(), fileComparisonByDate); // delete the oldest backup file we found // Base::FileInfo del = backup.front(); int nb = 0; @@ -1808,18 +1973,19 @@ private: try { if (!it.deleteFile()) { backupManagementError = true; - Base::Console().Warning("Cannot remove backup file : %s\n", it.fileName().c_str()); + Base::Console().Warning("Cannot remove backup file : %s\n", + it.fileName().c_str()); } } catch (...) { backupManagementError = true; - Base::Console().Warning("Cannot remove backup file : %s\n", it.fileName().c_str()); + Base::Console().Warning("Cannot remove backup file : %s\n", + it.fileName().c_str()); } } } - } - } //end remove backup + } // end remove backup // create a new backup file { @@ -1828,22 +1994,23 @@ private: std::stringstream str; Base::TimeInfo ti = fi.lastModified(); time_t s = ti.getTime_t(); - struct tm * timeinfo = localtime(& s); + struct tm* timeinfo = localtime(&s); char buffer[100]; - strftime(buffer,sizeof(buffer),saveBackupDateFormat.c_str(),timeinfo); - str << bn << buffer ; + strftime(buffer, sizeof(buffer), saveBackupDateFormat.c_str(), timeinfo); + str << bn << buffer; fn = str.str(); bool done = false; - if ((fn.empty()) || (fn[fn.length()-1] == ' ') || (fn[fn.length()-1] == '-')) { - if (fn[fn.length()-1] == ' ') { - fn = fn.substr(0,fn.length()-1); + if ((fn.empty()) || (fn[fn.length() - 1] == ' ') + || (fn[fn.length() - 1] == '-')) { + if (fn[fn.length() - 1] == ' ') { + fn = fn.substr(0, fn.length() - 1); } } else { - if (!renameFileNoErase(fi, fn+".FCBak")) { + if (!renameFileNoErase(fi, fn + ".FCBak")) { fn = fn + "-"; } else { @@ -1853,25 +2020,31 @@ private: if (!done) { while (ext < numberOfFiles + 10) { - if (renameFileNoErase(fi, fn+std::to_string(ext)+".FCBak")) + if (renameFileNoErase(fi, fn + std::to_string(ext) + ".FCBak")) { break; + } ext++; } } } else { - // changed but simpler and solves also the delay sometimes introduced by google drive + // changed but simpler and solves also the delay sometimes introduced by + // google drive while (ext < numberOfFiles + 10) { - // linux just replace the file if exists, and then the existence is to be tested before rename - if (renameFileNoErase(fi, fi.filePath()+std::to_string(ext))) + // linux just replace the file if exists, and then the existence is to + // be tested before rename + if (renameFileNoErase(fi, fi.filePath() + std::to_string(ext))) { break; + } ext++; } } if (ext >= numberOfFiles + 10) { - Base::Console().Error("File not saved: Cannot rename project file to backup file\n"); - //throw Base::FileException("File not saved: Cannot rename project file to backup file", fi); + Base::Console().Error( + "File not saved: Cannot rename project file to backup file\n"); + // throw Base::FileException("File not saved: Cannot rename project file to + // backup file", fi); } } } @@ -1880,7 +2053,8 @@ private: fi.deleteFile(); } catch (...) { - Base::Console().Warning("Cannot remove backup file: %s\n", fi.fileName().c_str()); + Base::Console().Warning("Cannot remove backup file: %s\n", + fi.fileName().c_str()); backupManagementError = true; } } @@ -1889,36 +2063,46 @@ private: Base::FileInfo tmp(sourcename); if (!tmp.renameFile(targetname.c_str())) { throw Base::FileException( - "Save interrupted: Cannot rename temporary file to project file", tmp); + "Save interrupted: Cannot rename temporary file to project file", + tmp); } if (backupManagementError) { - throw Base::FileException("Warning: Save complete, but error while managing backup history.", fi); + throw Base::FileException( + "Warning: Save complete, but error while managing backup history.", + fi); } } - static bool fileComparisonByDate(const Base::FileInfo& i, - const Base::FileInfo& j) { - return (i.lastModified()>j.lastModified()); + static bool fileComparisonByDate(const Base::FileInfo& i, const Base::FileInfo& j) + { + return (i.lastModified() > j.lastModified()); } - bool startsWith(const std::string& st1, - const std::string& st2) const { - return st1.substr(0,st2.length()) == st2; + bool startsWith(const std::string& st1, const std::string& st2) const + { + return st1.substr(0, st2.length()) == st2; } - bool checkValidString (const std::string& cmpl, const boost::regex& e) const { + bool checkValidString(const std::string& cmpl, const boost::regex& e) const + { boost::smatch what; - bool res = boost::regex_search (cmpl,what,e); + bool res = boost::regex_search(cmpl, what, e); return res; } - bool checkValidComplement(const std::string& file, const std::string& pbn, const std::string& ext) const { - std::string cmpl = file.substr(pbn.length(),file.length()- pbn.length() - ext.length()-1); - boost::regex e (R"(^[^.]*$)"); - return checkValidString(cmpl,e); + bool checkValidComplement(const std::string& file, + const std::string& pbn, + const std::string& ext) const + { + std::string cmpl = + file.substr(pbn.length(), file.length() - pbn.length() - ext.length() - 1); + boost::regex e(R"(^[^.]*$)"); + return checkValidString(cmpl, e); } - bool checkDigits (const std::string& cmpl) const { - boost::regex e (R"(^[0-9]*$)"); - return checkValidString(cmpl,e); + bool checkDigits(const std::string& cmpl) const + { + boost::regex e(R"(^[0-9]*$)"); + return checkValidString(cmpl, e); } - bool renameFileNoErase(Base::FileInfo fi, const std::string& newName) { + bool renameFileNoErase(Base::FileInfo fi, const std::string& newName) + { // linux just replaces the file if it exists, so the existence is to be tested before rename Base::FileInfo nf(newName); if (!nf.exists()) { @@ -1933,18 +2117,20 @@ private: bool useFCBakExtension; std::string saveBackupDateFormat; }; -} +} // namespace App bool Document::saveToFile(const char* filename) const { signalStartSave(*this, filename); - auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document"); - int compression = hGrp->GetInt("CompressionLevel",7); + auto hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Document"); + int compression = hGrp->GetInt("CompressionLevel", 7); compression = Base::clamp(compression, Z_NO_COMPRESSION, Z_BEST_COMPRESSION); - bool policy = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("BackupPolicy",true); + bool policy = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("BackupPolicy", true); auto canonical_path = [](const char* filename) { try { @@ -1975,7 +2161,7 @@ bool Document::saveToFile(const char* filename) const } }; - //realpath is canonical filename i.e. without symlink + // realpath is canonical filename i.e. without symlink std::string nativePath = canonical_path(filename); // make a tmp. file where to save the project data first and then rename to @@ -2002,12 +2188,14 @@ bool Document::saveToFile(const char* filename) const writer.setLevel(compression); writer.putNextEntry("Document.xml"); - if (hGrp->GetBool("SaveBinaryBrep", false)) + if (hGrp->GetBool("SaveBinaryBrep", false)) { writer.setMode("BinaryBrep"); + } writer.Stream() << "" << endl << "" << endl; Document::Save(writer); @@ -2026,17 +2214,23 @@ bool Document::saveToFile(const char* filename) const if (policy) { // if saving the project data succeeded rename to the actual file name - int count_bak = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetInt("CountBackupFiles",1); - bool backup = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("CreateBackupFiles",true); + int count_bak = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetInt("CountBackupFiles", 1); + bool backup = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("CreateBackupFiles", true); if (!backup) { count_bak = -1; } - bool useFCBakExtension = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("UseFCBakExtension",true); - std::string saveBackupDateFormat = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetASCII("SaveBackupDateFormat","%Y%m%d-%H%M%S"); + bool useFCBakExtension = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("UseFCBakExtension", true); + std::string saveBackupDateFormat = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetASCII("SaveBackupDateFormat", "%Y%m%d-%H%M%S"); BackupPolicy policy; if (useFCBakExtension) { @@ -2056,19 +2250,21 @@ bool Document::saveToFile(const char* filename) const return true; } -bool Document::isAnyRestoring() { +bool Document::isAnyRestoring() +{ return globalIsRestoring; } // Open the document -void Document::restore (const char *filename, - bool delaySignal, const std::vector &objNames) +void Document::restore(const char* filename, + bool delaySignal, + const std::vector& objNames) { clearUndos(); d->activeObject = nullptr; bool signal = false; - Document *activeDoc = GetApplication().getActiveDocument(); + Document* activeDoc = GetApplication().getActiveDocument(); if (!d->objectArray.empty()) { signal = true; GetApplication().signalDeleteDocument(*this); @@ -2077,7 +2273,7 @@ void Document::restore (const char *filename, Base::FlagToggler<> flag(globalIsRestoring, false); - setStatus(Document::PartialDoc,false); + setStatus(Document::PartialDoc, false); d->clearRecomputeLog(); d->objectArray.clear(); @@ -2085,37 +2281,43 @@ void Document::restore (const char *filename, d->objectIdMap.clear(); d->lastObjectId = 0; - if(signal) { - GetApplication().signalNewDocument(*this,true); - if(activeDoc == this) + if (signal) { + GetApplication().signalNewDocument(*this, true); + if (activeDoc == this) { GetApplication().setActiveDocument(this); + } } - if(!filename) + if (!filename) { filename = FileName.getValue(); + } Base::FileInfo fi(filename); Base::ifstream file(fi, std::ios::in | std::ios::binary); std::streambuf* buf = file.rdbuf(); std::streamoff size = buf->pubseekoff(0, std::ios::end, std::ios::in); buf->pubseekoff(0, std::ios::beg, std::ios::in); - if (size < 22) // an empty zip archive has 22 bytes - throw Base::FileException("Invalid project file",filename); + if (size < 22) { // an empty zip archive has 22 bytes + throw Base::FileException("Invalid project file", filename); + } zipios::ZipInputStream zipstream(file); Base::XMLReader reader(filename, zipstream); - if (!reader.isValid()) - throw Base::FileException("Error reading compression file",filename); + if (!reader.isValid()) { + throw Base::FileException("Error reading compression file", filename); + } GetApplication().signalStartRestoreDocument(*this); setStatus(Document::Restoring, true); d->partialLoadObjects.clear(); - for(auto &name : objNames) - d->partialLoadObjects.emplace(name,true); + for (auto& name : objNames) { + d->partialLoadObjects.emplace(name, true); + } try { Document::Restore(reader); - } catch (const Base::Exception& e) { + } + catch (const Base::Exception& e) { Base::Console().Error("Invalid Document.xml: %s\n", e.what()); setStatus(Document::RestoreError, true); } @@ -2134,16 +2336,20 @@ void Document::restore (const char *filename, if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestore)) { setStatus(Document::PartialRestore, true); - Base::Console().Error("There were errors while loading the file. Some data might have been modified or not recovered at all. Look above for more specific information about the objects involved.\n"); + Base::Console().Error("There were errors while loading the file. Some data might have been " + "modified or not recovered at all. Look above for more specific " + "information about the objects involved.\n"); } - if(!delaySignal) + if (!delaySignal) { afterRestore(true); + } } -bool Document::afterRestore(bool checkPartial) { +bool Document::afterRestore(bool checkPartial) +{ Base::FlagToggler<> flag(globalIsRestoring, false); - if(!afterRestore(d->objectArray,checkPartial)) { + if (!afterRestore(d->objectArray, checkPartial)) { FC_WARN("Reload partial document " << getName()); GetApplication().signalPendingReloadDocument(*this); return false; @@ -2153,11 +2359,12 @@ bool Document::afterRestore(bool checkPartial) { return true; } -bool Document::afterRestore(const std::vector &objArray, bool checkPartial) +bool Document::afterRestore(const std::vector& objArray, bool checkPartial) { checkPartial = checkPartial && testStatus(Document::PartialDoc); - if(checkPartial && !d->touchedObjs.empty()) + if (checkPartial && !d->touchedObjs.empty()) { return false; + } // some link type property cannot restore link information until other // objects has been restored. For example, PropertyExpressionEngine and @@ -2165,86 +2372,95 @@ bool Document::afterRestore(const std::vector &objArray, bool // Property::afterRestore() interface to let them sort it out. Note, this // API is not called in object dedpenency order, because the order // information is not ready yet. - std::map > propMap; - for(auto obj : objArray) { - auto &props = propMap[obj]; + std::map> propMap; + for (auto obj : objArray) { + auto& props = propMap[obj]; obj->getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { try { prop->afterRestore(); - } catch (const Base::Exception& e) { - FC_ERR("Failed to restore " << obj->getFullName() - << '.' << prop->getName() << ": " << e.what()); + } + catch (const Base::Exception& e) { + FC_ERR("Failed to restore " << obj->getFullName() << '.' << prop->getName() << ": " + << e.what()); } } } - if(checkPartial && !d->touchedObjs.empty()) { + if (checkPartial && !d->touchedObjs.empty()) { // partial document touched, signal full reload return false; } - std::set objSet(objArray.begin(),objArray.end()); - auto objs = getDependencyList(objArray.empty()?d->objectArray:objArray,DepSort); + std::set objSet(objArray.begin(), objArray.end()); + auto objs = getDependencyList(objArray.empty() ? d->objectArray : objArray, DepSort); for (auto obj : objs) { - if(objSet.find(obj)==objSet.end()) + if (objSet.find(obj) == objSet.end()) { continue; + } try { - for(auto prop : propMap[obj]) + for (auto prop : propMap[obj]) { prop->onContainerRestored(); + } bool touched = false; - auto returnCode = obj->ExpressionEngine.execute( - PropertyExpressionEngine::ExecuteOnRestore,&touched); - if(returnCode!=DocumentObject::StdReturn) { - FC_ERR("Expression engine failed to restore " << obj->getFullName() << ": " << returnCode->Why); + auto returnCode = + obj->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteOnRestore, &touched); + if (returnCode != DocumentObject::StdReturn) { + FC_ERR("Expression engine failed to restore " << obj->getFullName() << ": " + << returnCode->Why); d->addRecomputeLog(returnCode); } obj->onDocumentRestored(); - if(touched) + if (touched) { d->touchedObjs.insert(obj); + } } catch (const Base::Exception& e) { - d->addRecomputeLog(e.what(),obj); + d->addRecomputeLog(e.what(), obj); FC_ERR("Failed to restore " << obj->getFullName() << ": " << e.what()); } - catch (std::exception &e) { - d->addRecomputeLog(e.what(),obj); + catch (std::exception& e) { + d->addRecomputeLog(e.what(), obj); FC_ERR("Failed to restore " << obj->getFullName() << ": " << e.what()); } catch (...) { - d->addRecomputeLog("Unknown exception on restore",obj); + d->addRecomputeLog("Unknown exception on restore", obj); FC_ERR("Failed to restore " << obj->getFullName() << ": " << "unknown exception"); } - if(obj->isValid()) { - auto &props = propMap[obj]; + if (obj->isValid()) { + auto& props = propMap[obj]; props.clear(); // refresh properties in case the object changes its property list obj->getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { auto link = Base::freecad_dynamic_cast(prop); int res; std::string errMsg; - if(link && (res=link->checkRestore(&errMsg))) { + if (link && (res = link->checkRestore(&errMsg))) { d->touchedObjs.insert(obj); - if(res==1 || checkPartial) { + if (res == 1 || checkPartial) { FC_WARN(obj->getFullName() << '.' << prop->getName() << ": " << errMsg); setStatus(Document::LinkStampChanged, true); - if(checkPartial) + if (checkPartial) { return false; - } else { + } + } + else { FC_ERR(obj->getFullName() << '.' << prop->getName() << ": " << errMsg); - d->addRecomputeLog(errMsg,obj); + d->addRecomputeLog(errMsg, obj); setStatus(Document::PartialRestore, true); } } } } - if(checkPartial && !d->touchedObjs.empty()) { + if (checkPartial && !d->touchedObjs.empty()) { // partial document touched, signal full reload return false; - } else if(!d->touchedObjs.count(obj)) + } + else if (!d->touchedObjs.count(obj)) { obj->purgeTouched(); + } signalFinishRestoreObject(*obj); } @@ -2263,14 +2479,14 @@ bool Document::isSaved() const * or in the tree view. The label almost (but not always e.g. if you manually change it) * matches with the file name where the document is stored to. * In contrast to Label the method getName() returns the internal name of the document that only - * matches with Label when loading or creating a document because then both are set to the same value. - * Since the internal name cannot be changed during runtime it must differ from the Label after saving - * the document the first time or saving it under a new file name. + * matches with Label when loading or creating a document because then both are set to the same + * value. Since the internal name cannot be changed during runtime it must differ from the Label + * after saving the document the first time or saving it under a new file name. * @ note More than one document can have the same label name. - * @ note The internal is always guaranteed to be unique because @ref Application::newDocument() checks - * for a document with the same name and makes it unique if needed. Hence you cannot rely on that the - * internal name matches with the name you passed to Application::newDoument(). You should use the - * method getName() instead. + * @ note The internal is always guaranteed to be unique because @ref Application::newDocument() + * checks for a document with the same name and makes it unique if needed. Hence you cannot rely on + * that the internal name matches with the name you passed to Application::newDoument(). You should + * use the method getName() instead. */ const char* Document::getName() const { @@ -2278,7 +2494,8 @@ const char* Document::getName() const return myName.c_str(); } -std::string Document::getFullName() const { +std::string Document::getFullName() const +{ return myName; } @@ -2289,15 +2506,15 @@ const char* Document::getProgramVersion() const const char* Document::getFileName() const { - return testStatus(TempDoc) ? TransientDir.getValue() - : FileName.getValue(); + return testStatus(TempDoc) ? TransientDir.getValue() : FileName.getValue(); } /// Remove all modifications. After this call The document becomes valid again. void Document::purgeTouched() { - for (auto It : d->objectArray) + for (auto It : d->objectArray) { It->purgeTouched(); + } } bool Document::isTouched() const @@ -2335,63 +2552,76 @@ bool Document::isClosable() const int Document::countObjects() const { - return static_cast(d->objectArray.size()); + return static_cast(d->objectArray.size()); } -void Document::getLinksTo(std::set &links, - const DocumentObject *obj, int options, int maxCount, - const std::vector &objs) const +void Document::getLinksTo(std::set& links, + const DocumentObject* obj, + int options, + int maxCount, + const std::vector& objs) const { - std::map > linkMap; + std::map> linkMap; - for(auto o : !objs.empty() ? objs : d->objectArray) { - if (o == obj) + for (auto o : !objs.empty() ? objs : d->objectArray) { + if (o == obj) { continue; + } auto linked = o; if (options & GetLinkArrayElement) { linked = o->getLinkedObject(false); } else { auto ext = o->getExtensionByType(true); - if(ext) - linked = ext->getTrueLinkedObject(false,nullptr,0,true); - else + if (ext) { + linked = ext->getTrueLinkedObject(false, nullptr, 0, true); + } + else { linked = o->getLinkedObject(false); + } } - if(linked && linked!=o) { - if(options & GetLinkRecursive) + if (linked && linked != o) { + if (options & GetLinkRecursive) { linkMap[linked].push_back(o); - else if(linked == obj || !obj) { - if((options & GetLinkExternal) - && linked->getDocument()==o->getDocument()) + } + else if (linked == obj || !obj) { + if ((options & GetLinkExternal) && linked->getDocument() == o->getDocument()) { continue; - else if(options & GetLinkedObject) + } + else if (options & GetLinkedObject) { links.insert(linked); - else + } + else { links.insert(o); - if(maxCount && maxCount<=(int)links.size()) + } + if (maxCount && maxCount <= (int)links.size()) { return; + } } } } - if(!(options & GetLinkRecursive)) + if (!(options & GetLinkRecursive)) { return; + } - std::vector current(1,obj); - for(int depth=0;!current.empty();++depth) { - if(!GetApplication().checkLinkDepth(depth, MessageOption::Error)) + std::vector current(1, obj); + for (int depth = 0; !current.empty(); ++depth) { + if (!GetApplication().checkLinkDepth(depth, MessageOption::Error)) { break; + } std::vector next; - for(const App::DocumentObject *o : current) { + for (const App::DocumentObject* o : current) { auto iter = linkMap.find(o); - if(iter==linkMap.end()) + if (iter == linkMap.end()) { continue; - for (App::DocumentObject *link : iter->second) { + } + for (App::DocumentObject* link : iter->second) { if (links.insert(link).second) { - if(maxCount && maxCount<=(int)links.size()) + if (maxCount && maxCount <= (int)links.size()) { return; + } next.push_back(link); } } @@ -2401,9 +2631,10 @@ void Document::getLinksTo(std::set &links, return; } -bool Document::hasLinksTo(const DocumentObject *obj) const { - std::set links; - getLinksTo(links,obj,0,1); +bool Document::hasLinksTo(const DocumentObject* obj) const +{ + std::set links; + getLinksTo(links, obj, 0, 1); return !links.empty(); } @@ -2412,13 +2643,14 @@ std::vector Document::getInList(const DocumentObject* me) // result list std::vector result; // go through all objects - for (const auto & It : d->objectMap) { + for (const auto& It : d->objectMap) { // get the outList and search if me is in that list std::vector OutList = It.second->getOutList(); for (auto obj : OutList) { - if (obj && obj == me) + if (obj && obj == me) { // add the parent object result.push_back(It.second); + } } } return result; @@ -2437,103 +2669,122 @@ std::vector Document::getInList(const DocumentObject* me) // assumption is broken by the introduction of PropertyXLink which can link to // external object. // -static void _buildDependencyList(const std::vector &objectArray, - int options, std::vector *depObjs, - DependencyList *depList, std::map *objectMap, - bool *touchCheck = nullptr) +static void _buildDependencyList(const std::vector& objectArray, + int options, + std::vector* depObjs, + DependencyList* depList, + std::map* objectMap, + bool* touchCheck = nullptr) { - std::map > outLists; + std::map> outLists; std::deque objs; - if(objectMap) objectMap->clear(); - if(depList) depList->clear(); + if (objectMap) { + objectMap->clear(); + } + if (depList) { + depList->clear(); + } - int op = (options & Document::DepNoXLinked)?DocumentObject::OutListNoXLinked:0; + int op = (options & Document::DepNoXLinked) ? DocumentObject::OutListNoXLinked : 0; for (auto obj : objectArray) { objs.push_back(obj); - while(!objs.empty()) { + while (!objs.empty()) { auto obj = objs.front(); objs.pop_front(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } auto it = outLists.find(obj); - if(it!=outLists.end()) + if (it != outLists.end()) { continue; + } - if(touchCheck) { - if(obj->isTouched() || obj->mustExecute()) { + if (touchCheck) { + if (obj->isTouched() || obj->mustExecute()) { // early termination on touch check *touchCheck = true; return; } } - if(depObjs) depObjs->push_back(obj); - if(objectMap && depList) + if (depObjs) { + depObjs->push_back(obj); + } + if (objectMap && depList) { (*objectMap)[obj] = add_vertex(*depList); + } - auto &outList = outLists[obj]; + auto& outList = outLists[obj]; outList = obj->getOutList(op); - objs.insert(objs.end(),outList.begin(),outList.end()); + objs.insert(objs.end(), outList.begin(), outList.end()); } } - if(objectMap && depList) { - for (const auto &v : outLists) { - for(auto obj : v.second) { - if(obj && obj->isAttachedToDocument()) - add_edge((*objectMap)[v.first],(*objectMap)[obj],*depList); + if (objectMap && depList) { + for (const auto& v : outLists) { + for (auto obj : v.second) { + if (obj && obj->isAttachedToDocument()) { + add_edge((*objectMap)[v.first], (*objectMap)[obj], *depList); + } } } } } -std::vector Document::getDependencyList( - const std::vector& objectArray, int options) +std::vector +Document::getDependencyList(const std::vector& objectArray, int options) { std::vector ret; - if(!(options & DepSort)) { - _buildDependencyList(objectArray,options,&ret,nullptr,nullptr); + if (!(options & DepSort)) { + _buildDependencyList(objectArray, options, &ret, nullptr, nullptr); return ret; } DependencyList depList; - std::map objectMap; - std::map vertexMap; + std::map objectMap; + std::map vertexMap; - _buildDependencyList(objectArray,options,nullptr,&depList,&objectMap); + _buildDependencyList(objectArray, options, nullptr, &depList, &objectMap); - for(auto &v : objectMap) + for (auto& v : objectMap) { vertexMap[v.second] = v.first; + } std::list make_order; try { boost::topological_sort(depList, std::front_inserter(make_order)); - } catch (const std::exception& e) { - if(options & DepNoCycle) { + } + catch (const std::exception& e) { + if (options & DepNoCycle) { // Use boost::strong_components to find cycles. It groups strongly // connected vertices as components, and therefore each component // forms a cycle. std::vector c(vertexMap.size()); - std::map > components; - boost::strong_components(depList,boost::make_iterator_property_map( - c.begin(),boost::get(boost::vertex_index,depList),c[0])); - for(size_t i=0;i> components; + boost::strong_components( + depList, + boost::make_iterator_property_map(c.begin(), + boost::get(boost::vertex_index, depList), + c[0])); + for (size_t i = 0; i < c.size(); ++i) { components[c[i]].push_back(i); + } FC_ERR("Dependency cycles: "); std::ostringstream ss; ss << std::endl; - for(auto &v : components) { - if(v.second.size()==1) { + for (auto& v : components) { + if (v.second.size() == 1) { // For components with only one member, we still need to // check if there it is self looping. auto it = vertexMap.find(v.second[0]); - if(it==vertexMap.end()) + if (it == vertexMap.end()) { continue; + } // Try search the object in its own out list - for(auto obj : it->second->getOutList()) { - if(obj == it->second) { + for (auto obj : it->second->getOutList()) { + if (obj == it->second) { ss << std::endl << it->second->getFullName() << std::endl; break; } @@ -2541,12 +2792,14 @@ std::vector Document::getDependencyList( continue; } // For components with more than one member, they form a loop together - for(size_t i=0;isecond->getFullName() << ", "; } ss << std::endl; @@ -2556,81 +2809,94 @@ std::vector Document::getDependencyList( } FC_ERR(e.what()); ret = DocumentP::partialTopologicalSort(objectArray); - std::reverse(ret.begin(),ret.end()); + std::reverse(ret.begin(), ret.end()); return ret; } - for (std::list::reverse_iterator i = make_order.rbegin();i != make_order.rend(); ++i) + for (std::list::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) { ret.push_back(vertexMap[*i]); + } return ret; } -std::vector Document::getDependentDocuments(bool sort) { - return getDependentDocuments({this},sort); +std::vector Document::getDependentDocuments(bool sort) +{ + return getDependentDocuments({this}, sort); } -std::vector Document::getDependentDocuments( - std::vector pending, bool sort) +std::vector Document::getDependentDocuments(std::vector pending, + bool sort) { DependencyList depList; - std::map docMap; - std::map vertexMap; + std::map docMap; + std::map vertexMap; std::vector ret; - if(pending.empty()) + if (pending.empty()) { return ret; + } auto outLists = PropertyXLink::getDocumentOutList(); std::set docs; - docs.insert(pending.begin(),pending.end()); - if(sort) { - for(auto doc : pending) + docs.insert(pending.begin(), pending.end()); + if (sort) { + for (auto doc : pending) { docMap[doc] = add_vertex(depList); + } } - while(!pending.empty()) { + while (!pending.empty()) { auto doc = pending.back(); pending.pop_back(); auto it = outLists.find(doc); - if(it == outLists.end()) + if (it == outLists.end()) { continue; + } - auto &vertex = docMap[doc]; - for(auto depDoc : it->second) { - if(docs.insert(depDoc).second) { + auto& vertex = docMap[doc]; + for (auto depDoc : it->second) { + if (docs.insert(depDoc).second) { pending.push_back(depDoc); - if(sort) + if (sort) { docMap[depDoc] = add_vertex(depList); + } } - add_edge(vertex,docMap[depDoc],depList); + add_edge(vertex, docMap[depDoc], depList); } } - if(!sort) { - ret.insert(ret.end(),docs.begin(),docs.end()); + if (!sort) { + ret.insert(ret.end(), docs.begin(), docs.end()); return ret; } std::list make_order; try { boost::topological_sort(depList, std::front_inserter(make_order)); - } catch (const std::exception& e) { + } + catch (const std::exception& e) { std::string msg("Document::getDependentDocuments: "); msg += e.what(); throw Base::RuntimeError(msg); } - for(auto &v : docMap) + for (auto& v : docMap) { vertexMap[v.second] = v.first; - for (auto rIt=make_order.rbegin(); rIt!=make_order.rend(); ++rIt) + } + for (auto rIt = make_order.rbegin(); rIt != make_order.rend(); ++rIt) { ret.push_back(vertexMap[*rIt]); + } return ret; } -void Document::_rebuildDependencyList(const std::vector &objs) +void Document::_rebuildDependencyList(const std::vector& objs) { #ifdef USE_OLD_DAG - _buildDependencyList(objs.empty()?d->objectArray:objs,false,0,&d->DepList,&d->VertexObjectList); + _buildDependencyList(objs.empty() ? d->objectArray : objs, + false, + 0, + &d->DepList, + &d->VertexObjectList); #else (void)objs; #endif @@ -2645,9 +2911,9 @@ void Document::_rebuildDependencyList(const std::vector &o * @param paths Map with current and new names */ -void Document::renameObjectIdentifiers(const std::map &paths, - const std::function & selector) +void Document::renameObjectIdentifiers( + const std::map& paths, + const std::function& selector) { std::map extendedPaths; @@ -2665,7 +2931,7 @@ void Document::renameObjectIdentifiers(const std::map &objs, bool force) +int Document::recompute(const std::vector& objs, bool force) { if (testStatus(Document::Recomputing)) { // this is clearly a bug in the calling instance @@ -2676,8 +2942,9 @@ int Document::recompute(const std::vector &objs, bool forc // The 'SkipRecompute' flag can be (tmp.) set to avoid too many // time expensive recomputes - if(!force && testStatus(Document::SkipRecompute)) + if (!force && testStatus(Document::SkipRecompute)) { return 0; + } Base::ObjectStatusLocker exe(Document::Recomputing, this); @@ -2700,8 +2967,11 @@ int Document::recompute(const std::vector &objs, bool forc } // caching vertex to DocObject - for (std::map::const_iterator It1= d->VertexObjectList.begin();It1 != d->VertexObjectList.end(); ++It1) + for (std::map::const_iterator It1 = d->VertexObjectList.begin(); + It1 != d->VertexObjectList.end(); + ++It1) { d->vertexMap[It1->second] = It1->first; + } #ifdef FC_LOGFEATUREUPDATE std::clog << "make ordering: " << std::endl; @@ -2709,7 +2979,7 @@ int Document::recompute(const std::vector &objs, bool forc std::set recomputeList; - for (std::list::reverse_iterator i = make_order.rbegin();i != make_order.rend(); ++i) { + for (std::list::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) { DocumentObject* Cur = d->vertexMap[*i]; // Because of PropertyXLink, we should account for external objects // TODO: make sure it is safe to rely on getNameInDocument() to check if @@ -2717,9 +2987,11 @@ int Document::recompute(const std::vector &objs, bool forc // to properly nullify getNameInDocument(), rather than revert back to // the inefficient isIn() // if (!Cur || !isIn(Cur)) continue; - if (!Cur || !Cur->getNameInDocument()) continue; + if (!Cur || !Cur->getNameInDocument()) { + continue; + } #ifdef FC_LOGFEATUREUPDATE - std::clog << Cur->getNameInDocument() << " dep on:" ; + std::clog << Cur->getNameInDocument() << " dep on:"; #endif bool NeedUpdate = false; @@ -2730,12 +3002,14 @@ int Document::recompute(const std::vector &objs, bool forc #endif NeedUpdate = true; } - else {// if (Cur->mustExecute() == -1) + else { // if (Cur->mustExecute() == -1) // update if one of the dependencies is touched for (boost::tie(j, jend) = out_edges(*i, d->DepList); j != jend; ++j) { DocumentObject* Test = d->vertexMap[target(*j, d->DepList)]; - if (!Test) continue; + if (!Test) { + continue; + } #ifdef FC_LOGFEATUREUPDATE std::clog << " " << Test->getNameInDocument(); #endif @@ -2762,18 +3036,22 @@ int Document::recompute(const std::vector &objs, bool forc #ifdef FC_LOGFEATUREUPDATE std::clog << "Have to recompute the following document objects" << std::endl; - for (std::set::const_iterator it = recomputeList.begin(); it != recomputeList.end(); ++it) { + for (std::set::const_iterator it = recomputeList.begin(); + it != recomputeList.end(); + ++it) { std::clog << " " << (*it)->getNameInDocument() << std::endl; } #endif - for (std::list::reverse_iterator i = make_order.rbegin();i != make_order.rend(); ++i) { + for (std::list::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) { DocumentObject* Cur = d->vertexMap[*i]; - if (!Cur || !isIn(Cur)) continue; + if (!Cur || !isIn(Cur)) { + continue; + } - if (recomputeList.find(Cur) != recomputeList.end() || - Cur->ExpressionEngine.depsAreTouched()) { - if ( _recomputeFeature(Cur)) { + if (recomputeList.find(Cur) != recomputeList.end() + || Cur->ExpressionEngine.depsAreTouched()) { + if (_recomputeFeature(Cur)) { // if something happened break execution of recompute d->vertexMap.clear(); return -1; @@ -2784,11 +3062,14 @@ int Document::recompute(const std::vector &objs, bool forc } // reset all touched - for (std::map::iterator it = d->vertexMap.begin(); it != d->vertexMap.end(); ++it) { + for (std::map::iterator it = d->vertexMap.begin(); + it != d->vertexMap.end(); + ++it) { // TODO: check the TODO comments above for details // if ((it->second) && isIn(it->second)) - if ((it->second) && it->second->getNameInDocument()) + if ((it->second) && it->second->getNameInDocument()) { it->second->purgeTouched(); + } } d->vertexMap.clear(); @@ -2797,20 +3078,26 @@ int Document::recompute(const std::vector &objs, bool forc return objectCount; } -#else //ifdef USE_OLD_DAG +#else // ifdef USE_OLD_DAG -int Document::recompute(const std::vector &objs, bool force, bool *hasError, int options) +int Document::recompute(const std::vector& objs, + bool force, + bool* hasError, + int options) { if (d->undoing || d->rollback) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Ignore document recompute on undo/redo"); + } return 0; } int objectCount = 0; if (testStatus(Document::PartialDoc)) { - if(mustExecute()) - FC_WARN("Please reload partial document '" << Label.getValue() << "' for recomputation."); + if (mustExecute()) { + FC_WARN("Please reload partial document '" << Label.getValue() + << "' for recomputation."); + } return 0; } if (testStatus(Document::Recomputing)) { @@ -2820,8 +3107,8 @@ int Document::recompute(const std::vector &objs, bool forc } // The 'SkipRecompute' flag can be (tmp.) set to avoid too many // time expensive recomputes - if(!force && testStatus(Document::SkipRecompute)) { - signalSkipRecompute(*this,objs); + if (!force && testStatus(Document::SkipRecompute)) { + signalSkipRecompute(*this, objs); return 0; } @@ -2852,96 +3139,106 @@ int Document::recompute(const std::vector &objs, bool forc } std::reverse(topoSortedObjects.begin(),topoSortedObjects.end()); #else - auto topoSortedObjects = getDependencyList(objs.empty()?d->objectArray:objs,DepSort|options); + auto topoSortedObjects = + getDependencyList(objs.empty() ? d->objectArray : objs, DepSort | options); #endif - for(auto obj : topoSortedObjects) - obj->setStatus(ObjectStatus::PendingRecompute,true); + for (auto obj : topoSortedObjects) { + obj->setStatus(ObjectStatus::PendingRecompute, true); + } - ParameterGrp::handle hGrp = GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Document"); - bool canAbort = hGrp->GetBool("CanAbortRecompute",true); + ParameterGrp::handle hGrp = + GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document"); + bool canAbort = hGrp->GetBool("CanAbortRecompute", true); - std::set filter; + std::set filter; size_t idx = 0; FC_TIME_INIT(t2); try { // maximum two passes to allow some form of dependency inversion - for(int passes=0; passes<2 && idx seq; - if(canAbort) { - seq = std::make_unique("Recompute...", topoSortedObjects.size()); + if (canAbort) { + seq = std::make_unique("Recompute...", + topoSortedObjects.size()); } FC_LOG("Recompute pass " << passes); for (; idx < topoSortedObjects.size(); ++idx) { auto obj = topoSortedObjects[idx]; - if(!obj->isAttachedToDocument() || filter.find(obj)!=filter.end()) + if (!obj->isAttachedToDocument() || filter.find(obj) != filter.end()) { continue; + } // ask the object if it should be recomputed bool doRecompute = false; if (obj->mustRecompute()) { doRecompute = true; ++objectCount; int res = _recomputeFeature(obj); - if(res) { - if(hasError) + if (res) { + if (hasError) { *hasError = true; - if(res < 0) { + } + if (res < 0) { passes = 2; break; } // if something happened filter all object in its // inListRecursive from the queue then proceed - obj->getInListEx(filter,true); + obj->getInListEx(filter, true); filter.insert(obj); continue; } } - if(obj->isTouched() || doRecompute) { + if (obj->isTouched() || doRecompute) { signalRecomputedObject(*obj); obj->purgeTouched(); // set all dependent object touched to force recompute - for (auto inObjIt : obj->getInList()) + for (auto inObjIt : obj->getInList()) { inObjIt->enforceRecompute(); + } } - if (seq) + if (seq) { seq->next(true); + } } // check if all objects are recomputed but still thouched - for (size_t i=0;isetStatus(ObjectStatus::Recompute2,false); - if(!filter.count(obj) && obj->isTouched()) { - if(passes>0) + obj->setStatus(ObjectStatus::Recompute2, false); + if (!filter.count(obj) && obj->isTouched()) { + if (passes > 0) { FC_ERR(obj->getFullName() << " still touched after recompute"); - else{ + } + else { FC_LOG(obj->getFullName() << " still touched after recompute"); - if(idx>=topoSortedObjects.size()) { + if (idx >= topoSortedObjects.size()) { // let's start the next pass on the first touched object idx = i; } - obj->setStatus(ObjectStatus::Recompute2,true); + obj->setStatus(ObjectStatus::Recompute2, true); } } } } - }catch(Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); } FC_TIME_LOG(t2, "Recompute"); - for(auto obj : topoSortedObjects) { - if(!obj->isAttachedToDocument()) + for (auto obj : topoSortedObjects) { + if (!obj->isAttachedToDocument()) { continue; - obj->setStatus(ObjectStatus::PendingRecompute,false); - obj->setStatus(ObjectStatus::Recompute2,false); + } + obj->setStatus(ObjectStatus::PendingRecompute, false); + obj->setStatus(ObjectStatus::Recompute2, false); } - signalRecomputed(*this,topoSortedObjects); + signalRecomputed(*this, topoSortedObjects); - FC_TIME_LOG(t,"Recompute total"); + FC_TIME_LOG(t, "Recompute total"); if (!d->_RecomputeLog.empty()) { if (!testStatus(Status::IgnoreErrorOnRecompute)) { @@ -2959,21 +3256,23 @@ int Document::recompute(const std::vector &objs, bool forc for (auto doc : GetApplication().getDocuments()) { decltype(doc->d->pendingRemove) objs; objs.swap(doc->d->pendingRemove); - for(auto &o : objs) { + for (auto& o : objs) { try { if (auto obj = o.getObject()) { obj->getDocument()->removeObject(obj->getNameInDocument()); } - } catch (Base::Exception & e) { + } + catch (Base::Exception& e) { e.ReportException(); - FC_ERR("error when removing object " << o.getDocumentName() << '#' << o.getObjectName()); + FC_ERR("error when removing object " << o.getDocumentName() << '#' + << o.getObjectName()); } } } return objectCount; } -#endif // USE_OLD_DAG +#endif // USE_OLD_DAG /*! Does almost the same as topologicalSort() until no object with an input degree of zero @@ -2983,21 +3282,21 @@ int Document::recompute(const std::vector &objs, bool forc An alternative to this method might be: https://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm */ -std::vector DocumentP::partialTopologicalSort( - const std::vector& objects) +std::vector +DocumentP::partialTopologicalSort(const std::vector& objects) { - vector < App::DocumentObject* > ret; + vector ret; ret.reserve(objects.size()); // pairs of input and output degree - map < App::DocumentObject*, std::pair > countMap; + map> countMap; for (auto objectIt : objects) { - //we need inlist with unique entries + // we need inlist with unique entries auto in = objectIt->getInList(); std::sort(in.begin(), in.end()); in.erase(std::unique(in.begin(), in.end()), in.end()); - //we need outlist with unique entries + // we need outlist with unique entries auto out = objectIt->getOutList(); std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); @@ -3013,25 +3312,27 @@ std::vector DocumentP::partialTopologicalSort( removeVertex = false; // try input degree - auto degInIt = find_if(countMap.begin(), countMap.end(), - [](pair< App::DocumentObject*, pair > vertex)->bool { - return vertex.second.first == 0; - }); + auto degInIt = find_if(countMap.begin(), + countMap.end(), + [](pair> vertex) -> bool { + return vertex.second.first == 0; + }); if (degInIt != countMap.end()) { removeVertex = true; degIn.push_back(degInIt->first); degInIt->second.first = degInIt->second.first - 1; - //we need outlist with unique entries + // we need outlist with unique entries auto out = degInIt->first->getOutList(); std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); for (auto outListIt : out) { auto outListMapIt = countMap.find(outListIt); - if (outListMapIt != countMap.end()) + if (outListMapIt != countMap.end()) { outListMapIt->second.first = outListMapIt->second.first - 1; + } } } } @@ -3048,25 +3349,27 @@ std::vector DocumentP::partialTopologicalSort( while (removeVertex) { removeVertex = false; - auto degOutIt = find_if(countMap.begin(), countMap.end(), - [](pair< App::DocumentObject*, pair > vertex)->bool { - return vertex.second.second == 0; - }); + auto degOutIt = find_if(countMap.begin(), + countMap.end(), + [](pair> vertex) -> bool { + return vertex.second.second == 0; + }); if (degOutIt != countMap.end()) { removeVertex = true; degOut.push_front(degOutIt->first); degOutIt->second.second = degOutIt->second.second - 1; - //we need inlist with unique entries + // we need inlist with unique entries auto in = degOutIt->first->getInList(); std::sort(in.begin(), in.end()); in.erase(std::unique(in.begin(), in.end()), in.end()); for (auto inListIt : in) { auto inListMapIt = countMap.find(inListIt); - if (inListMapIt != countMap.end()) + if (inListMapIt != countMap.end()) { inListMapIt->second.second = inListMapIt->second.second - 1; + } } } } @@ -3084,20 +3387,22 @@ std::vector DocumentP::partialTopologicalSort( return ret; } -std::vector DocumentP::topologicalSort(const std::vector& objects) const +std::vector +DocumentP::topologicalSort(const std::vector& objects) const { // topological sort algorithm described here: // https://de.wikipedia.org/wiki/Topologische_Sortierung#Algorithmus_f.C3.BCr_das_Topologische_Sortieren - vector < App::DocumentObject* > ret; + vector ret; ret.reserve(objects.size()); - map < App::DocumentObject*,int > countMap; + map countMap; for (auto objectIt : objects) { // We now support externally linked objects // if(!obj->isAttachedToDocument() || obj->getDocument()!=this) - if(!objectIt->isAttachedToDocument()) + if (!objectIt->isAttachedToDocument()) { continue; - //we need inlist with unique entries + } + // we need inlist with unique entries auto in = objectIt->getInList(); std::sort(in.begin(), in.end()); in.erase(std::unique(in.begin(), in.end()), in.end()); @@ -3105,33 +3410,38 @@ std::vector DocumentP::topologicalSort(const std::vector count)->bool { - return count.second == 0; - }); + auto rootObjeIt = find_if(countMap.begin(), + countMap.end(), + [](pair count) -> bool { + return count.second == 0; + }); - if (rootObjeIt == countMap.end()){ + if (rootObjeIt == countMap.end()) { cerr << "Document::topologicalSort: cyclic dependency detected (no root object)" << endl; return ret; } - while (rootObjeIt != countMap.end()){ + while (rootObjeIt != countMap.end()) { rootObjeIt->second = rootObjeIt->second - 1; - //we need outlist with unique entries + // we need outlist with unique entries auto out = rootObjeIt->first->getOutList(); std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); for (auto outListIt : out) { auto outListMapIt = countMap.find(outListIt); - if (outListMapIt != countMap.end()) + if (outListMapIt != countMap.end()) { outListMapIt->second = outListMapIt->second - 1; + } } ret.push_back(rootObjeIt->first); - rootObjeIt = find_if(countMap.begin(), countMap.end(), [](pair < App::DocumentObject*, int > count)->bool { - return count.second == 0; - }); + rootObjeIt = find_if(countMap.begin(), + countMap.end(), + [](pair count) -> bool { + return count.second == 0; + }); } return ret; @@ -3142,7 +3452,7 @@ std::vector Document::topologicalSort() const return d->topologicalSort(d->objectArray); } -const char * Document::getErrorDescription(const App::DocumentObject*Obj) const +const char* Document::getErrorDescription(const App::DocumentObject* Obj) const { return d->findRecomputeLog(Obj); } @@ -3152,41 +3462,43 @@ int Document::_recomputeFeature(DocumentObject* Feat) { FC_LOG("Recomputing " << Feat->getFullName()); - DocumentObjectExecReturn *returnCode = nullptr; + DocumentObjectExecReturn* returnCode = nullptr; try { returnCode = Feat->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteNonOutput); if (returnCode == DocumentObject::StdReturn) { returnCode = Feat->recompute(); - if(returnCode == DocumentObject::StdReturn) - returnCode = Feat->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteOutput); + if (returnCode == DocumentObject::StdReturn) { + returnCode = + Feat->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteOutput); + } } } - catch(Base::AbortException &e){ + catch (Base::AbortException& e) { e.ReportException(); FC_LOG("Failed to recompute " << Feat->getFullName() << ": " << e.what()); - d->addRecomputeLog("User abort",Feat); + d->addRecomputeLog("User abort", Feat); return -1; } catch (const Base::MemoryException& e) { FC_ERR("Memory exception in " << Feat->getFullName() << " thrown: " << e.what()); - d->addRecomputeLog("Out of memory exception",Feat); + d->addRecomputeLog("Out of memory exception", Feat); return 1; } - catch (Base::Exception &e) { + catch (Base::Exception& e) { e.ReportException(); FC_LOG("Failed to recompute " << Feat->getFullName() << ": " << e.what()); - d->addRecomputeLog(e.what(),Feat); + d->addRecomputeLog(e.what(), Feat); return 1; } - catch (std::exception &e) { + catch (std::exception& e) { FC_ERR("exception in " << Feat->getFullName() << " thrown: " << e.what()); - d->addRecomputeLog(e.what(),Feat); + d->addRecomputeLog(e.what(), Feat); return 1; } #ifndef FC_DEBUG catch (...) { FC_ERR("Unknown exception in " << Feat->getFullName() << " thrown"); - d->addRecomputeLog("Unknown exception!",Feat); + d->addRecomputeLog("Unknown exception!", Feat); return 1; } #endif @@ -3210,23 +3522,30 @@ bool Document::recomputeFeature(DocumentObject* Feat, bool recursive) // verify that the feature is (active) part of the document if (Feat->isAttachedToDocument()) { - if(recursive) { + if (recursive) { bool hasError = false; - recompute({Feat},true,&hasError); + recompute({Feat}, true, &hasError); return !hasError; - } else { + } + else { _recomputeFeature(Feat); signalRecomputedObject(*Feat); return Feat->isValid(); } - }else + } + else { return false; + } } -DocumentObject * Document::addObject(const char* sType, const char* pObjectName, - bool isNew, const char* viewType, bool isPartial) +DocumentObject* Document::addObject(const char* sType, + const char* pObjectName, + bool isNew, + const char* viewType, + bool isPartial) { - Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + Base::Type type = + Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; @@ -3234,8 +3553,9 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, } void* typeInstance = type.createInstance(); - if (!typeInstance) + if (!typeInstance) { return nullptr; + } App::DocumentObject* pcObject = static_cast(typeInstance); @@ -3244,18 +3564,21 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); - if (d->activeUndoTransaction) + _checkTransaction(nullptr, nullptr, __LINE__); + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); + } } // get Unique name string ObjectName; - if (pObjectName && pObjectName[0] != '\0') + if (pObjectName && pObjectName[0] != '\0') { ObjectName = getUniqueObjectName(pObjectName); - else + } + else { ObjectName = getUniqueObjectName(sType); + } d->activeObject = pcObject; @@ -3265,19 +3588,21 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, // generate object id and add to id map; pcObject->_Id = ++d->lastObjectId; d->objectIdMap[pcObject->_Id] = pcObject; - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector d->objectArray.push_back(pcObject); - // If we are restoring, don't set the Label object now; it will be restored later. This is to avoid potential duplicate - // label conflicts later. - if (!d->StatusBits.test(Restoring)) - pcObject->Label.setValue( ObjectName ); + // If we are restoring, don't set the Label object now; it will be restored later. This is to + // avoid potential duplicate label conflicts later. + if (!d->StatusBits.test(Restoring)) { + pcObject->Label.setValue(ObjectName); + } // Call the object-specific initialization if (!d->undoing && !d->rollback && isNew) { - pcObject->setupObject (); + pcObject->setupObject(); } // mark the object as new (i.e. set status bit 2) and send the signal @@ -3285,11 +3610,13 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, pcObject->setStatus(ObjectStatus::PartialObject, isPartial); - if (!viewType || viewType[0] == '\0') + if (!viewType || viewType[0] == '\0') { viewType = pcObject->getViewProviderNameOverride(); + } - if (viewType && viewType[0] != '\0') + if (viewType && viewType[0] != '\0') { pcObject->_pcViewProviderName = viewType; + } signalNewObject(*pcObject); @@ -3304,19 +3631,22 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, return pcObject; } -std::vector Document::addObjects(const char* sType, const std::vector& objectNames, bool isNew) +std::vector +Document::addObjects(const char* sType, const std::vector& objectNames, bool isNew) { - Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + Base::Type type = + Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; throw Base::TypeError(str.str()); } - std::vector objects; + std::vector objects; objects.resize(objectNames.size()); - std::generate(objects.begin(), objects.end(), - [&]{ return static_cast(type.createInstance()); }); + std::generate(objects.begin(), objects.end(), [&] { + return static_cast(type.createInstance()); + }); // the type instance could be a null pointer, it is enough to check the first element if (!objects.empty() && !objects[0]) { objects.clear(); @@ -3326,7 +3656,7 @@ std::vector Document::addObjects(const char* sType, const std: // get all existing object names std::vector reservedNames; reservedNames.reserve(d->objectMap.size()); - for (const auto & pos : d->objectMap) { + for (const auto& pos : d->objectMap) { reservedNames.push_back(pos.first); } @@ -3338,7 +3668,7 @@ std::vector Document::addObjects(const char* sType, const std: // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); + _checkTransaction(nullptr, nullptr, __LINE__); if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); } @@ -3346,16 +3676,17 @@ std::vector Document::addObjects(const char* sType, const std: // get unique name std::string ObjectName = objectNames[index]; - if (ObjectName.empty()) + if (ObjectName.empty()) { ObjectName = sType; + } ObjectName = Base::Tools::getIdentifier(ObjectName); if (d->objectMap.find(ObjectName) != d->objectMap.end()) { // remove also trailing digits from clean name which is to avoid to create lengthy names // like 'Box001001' if (!testStatus(KeepTrailingDigits)) { std::string::size_type index = ObjectName.find_last_not_of("0123456789"); - if (index+1 < ObjectName.size()) { - ObjectName = ObjectName.substr(0,index+1); + if (index + 1 < ObjectName.size()) { + ObjectName = ObjectName.substr(0, index + 1); } } @@ -3369,7 +3700,8 @@ std::vector Document::addObjects(const char* sType, const std: // generate object id and add to id map; pcObject->_Id = ++d->lastObjectId; d->objectIdMap[pcObject->_Id] = pcObject; - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector d->objectArray.push_back(pcObject); @@ -3384,7 +3716,7 @@ std::vector Document::addObjects(const char* sType, const std: // mark the object as new (i.e. set status bit 2) and send the signal pcObject->setStatus(ObjectStatus::New, true); - const char *viewType = pcObject->getViewProviderNameOverride(); + const char* viewType = pcObject->getViewProviderNameOverride(); pcObject->_pcViewProviderName = viewType ? viewType : ""; signalNewObject(*pcObject); @@ -3414,36 +3746,42 @@ void Document::addObject(DocumentObject* pcObject, const char* pObjectName) // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); - if (d->activeUndoTransaction) + _checkTransaction(nullptr, nullptr, __LINE__); + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); + } } // get unique name string ObjectName; - if (pObjectName && pObjectName[0] != '\0') + if (pObjectName && pObjectName[0] != '\0') { ObjectName = getUniqueObjectName(pObjectName); - else + } + else { ObjectName = getUniqueObjectName(pcObject->getTypeId().getName()); + } d->activeObject = pcObject; // insert in the name map d->objectMap[ObjectName] = pcObject; // generate object id and add to id map; - if(!pcObject->_Id) pcObject->_Id = ++d->lastObjectId; + if (!pcObject->_Id) { + pcObject->_Id = ++d->lastObjectId; + } d->objectIdMap[pcObject->_Id] = pcObject; - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector d->objectArray.push_back(pcObject); - pcObject->Label.setValue( ObjectName ); + pcObject->Label.setValue(ObjectName); // mark the object as new (i.e. set status bit 2) and send the signal pcObject->setStatus(ObjectStatus::New, true); - const char *viewType = pcObject->getViewProviderNameOverride(); + const char* viewType = pcObject->getViewProviderNameOverride(); pcObject->_pcViewProviderName = viewType ? viewType : ""; signalNewObject(*pcObject); @@ -3461,21 +3799,25 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName) std::string ObjectName = getUniqueObjectName(pObjectName); d->objectMap[ObjectName] = pcObject; // generate object id and add to id map; - if(!pcObject->_Id) pcObject->_Id = ++d->lastObjectId; + if (!pcObject->_Id) { + pcObject->_Id = ++d->lastObjectId; + } d->objectIdMap[pcObject->_Id] = pcObject; d->objectArray.push_back(pcObject); - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); - if (d->activeUndoTransaction) + _checkTransaction(nullptr, nullptr, __LINE__); + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); + } } - const char *viewType = pcObject->getViewProviderNameOverride(); + const char* viewType = pcObject->getViewProviderNameOverride(); pcObject->_pcViewProviderName = viewType ? viewType : ""; // send the signal @@ -3496,8 +3838,9 @@ void Document::removeObject(const char* sName) auto pos = d->objectMap.find(sName); // name not found? - if (pos == d->objectMap.end()) + if (pos == d->objectMap.end()) { return; + } if (pos->second->testStatus(ObjectStatus::PendingRecompute)) { // TODO: shall we allow removal if there is active undo transaction? @@ -3508,10 +3851,11 @@ void Document::removeObject(const char* sName) TransactionLocker tlock; - _checkTransaction(pos->second,nullptr,__LINE__); + _checkTransaction(pos->second, nullptr, __LINE__); - if (d->activeObject == pos->second) + if (d->activeObject == pos->second) { d->activeObject = nullptr; + } // Mark the object as about to be deleted pos->second->setStatus(ObjectStatus::Remove, true); @@ -3534,20 +3878,22 @@ void Document::removeObject(const char* sName) #ifdef USE_OLD_DAG if (!d->vertexMap.empty()) { // recompute of document is running - for (std::map::iterator it = d->vertexMap.begin(); it != d->vertexMap.end(); ++it) { + for (std::map::iterator it = d->vertexMap.begin(); + it != d->vertexMap.end(); + ++it) { if (it->second == pos->second) { - it->second = 0; // just nullify the pointer + it->second = 0; // just nullify the pointer break; } } } -#endif //USE_OLD_DAG +#endif // USE_OLD_DAG // Before deleting we must nullify all dependent objects breakDependency(pos->second, true); - //and remove the tip if needed - if (Tip.getValue() && strcmp(Tip.getValue()->getNameInDocument(), sName)==0) { + // and remove the tip if needed + if (Tip.getValue() && strcmp(Tip.getValue()->getNameInDocument(), sName) == 0) { Tip.setValue(nullptr); TipName.setValue(""); } @@ -3573,7 +3919,9 @@ void Document::removeObject(const char* sName) } } - for (std::vector::iterator obj = d->objectArray.begin(); obj != d->objectArray.end(); ++obj) { + for (std::vector::iterator obj = d->objectArray.begin(); + obj != d->objectArray.end(); + ++obj) { if (*obj == pos->second) { d->objectArray.erase(obj); break; @@ -3598,26 +3946,30 @@ void Document::_removeObject(DocumentObject* pcObject) TransactionLocker tlock; // TODO Refactoring: share code with Document::removeObject() (2015-09-01, Fat-Zer) - _checkTransaction(pcObject,nullptr,__LINE__); + _checkTransaction(pcObject, nullptr, __LINE__); auto pos = d->objectMap.find(pcObject->getNameInDocument()); - if(!d->rollback && d->activeUndoTransaction && pos->second->hasChildElement()) { + if (!d->rollback && d->activeUndoTransaction && pos->second->hasChildElement()) { // Preserve link group children global visibility. See comments in // removeObject() for more details. - for(auto &sub : pos->second->getSubObjects()) { - if(sub.empty()) + for (auto& sub : pos->second->getSubObjects()) { + if (sub.empty()) { continue; - if(sub[sub.size()-1]!='.') + } + if (sub[sub.size() - 1] != '.') { sub += '.'; + } auto sobj = pos->second->getSubObject(sub.c_str()); - if(sobj && sobj->getDocument()==this && !sobj->Visibility.getValue()) - d->activeUndoTransaction->addObjectChange(sobj,&sobj->Visibility); + if (sobj && sobj->getDocument() == this && !sobj->Visibility.getValue()) { + d->activeUndoTransaction->addObjectChange(sobj, &sobj->Visibility); + } } } - if (d->activeObject == pcObject) + if (d->activeObject == pcObject) { d->activeObject = nullptr; + } // Mark the object as about to be removed pcObject->setStatus(ObjectStatus::Remove, true); @@ -3627,7 +3979,7 @@ void Document::_removeObject(DocumentObject* pcObject) signalDeletedObject(*pcObject); // TODO Check me if it's needed (2015-09-01, Fat-Zer) - //remove the tip if needed + // remove the tip if needed if (Tip.getValue() == pcObject) { Tip.setValue(nullptr); TipName.setValue(""); @@ -3647,11 +3999,13 @@ void Document::_removeObject(DocumentObject* pcObject) breakDependency(pcObject, true); // remove from map - pcObject->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side + pcObject->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side d->objectIdMap.erase(pcObject->_Id); d->objectMap.erase(pos); - for (std::vector::iterator it = d->objectArray.begin(); it != d->objectArray.end(); ++it) { + for (std::vector::iterator it = d->objectArray.begin(); + it != d->objectArray.end(); + ++it) { if (*it == pcObject) { d->objectArray.erase(it); break; @@ -3668,33 +4022,36 @@ void Document::_removeObject(DocumentObject* pcObject) void Document::breakDependency(DocumentObject* pcObject, bool clear) { // Nullify all dependent objects - PropertyLinkBase::breakLinks(pcObject,d->objectArray,clear); + PropertyLinkBase::breakLinks(pcObject, d->objectArray, clear); } -std::vector Document::copyObject( - const std::vector &objs, bool recursive, bool returnAll) +std::vector +Document::copyObject(const std::vector& objs, bool recursive, bool returnAll) { std::vector deps; - if(!recursive) + if (!recursive) { deps = objs; - else - deps = getDependencyList(objs,DepNoXLinked|DepSort); + } + else { + deps = getDependencyList(objs, DepNoXLinked | DepSort); + } if (!testStatus(TempDoc) && !isSaved() && PropertyXLink::hasXLink(deps)) { throw Base::RuntimeError( - "Document must be saved at least once before link to external objects"); + "Document must be saved at least once before link to external objects"); } MergeDocuments md(this); // if not copying recursively then suppress possible warnings md.setVerbose(recursive); - unsigned int memsize=1000; // ~ for the meta-information - for (auto it : deps) + unsigned int memsize = 1000; // ~ for the meta-information + for (auto it : deps) { memsize += it->getMemSize(); + } // if less than ~10 MB - bool use_buffer=(memsize < 0xA00000); + bool use_buffer = (memsize < 0xA00000); QByteArray res; try { res.reserve(memsize); @@ -3713,7 +4070,8 @@ std::vector Document::copyObject( std::istream istr(nullptr); istr.rdbuf(&ibuf); imported = md.importObjects(istr); - } else { + } + else { static Base::FileInfo fi(App::Application::getTempFileName()); Base::ofstream ostr(fi, std::ios::out | std::ios::binary); exportObjects(deps, ostr); @@ -3723,42 +4081,45 @@ std::vector Document::copyObject( imported = md.importObjects(istr); } - if (returnAll || imported.size()!=deps.size()) + if (returnAll || imported.size() != deps.size()) { return imported; + } - std::unordered_map indices; - size_t i=0; - for(auto o : deps) + std::unordered_map indices; + size_t i = 0; + for (auto o : deps) { indices[o] = i++; + } std::vector result; result.reserve(objs.size()); - for(auto o : objs) + for (auto o : objs) { result.push_back(imported[indices[o]]); + } return result; } std::vector -Document::importLinks(const std::vector &objArray) +Document::importLinks(const std::vector& objArray) { std::set links; - getLinksTo(links,nullptr,GetLinkExternal,0,objArray); + getLinksTo(links, nullptr, GetLinkExternal, 0, objArray); std::vector objs; - objs.insert(objs.end(),links.begin(),links.end()); + objs.insert(objs.end(), links.begin(), links.end()); objs = App::Document::getDependencyList(objs); - if(objs.empty()) { + if (objs.empty()) { FC_ERR("nothing to import"); return objs; } - for(auto it=objs.begin();it!=objs.end();) { + for (auto it = objs.begin(); it != objs.end();) { auto obj = *it; - if(obj->getDocument() == this) { + if (obj->getDocument() == this) { it = objs.erase(it); continue; } ++it; - if(obj->testStatus(App::PartialObject)) { + if (obj->testStatus(App::PartialObject)) { throw Base::RuntimeError( "Cannot import partial loaded object. Please reload the current document"); } @@ -3778,20 +4139,21 @@ Document::importLinks(const std::vector &objArray) str.close(); fi.deleteFile(); - const auto &nameMap = mimeView.getNameMap(); + const auto& nameMap = mimeView.getNameMap(); // First, find all link type properties that needs to be changed - std::map > propMap; + std::map> propMap; std::vector propList; - for(auto obj : links) { + for (auto obj : links) { propList.clear(); obj->getPropertyList(propList); - for(auto prop : propList) { + for (auto prop : propList) { auto linkProp = Base::freecad_dynamic_cast(prop); - if(linkProp && !prop->testStatus(Property::Immutable) && !obj->isReadOnly(prop)) { + if (linkProp && !prop->testStatus(Property::Immutable) && !obj->isReadOnly(prop)) { auto copy = linkProp->CopyOnImportExternal(nameMap); - if(copy) + if (copy) { propMap[linkProp].reset(copy); + } } } } @@ -3801,23 +4163,26 @@ Document::importLinks(const std::vector &objArray) // properties, e.g. a link sub referring to some sub object of an xlink, If // that sub object is imported with a different name, and xlink is changed // before this link sub, it will break. - for(auto &v : propMap) + for (auto& v : propMap) { v.first->Paste(*v.second); + } return objs; } DocumentObject* Document::moveObject(DocumentObject* obj, bool recursive) { - if(!obj) + if (!obj) { return nullptr; + } Document* that = obj->getDocument(); - if (that == this) - return nullptr; // nothing todo + if (that == this) { + return nullptr; // nothing todo + } // True object move without copy is only safe when undo is off on both // documents. - if(!recursive && !d->iUndoMode && !that->d->iUndoMode && !that->d->rollback) { + if (!recursive && !d->iUndoMode && !that->d->iUndoMode && !that->d->rollback) { // all object of the other document that refer to this object must be nullified that->breakDependency(obj, false); std::string objname = getUniqueObjectName(obj->getNameInDocument()); @@ -3828,83 +4193,95 @@ DocumentObject* Document::moveObject(DocumentObject* obj, bool recursive) } std::vector deps; - if(recursive) - deps = getDependencyList({obj},DepNoXLinked|DepSort); - else + if (recursive) { + deps = getDependencyList({obj}, DepNoXLinked | DepSort); + } + else { deps.push_back(obj); + } - auto objs = copyObject(deps,false); - if(objs.empty()) + auto objs = copyObject(deps, false); + if (objs.empty()) { return nullptr; + } // Some object may delete its children if deleted, so we collect the IDs // or all depending objects for safety reason. std::vector ids; ids.reserve(deps.size()); - for(auto o : deps) + for (auto o : deps) { ids.push_back(o->getID()); + } // We only remove object if it is the moving object or it has no // depending objects, i.e. an empty inList, which is why we need to // iterate the depending list backwards. - for(auto iter=ids.rbegin();iter!=ids.rend();++iter) { + for (auto iter = ids.rbegin(); iter != ids.rend(); ++iter) { auto o = that->getObjectByID(*iter); - if(!o) continue; - if(iter==ids.rbegin() - || o->getInList().empty()) + if (!o) { + continue; + } + if (iter == ids.rbegin() || o->getInList().empty()) { that->removeObject(o->getNameInDocument()); + } } return objs.back(); } -DocumentObject * Document::getActiveObject() const +DocumentObject* Document::getActiveObject() const { return d->activeObject; } -DocumentObject * Document::getObject(const char *Name) const +DocumentObject* Document::getObject(const char* Name) const { auto pos = d->objectMap.find(Name); - if (pos != d->objectMap.end()) + if (pos != d->objectMap.end()) { return pos->second; - else + } + else { return nullptr; + } } -DocumentObject * Document::getObjectByID(long id) const +DocumentObject* Document::getObjectByID(long id) const { auto it = d->objectIdMap.find(id); - if(it!=d->objectIdMap.end()) + if (it != d->objectIdMap.end()) { return it->second; + } return nullptr; } // Note: This method is only used in Tree.cpp slotChangeObject(), see explanation there -bool Document::isIn(const DocumentObject *pFeat) const +bool Document::isIn(const DocumentObject* pFeat) const { - for (const auto & pos : d->objectMap) { - if (pos.second == pFeat) + for (const auto& pos : d->objectMap) { + if (pos.second == pFeat) { return true; + } } return false; } -const char * Document::getObjectName(DocumentObject *pFeat) const +const char* Document::getObjectName(DocumentObject* pFeat) const { - for (const auto & pos : d->objectMap) { - if (pos.second == pFeat) + for (const auto& pos : d->objectMap) { + if (pos.second == pFeat) { return pos.first.c_str(); + } } return nullptr; } -std::string Document::getUniqueObjectName(const char *Name) const +std::string Document::getUniqueObjectName(const char* Name) const { - if (!Name || *Name == '\0') + if (!Name || *Name == '\0') { return {}; + } std::string CleanName = Base::Tools::getIdentifier(Name); // name in use? @@ -3919,21 +4296,21 @@ std::string Document::getUniqueObjectName(const char *Name) const // like 'Box001001' if (!testStatus(KeepTrailingDigits)) { std::string::size_type index = CleanName.find_last_not_of("0123456789"); - if (index+1 < CleanName.size()) { - CleanName = CleanName.substr(0,index+1); + if (index + 1 < CleanName.size()) { + CleanName = CleanName.substr(0, index + 1); } } std::vector names; names.reserve(d->objectMap.size()); - for (pos = d->objectMap.begin();pos != d->objectMap.end();++pos) { + for (pos = d->objectMap.begin(); pos != d->objectMap.end(); ++pos) { names.push_back(pos->first); } return Base::Tools::getUniqueName(CleanName, names, 3); } } -std::string Document::getStandardObjectName(const char *Name, int d) const +std::string Document::getStandardObjectName(const char* Name, int d) const { std::vector mm = getObjects(); std::vector labels; @@ -3951,7 +4328,7 @@ std::vector Document::getDependingObjects() const return getDependencyList(d->objectArray); } -const std::vector &Document::getObjects() const +const std::vector& Document::getObjects() const { return d->objectArray; } @@ -3961,33 +4338,40 @@ std::vector Document::getObjectsOfType(const Base::Type& typeId { std::vector Objects; for (auto it : d->objectArray) { - if (it->getTypeId().isDerivedFrom(typeId)) + if (it->getTypeId().isDerivedFrom(typeId)) { Objects.push_back(it); + } } return Objects; } -std::vector< DocumentObject* > Document::getObjectsWithExtension(const Base::Type& typeId, bool derived) const { +std::vector Document::getObjectsWithExtension(const Base::Type& typeId, + bool derived) const +{ std::vector Objects; for (auto it : d->objectArray) { - if (it->hasExtension(typeId, derived)) + if (it->hasExtension(typeId, derived)) { Objects.push_back(it); + } } return Objects; } -std::vector Document::findObjects(const Base::Type& typeId, const char* objname, const char* label) const +std::vector +Document::findObjects(const Base::Type& typeId, const char* objname, const char* label) const { boost::cmatch what; boost::regex rx_name, rx_label; - if (objname) + if (objname) { rx_name.set_expression(objname); + } - if (label) + if (label) { rx_label.set_expression(label); + } std::vector Objects; DocumentObject* found = nullptr; @@ -3995,14 +4379,17 @@ std::vector Document::findObjects(const Base::Type& typeId, con if (it->getTypeId().isDerivedFrom(typeId)) { found = it; - if (!rx_name.empty() && !boost::regex_search(it->getNameInDocument(), what, rx_name)) + if (!rx_name.empty() && !boost::regex_search(it->getNameInDocument(), what, rx_name)) { found = nullptr; + } - if (!rx_label.empty() && !boost::regex_search(it->Label.getValue(), what, rx_label)) + if (!rx_label.empty() && !boost::regex_search(it->Label.getValue(), what, rx_label)) { found = nullptr; + } - if (found) + if (found) { Objects.push_back(found); + } } } return Objects; @@ -4010,27 +4397,29 @@ std::vector Document::findObjects(const Base::Type& typeId, con int Document::countObjectsOfType(const Base::Type& typeId) const { - int ct=0; - for (const auto & it : d->objectMap) { - if (it.second->getTypeId().isDerivedFrom(typeId)) + int ct = 0; + for (const auto& it : d->objectMap) { + if (it.second->getTypeId().isDerivedFrom(typeId)) { ct++; + } } return ct; } -PyObject * Document::getPyObject() +PyObject* Document::getPyObject() { return Py::new_reference_to(d->DocumentPythonObject); } std::vector Document::getRootObjects() const { - std::vector < App::DocumentObject* > ret; + std::vector ret; for (auto objectIt : d->objectArray) { - if (objectIt->getInList().empty()) + if (objectIt->getInList().empty()) { ret.push_back(objectIt); + } } return ret; @@ -4046,9 +4435,9 @@ std::vector Document::getRootObjectsIgnoreLinks() const if (!noParents) { // App::Document getRootObjects returns the root objects of the dependency graph. - // So if an object is referenced by a App::Link, it will not be returned by that function. - // So here, as we want the tree-root level objects, - // we check if all the parents are links. In which case its still a root object. + // So if an object is referenced by a App::Link, it will not be returned by that + // function. So here, as we want the tree-root level objects, we check if all the + // parents are links. In which case its still a root object. noParents = std::all_of(list.cbegin(), list.cend(), [](App::DocumentObject* obj) { return obj->isDerivedFrom(); }); @@ -4062,14 +4451,16 @@ std::vector Document::getRootObjectsIgnoreLinks() const return ret; } -void DocumentP::findAllPathsAt(const std::vector &all_nodes, size_t id, - std::vector &all_paths, Path tmp) +void DocumentP::findAllPathsAt(const std::vector& all_nodes, + size_t id, + std::vector& all_paths, + Path tmp) { if (std::find(tmp.begin(), tmp.end(), id) != tmp.end()) { Path tmp2(tmp); tmp2.push_back(id); all_paths.push_back(tmp2); - return; // a cycle + return; // a cycle } tmp.push_back(id); @@ -4078,22 +4469,22 @@ void DocumentP::findAllPathsAt(const std::vector &all_nodes, size_t id, return; } - for (size_t i=0; i < all_nodes[id].size(); i++) { + for (size_t i = 0; i < all_nodes[id].size(); i++) { Path tmp2(tmp); findAllPathsAt(all_nodes, all_nodes[id][i], all_paths, tmp2); } } -std::vector > +std::vector> Document::getPathsByOutList(const App::DocumentObject* from, const App::DocumentObject* to) const { std::map indexMap; - for (size_t i=0; iobjectArray.size(); ++i) { + for (size_t i = 0; i < d->objectArray.size(); ++i) { indexMap[d->objectArray[i]] = i; } - std::vector all_nodes(d->objectArray.size()); - for (size_t i=0; iobjectArray.size(); ++i) { + std::vector all_nodes(d->objectArray.size()); + for (size_t i = 0; i < d->objectArray.size(); ++i) { DocumentObject* obj = d->objectArray[i]; std::vector outList = obj->getOutList(); for (auto it : outList) { @@ -4101,9 +4492,10 @@ Document::getPathsByOutList(const App::DocumentObject* from, const App::Document } } - std::vector > array; - if (from == to) + std::vector> array; + if (from == to) { return array; + } size_t index_from = indexMap[from]; size_t index_to = indexMap[to]; @@ -4133,15 +4525,16 @@ Document::getPathsByOutList(const App::DocumentObject* from, const App::Document bool Document::mustExecute() const { - if(PropertyXLink::hasXLink(this)) { + if (PropertyXLink::hasXLink(this)) { bool touched = false; - _buildDependencyList(d->objectArray,false,nullptr,nullptr,nullptr,&touched); + _buildDependencyList(d->objectArray, false, nullptr, nullptr, nullptr, &touched); return touched; } for (auto It : d->objectArray) { - if (It->isTouched() || It->mustExecute()==1) + if (It->isTouched() || It->mustExecute() == 1) { return true; + } } return false; } diff --git a/src/App/Document.h b/src/App/Document.h index c49434ff7b..36a878ee10 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -37,33 +37,32 @@ #include #include -namespace Base { - class Writer; -} - -namespace App -{ - class TransactionalObject; - class DocumentObject; - class DocumentObjectExecReturn; - class Document; - class DocumentPy; // the python document class - class Application; - class Transaction; - class StringHasher; - using StringHasherRef = Base::Reference; +namespace Base +{ +class Writer; } namespace App { +class TransactionalObject; +class DocumentObject; +class DocumentObjectExecReturn; +class Document; +class DocumentPy; +class Application; +class Transaction; +class StringHasher; +using StringHasherRef = Base::Reference; /// 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 signalBeforeChange; + boost::signals2::signal signalBeforeChange; /// signal on changed doc property - boost::signals2::signal signalChanged; + boost::signals2::signal signalChanged; /// signal on new Object - boost::signals2::signal signalNewObject; - //boost::signals2::signal m_sig; + boost::signals2::signal signalNewObject; /// signal on deleted Object - boost::signals2::signal signalDeletedObject; + boost::signals2::signal signalDeletedObject; /// signal before changing an Object - boost::signals2::signal signalBeforeChangeObject; + boost::signals2::signal signalBeforeChangeObject; /// signal on changed Object - boost::signals2::signal signalChangedObject; + boost::signals2::signal signalChangedObject; /// signal on manually called DocumentObject::touch() - boost::signals2::signal signalTouchedObject; + boost::signals2::signal signalTouchedObject; /// signal on relabeled Object - boost::signals2::signal signalRelabelObject; + boost::signals2::signal signalRelabelObject; /// signal on activated Object - boost::signals2::signal signalActivatedObject; + boost::signals2::signal signalActivatedObject; /// signal on created object - boost::signals2::signal signalTransactionAppend; + boost::signals2::signal signalTransactionAppend; /// signal on removed object - boost::signals2::signal signalTransactionRemove; + boost::signals2::signal signalTransactionRemove; /// signal on undo - boost::signals2::signal signalUndo; + boost::signals2::signal signalUndo; /// signal on redo - boost::signals2::signal signalRedo; + boost::signals2::signal 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 signalSaveDocument; - boost::signals2::signal signalRestoreDocument; - boost::signals2::signal&, - Base::Writer &)> signalExportObjects; - boost::signals2::signal&, - Base::Writer &)> signalExportViewObjects; - boost::signals2::signal&, - Base::XMLReader&)> signalImportObjects; - boost::signals2::signal&, Base::Reader&, - const std::map&)> signalImportViewObjects; - boost::signals2::signal&)> signalFinishImportObjects; - //signal starting a save action to a file - boost::signals2::signal signalStartSave; - //signal finishing a save action to a file - boost::signals2::signal signalFinishSave; - boost::signals2::signal signalBeforeRecompute; - boost::signals2::signal&)> signalRecomputed; - boost::signals2::signal signalRecomputedObject; - //signal a new opened transaction - boost::signals2::signal signalOpenTransaction; + boost::signals2::signal signalSaveDocument; + boost::signals2::signal signalRestoreDocument; + boost::signals2::signal&, Base::Writer&)> signalExportObjects; + boost::signals2::signal&, Base::Writer&)> signalExportViewObjects; + boost::signals2::signal&, Base::XMLReader&)> signalImportObjects; + boost::signals2::signal&, Base::Reader&, + const std::map&)> signalImportViewObjects; + boost::signals2::signal&)> signalFinishImportObjects; + // signal starting a save action to a file + boost::signals2::signal signalStartSave; + // signal finishing a save action to a file + boost::signals2::signal signalFinishSave; + boost::signals2::signal signalBeforeRecompute; + boost::signals2::signal&)> signalRecomputed; + boost::signals2::signal signalRecomputedObject; + // signal a new opened transaction + boost::signals2::signal signalOpenTransaction; // signal a committed transaction - boost::signals2::signal signalCommitTransaction; + boost::signals2::signal signalCommitTransaction; // signal an aborted transaction - boost::signals2::signal signalAbortTransaction; - boost::signals2::signal&)> signalSkipRecompute; - boost::signals2::signal signalFinishRestoreObject; - boost::signals2::signal signalChangePropertyEditor; + boost::signals2::signal signalAbortTransaction; + boost::signals2::signal&)> signalSkipRecompute; + boost::signals2::signal signalFinishRestoreObject; + boost::signals2::signal signalChangePropertyEditor; + boost::signals2::signal signalLinkXsetValue; + // clang-format on //@} - boost::signals2::signal 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 &objNames={}); - bool afterRestore(bool checkPartial=false); - bool afterRestore(const std::vector &, bool checkPartial=false); - enum ExportStatus { + void restore(const char* filename = nullptr, + bool delaySignal = false, + const std::vector& objNames = {}); + bool afterRestore(bool checkPartial = false); + bool afterRestore(const std::vector&, 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&, std::ostream&); void exportGraphviz(std::ostream&) const; std::vector importObjects(Base::XMLReader& reader); @@ -222,10 +224,10 @@ public: * * @return the list of imported objects */ - std::vector importLinks( - const std::vector &objs = {}); + std::vector + importLinks(const std::vector& 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::vectoraddObjects(const char* sType, const std::vector& objectNames, bool isNew=true); + std::vector + addObjects(const char* sType, const std::vector& 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 copyObject( - const std::vector &objs, - bool recursive=false, bool returnAll=false); + std::vector copyObject(const std::vector& 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 getDependingObjects() const; /// Returns a list of all Objects - const std::vector &getObjects() const; + const std::vector& getObjects() const; std::vector 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 getObjectsWithExtension(const Base::Type& typeId, bool derived = true) const; - std::vector 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 getObjectsWithExtension(const Base::Type& typeId, + bool derived = true) const; + std::vector + findObjects(const Base::Type& typeId, const char* objname, const char* label) const; /// Returns an array with the correct types already. - template inline std::vector getObjectsOfType() const; + template + inline std::vector 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 getTouched() const; + std::vector 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 &objs={}, - bool force=false,bool *hasError=nullptr, int options=0); + int recompute(const std::vector& 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 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 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 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 getDependencyList( - const std::vector &objs, int options=0); + static std::vector + getDependencyList(const std::vector& objs, int options = 0); - std::vector getDependentDocuments(bool sort=true); - static std::vector getDependentDocuments(std::vector docs, bool sort); + std::vector getDependentDocuments(bool sort = true); + static std::vector getDependentDocuments(std::vector 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 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 getRootObjectsIgnoreLinks() const; /// get all possible paths from one object to another following the OutList - std::vector > getPathsByOutList - (const App::DocumentObject* from, const App::DocumentObject* to) const; + std::vector> + 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 addStringHasher(const StringHasherRef & hasher) const; + std::pair 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 &links, - const DocumentObject *obj, int options, int maxCount=0, - const std::vector &objs = {}) const; + void getLinksTo(std::set& links, + const DocumentObject* obj, + int options, + int maxCount = 0, + const std::vector& 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 & paths, const std::function &selector = [](const App::DocumentObject *) { return true; }); + void renameObjectIdentifiers( + const std::map& paths, + const std::function& 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 readObjects(Base::XMLReader& reader); - void writeObjects(const std::vector&, Base::Writer &writer) const; + void writeObjects(const std::vector&, 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 &objs = std::vector()); + const std::vector& objs = std::vector()); - 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 mUndoTransactions; - std::map mUndoMap; + std::map mUndoMap; std::list mRedoTransactions; - std::map mRedoMap; + std::map mRedoMap; struct DocumentP* d; @@ -613,12 +644,13 @@ inline std::vector Document::getObjectsOfType() const std::vector type; std::vector obj = this->getObjectsOfType(T::getClassTypeId()); type.reserve(obj.size()); - for (std::vector::iterator it = obj.begin(); it != obj.end(); ++it) - type.push_back(static_cast(*it)); + for (auto it : obj) { + type.push_back(static_cast(it)); + } return type; } -} //namespace App +} // namespace App -#endif // APP_DOCUMENT_H +#endif // APP_DOCUMENT_H diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index a7f1f93efe..abff0d876f 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -46,7 +46,7 @@ #include "PropertyLinks.h" -FC_LOG_LEVEL_INIT("App",true,true) +FC_LOG_LEVEL_INIT("App", true, true) using namespace App; @@ -57,7 +57,7 @@ using namespace App; PROPERTY_SOURCE(App::DocumentObject, App::TransactionalObject) -DocumentObjectExecReturn *DocumentObject::StdReturn = nullptr; +DocumentObjectExecReturn* DocumentObject::StdReturn = nullptr; //=========================================================================== // DocumentObject @@ -67,30 +67,30 @@ DocumentObject::DocumentObject() : ExpressionEngine() { // define Label of type 'Output' to avoid being marked as touched after relabeling - ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)"); - ADD_PROPERTY_TYPE(Label2,(""),"Base",Prop_Hidden,"User description of the object (UTF8)"); - Label2.setStatus(App::Property::Output,true); - ADD_PROPERTY_TYPE(ExpressionEngine,(),"Base",Prop_Hidden,"Property expressions"); + ADD_PROPERTY_TYPE(Label, ("Unnamed"), "Base", Prop_Output, "User name of the object (UTF8)"); + ADD_PROPERTY_TYPE(Label2, (""), "Base", Prop_Hidden, "User description of the object (UTF8)"); + Label2.setStatus(App::Property::Output, true); + ADD_PROPERTY_TYPE(ExpressionEngine, (), "Base", Prop_Hidden, "Property expressions"); ADD_PROPERTY(Visibility, (true)); // default set Visibility status to hidden and output (no touch) for - // compatibitily reason. We use setStatus instead of PropertyType to + // compatibitily reason. We use setStatus instead of PropertyType to // allow user to change its status later - Visibility.setStatus(Property::Output,true); - Visibility.setStatus(Property::Hidden,true); - Visibility.setStatus(Property::NoModify,true); + Visibility.setStatus(Property::Output, true); + Visibility.setStatus(Property::Hidden, true); + Visibility.setStatus(Property::NoModify, true); } DocumentObject::~DocumentObject() { - if (!PythonObject.is(Py::_None())){ + if (!PythonObject.is(Py::_None())) { Base::PyGILStateLocker lock; // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed - // Python object or not. In the constructor we forced the wrapper to own the object so we need - // not to dec'ref the Python object any more. - // But we must still invalidate the Python object because it need not to be - // destructed right now because the interpreter can own several references to it. + // Python object or not. In the constructor we forced the wrapper to own the object so we + // need not to dec'ref the Python object any more. But we must still invalidate the Python + // object because it need not to be destructed right now because the interpreter can own + // several references to it. Base::PyObjectBase* obj = static_cast(PythonObject.ptr()); // Call before decrementing the reference counter, otherwise a heap error can occur obj->setInvalid(); @@ -101,7 +101,8 @@ void DocumentObject::printInvalidLinks() const { try { // Get objects that have invalid link scope, and print their names. - // Truncate the invalid object list name strings for readability, if they happen to be very long. + // Truncate the invalid object list name strings for readability, if they happen to be very + // long. std::vector invalid_linkobjs; std::string objnames, scopenames; GeoFeatureGroupExtension::getInvalidLinkObjects(this, invalid_linkobjs); @@ -138,17 +139,21 @@ void DocumentObject::printInvalidLinks() const scopenames.pop_back(); } - Base::Console().Warning("%s: Link(s) to object(s) '%s' go out of the allowed scope '%s'. Instead, the linked object(s) reside within '%s'.\n", - getTypeId().getName(), objnames.c_str(), getNameInDocument(), scopenames.c_str()); + Base::Console().Warning("%s: Link(s) to object(s) '%s' go out of the allowed scope '%s'. " + "Instead, the linked object(s) reside within '%s'.\n", + getTypeId().getName(), + objnames.c_str(), + getNameInDocument(), + scopenames.c_str()); } catch (const Base::Exception& e) { e.ReportException(); } } -App::DocumentObjectExecReturn *DocumentObject::recompute() +App::DocumentObjectExecReturn* DocumentObject::recompute() { - //check if the links are valid before making the recompute + // check if the links are valid before making the recompute if (!GeoFeatureGroupExtension::areLinksValid(this)) { printInvalidLinks(); } @@ -171,20 +176,21 @@ App::DocumentObjectExecReturn *DocumentObject::recompute() return ret; } -DocumentObjectExecReturn *DocumentObject::execute() +DocumentObjectExecReturn* DocumentObject::execute() { return executeExtensions(); } App::DocumentObjectExecReturn* DocumentObject::executeExtensions() { - //execute extensions but stop on error - this->setStatus(App::RecomputeExtension, false); // reset the flag + // execute extensions but stop on error + this->setStatus(App::RecomputeExtension, false); // reset the flag auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) { + for (auto ext : vector) { auto ret = ext->extensionExecute(); - if (ret != StdReturn) + if (ret != StdReturn) { return ret; + } } return StdReturn; @@ -193,8 +199,9 @@ App::DocumentObjectExecReturn* DocumentObject::executeExtensions() bool DocumentObject::recomputeFeature(bool recursive) { Document* doc = this->getDocument(); - if (doc) - return doc->recomputeFeature(this,recursive); + if (doc) { + return doc->recomputeFeature(this, recursive); + } return isValid(); } @@ -207,11 +214,13 @@ bool DocumentObject::recomputeFeature(bool recursive) */ void DocumentObject::touch(bool noRecompute) { - if(!noRecompute) + if (!noRecompute) { StatusBits.set(ObjectStatus::Enforce); + } StatusBits.set(ObjectStatus::Touch); - if (_pDoc) + if (_pDoc) { _pDoc->signalTouchedObject(*this); + } } /** @@ -222,8 +231,9 @@ void DocumentObject::freeze() { StatusBits.set(ObjectStatus::Freeze); // use the signalTouchedObject to refresh the Gui - if (_pDoc) + if (_pDoc) { _pDoc->signalTouchedObject(*this); + } } /** @@ -263,25 +273,29 @@ void DocumentObject::enforceRecompute() */ bool DocumentObject::mustRecompute() const { - if (StatusBits.test(ObjectStatus::Freeze)) + if (StatusBits.test(ObjectStatus::Freeze)) { return false; + } - if (StatusBits.test(ObjectStatus::Enforce)) + if (StatusBits.test(ObjectStatus::Enforce)) { return true; + } return mustExecute() > 0; } short DocumentObject::mustExecute() const { - if (ExpressionEngine.isTouched()) + if (ExpressionEngine.isTouched()) { return 1; + } - //ask all extensions + // ask all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) { - if (ext->extensionMustExecute()) + for (auto ext : vector) { + if (ext->extensionMustExecute()) { return 1; + } } return 0; @@ -293,24 +307,30 @@ const char* DocumentObject::getStatusString() const const char* text = getDocument()->getErrorDescription(this); return text ? text : "Error"; } - else if (isTouched()) + else if (isTouched()) { return "Touched"; - else + } + else { return "Valid"; + } } -std::string DocumentObject::getFullName() const { - if(!getDocument() || !isAttachedToDocument()) +std::string DocumentObject::getFullName() const +{ + if (!getDocument() || !isAttachedToDocument()) { return "?"; + } std::string name(getDocument()->getName()); name += '#'; name += *pcNameInDocument; return name; } -std::string DocumentObject::getFullLabel() const { - if(!getDocument()) +std::string DocumentObject::getFullLabel() const +{ + if (!getDocument()) { return "?"; + } auto name = getDocument()->Label.getStrValue(); name += "#"; @@ -320,37 +340,42 @@ std::string DocumentObject::getFullLabel() const { const char* DocumentObject::getDagKey() const { - if(!pcNameInDocument) - { + if (!pcNameInDocument) { return nullptr; } return pcNameInDocument->c_str(); } -const char *DocumentObject::getNameInDocument() const +const char* DocumentObject::getNameInDocument() const { // Note: It can happen that we query the internal name of an object even if it is not // part of a document (anymore). This is the case e.g. if we have a reference in Python // to an object that has been removed from the document. In this case we should rather // return 0. - //assert(pcNameInDocument); - if (!pcNameInDocument) + // assert(pcNameInDocument); + if (!pcNameInDocument) { return nullptr; + } return pcNameInDocument->c_str(); } -int DocumentObject::isExporting() const { - if(!getDocument() || !isAttachedToDocument()) +int DocumentObject::isExporting() const +{ + if (!getDocument() || !isAttachedToDocument()) { return 0; + } return getDocument()->isExporting(this); } -std::string DocumentObject::getExportName(bool forced) const { - if(!isAttachedToDocument()) +std::string DocumentObject::getExportName(bool forced) const +{ + if (!isAttachedToDocument()) { return {}; + } - if(!forced && !isExporting()) + if (!forced && !isExporting()) { return *pcNameInDocument; + } // '@' is an invalid character for an internal name, which ensures the // following returned name will be unique in any document. Saving external @@ -371,10 +396,11 @@ const char* DocumentObject::detachFromDocument() return name ? name->c_str() : nullptr; } -const std::vector &DocumentObject::getOutList() const { - if(!_outListCached) { +const std::vector& DocumentObject::getOutList() const +{ + if (!_outListCached) { _outList.clear(); - getOutList(0,_outList); + getOutList(0, _outList); _outListCached = true; } return _outList; @@ -383,34 +409,39 @@ const std::vector &DocumentObject::getOutList() const { std::vector DocumentObject::getOutList(int options) const { std::vector res; - getOutList(options,res); + getOutList(options, res); return res; } -void DocumentObject::getOutList(int options, std::vector &res) const { - if(_outListCached && !options) { - res.insert(res.end(),_outList.begin(),_outList.end()); +void DocumentObject::getOutList(int options, std::vector& res) const +{ + if (_outListCached && !options) { + res.insert(res.end(), _outList.begin(), _outList.end()); return; } std::vector props; getPropertyList(props); bool noHidden = !!(options & OutListNoHidden); std::size_t size = res.size(); - for(auto prop : props) { + for (auto prop : props) { auto link = dynamic_cast(prop); - if(link) - link->getLinks(res,noHidden); + if (link) { + link->getLinks(res, noHidden); + } } - if(!(options & OutListNoExpression)) + if (!(options & OutListNoExpression)) { ExpressionEngine.getLinks(res); + } - if(options & OutListNoXLinked) { - for(auto it=res.begin()+size;it!=res.end();) { + if (options & OutListNoXLinked) { + for (auto it = res.begin() + size; it != res.end();) { auto obj = *it; - if(obj && obj->getDocument()!=getDocument()) + if (obj && obj->getDocument() != getDocument()) { it = res.erase(it); - else + } + else { ++it; + } } } } @@ -418,32 +449,36 @@ void DocumentObject::getOutList(int options, std::vector &res) std::vector DocumentObject::getOutListOfProperty(App::Property* prop) const { std::vector ret; - if (!prop || prop->getContainer() != this) + if (!prop || prop->getContainer() != this) { return ret; + } auto link = dynamic_cast(prop); - if(link) + if (link) { link->getLinks(ret); + } return ret; } #ifdef USE_OLD_DAG std::vector DocumentObject::getInList(void) const { - if (_pDoc) + if (_pDoc) { return _pDoc->getInList(this); - else + } + else { return std::vector(); + } } -#else // ifndef USE_OLD_DAG +#else // ifndef USE_OLD_DAG -const std::vector &DocumentObject::getInList() const +const std::vector& DocumentObject::getInList() const { return _inList; } -#endif // if USE_OLD_DAG +#endif // if USE_OLD_DAG // The original algorithm is highly inefficient in some special case. @@ -454,10 +489,11 @@ const std::vector &DocumentObject::getInList() const // of objects. And this may not be the worst case. getInListEx() has no such // problem. -std::vector DocumentObject::getInListRecursive() const { +std::vector DocumentObject::getInListRecursive() const +{ std::set inSet; std::vector res; - getInListEx(inSet,true,&res); + getInListEx(inSet, true, &res); return res; } @@ -465,61 +501,64 @@ std::vector DocumentObject::getInListRecursive() const { // More efficient algorithm to find the recursive inList of an object, // including possible external parents. One shortcoming of this algorithm is // it does not detect cyclic reference, althgouth it won't crash either. -void DocumentObject::getInListEx(std::set &inSet, - bool recursive, std::vector *inList) const +void DocumentObject::getInListEx(std::set& inSet, + bool recursive, + std::vector* inList) const { #ifdef USE_OLD_DAG - std::map > outLists; + std::map> outLists; // Old DAG does not have pre-built InList, and must calculate The InList by // going through all objects' OutLists. So we collect all objects and their // outLists first here. - for(auto doc : GetApplication().getDocuments()) { - for(auto obj : doc->getObjects()) { - if(!obj || !obj->isAttachedToDocument() || obj==this) + for (auto doc : GetApplication().getDocuments()) { + for (auto obj : doc->getObjects()) { + if (!obj || !obj->isAttachedToDocument() || obj == this) { continue; - const auto &outList = obj->getOutList(); - outLists[obj].insert(outList.begin(),outList.end()); + } + const auto& outList = obj->getOutList(); + outLists[obj].insert(outList.begin(), outList.end()); } } std::stack pendings; pendings.push(const_cast(this)); - while(pendings.size()) { + while (pendings.size()) { auto obj = pendings.top(); pendings.pop(); - for(auto &v : outLists) { - if(v.first == obj) continue; - auto &outList = v.second; + for (auto& v : outLists) { + if (v.first == obj) { + continue; + } + auto& outList = v.second; // Check the outList to see if the object is there, and pend the // object for recursive check if it's not already in the inList - if(outList.find(obj)!=outList.end() && - inSet.insert(v.first).second && - recursive) - { + if (outList.find(obj) != outList.end() && inSet.insert(v.first).second && recursive) { pendings.push(v.first); } } } -#else // USE_OLD_DAG +#else // USE_OLD_DAG - if(!recursive) { - inSet.insert(_inList.begin(),_inList.end()); - if(inList) + if (!recursive) { + inSet.insert(_inList.begin(), _inList.end()); + if (inList) { *inList = _inList; + } return; } std::stack pendings; pendings.push(const_cast(this)); - while(!pendings.empty()) { + while (!pendings.empty()) { auto obj = pendings.top(); pendings.pop(); - for(auto o : obj->getInList()) { - if(o && o->isAttachedToDocument() && inSet.insert(o).second) { + for (auto o : obj->getInList()) { + if (o && o->isAttachedToDocument() && inSet.insert(o).second) { pendings.push(o); - if(inList) + if (inList) { inList->push_back(o); + } } } } @@ -527,26 +566,30 @@ void DocumentObject::getInListEx(std::set &inSet, #endif } -std::set DocumentObject::getInListEx(bool recursive) const { +std::set DocumentObject::getInListEx(bool recursive) const +{ std::set ret; - getInListEx(ret,recursive); + getInListEx(ret, recursive); return ret; } void _getOutListRecursive(std::set& objSet, const DocumentObject* obj, - const DocumentObject* checkObj, int depth) + const DocumentObject* checkObj, + int depth) { for (const auto objIt : obj->getOutList()) { // if the check object is in the recursive inList we have a cycle! if (objIt == checkObj || depth <= 0) { - throw Base::BadGraphError("DocumentObject::getOutListRecursive(): cyclic dependency detected!"); + throw Base::BadGraphError( + "DocumentObject::getOutListRecursive(): cyclic dependency detected!"); } // if the element was already in the set then there is no need to process it again auto pair = objSet.insert(objIt); - if (pair.second) - _getOutListRecursive(objSet, objIt, checkObj, depth-1); + if (pair.second) { + _getOutListRecursive(objSet, objIt, checkObj, depth - 1); + } } } @@ -565,20 +608,22 @@ std::vector DocumentObject::getOutListRecursive() const } // helper for isInInListRecursive() -bool _isInInListRecursive(const DocumentObject* act, - const DocumentObject* checkObj, int depth) +bool _isInInListRecursive(const DocumentObject* act, const DocumentObject* checkObj, int depth) { -#ifndef USE_OLD_DAG +#ifndef USE_OLD_DAG for (auto obj : act->getInList()) { - if (obj == checkObj) + if (obj == checkObj) { return true; + } // if we reach the depth limit we have a cycle! if (depth <= 0) { - throw Base::BadGraphError("DocumentObject::isInInListRecursive(): cyclic dependency detected!"); + throw Base::BadGraphError( + "DocumentObject::isInInListRecursive(): cyclic dependency detected!"); } - if (_isInInListRecursive(obj, checkObj, depth - 1)) + if (_isInInListRecursive(obj, checkObj, depth - 1)) { return true; + } } #else (void)act; @@ -589,18 +634,20 @@ bool _isInInListRecursive(const DocumentObject* act, return false; } -bool DocumentObject::isInInListRecursive(DocumentObject *linkTo) const +bool DocumentObject::isInInListRecursive(DocumentObject* linkTo) const { - return this==linkTo || getInListEx(true).count(linkTo); + return this == linkTo || getInListEx(true).count(linkTo); } -bool DocumentObject::isInInList(DocumentObject *linkTo) const +bool DocumentObject::isInInList(DocumentObject* linkTo) const { -#ifndef USE_OLD_DAG - if (std::find(_inList.begin(), _inList.end(), linkTo) != _inList.end()) +#ifndef USE_OLD_DAG + if (std::find(_inList.begin(), _inList.end(), linkTo) != _inList.end()) { return true; - else + } + else { return false; + } #else (void)linkTo; return false; @@ -608,20 +655,22 @@ bool DocumentObject::isInInList(DocumentObject *linkTo) const } // helper for isInOutListRecursive() -bool _isInOutListRecursive(const DocumentObject* act, - const DocumentObject* checkObj, int depth) +bool _isInOutListRecursive(const DocumentObject* act, const DocumentObject* checkObj, int depth) { -#ifndef USE_OLD_DAG +#ifndef USE_OLD_DAG for (auto obj : act->getOutList()) { - if (obj == checkObj) + if (obj == checkObj) { return true; + } // if we reach the depth limit we have a cycle! if (depth <= 0) { - throw Base::BadGraphError("DocumentObject::isInOutListRecursive(): cyclic dependency detected!"); + throw Base::BadGraphError( + "DocumentObject::isInOutListRecursive(): cyclic dependency detected!"); } - if (_isInOutListRecursive(obj, checkObj, depth - 1)) + if (_isInOutListRecursive(obj, checkObj, depth - 1)) { return true; + } } #else (void)act; @@ -632,13 +681,13 @@ bool _isInOutListRecursive(const DocumentObject* act, return false; } -bool DocumentObject::isInOutListRecursive(DocumentObject *linkTo) const +bool DocumentObject::isInOutListRecursive(DocumentObject* linkTo) const { int maxDepth = getDocument()->countObjects() + 2; return _isInOutListRecursive(this, linkTo, maxDepth); } -std::vector > +std::vector> DocumentObject::getPathsByOutList(App::DocumentObject* to) const { return _pDoc->getPathsByOutList(this, to); @@ -649,30 +698,32 @@ DocumentObjectGroup* DocumentObject::getGroup() const return dynamic_cast(GroupExtension::getGroupOfObject(this)); } -bool DocumentObject::testIfLinkDAGCompatible(DocumentObject *linkTo) const +bool DocumentObject::testIfLinkDAGCompatible(DocumentObject* linkTo) const { std::vector linkTo_in_vector; linkTo_in_vector.push_back(linkTo); return this->testIfLinkDAGCompatible(linkTo_in_vector); } -bool DocumentObject::testIfLinkDAGCompatible(const std::vector &linksTo) const +bool DocumentObject::testIfLinkDAGCompatible(const std::vector& linksTo) const { auto inLists = getInListEx(true); inLists.emplace(const_cast(this)); - for(auto obj : linksTo) - if(inLists.count(obj)) + for (auto obj : linksTo) { + if (inLists.count(obj)) { return false; + } + } return true; } -bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSubList &linksTo) const +bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSubList& linksTo) const { - const std::vector &linksTo_in_vector = linksTo.getValues(); + const std::vector& linksTo_in_vector = linksTo.getValues(); return this->testIfLinkDAGCompatible(linksTo_in_vector); } -bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub &linkTo) const +bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub& linkTo) const { std::vector linkTo_in_vector; linkTo_in_vector.reserve(1); @@ -681,32 +732,33 @@ bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub &linkTo) const } void DocumentObject::onLostLinkToObject(DocumentObject*) -{ +{} -} - -App::Document *DocumentObject::getDocument() const +App::Document* DocumentObject::getDocument() const { return _pDoc; } void DocumentObject::setDocument(App::Document* doc) { - _pDoc=doc; + _pDoc = doc; onSettingDocument(); } bool DocumentObject::removeDynamicProperty(const char* name) { - if (!_pDoc || testStatus(ObjectStatus::Destroy)) + if (!_pDoc || testStatus(ObjectStatus::Destroy)) { return false; + } Property* prop = getDynamicPropertyByName(name); - if(!prop || prop->testStatus(App::Property::LockDynamic)) + if (!prop || prop->testStatus(App::Property::LockDynamic)) { return false; + } - if(prop->isDerivedFrom(PropertyLinkBase::getClassTypeId())) + if (prop->isDerivedFrom(PropertyLinkBase::getClassTypeId())) { clearOutListCache(); + } _pDoc->addOrRemovePropertyOfObject(this, prop, false); @@ -726,44 +778,49 @@ bool DocumentObject::removeDynamicProperty(const char* name) return TransactionalObject::removeDynamicProperty(name); } -App::Property* DocumentObject::addDynamicProperty( - const char* type, const char* name, const char* group, const char* doc, - short attr, bool ro, bool hidden) +App::Property* DocumentObject::addDynamicProperty(const char* type, + const char* name, + const char* group, + const char* doc, + short attr, + bool ro, + bool hidden) { - auto prop = TransactionalObject::addDynamicProperty(type,name,group,doc,attr,ro,hidden); - if(prop && _pDoc) + auto prop = TransactionalObject::addDynamicProperty(type, name, group, doc, attr, ro, hidden); + if (prop && _pDoc) { _pDoc->addOrRemovePropertyOfObject(this, prop, true); + } return prop; } void DocumentObject::onBeforeChange(const Property* prop) { - // Store current name in oldLabel, to be able to easily retrieve old name of document object later - // when renaming expressions. - if (prop == &Label) + // Store current name in oldLabel, to be able to easily retrieve old name of document object + // later when renaming expressions. + if (prop == &Label) { oldLabel = Label.getStrValue(); + } - if (_pDoc) + if (_pDoc) { onBeforeChangeProperty(_pDoc, prop); + } - signalBeforeChange(*this,*prop); + signalBeforeChange(*this, *prop); } -void DocumentObject::onEarlyChange(const Property *prop) +void DocumentObject::onEarlyChange(const Property* prop) { - if(GetApplication().isClosingAll()) + if (GetApplication().isClosingAll()) { return; + } - if(!GetApplication().isRestoring() && - !prop->testStatus(Property::PartialTrigger) && - getDocument() && - getDocument()->testStatus(Document::PartialDoc)) - { - static App::Document *warnedDoc; - if(warnedDoc != getDocument()) { + if (!GetApplication().isRestoring() && !prop->testStatus(Property::PartialTrigger) + && getDocument() && getDocument()->testStatus(Document::PartialDoc)) { + static App::Document* warnedDoc; + if (warnedDoc != getDocument()) { warnedDoc = getDocument(); - FC_WARN("Changes to partial loaded document will not be saved: " - << getFullName() << '.' << prop->getName()); + FC_WARN("Changes to partial loaded document will not be saved: " << getFullName() << '.' + << prop->getName()); } } @@ -773,22 +830,21 @@ void DocumentObject::onEarlyChange(const Property *prop) /// get called by the container when a Property was changed void DocumentObject::onChanged(const Property* prop) { - if (isFreezed()) + if (isFreezed()) { return; + } - if(GetApplication().isClosingAll()) + if (GetApplication().isClosingAll()) { return; + } - if(!GetApplication().isRestoring() && - !prop->testStatus(Property::PartialTrigger) && - getDocument() && - getDocument()->testStatus(Document::PartialDoc)) - { - static App::Document *warnedDoc; - if(warnedDoc != getDocument()) { + if (!GetApplication().isRestoring() && !prop->testStatus(Property::PartialTrigger) + && getDocument() && getDocument()->testStatus(Document::PartialDoc)) { + static App::Document* warnedDoc; + if (warnedDoc != getDocument()) { warnedDoc = getDocument(); - FC_WARN("Changes to partial loaded document will not be saved: " - << getFullName() << '.' << prop->getName()); + FC_WARN("Changes to partial loaded document will not be saved: " << getFullName() << '.' + << prop->getName()); } } @@ -797,94 +853,106 @@ void DocumentObject::onChanged(const Property* prop) // if (_pDoc) // _pDoc->onChangedProperty(this,prop); - if (prop == &Label && _pDoc && oldLabel != Label.getStrValue()) + if (prop == &Label && _pDoc && oldLabel != Label.getStrValue()) { _pDoc->signalRelabelObject(*this); + } // set object touched if it is an input property - if (!testStatus(ObjectStatus::NoTouch) - && !(prop->getType() & Prop_Output) - && !prop->testStatus(Property::Output)) - { - if(!StatusBits.test(ObjectStatus::Touch)) { + if (!testStatus(ObjectStatus::NoTouch) && !(prop->getType() & Prop_Output) + && !prop->testStatus(Property::Output)) { + if (!StatusBits.test(ObjectStatus::Touch)) { FC_TRACE("touch '" << getFullName() << "' on change of '" << prop->getName() << "'"); StatusBits.set(ObjectStatus::Touch); } // must execute on document recompute - if (!(prop->getType() & Prop_NoRecompute)) + if (!(prop->getType() & Prop_NoRecompute)) { StatusBits.set(ObjectStatus::Enforce); + } } - //call the parent for appropriate handling + // call the parent for appropriate handling TransactionalObject::onChanged(prop); // Now signal the view provider - if (_pDoc) - _pDoc->onChangedProperty(this,prop); + if (_pDoc) { + _pDoc->onChangedProperty(this, prop); + } - signalChanged(*this,*prop); + signalChanged(*this, *prop); } -void DocumentObject::clearOutListCache() const { +void DocumentObject::clearOutListCache() const +{ _outList.clear(); _outListMap.clear(); _outListCached = false; } -PyObject *DocumentObject::getPyObject() +PyObject* DocumentObject::getPyObject() { if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectPy(this),true); + PythonObject = Py::Object(new DocumentObjectPy(this), true); } return Py::new_reference_to(PythonObject); } -DocumentObject *DocumentObject::getSubObject(const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const +DocumentObject* DocumentObject::getSubObject(const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const { - DocumentObject *ret = nullptr; + DocumentObject* ret = nullptr; auto exts = getExtensionsDerivedFromType(); - for(auto ext : exts) { - if(ext->extensionGetSubObject(ret,subname,pyObj,mat,transform, depth)) + for (auto ext : exts) { + if (ext->extensionGetSubObject(ret, subname, pyObj, mat, transform, depth)) { return ret; + } } std::string name; - const char *dot=nullptr; - if(!subname || !(dot=strchr(subname,'.'))) { + const char* dot = nullptr; + if (!subname || !(dot = strchr(subname, '.'))) { ret = const_cast(this); - }else if(subname[0]=='$') { - name = std::string(subname+1,dot); - for(auto obj : getOutList()) { - if(name == obj->Label.getValue()) { + } + else if (subname[0] == '$') { + name = std::string(subname + 1, dot); + for (auto obj : getOutList()) { + if (name == obj->Label.getValue()) { ret = obj; break; } } - }else{ - name = std::string(subname,dot); - const auto &outList = getOutList(); - if(outList.size()!=_outListMap.size()) { + } + else { + name = std::string(subname, dot); + const auto& outList = getOutList(); + if (outList.size() != _outListMap.size()) { _outListMap.clear(); - for(auto obj : outList) + for (auto obj : outList) { _outListMap[obj->getDagKey()] = obj; + } } auto it = _outListMap.find(name.c_str()); - if(it != _outListMap.end()) + if (it != _outListMap.end()) { ret = it->second; + } } // TODO: By right, normal object's placement does not transform its sub // objects (think of the claimed children of a Fusion). But I do think we // should change that. - if(transform && mat) { + if (transform && mat) { auto pla = Base::freecad_dynamic_cast(getPropertyByName("Placement")); - if(pla) + if (pla) { *mat *= pla->getValue().toMatrix(); + } } - if(ret && dot) - return ret->getSubObject(dot+1,pyObj,mat,true,depth+1); + if (ret && dot) { + return ret->getSubObject(dot + 1, pyObj, mat, true, depth + 1); + } return ret; } @@ -979,18 +1047,22 @@ std::vector DocumentObject::getSubObjectList(const char* subnam return res; } -std::vector DocumentObject::getSubObjects(int reason) const { +std::vector DocumentObject::getSubObjects(int reason) const +{ std::vector ret; auto exts = getExtensionsDerivedFromType(); - for(auto ext : exts) { - if(ext->extensionGetSubObjects(ret,reason)) + for (auto ext : exts) { + if (ext->extensionGetSubObjects(ret, reason)) { return ret; + } } return ret; } -std::vector> DocumentObject::getParents(int depth) const { - std::vector> ret; +std::vector> +DocumentObject::getParents(int depth) const +{ + std::vector> ret; if (!isAttachedToDocument() || !GetApplication().checkLinkDepth(depth, MessageOption::Throw)) { return ret; } @@ -1002,8 +1074,8 @@ std::vector> DocumentObject::getPar continue; } - if (!parent->hasChildElement() && - !parent->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId())) { + if (!parent->hasChildElement() + && !parent->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId())) { continue; } @@ -1020,7 +1092,7 @@ std::vector> DocumentObject::getPar parents.emplace_back(parent, std::string()); } - for (auto &v : parents) { + for (auto& v : parents) { ret.emplace_back(v.first, v.second + name); } } @@ -1040,27 +1112,32 @@ App::DocumentObject* DocumentObject::getFirstParent() const return nullptr; } -DocumentObject *DocumentObject::getLinkedObject( - bool recursive, Base::Matrix4D *mat, bool transform, int depth) const +DocumentObject* DocumentObject::getLinkedObject(bool recursive, + Base::Matrix4D* mat, + bool transform, + int depth) const { - DocumentObject *ret = nullptr; + DocumentObject* ret = nullptr; auto exts = getExtensionsDerivedFromType(); - for(auto ext : exts) { - if(ext->extensionGetLinkedObject(ret,recursive,mat,transform,depth)) + for (auto ext : exts) { + if (ext->extensionGetLinkedObject(ret, recursive, mat, transform, depth)) { return ret; + } } - if(transform && mat) { + if (transform && mat) { auto pla = dynamic_cast(getPropertyByName("Placement")); - if(pla) + if (pla) { *mat *= pla->getValue().toMatrix(); + } } return const_cast(this); } -void DocumentObject::Save (Base::Writer &writer) const +void DocumentObject::Save(Base::Writer& writer) const { - if (this->isAttachedToDocument()) + if (this->isAttachedToDocument()) { writer.ObjectName = this->getNameInDocument(); + } App::ExtensionContainer::Save(writer); } @@ -1070,7 +1147,7 @@ void DocumentObject::Save (Base::Writer &writer) const * @param expr Expression tree */ -void DocumentObject::setExpression(const ObjectIdentifier &path, std::shared_ptr expr) +void DocumentObject::setExpression(const ObjectIdentifier& path, std::shared_ptr expr) { ExpressionEngine.setValue(path, expr); } @@ -1080,7 +1157,7 @@ void DocumentObject::setExpression(const ObjectIdentifier &path, std::shared_ptr * @param path Target object identifier */ -void DocumentObject::clearExpression(const ObjectIdentifier & path) +void DocumentObject::clearExpression(const ObjectIdentifier& path) { setExpression(path, std::shared_ptr()); } @@ -1091,14 +1168,17 @@ void DocumentObject::clearExpression(const ObjectIdentifier & path) * @return Expression info, containing expression and optional comment. */ -const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(const ObjectIdentifier &path) const +const PropertyExpressionEngine::ExpressionInfo +DocumentObject::getExpression(const ObjectIdentifier& path) const { boost::any value = ExpressionEngine.getPathValue(path); - if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo)) + if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo)) { return boost::any_cast(value); - else + } + else { return PropertyExpressionEngine::ExpressionInfo(); + } } /** @@ -1108,58 +1188,63 @@ const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(con * @param paths */ -void DocumentObject::renameObjectIdentifiers(const std::map &paths) +void DocumentObject::renameObjectIdentifiers( + const std::map& paths) { ExpressionEngine.renameObjectIdentifiers(paths); } void DocumentObject::onDocumentRestored() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedDocumentRestored(); - if(Visibility.testStatus(Property::Output)) - Visibility.setStatus(Property::NoModify,true); + } + if (Visibility.testStatus(Property::Output)) { + Visibility.setStatus(Property::NoModify, true); + } } void DocumentObject::onUndoRedoFinished() -{ - -} +{} void DocumentObject::onSettingDocument() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedSettingDocument(); + } } void DocumentObject::setupObject() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedSetupObject(); + } } void DocumentObject::unsetupObject() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedUnsetupObject(); + } } void App::DocumentObject::_removeBackLink(DocumentObject* rmvObj) { #ifndef USE_OLD_DAG - //do not use erase-remove idom, as this erases ALL entries that match. we only want to remove a - //single one. + // do not use erase-remove idom, as this erases ALL entries that match. we only want to remove a + // single one. auto it = std::find(_inList.begin(), _inList.end(), rmvObj); - if(it != _inList.end()) + if (it != _inList.end()) { _inList.erase(it); + } #else (void)rmvObj; #endif @@ -1168,110 +1253,131 @@ void App::DocumentObject::_removeBackLink(DocumentObject* rmvObj) void App::DocumentObject::_addBackLink(DocumentObject* newObj) { #ifndef USE_OLD_DAG - //we need to add all links, even if they are available multiple times. The reason for this is the - //removal: If a link loses this object it removes the backlink. If we would have added it only once - //this removal would clear the object from the inlist, even though there may be other link properties - //from this object that link to us. + // we need to add all links, even if they are available multiple times. The reason for this is + // the removal: If a link loses this object it removes the backlink. If we would have added it + // only once this removal would clear the object from the inlist, even though there may be other + // link properties from this object that link to us. _inList.push_back(newObj); #else (void)newObj; -#endif //USE_OLD_DAG +#endif // USE_OLD_DAG } -int DocumentObject::setElementVisible(const char *element, bool visible) { - for(auto ext : getExtensionsDerivedFromType()) { - int ret = ext->extensionSetElementVisible(element,visible); - if(ret>=0) +int DocumentObject::setElementVisible(const char* element, bool visible) +{ + for (auto ext : getExtensionsDerivedFromType()) { + int ret = ext->extensionSetElementVisible(element, visible); + if (ret >= 0) { return ret; + } } return -1; } -int DocumentObject::isElementVisible(const char *element) const { - for(auto ext : getExtensionsDerivedFromType()) { +int DocumentObject::isElementVisible(const char* element) const +{ + for (auto ext : getExtensionsDerivedFromType()) { int ret = ext->extensionIsElementVisible(element); - if(ret>=0) + if (ret >= 0) { return ret; + } } return -1; } -bool DocumentObject::hasChildElement() const { - for(auto ext : getExtensionsDerivedFromType()) { - if(ext->extensionHasChildElement()) +bool DocumentObject::hasChildElement() const +{ + for (auto ext : getExtensionsDerivedFromType()) { + if (ext->extensionHasChildElement()) { return true; + } } return false; } -DocumentObject *DocumentObject::resolve(const char *subname, - App::DocumentObject **parent, std::string *childName, const char **subElement, - PyObject **pyObj, Base::Matrix4D *pmat, bool transform, int depth) const +DocumentObject* DocumentObject::resolve(const char* subname, + App::DocumentObject** parent, + std::string* childName, + const char** subElement, + PyObject** pyObj, + Base::Matrix4D* pmat, + bool transform, + int depth) const { auto self = const_cast(this); - if(parent) *parent = nullptr; - if(subElement) *subElement = nullptr; + if (parent) { + *parent = nullptr; + } + if (subElement) { + *subElement = nullptr; + } - auto obj = getSubObject(subname,pyObj,pmat,transform,depth); - if(!obj || !subname || *subname==0) + auto obj = getSubObject(subname, pyObj, pmat, transform, depth); + if (!obj || !subname || *subname == 0) { return self; + } - if(!parent && !subElement) + if (!parent && !subElement) { return obj; + } // NOTE, the convention of '.' separated SubName demands a mandatory ending // '.' for each object name in SubName, even if there is no subelement // following it. So finding the last dot will give us the end of the last // object name. - const char *dot=nullptr; - if(Data::isMappedElement(subname) || - !(dot=strrchr(subname,'.')) || - dot == subname) - { - if(subElement) - *subElement = dot?dot+1:subname; - return obj; // this means no parent object reference in SubName + const char* dot = nullptr; + if (Data::isMappedElement(subname) || !(dot = strrchr(subname, '.')) || dot == subname) { + if (subElement) { + *subElement = dot ? dot + 1 : subname; + } + return obj; // this means no parent object reference in SubName } - if(parent) + if (parent) { *parent = self; + } bool elementMapChecked = false; - const char *lastDot = dot; - for(--dot;;--dot) { + const char* lastDot = dot; + for (--dot;; --dot) { // check for the second last dot, which is the end of the last parent object - if(*dot == '.' || dot == subname) { + if (*dot == '.' || dot == subname) { // We can't get parent object by its name, because the object may be // externally linked (i.e. in a different document). So go through // getSubObject again. - if(!elementMapChecked) { + if (!elementMapChecked) { elementMapChecked = true; - const char *sub = dot==subname?dot:dot+1; - if(Data::isMappedElement(sub)) { + const char* sub = dot == subname ? dot : dot + 1; + if (Data::isMappedElement(sub)) { lastDot = dot; - if(dot==subname) + if (dot == subname) { break; - else + } + else { continue; + } } } - if(dot==subname) + if (dot == subname) { break; - auto sobj = getSubObject(std::string(subname,dot-subname+1).c_str()); - if(sobj!=obj) { - if(parent) { + } + auto sobj = getSubObject(std::string(subname, dot - subname + 1).c_str()); + if (sobj != obj) { + if (parent) { // Link/LinkGroup has special visibility handling of plain // group, so keep ascending - if(!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) { + if (!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { *parent = sobj; break; } - for(auto ddot=dot-1;ddot!=subname;--ddot) { - if(*ddot != '.') continue; - auto sobj = getSubObject(std::string(subname,ddot-subname+1).c_str()); - if(!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) { + for (auto ddot = dot - 1; ddot != subname; --ddot) { + if (*ddot != '.') { + continue; + } + auto sobj = getSubObject(std::string(subname, ddot - subname + 1).c_str()); + if (!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { *parent = sobj; break; } @@ -1281,97 +1387,105 @@ DocumentObject *DocumentObject::resolve(const char *subname, } } } - if(childName && lastDot!=dot) { - if(*dot == '.') + if (childName && lastDot != dot) { + if (*dot == '.') { ++dot; - const char *nextDot = strchr(dot,'.'); + } + const char* nextDot = strchr(dot, '.'); assert(nextDot); - *childName = std::string(dot,nextDot-dot); + *childName = std::string(dot, nextDot - dot); + } + if (subElement) { + *subElement = *lastDot == '.' ? lastDot + 1 : lastDot; } - if(subElement) - *subElement = *lastDot=='.'?lastDot+1:lastDot; return obj; } -DocumentObject *DocumentObject::resolveRelativeLink(std::string &subname, - DocumentObject *&link, std::string &linkSub) const +DocumentObject* DocumentObject::resolveRelativeLink(std::string& subname, + DocumentObject*& link, + std::string& linkSub) const { - if(!link || !link->isAttachedToDocument() || !isAttachedToDocument()) + if (!link || !link->isAttachedToDocument() || !isAttachedToDocument()) { return nullptr; + } auto ret = const_cast(this); - if(link != ret) { + if (link != ret) { auto sub = subname.c_str(); auto nextsub = sub; - for(auto dot=strchr(nextsub,'.');dot;nextsub=dot+1,dot=strchr(nextsub,'.')) { - std::string subcheck(sub,nextsub-sub); + for (auto dot = strchr(nextsub, '.'); dot; nextsub = dot + 1, dot = strchr(nextsub, '.')) { + std::string subcheck(sub, nextsub - sub); subcheck += link->getNameInDocument(); subcheck += '.'; - if(getSubObject(subcheck.c_str())==link) { - ret = getSubObject(std::string(sub,dot+1-sub).c_str()); - if(!ret) + if (getSubObject(subcheck.c_str()) == link) { + ret = getSubObject(std::string(sub, dot + 1 - sub).c_str()); + if (!ret) { return nullptr; - subname = std::string(dot+1); + } + subname = std::string(dot + 1); break; } } return ret; } - size_t pos=0,linkPos=0; - std::string linkssub,ssub; + size_t pos = 0, linkPos = 0; + std::string linkssub, ssub; do { - linkPos = linkSub.find('.',linkPos); - if(linkPos == std::string::npos) { + linkPos = linkSub.find('.', linkPos); + if (linkPos == std::string::npos) { link = nullptr; return nullptr; } ++linkPos; - pos = subname.find('.',pos); - if(pos == std::string::npos) { + pos = subname.find('.', pos); + if (pos == std::string::npos) { subname.clear(); ret = nullptr; break; } ++pos; - }while(subname.compare(0,pos,linkSub,0,linkPos)==0); + } while (subname.compare(0, pos, linkSub, 0, linkPos) == 0); - if(pos != std::string::npos) { - ret = getSubObject(subname.substr(0,pos).c_str()); - if(!ret) { + if (pos != std::string::npos) { + ret = getSubObject(subname.substr(0, pos).c_str()); + if (!ret) { link = nullptr; return nullptr; } subname = subname.substr(pos); } - if(linkPos) { - link = link->getSubObject(linkSub.substr(0,linkPos).c_str()); - if(!link) + if (linkPos) { + link = link->getSubObject(linkSub.substr(0, linkPos).c_str()); + if (!link) { return nullptr; + } linkSub = linkSub.substr(linkPos); } return ret; } -bool DocumentObject::adjustRelativeLinks( - const std::set &inList, - std::set *visited) +bool DocumentObject::adjustRelativeLinks(const std::set& inList, + std::set* visited) { - if(visited) + if (visited) { visited->insert(this); + } bool touched = false; std::vector props; getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { auto linkProp = Base::freecad_dynamic_cast(prop); - if(linkProp && linkProp->adjustLink(inList)) + if (linkProp && linkProp->adjustLink(inList)) { touched = true; + } } - if(visited) { - for(auto obj : getOutList()) { - if(!visited->count(obj)) { - if(obj->adjustRelativeLinks(inList,visited)) + if (visited) { + for (auto obj : getOutList()) { + if (!visited->count(obj)) { + if (obj->adjustRelativeLinks(inList, visited)) { touched = true; + } } } } @@ -1396,28 +1510,36 @@ bool DocumentObject::checkElementMapVersion(const App::Property* _prop, const ch return prop->checkElementMapVersion(ver); } -const std::string &DocumentObject::hiddenMarker() { +const std::string& DocumentObject::hiddenMarker() +{ static std::string marker("!hide"); return marker; } -const char *DocumentObject::hasHiddenMarker(const char *subname) { - if(!subname) +const char* DocumentObject::hasHiddenMarker(const char* subname) +{ + if (!subname) { return nullptr; - const char *marker = strrchr(subname,'.'); - if(!marker) + } + const char* marker = strrchr(subname, '.'); + if (!marker) { marker = subname; - else + } + else { ++marker; - return hiddenMarker()==marker?marker:nullptr; + } + return hiddenMarker() == marker ? marker : nullptr; } -bool DocumentObject::redirectSubName(std::ostringstream &, DocumentObject *, DocumentObject *) const { +bool DocumentObject::redirectSubName(std::ostringstream&, DocumentObject*, DocumentObject*) const +{ return false; } -void DocumentObject::onPropertyStatusChanged(const Property &prop, unsigned long oldStatus) { +void DocumentObject::onPropertyStatusChanged(const Property& prop, unsigned long oldStatus) +{ (void)oldStatus; - if(!Document::isAnyRestoring() && isAttachedToDocument() && getDocument()) - getDocument()->signalChangePropertyEditor(*getDocument(),prop); + if (!Document::isAnyRestoring() && isAttachedToDocument() && getDocument()) { + getDocument()->signalChangePropertyEditor(*getDocument(), prop); + } } diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index 8c5ae02155..72f78fe13d 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -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 signalBeforeChange; + boost::signals2::signal signalBeforeChange; /// signal on changed property of this object - boost::signals2::signal signalChanged; + boost::signals2::signal signalChanged; /// signal on changed property of this object before document scoped signalChangedObject - boost::signals2::signal signalEarlyChanged; + boost::signals2::signal 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 &getOutList() const; + const std::vector& getOutList() const; std::vector getOutList(int option) const; - void getOutList(int option, std::vector &res) const; + void getOutList(int option, std::vector& res) const; /// returns a list of objects linked by the property std::vector 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 > getPathsByOutList(App::DocumentObject* to) const; + std::vector> getPathsByOutList(App::DocumentObject* to) const; #ifdef USE_OLD_DAG /// get all objects link to this object std::vector getInList(void) const #else - const std::vector &getInList() const; + const std::vector& getInList() const; #endif - /// get all objects link directly or indirectly to this object - std::vector getInListRecursive() const; + /// get all objects link directly or indirectly to this object + std::vector 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 &inSet, - bool recursive, std::vector *inList=nullptr) const; - /** Return a set of all objects linking to this object, including possible external parent objects + void getInListEx(std::set& inSet, + bool recursive, + std::vector* 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 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 &linksTo) const; - bool testIfLinkDAGCompatible(App::PropertyLinkSubList &linksTo) const; - bool testIfLinkDAGCompatible(App::PropertyLinkSub &linkTo) const; + bool testIfLinkDAGCompatible(const std::vector& 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 getSubObjects(int reason=0) const; + virtual std::vector getSubObjects(int reason = 0) const; - ///Obtain top parents and subnames of this object using its InList - std::vector > getParents(int depth=0) const; + /// Obtain top parents and subnames of this object using its InList + std::vector> 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 expr); + virtual void setExpression(const ObjectIdentifier& path, std::shared_ptr 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 & paths); + virtual void + renameObjectIdentifiers(const std::map& 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 &inList, - std::set *visited=nullptr); + virtual bool adjustRelativeLinks(const std::set& inList, + std::set* 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 _inList; - mutable std::vector _outList; - mutable std::unordered_map _outListMap; + mutable std::vector _outList; + mutable std::unordered_map + _outListMap; mutable bool _outListCached = false; }; -} //namespace App +} // namespace App -#endif // APP_DOCUMENTOBJECT_H +#endif // APP_DOCUMENTOBJECT_H diff --git a/src/App/ExpressionParser.h b/src/App/ExpressionParser.h index 4535e64719..3836d64a99 100644 --- a/src/App/ExpressionParser.h +++ b/src/App/ExpressionParser.h @@ -30,7 +30,8 @@ #include #include -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 _args = std::vector()); + explicit FunctionExpression(const App::DocumentObject* _owner = nullptr, + Function _f = NONE, + std::string&& name = std::string(), + std::vector _args = std::vector()); ~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 &args); + static Py::Object + evaluate(const Expression* owner, int type, const std::vector& args); - Function getFunction() const {return f;} - const std::vector &getArgs() const {return args;} + Function getFunction() const + { + return f; + } + const std::vector& getArgs() const + { + return args; + } protected: - static Py::Object evalAggregate(const Expression *owner, int type, const std::vector &args); - static Base::Vector3d evaluateSecondVectorArgument(const Expression *expression, const std::vector &arguments); - static double extractLengthValueArgument(const Expression *expression, const std::vector &arguments, int argumentIndex); - static Base::Vector3d extractVectorArgument(const Expression *expression, const std::vector &arguments, int argumentIndex); - static void initialiseObject(const Py::Object *object, const std::vector &arguments, const unsigned long offset = 0); - static Py::Object transformFirstArgument( - const Expression *expression, - const std::vector &arguments, - const Base::Matrix4D *transformationMatrix); + static Py::Object + evalAggregate(const Expression* owner, int type, const std::vector& args); + static Base::Vector3d evaluateSecondVectorArgument(const Expression* expression, + const std::vector& arguments); + static double extractLengthValueArgument(const Expression* expression, + const std::vector& arguments, + int argumentIndex); + static Base::Vector3d extractVectorArgument(const Expression* expression, + const std::vector& arguments, + int argumentIndex); + static void initialiseObject(const Py::Object* object, + const std::vector& arguments, + const unsigned long offset = 0); + static Py::Object transformFirstArgument(const Expression* expression, + const std::vector& 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 args; /** Arguments to function*/ + std::vector 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 &) const override; - bool _adjustLinks(const std::set &, 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 &, - const ObjectIdentifier &, ExpressionVisitor &) override; - void _collectReplacement(std::map &, - 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&) const override; + bool _adjustLinks(const std::set&, 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&, + const ObjectIdentifier&, + ExpressionVisitor&) override; + void _collectReplacement(std::map&, + 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 &) const override; - bool _renameObjectIdentifier(const std::map &, - const ObjectIdentifier &, ExpressionVisitor &) override; - void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override; - void _offsetCells(int, int, ExpressionVisitor &) override; + void _getIdentifiers(std::map&) const override; + bool _renameObjectIdentifier(const std::map&, + 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 > 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> 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 components; - long long int ivalue{0}; - double fvalue{0}; - struct { - const char *name = ""; - double fvalue = 0; - } constant; - std::vector arguments; - std::vector list; - std::string string; - std::pair 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 components; + long long int ivalue {0}; + double fvalue {0}; + struct + { + const char* name = ""; + double fvalue = 0; + } constant; + std::vector arguments; + std::vector list; + std::string string; + std::pair 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 diff --git a/src/App/ExpressionTokenizer.cpp b/src/App/ExpressionTokenizer.cpp index 57e5bea07c..aefa56c61f 100644 --- a/src/App/ExpressionTokenizer.cpp +++ b/src/App/ExpressionTokenizer.cpp @@ -44,16 +44,16 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) std::vector> result = ExpressionParser::tokenize(expr.toStdString()); std::vector> tokens; - std::transform(result.cbegin(), - result.cend(), - std::back_inserter(tokens), - [&](const std::tuple& 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& 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 > tokens = tokenizeExpression(prefix.mid(start)); + std::vector> 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(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(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(tokens.size())) + if (i == static_cast(tokens.size())) { prefixStart = prefixEnd; - else + } + else { prefixStart = start + std::get<1>(tokens[i]); + } // Build prefix from tokens while (i < static_cast(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; } diff --git a/src/App/ExpressionTokenizer.h b/src/App/ExpressionTokenizer.h index 17ffad250d..273179bf0d 100644 --- a/src/App/ExpressionTokenizer.h +++ b/src/App/ExpressionTokenizer.h @@ -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 diff --git a/src/App/ExpressionVisitors.h b/src/App/ExpressionVisitors.h index 2dc3c46b2b..ea111821e9 100644 --- a/src/App/ExpressionVisitors.h +++ b/src/App/ExpressionVisitors.h @@ -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 RenameObjectIdentifierExpressionVisitor : public ExpressionModifier

{ +template +class RenameObjectIdentifierExpressionVisitor: public ExpressionModifier

+{ public: RenameObjectIdentifierExpressionVisitor( - P &_prop, - const std::map &_paths, - const ObjectIdentifier &_owner) + P& _prop, + const std::map& _paths, + const ObjectIdentifier& _owner) : ExpressionModifier

(_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 &paths; /**< Map with current and new object identifiers */ - const ObjectIdentifier owner; /**< Owner of expression */ + const std::map& + paths; /**< Map with current and new object identifiers */ + const ObjectIdentifier owner; /**< Owner of expression */ }; -template class UpdateElementReferenceExpressionVisitor : public ExpressionModifier

{ +template +class UpdateElementReferenceExpressionVisitor: public ExpressionModifier

+{ public: + explicit UpdateElementReferenceExpressionVisitor(P& _prop, + App::DocumentObject* feature = nullptr, + bool reverse = false) + : ExpressionModifier

(_prop) + , feature(feature) + , reverse(reverse) + {} - explicit UpdateElementReferenceExpressionVisitor(P & _prop, App::DocumentObject *feature=nullptr, bool reverse=false) - : ExpressionModifier

(_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 MoveCellsExpressionVisitor : public ExpressionModifier

{ +template +class MoveCellsExpressionVisitor: public ExpressionModifier

+{ public: - MoveCellsExpressionVisitor(P &prop, const CellAddress &address, int rowCount, int colCount) - : ExpressionModifier

(prop),address(address),rowCount(rowCount),colCount(colCount) + MoveCellsExpressionVisitor(P& prop, const CellAddress& address, int rowCount, int colCount) + : ExpressionModifier

(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 OffsetCellsExpressionVisitor : public ExpressionModifier

{ +template +class OffsetCellsExpressionVisitor: public ExpressionModifier

+{ public: - OffsetCellsExpressionVisitor(P &prop, int rowOffset, int colOffset) - : ExpressionModifier

(prop),rowOffset(rowOffset),colOffset(colOffset) + OffsetCellsExpressionVisitor(P& prop, int rowOffset, int colOffset) + : ExpressionModifier

(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 diff --git a/src/App/FeatureTest.cpp b/src/App/FeatureTest.cpp index 9b804d0d63..4d5592447f 100644 --- a/src/App/FeatureTest.cpp +++ b/src/App/FeatureTest.cpp @@ -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) { diff --git a/src/App/FeatureTest.h b/src/App/FeatureTest.h index 2a52a6ed83..bd10619f32 100644 --- a/src/App/FeatureTest.h +++ b/src/App/FeatureTest.h @@ -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 diff --git a/src/App/GeoFeature.cpp b/src/App/GeoFeature.cpp index e3f448fac9..c434b599e5 100644 --- a/src/App/GeoFeature.cpp +++ b/src/App/GeoFeature.cpp @@ -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(); 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(linked); - if(!geo && linked) { + if (!geo && linked) { auto ext = linked->getExtensionByType(true); - if(ext) + if (ext) { geo = Base::freecad_dynamic_cast(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 GeoFeature::getElementTypes(bool /*all*/) const return prop->getComplexData()->getElementTypes(); } -std::vector -GeoFeature::getHigherElements(const char *element, bool silent) const +std::vector 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(); diff --git a/src/App/GeoFeature.h b/src/App/GeoFeature.h index 1f35ab1e79..7288a5f3bd 100644 --- a/src/App/GeoFeature.h +++ b/src/App/GeoFeature.h @@ -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& searchElementCache(const std::string &element, - Data::SearchOptions options = Data::SearchOption::CheckGeometry, - double tol = 1e-7, - double atol = 1e-10) const; + virtual const std::vector& + 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 getElementTypes(bool all=true) const; + virtual std::vector getElementTypes(bool all = true) const; /// Return the higher level element names of the given element - virtual std::vector getHigherElements(const char *name, bool silent=false) const; + virtual std::vector 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 diff --git a/src/App/Link.cpp b/src/App/Link.cpp index 815787de66..c520d43a20 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -37,13 +37,13 @@ #include "Link.h" #include "LinkBaseExtensionPy.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 -FC_LOG_LEVEL_INIT("App::Link", true,true) +FC_LOG_LEVEL_INIT("App::Link", true, true) using namespace App; using namespace Base; @@ -58,22 +58,27 @@ import LinkParams LinkParams.define() ]]]*/ -namespace { +namespace +{ // Auto generated code. See class document of LinkParams. -class LinkParamsP: public ParameterGrp::ObserverType { +class LinkParamsP: public ParameterGrp::ObserverType +{ public: // Auto generated code. See class document of LinkParams. ParameterGrp::handle handle; // Auto generated code. See class document of LinkParams. - std::unordered_map funcs; + std::unordered_map + funcs; - bool CopyOnChangeApplyToAll; // Auto generated code. See class document of LinkParams. + bool CopyOnChangeApplyToAll; // Auto generated code. See class document of LinkParams. // Auto generated code. See class document of LinkParams. - LinkParamsP() { - handle = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Link"); + LinkParamsP() + { + handle = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Link"); handle->Attach(this); CopyOnChangeApplyToAll = handle->GetBool("CopyOnChangeApplyToAll", true); @@ -84,61 +89,73 @@ public: ~LinkParamsP() override = default; // Auto generated code. See class document of LinkParams. - void OnChange(Base::Subject &, const char* sReason) override { - if(!sReason) + void OnChange(Base::Subject&, const char* sReason) override + { + if (!sReason) { return; + } auto it = funcs.find(sReason); - if(it == funcs.end()) + if (it == funcs.end()) { return; + } it->second(this); } // Auto generated code. See class document of LinkParams. - static void updateCopyOnChangeApplyToAll(LinkParamsP *self) { + static void updateCopyOnChangeApplyToAll(LinkParamsP* self) + { self->CopyOnChangeApplyToAll = self->handle->GetBool("CopyOnChangeApplyToAll", true); } }; // Auto generated code. See class document of LinkParams. -LinkParamsP *instance() { - static LinkParamsP *inst = new LinkParamsP; +LinkParamsP* instance() +{ + static LinkParamsP* inst = new LinkParamsP; return inst; } -} // Anonymous namespace +} // Anonymous namespace // Auto generated code. See class document of LinkParams. -ParameterGrp::handle LinkParams::getHandle() { +ParameterGrp::handle LinkParams::getHandle() +{ return instance()->handle; } // Auto generated code. See class document of LinkParams. -const char *LinkParams::docCopyOnChangeApplyToAll() { - return QT_TRANSLATE_NOOP("LinkParams", -"Stores the last user choice of whether to apply CopyOnChange setup to all links\n" -"that reference the same configurable object"); +const char* LinkParams::docCopyOnChangeApplyToAll() +{ + return QT_TRANSLATE_NOOP( + "LinkParams", + "Stores the last user choice of whether to apply CopyOnChange setup to all links\n" + "that reference the same configurable object"); } // Auto generated code. See class document of LinkParams. -const bool & LinkParams::getCopyOnChangeApplyToAll() { +const bool& LinkParams::getCopyOnChangeApplyToAll() +{ return instance()->CopyOnChangeApplyToAll; } // Auto generated code. See class document of LinkParams. -const bool & LinkParams::defaultCopyOnChangeApplyToAll() { +const bool& LinkParams::defaultCopyOnChangeApplyToAll() +{ static const bool def = true; return def; } // Auto generated code. See class document of LinkParams. -void LinkParams::setCopyOnChangeApplyToAll(const bool &v) { - instance()->handle->SetBool("CopyOnChangeApplyToAll",v); +void LinkParams::setCopyOnChangeApplyToAll(const bool& v) +{ + instance()->handle->SetBool("CopyOnChangeApplyToAll", v); instance()->CopyOnChangeApplyToAll = v; } // Auto generated code. See class document of LinkParams. -void LinkParams::removeCopyOnChangeApplyToAll() { +void LinkParams::removeCopyOnChangeApplyToAll() +{ instance()->handle->RemoveBool("CopyOnChangeApplyToAll"); } //[[[end]]] @@ -150,235 +167,267 @@ EXTENSION_PROPERTY_SOURCE(App::LinkBaseExtension, App::DocumentObjectExtension) LinkBaseExtension::LinkBaseExtension() { initExtensionType(LinkBaseExtension::getExtensionClassTypeId()); - EXTENSION_ADD_PROPERTY_TYPE(_LinkTouched, (false), " Link", - PropertyType(Prop_Hidden|Prop_NoPersist),0); - EXTENSION_ADD_PROPERTY_TYPE(_ChildCache, (), " Link", - PropertyType(Prop_Hidden|Prop_NoPersist|Prop_ReadOnly),0); + EXTENSION_ADD_PROPERTY_TYPE(_LinkTouched, + (false), + " Link", + PropertyType(Prop_Hidden | Prop_NoPersist), + 0); + EXTENSION_ADD_PROPERTY_TYPE(_ChildCache, + (), + " Link", + PropertyType(Prop_Hidden | Prop_NoPersist | Prop_ReadOnly), + 0); _ChildCache.setScope(LinkScope::Global); - EXTENSION_ADD_PROPERTY_TYPE(_LinkOwner, (0), " Link", - PropertyType(Prop_Hidden|Prop_Output),0); - props.resize(PropMax,nullptr); + EXTENSION_ADD_PROPERTY_TYPE(_LinkOwner, + (0), + " Link", + PropertyType(Prop_Hidden | Prop_Output), + 0); + props.resize(PropMax, nullptr); } -PyObject* LinkBaseExtension::getExtensionPyObject() { - if (ExtensionPythonObject.is(Py::_None())){ +PyObject* LinkBaseExtension::getExtensionPyObject() +{ + if (ExtensionPythonObject.is(Py::_None())) { // ref counter is set to 1 - ExtensionPythonObject = Py::Object(new LinkBaseExtensionPy(this),true); + ExtensionPythonObject = Py::Object(new LinkBaseExtensionPy(this), true); } return Py::new_reference_to(ExtensionPythonObject); } -const std::vector &LinkBaseExtension::getPropertyInfo() const { +const std::vector& LinkBaseExtension::getPropertyInfo() const +{ static std::vector PropsInfo; - if(PropsInfo.empty()) { - BOOST_PP_SEQ_FOR_EACH(LINK_PROP_INFO,PropsInfo,LINK_PARAMS); + if (PropsInfo.empty()) { + BOOST_PP_SEQ_FOR_EACH(LINK_PROP_INFO, PropsInfo, LINK_PARAMS); } return PropsInfo; } -const LinkBaseExtension::PropInfoMap &LinkBaseExtension::getPropertyInfoMap() const { +const LinkBaseExtension::PropInfoMap& LinkBaseExtension::getPropertyInfoMap() const +{ static PropInfoMap PropsMap; - if(PropsMap.empty()) { - const auto &infos = getPropertyInfo(); - for(const auto &info : infos) + if (PropsMap.empty()) { + const auto& infos = getPropertyInfo(); + for (const auto& info : infos) { PropsMap[info.name] = info; + } } return PropsMap; } -Property *LinkBaseExtension::getProperty(int idx) { - if(idx>=0 && idx<(int)props.size()) +Property* LinkBaseExtension::getProperty(int idx) +{ + if (idx >= 0 && idx < (int)props.size()) { return props[idx]; + } return nullptr; } -Property *LinkBaseExtension::getProperty(const char *name) { - const auto &info = getPropertyInfoMap(); +Property* LinkBaseExtension::getProperty(const char* name) +{ + const auto& info = getPropertyInfoMap(); auto it = info.find(name); - if(it == info.end()) + if (it == info.end()) { return nullptr; + } return getProperty(it->second.index); } -void LinkBaseExtension::setProperty(int idx, Property *prop) { - const auto &infos = getPropertyInfo(); - if(idx<0 || idx>=(int)infos.size()) - LINK_THROW(Base::RuntimeError,"App::LinkBaseExtension: property index out of range"); +void LinkBaseExtension::setProperty(int idx, Property* prop) +{ + const auto& infos = getPropertyInfo(); + if (idx < 0 || idx >= (int)infos.size()) { + LINK_THROW(Base::RuntimeError, "App::LinkBaseExtension: property index out of range"); + } - if(props[idx]) { - props[idx]->setStatus(Property::LockDynamic,false); + if (props[idx]) { + props[idx]->setStatus(Property::LockDynamic, false); props[idx] = nullptr; } - if(!prop) + if (!prop) { return; - if(!prop->isDerivedFrom(infos[idx].type)) { + } + if (!prop->isDerivedFrom(infos[idx].type)) { std::ostringstream str; - str << "App::LinkBaseExtension: expected property type '" << - infos[idx].type.getName() << "', instead of '" << - prop->getClassTypeId().getName() << "'"; - LINK_THROW(Base::TypeError,str.str().c_str()); + str << "App::LinkBaseExtension: expected property type '" << infos[idx].type.getName() + << "', instead of '" << prop->getClassTypeId().getName() << "'"; + LINK_THROW(Base::TypeError, str.str().c_str()); } props[idx] = prop; - props[idx]->setStatus(Property::LockDynamic,true); + props[idx]->setStatus(Property::LockDynamic, true); - switch(idx) { - case PropLinkMode: { - static const char *linkModeEnums[] = {"None","Auto Delete","Auto Link","Auto Unlink",nullptr}; - auto propLinkMode = static_cast(prop); - if(!propLinkMode->hasEnums()) - propLinkMode->setEnums(linkModeEnums); - break; - } - case PropLinkCopyOnChange: { - static const char *enums[] = {"Disabled","Enabled","Owned","Tracking",nullptr}; - auto propEnum = static_cast(prop); - if(!propEnum->hasEnums()) - propEnum->setEnums(enums); - break; - } - case PropLinkCopyOnChangeSource: - case PropLinkCopyOnChangeGroup: - if (auto linkProp = Base::freecad_dynamic_cast(prop)) { - linkProp->setScope(LinkScope::Global); + switch (idx) { + case PropLinkMode: { + static const char* linkModeEnums[] = {"None", + "Auto Delete", + "Auto Link", + "Auto Unlink", + nullptr}; + auto propLinkMode = static_cast(prop); + if (!propLinkMode->hasEnums()) { + propLinkMode->setEnums(linkModeEnums); + } + break; } - // fall through - case PropLinkCopyOnChangeTouched: - prop->setStatus(Property::Hidden, true); - break; - case PropLinkTransform: - case PropLinkPlacement: - case PropPlacement: - if(getLinkTransformProperty() && - getLinkPlacementProperty() && - getPlacementProperty()) - { - bool transform = getLinkTransformValue(); - getPlacementProperty()->setStatus(Property::Hidden, transform); - getLinkPlacementProperty()->setStatus(Property::Hidden, !transform); + case PropLinkCopyOnChange: { + static const char* enums[] = {"Disabled", "Enabled", "Owned", "Tracking", nullptr}; + auto propEnum = static_cast(prop); + if (!propEnum->hasEnums()) { + propEnum->setEnums(enums); + } + break; } - break; - case PropElementList: - getElementListProperty()->setScope(LinkScope::Global); - getElementListProperty()->setStatus(Property::Hidden, true); - // fall through - case PropLinkedObject: - // Make ElementList as read-only if we are not a group (i.e. having - // LinkedObject property), because it is for holding array elements. - if(getElementListProperty()) { - getElementListProperty()->setStatus( - Property::Immutable, getLinkedObjectProperty() != nullptr); - } - if (auto linkProp = getLinkedObjectProperty()) { - linkProp->setScope(LinkScope::Global); - } - break; - case PropVisibilityList: - getVisibilityListProperty()->setStatus(Property::Immutable, true); - getVisibilityListProperty()->setStatus(Property::Hidden, true); - break; + case PropLinkCopyOnChangeSource: + case PropLinkCopyOnChangeGroup: + if (auto linkProp = Base::freecad_dynamic_cast(prop)) { + linkProp->setScope(LinkScope::Global); + } + // fall through + case PropLinkCopyOnChangeTouched: + prop->setStatus(Property::Hidden, true); + break; + case PropLinkTransform: + case PropLinkPlacement: + case PropPlacement: + if (getLinkTransformProperty() && getLinkPlacementProperty() + && getPlacementProperty()) { + bool transform = getLinkTransformValue(); + getPlacementProperty()->setStatus(Property::Hidden, transform); + getLinkPlacementProperty()->setStatus(Property::Hidden, !transform); + } + break; + case PropElementList: + getElementListProperty()->setScope(LinkScope::Global); + getElementListProperty()->setStatus(Property::Hidden, true); + // fall through + case PropLinkedObject: + // Make ElementList as read-only if we are not a group (i.e. having + // LinkedObject property), because it is for holding array elements. + if (getElementListProperty()) { + getElementListProperty()->setStatus(Property::Immutable, + getLinkedObjectProperty() != nullptr); + } + if (auto linkProp = getLinkedObjectProperty()) { + linkProp->setScope(LinkScope::Global); + } + break; + case PropVisibilityList: + getVisibilityListProperty()->setStatus(Property::Immutable, true); + getVisibilityListProperty()->setStatus(Property::Hidden, true); + break; } - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_TRACE)) { - const char *propName; - if(!prop) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_TRACE)) { + const char* propName; + if (!prop) { propName = ""; - else if(prop->getContainer()) + } + else if (prop->getContainer()) { propName = prop->getName(); - else + } + else { propName = extensionGetPropertyName(prop); - if(!Property::isValidName(propName)) + } + if (!Property::isValidName(propName)) { propName = "?"; + } FC_TRACE("set property " << infos[idx].name << ": " << propName); } } static const char _GroupPrefix[] = "Configuration ("; -App::DocumentObjectExecReturn *LinkBaseExtension::extensionExecute() { +App::DocumentObjectExecReturn* LinkBaseExtension::extensionExecute() +{ // The actual value of LinkTouched is not important, just to notify view // provider that the link (in fact, its dependents, i.e. linked ones) have // recomputed. _LinkTouched.touch(); - if(getLinkedObjectProperty()) { - DocumentObject *linked = getTrueLinkedObject(true); - if(!linked) { + if (getLinkedObjectProperty()) { + DocumentObject* linked = getTrueLinkedObject(true); + if (!linked) { std::ostringstream ss; ss << "Link broken!"; - auto xlink = Base::freecad_dynamic_cast( - getLinkedObjectProperty()); + auto xlink = Base::freecad_dynamic_cast(getLinkedObjectProperty()); if (xlink) { - const char *objname = xlink->getObjectName(); - if (objname && objname[0]) + const char* objname = xlink->getObjectName(); + if (objname && objname[0]) { ss << "\nObject: " << objname; - const char *filename = xlink->getFilePath(); - if (filename && filename[0]) + } + const char* filename = xlink->getFilePath(); + if (filename && filename[0]) { ss << "\nFile: " << filename; + } } return new App::DocumentObjectExecReturn(ss.str().c_str()); } - App::DocumentObject *container = getContainer(); + App::DocumentObject* container = getContainer(); auto source = getLinkCopyOnChangeSourceValue(); if (source && getLinkCopyOnChangeValue() == CopyOnChangeTracking - && getLinkCopyOnChangeTouchedValue()) - { + && getLinkCopyOnChangeTouchedValue()) { syncCopyOnChange(); } // the previous linked object could be deleted by syncCopyOnChange - #12281 linked = getTrueLinkedObject(true); - if(!linked) { + if (!linked) { return new App::DocumentObjectExecReturn("Error in processing variable link"); } - PropertyPythonObject *proxy = nullptr; - if(getLinkExecuteProperty() - && !boost::iequals(getLinkExecuteValue(), "none") - && (!_LinkOwner.getValue() - || !container->getDocument()->getObjectByID(_LinkOwner.getValue()))) - { + PropertyPythonObject* proxy = nullptr; + if (getLinkExecuteProperty() && !boost::iequals(getLinkExecuteValue(), "none") + && (!_LinkOwner.getValue() + || !container->getDocument()->getObjectByID(_LinkOwner.getValue()))) { // Check if this is an element link. Do not invoke appLinkExecute() // if so, because it will be called from the link array. proxy = Base::freecad_dynamic_cast( - linked->getPropertyByName("Proxy")); + linked->getPropertyByName("Proxy")); } - if(proxy) { + if (proxy) { Base::PyGILStateLocker lock; - const char *errMsg = "Linked proxy execute failed"; + const char* errMsg = "Linked proxy execute failed"; try { Py::Tuple args(3); Py::Object proxyValue = proxy->getValue(); - const char *method = getLinkExecuteValue(); - if(!method || !method[0]) + const char* method = getLinkExecuteValue(); + if (!method || !method[0]) { method = "appLinkExecute"; - if(proxyValue.hasAttr(method)) { + } + if (proxyValue.hasAttr(method)) { Py::Object attr = proxyValue.getAttr(method); - if(attr.ptr() && attr.isCallable()) { + if (attr.ptr() && attr.isCallable()) { Py::Tuple args(4); args.setItem(0, Py::asObject(linked->getPyObject())); args.setItem(1, Py::asObject(container->getPyObject())); - if(!_getElementCountValue()) { + if (!_getElementCountValue()) { Py::Callable(attr).apply(args); - } else { - const auto &elements = _getElementListValue(); - for(int i=0; i<_getElementCountValue(); ++i) { + } + else { + const auto& elements = _getElementListValue(); + for (int i = 0; i < _getElementCountValue(); ++i) { args.setItem(2, Py::Int(i)); - if(i < (int)elements.size()) + if (i < (int)elements.size()) { args.setItem(3, Py::asObject(elements[i]->getPyObject())); - else + } + else { args.setItem(3, Py::Object()); + } Py::Callable(attr).apply(args); } } } } - } catch (Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException e; e.ReportException(); return new App::DocumentObjectExecReturn(errMsg); - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); return new App::DocumentObjectExecReturn(errMsg); } @@ -387,17 +436,19 @@ App::DocumentObjectExecReturn *LinkBaseExtension::extensionExecute() { auto parent = getContainer(); setupCopyOnChange(parent); - if(hasCopyOnChange && getLinkCopyOnChangeValue()==CopyOnChangeDisabled) { + if (hasCopyOnChange && getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { hasCopyOnChange = false; std::vector props; parent->getPropertyList(props); - for(auto prop : props) { - if(isCopyOnChangeProperty(parent, *prop)) { + for (auto prop : props) { + if (isCopyOnChangeProperty(parent, *prop)) { try { parent->removeDynamicProperty(prop->getName()); - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); - } catch (...) { + } + catch (...) { } } } @@ -406,46 +457,53 @@ App::DocumentObjectExecReturn *LinkBaseExtension::extensionExecute() { return inherited::extensionExecute(); } -short LinkBaseExtension::extensionMustExecute() { +short LinkBaseExtension::extensionMustExecute() +{ auto link = getLink(); - if(!link) + if (!link) { return 0; + } return link->mustExecute(); } std::vector -LinkBaseExtension::getOnChangeCopyObjects( - std::vector *excludes, - App::DocumentObject *src) +LinkBaseExtension::getOnChangeCopyObjects(std::vector* excludes, + App::DocumentObject* src) { auto parent = getContainer(); - if (!src) + if (!src) { src = getLinkCopyOnChangeSourceValue(); - if (!src || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) + } + if (!src || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return {}; + } auto res = Document::getDependencyList({src}, Document::DepSort); - for (auto it=res.begin(); it!=res.end();) { + for (auto it = res.begin(); it != res.end();) { auto obj = *it; if (obj == src) { ++it; continue; } - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_CopyOnChangeControl")); + auto prop = + Base::freecad_dynamic_cast(obj->getPropertyByName("_CopyOnChangeControl")); static std::map dummy; - const auto & map = prop && prop->getContainer()==obj ? prop->getValues() : dummy; - const char *v = ""; - if (src->getDocument() != obj->getDocument()) + const auto& map = prop && prop->getContainer() == obj ? prop->getValues() : dummy; + const char* v = ""; + if (src->getDocument() != obj->getDocument()) { v = "-"; + } auto iter = map.find("*"); - if (iter != map.end()) + if (iter != map.end()) { v = iter->second.c_str(); - else if ((iter = map.find(parent->getNameInDocument())) != map.end()) + } + else if ((iter = map.find(parent->getNameInDocument())) != map.end()) { v = iter->second.c_str(); + } if (boost::equals(v, "-")) { - if (excludes) + if (excludes) { excludes->push_back(obj); + } else { it = res.erase(it); continue; @@ -456,24 +514,25 @@ LinkBaseExtension::getOnChangeCopyObjects( return res; } -void LinkBaseExtension::setOnChangeCopyObject( - App::DocumentObject *obj, OnChangeCopyOptions options) +void LinkBaseExtension::setOnChangeCopyObject(App::DocumentObject* obj, OnChangeCopyOptions options) { auto parent = getContainer(); Base::Flags flags(options); bool exclude = flags.testFlag(OnChangeCopyOptions::Exclude); bool external = parent->getDocument() != obj->getDocument(); - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_CopyOnChangeControl")); + auto prop = + Base::freecad_dynamic_cast(obj->getPropertyByName("_CopyOnChangeControl")); - if (external == exclude && !prop) + if (external == exclude && !prop) { return; + } if (!prop) { try { prop = static_cast( - obj->addDynamicProperty("App::PropertyMap", "_CopyOnChangeControl")); - } catch (Base::Exception &e) { + obj->addDynamicProperty("App::PropertyMap", "_CopyOnChangeControl")); + } + catch (Base::Exception& e) { e.ReportException(); } if (!prop) { @@ -482,11 +541,13 @@ void LinkBaseExtension::setOnChangeCopyObject( } } - const char *key = flags.testFlag(OnChangeCopyOptions::ApplyAll) ? "*" : parent->getDagKey(); - if (external) + const char* key = flags.testFlag(OnChangeCopyOptions::ApplyAll) ? "*" : parent->getDagKey(); + if (external) { prop->setValue(key, exclude ? "" : "+"); - else + } + else { prop->setValue(key, exclude ? "-" : ""); + } } // The purpose of this function is to synchronize the mutated copy to the @@ -494,18 +555,16 @@ void LinkBaseExtension::setOnChangeCopyObject( // non-CopyOnChange property of the original object has changed. void LinkBaseExtension::syncCopyOnChange() { - if (!getLinkCopyOnChangeValue()) + if (!getLinkCopyOnChangeValue()) { return; + } auto linkProp = getLinkedObjectProperty(); auto srcProp = getLinkCopyOnChangeSourceProperty(); auto srcTouched = getLinkCopyOnChangeTouchedProperty(); - if (!linkProp - || !srcProp - || !srcTouched - || !srcProp->getValue() - || !linkProp->getValue() - || srcProp->getValue() == linkProp->getValue()) + if (!linkProp || !srcProp || !srcTouched || !srcProp->getValue() || !linkProp->getValue() + || srcProp->getValue() == linkProp->getValue()) { return; + } auto parent = getContainer(); @@ -517,7 +576,7 @@ void LinkBaseExtension::syncCopyOnChange() // CopyOnChangeGroup is a hidden dynamic property for holding a LinkGroup // for holding the mutated copy of the original linked object and all its // dependencies. - LinkGroup *copyOnChangeGroup = nullptr; + LinkGroup* copyOnChangeGroup = nullptr; if (auto prop = getLinkCopyOnChangeGroupProperty()) { copyOnChangeGroup = Base::freecad_dynamic_cast(prop->getValue()); if (!copyOnChangeGroup) { @@ -526,20 +585,24 @@ void LinkBaseExtension::syncCopyOnChange() group->LinkMode.setValue(LinkModeAutoDelete); parent->getDocument()->addObject(group, "CopyOnChangeGroup"); prop->setValue(group); - } else { + } + else { // If it exists, then obtain all copied objects. Note that we stores // the dynamic property _SourceUUID in oldObjs if possible, in order // to match the possible new copy later. objs = copyOnChangeGroup->ElementList.getValues(); for (auto obj : objs) { - if (!obj->isAttachedToDocument()) + if (!obj->isAttachedToDocument()) { continue; - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_SourceUUID")); - if (prop && prop->getContainer() == obj) + } + auto prop = + Base::freecad_dynamic_cast(obj->getPropertyByName("_SourceUUID")); + if (prop && prop->getContainer() == obj) { oldObjs.emplace_back(prop); - else + } + else { oldObjs.emplace_back(obj); + } } std::sort(objs.begin(), objs.end()); } @@ -555,8 +618,9 @@ void LinkBaseExtension::syncCopyOnChange() // copyObject()) will generate a _ObjectUUID for each source object and // match it with a _SourceUUID in the copy. auto copiedObjs = parent->getDocument()->copyObject(srcObjs); - if(copiedObjs.empty()) + if (copiedObjs.empty()) { return; + } // copyObject() will return copy in order of the same order of the input, // so the last object will be the copy of the original linked object @@ -568,9 +632,9 @@ void LinkBaseExtension::syncCopyOnChange() std::vector propList; linked->getPropertyList(propList); for (auto prop : propList) { - if(!prop->testStatus(Property::CopyOnChange) - || prop->getContainer()!=linked) + if (!prop->testStatus(Property::CopyOnChange) || prop->getContainer() != linked) { continue; + } auto p = newLinked->getPropertyByName(prop->getName()); if (p && p->getTypeId() == prop->getTypeId()) { std::unique_ptr pCopy(prop->Copy()); @@ -596,53 +660,59 @@ void LinkBaseExtension::syncCopyOnChange() std::map newObjs; for (auto obj : copiedObjs) { - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_SourceUUID")); - if (prop) + auto prop = Base::freecad_dynamic_cast(obj->getPropertyByName("_SourceUUID")); + if (prop) { newObjs.insert(std::make_pair(prop->getValue(), obj)); + } } - std::vector > replacements; - for (const auto &objT : oldObjs) { + std::vector> replacements; + for (const auto& objT : oldObjs) { auto prop = Base::freecad_dynamic_cast(objT.getProperty()); - if (!prop) + if (!prop) { continue; + } auto it = newObjs.find(prop->getValue()); - if (it == newObjs.end()) + if (it == newObjs.end()) { continue; + } auto oldObj = objT.getObject(); auto newObj = it->second.getObject(); - if (oldObj && newObj) + if (oldObj && newObj) { replacements.emplace_back(oldObj, newObj); + } } - std::vector > > propChanges; + std::vector>> propChanges; if (!replacements.empty()) { std::sort(copiedObjs.begin(), copiedObjs.end()); // Global search for links affected by the replacement. We accumulate // the changes in propChanges without applying, in order to avoid any // side effect of changing while searching. - for(auto doc : App::GetApplication().getDocuments()) { - for(auto o : doc->getObjects()) { - if (o == parent - || std::binary_search(objs.begin(), objs.end(), o) - || std::binary_search(copiedObjs.begin(), copiedObjs.end(), o)) + for (auto doc : App::GetApplication().getDocuments()) { + for (auto o : doc->getObjects()) { + if (o == parent || std::binary_search(objs.begin(), objs.end(), o) + || std::binary_search(copiedObjs.begin(), copiedObjs.end(), o)) { continue; + } propList.clear(); o->getPropertyList(propList); - for(auto prop : propList) { - if (prop->getContainer() != o) + for (auto prop : propList) { + if (prop->getContainer() != o) { continue; + } auto linkProp = Base::freecad_dynamic_cast(prop); - if(!linkProp) + if (!linkProp) { continue; - for (const auto &v : replacements) { + } + for (const auto& v : replacements) { std::unique_ptr copy( - linkProp->CopyOnLinkReplace(parent,v.first,v.second)); - if(!copy) + linkProp->CopyOnLinkReplace(parent, v.first, v.second)); + if (!copy) { continue; - propChanges.emplace_back(App::DocumentObjectT(prop),std::move(copy)); + } + propChanges.emplace_back(App::DocumentObjectT(prop), std::move(copy)); } } } @@ -655,20 +725,22 @@ void LinkBaseExtension::syncCopyOnChange() srcTouched->setValue(false); // Apply the global link changes. - for(const auto &v : propChanges) { + for (const auto& v : propChanges) { auto prop = v.first.getProperty(); - if(prop) + if (prop) { prop->Paste(*v.second.get()); + } } // Finally, remove all old copies. oldObjs stores type of DocumentObjectT // which stores the object name. Before removing, we need to make sure the // object exists, and it is not some new object with the same name, by // checking objs which stores DocumentObject pointer. - for (const auto &objT : oldObjs) { + for (const auto& objT : oldObjs) { auto obj = objT.getObject(); - if (obj && std::binary_search(objs.begin(), objs.end(), obj)) + if (obj && std::binary_search(objs.begin(), objs.end(), obj)) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } @@ -678,101 +750,113 @@ bool LinkBaseExtension::isLinkedToConfigurableObject() const std::vector propList; linked->getPropertyList(propList); for (auto prop : propList) { - if(prop->testStatus(Property::CopyOnChange) - && prop->getContainer()==linked) + if (prop->testStatus(Property::CopyOnChange) && prop->getContainer() == linked) { return true; + } } } return false; } -bool LinkBaseExtension::isCopyOnChangeProperty(DocumentObject *obj, const App::Property &prop) { - if(obj!=prop.getContainer() || !prop.testStatus(App::Property::PropDynamic)) +bool LinkBaseExtension::isCopyOnChangeProperty(DocumentObject* obj, const App::Property& prop) +{ + if (obj != prop.getContainer() || !prop.testStatus(App::Property::PropDynamic)) { return false; + } auto group = prop.getGroup(); - return group && boost::starts_with(group,_GroupPrefix); + return group && boost::starts_with(group, _GroupPrefix); } -void LinkBaseExtension::setupCopyOnChange(DocumentObject *parent, bool checkSource) { +void LinkBaseExtension::setupCopyOnChange(DocumentObject* parent, bool checkSource) +{ copyOnChangeConns.clear(); copyOnChangeSrcConns.clear(); auto linked = getTrueLinkedObject(false); - if(!linked || getLinkCopyOnChangeValue()==CopyOnChangeDisabled) + if (!linked || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return; + } if (checkSource && !pauseCopyOnChange) { - PropertyLink *source = getLinkCopyOnChangeSourceProperty(); + PropertyLink* source = getLinkCopyOnChangeSourceProperty(); if (source) { source->setValue(linked); - if (auto touched = getLinkCopyOnChangeTouchedProperty()) + if (auto touched = getLinkCopyOnChangeTouchedProperty()) { touched->setValue(false); + } } } - hasCopyOnChange = setupCopyOnChange(parent,linked,©OnChangeConns,hasCopyOnChange); - if (hasCopyOnChange && getLinkCopyOnChangeValue() == CopyOnChangeOwned - && getLinkedObjectValue() - && getLinkedObjectValue() == getLinkCopyOnChangeSourceValue()) - { + hasCopyOnChange = setupCopyOnChange(parent, linked, ©OnChangeConns, hasCopyOnChange); + if (hasCopyOnChange && getLinkCopyOnChangeValue() == CopyOnChangeOwned && getLinkedObjectValue() + && getLinkedObjectValue() == getLinkCopyOnChangeSourceValue()) { makeCopyOnChange(); } } -bool LinkBaseExtension::setupCopyOnChange(DocumentObject *parent, DocumentObject *linked, - std::vector *copyOnChangeConns, bool checkExisting) +bool LinkBaseExtension::setupCopyOnChange( + DocumentObject* parent, + DocumentObject* linked, + std::vector* copyOnChangeConns, + bool checkExisting) { - if(!parent || !linked) + if (!parent || !linked) { return false; + } bool res = false; std::unordered_map newProps; std::vector props; linked->getPropertyList(props); - for(auto prop : props) { - if(!prop->testStatus(Property::CopyOnChange) - || prop->getContainer()!=linked) + for (auto prop : props) { + if (!prop->testStatus(Property::CopyOnChange) || prop->getContainer() != linked) { continue; + } res = true; const char* linkedGroupName = prop->getGroup(); - if(!linkedGroupName || !linkedGroupName[0]) + if (!linkedGroupName || !linkedGroupName[0]) { linkedGroupName = "Base"; + } std::string groupName; groupName = _GroupPrefix; - if(boost::starts_with(linkedGroupName,_GroupPrefix)) - groupName += linkedGroupName + sizeof(_GroupPrefix)-1; + if (boost::starts_with(linkedGroupName, _GroupPrefix)) { + groupName += linkedGroupName + sizeof(_GroupPrefix) - 1; + } else { groupName += linkedGroupName; groupName += ")"; } auto p = parent->getPropertyByName(prop->getName()); - if(p) { - if(p->getContainer()!=parent) + if (p) { + if (p->getContainer() != parent) { p = nullptr; + } else { const char* otherGroupName = p->getGroup(); - if(!otherGroupName || !boost::starts_with(otherGroupName, _GroupPrefix)) { - FC_WARN(p->getFullName() << " shadows another CopyOnChange property " - << prop->getFullName()); + if (!otherGroupName || !boost::starts_with(otherGroupName, _GroupPrefix)) { + FC_WARN(p->getFullName() + << " shadows another CopyOnChange property " << prop->getFullName()); continue; } - if(p->getTypeId() != prop->getTypeId() || groupName != otherGroupName) { + if (p->getTypeId() != prop->getTypeId() || groupName != otherGroupName) { parent->removeDynamicProperty(p->getName()); p = nullptr; } } } - if(!p) { + if (!p) { p = parent->addDynamicProperty(prop->getTypeId().getName(), - prop->getName(), groupName.c_str(), prop->getDocumentation()); + prop->getName(), + groupName.c_str(), + prop->getDocumentation()); std::unique_ptr pcopy(prop->Copy()); - Base::ObjectStatusLocker guard(Property::User3, p); - if(pcopy) { + Base::ObjectStatusLocker guard(Property::User3, p); + if (pcopy) { p->Paste(*pcopy); } p->setStatusValue(prop->getStatus()); @@ -780,99 +864,112 @@ bool LinkBaseExtension::setupCopyOnChange(DocumentObject *parent, DocumentObject newProps[p] = prop; } - if(checkExisting) { + if (checkExisting) { props.clear(); parent->getPropertyList(props); - for(auto prop : props) { - if(prop->getContainer()!=parent) + for (auto prop : props) { + if (prop->getContainer() != parent) { continue; + } auto gname = prop->getGroup(); - if(!gname || !boost::starts_with(gname, _GroupPrefix)) + if (!gname || !boost::starts_with(gname, _GroupPrefix)) { continue; - if(!newProps.count(prop)) + } + if (!newProps.count(prop)) { parent->removeDynamicProperty(prop->getName()); + } } } - if(!copyOnChangeConns) + if (!copyOnChangeConns) { return res; + } - for(const auto &v : newProps) { + for (const auto& v : newProps) { // sync configuration properties - copyOnChangeConns->push_back(v.second->signalChanged.connect([parent](const Property &prop) { - if(!prop.testStatus(Property::CopyOnChange)) - return; - auto p = parent->getPropertyByName(prop.getName()); - if(p && p->getTypeId()==prop.getTypeId()) { - std::unique_ptr pcopy(prop.Copy()); - // temperoray set Output to prevent touching - p->setStatus(Property::Output, true); - // temperoray block copy on change - Base::ObjectStatusLocker guard(Property::User3, p); - if(pcopy) - p->Paste(*pcopy); - p->setStatusValue(prop.getStatus()); - } - })); + copyOnChangeConns->push_back( + v.second->signalChanged.connect([parent](const Property& prop) { + if (!prop.testStatus(Property::CopyOnChange)) { + return; + } + auto p = parent->getPropertyByName(prop.getName()); + if (p && p->getTypeId() == prop.getTypeId()) { + std::unique_ptr pcopy(prop.Copy()); + // temperoray set Output to prevent touching + p->setStatus(Property::Output, true); + // temperoray block copy on change + Base::ObjectStatusLocker guard(Property::User3, p); + if (pcopy) { + p->Paste(*pcopy); + } + p->setStatusValue(prop.getStatus()); + } + })); } return res; } -void LinkBaseExtension::checkCopyOnChange(App::DocumentObject *parent, const App::Property &prop) +void LinkBaseExtension::checkCopyOnChange(App::DocumentObject* parent, const App::Property& prop) { - if(!parent || !parent->getDocument() - || parent->getDocument()->isPerformingTransaction()) + if (!parent || !parent->getDocument() || parent->getDocument()->isPerformingTransaction()) { return; + } auto linked = getLinkedObjectValue(); - if(!linked || getLinkCopyOnChangeValue()==CopyOnChangeDisabled - || !isCopyOnChangeProperty(parent,prop)) + if (!linked || getLinkCopyOnChangeValue() == CopyOnChangeDisabled + || !isCopyOnChangeProperty(parent, prop)) { return; + } - if(getLinkCopyOnChangeValue() == CopyOnChangeOwned || - (getLinkCopyOnChangeValue() == CopyOnChangeTracking - && linked != getLinkCopyOnChangeSourceValue())) - { + if (getLinkCopyOnChangeValue() == CopyOnChangeOwned + || (getLinkCopyOnChangeValue() == CopyOnChangeTracking + && linked != getLinkCopyOnChangeSourceValue())) { auto p = linked->getPropertyByName(prop.getName()); - if(p && p->getTypeId()==prop.getTypeId()) { + if (p && p->getTypeId() == prop.getTypeId()) { std::unique_ptr pcopy(prop.Copy()); - if(pcopy) + if (pcopy) { p->Paste(*pcopy); + } } return; } auto linkedProp = linked->getPropertyByName(prop.getName()); - if(!linkedProp || linkedProp->getTypeId()!=prop.getTypeId() || linkedProp->isSame(prop)) + if (!linkedProp || linkedProp->getTypeId() != prop.getTypeId() || linkedProp->isSame(prop)) { return; + } auto copied = makeCopyOnChange(); if (copied) { linkedProp = copied->getPropertyByName(prop.getName()); - if(linkedProp && linkedProp->getTypeId()==prop.getTypeId()) { + if (linkedProp && linkedProp->getTypeId() == prop.getTypeId()) { std::unique_ptr pcopy(prop.Copy()); - if(pcopy) + if (pcopy) { linkedProp->Paste(*pcopy); + } } } } -App::DocumentObject *LinkBaseExtension::makeCopyOnChange() { +App::DocumentObject* LinkBaseExtension::makeCopyOnChange() +{ auto linked = getLinkedObjectValue(); - if (pauseCopyOnChange || !linked) + if (pauseCopyOnChange || !linked) { return nullptr; + } auto parent = getContainer(); auto srcobjs = getOnChangeCopyObjects(nullptr, linked); for (auto obj : srcobjs) { if (obj->testStatus(App::PartialObject)) { - FC_THROWM(Base::RuntimeError, "Cannot copy partial loaded object: " - << obj->getFullName()); + FC_THROWM(Base::RuntimeError, + "Cannot copy partial loaded object: " << obj->getFullName()); } } auto objs = parent->getDocument()->copyObject(srcobjs); - if(objs.empty()) + if (objs.empty()) { return nullptr; + } monitorOnChangeCopyObjects(srcobjs); @@ -881,13 +978,15 @@ App::DocumentObject *LinkBaseExtension::makeCopyOnChange() { Base::StateLocker guard(pauseCopyOnChange); getLinkedObjectProperty()->setValue(linked); - if (getLinkCopyOnChangeValue() == CopyOnChangeEnabled) + if (getLinkCopyOnChangeValue() == CopyOnChangeEnabled) { getLinkCopyOnChangeProperty()->setValue(CopyOnChangeOwned); + } if (auto prop = getLinkCopyOnChangeGroupProperty()) { if (auto obj = prop->getValue()) { - if (obj->isAttachedToDocument() && obj->getDocument()) + if (obj->isAttachedToDocument() && obj->getDocument()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } auto group = new LinkGroup; group->LinkMode.setValue(LinkModeAutoDelete); @@ -905,328 +1004,410 @@ App::DocumentObject *LinkBaseExtension::makeCopyOnChange() { return linked; } -void LinkBaseExtension::monitorOnChangeCopyObjects( - const std::vector &objs) +void LinkBaseExtension::monitorOnChangeCopyObjects(const std::vector& objs) { copyOnChangeSrcConns.clear(); - if (getLinkCopyOnChangeValue() == CopyOnChangeDisabled) + if (getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return; - for(auto obj : objs) { + } + for (auto obj : objs) { obj->setStatus(App::ObjectStatus::TouchOnColorChange, true); - copyOnChangeSrcConns.emplace_back(obj->signalChanged.connect( - [this](const DocumentObject &, const Property &) { + copyOnChangeSrcConns.emplace_back( + obj->signalChanged.connect([this](const DocumentObject&, const Property&) { if (auto prop = this->getLinkCopyOnChangeTouchedProperty()) { - if (this->getLinkCopyOnChangeValue() != CopyOnChangeDisabled) + if (this->getLinkCopyOnChangeValue() != CopyOnChangeDisabled) { prop->setValue(true); + } } })); } } -App::GroupExtension *LinkBaseExtension::linkedPlainGroup() const { - if(!mySubElements.empty() && !mySubElements[0].empty()) +App::GroupExtension* LinkBaseExtension::linkedPlainGroup() const +{ + if (!mySubElements.empty() && !mySubElements[0].empty()) { return nullptr; + } auto linked = getTrueLinkedObject(false); - if(!linked) + if (!linked) { return nullptr; - return linked->getExtensionByType(true,false); + } + return linked->getExtensionByType(true, false); } -App::PropertyLinkList *LinkBaseExtension::_getElementListProperty() const { +App::PropertyLinkList* LinkBaseExtension::_getElementListProperty() const +{ auto group = linkedPlainGroup(); - if(group) + if (group) { return &group->Group; + } return const_cast(getElementListProperty()); } -const std::vector &LinkBaseExtension::_getElementListValue() const { - if(_ChildCache.getSize()) +const std::vector& LinkBaseExtension::_getElementListValue() const +{ + if (_ChildCache.getSize()) { return _ChildCache.getValues(); - if(getElementListProperty()) + } + if (getElementListProperty()) { return getElementListProperty()->getValues(); + } static const std::vector empty; return empty; } -App::PropertyBool *LinkBaseExtension::_getShowElementProperty() const { +App::PropertyBool* LinkBaseExtension::_getShowElementProperty() const +{ auto prop = getShowElementProperty(); - if(prop && !linkedPlainGroup()) + if (prop && !linkedPlainGroup()) { return const_cast(prop); + } return nullptr; } -bool LinkBaseExtension::_getShowElementValue() const { +bool LinkBaseExtension::_getShowElementValue() const +{ auto prop = _getShowElementProperty(); - if(prop) + if (prop) { return prop->getValue(); + } return true; } -App::PropertyInteger *LinkBaseExtension::_getElementCountProperty() const { +App::PropertyInteger* LinkBaseExtension::_getElementCountProperty() const +{ auto prop = getElementCountProperty(); - if(prop && !linkedPlainGroup()) + if (prop && !linkedPlainGroup()) { return const_cast(prop); + } return nullptr; } -int LinkBaseExtension::_getElementCountValue() const { +int LinkBaseExtension::_getElementCountValue() const +{ auto prop = _getElementCountProperty(); - if(prop) + if (prop) { return prop->getValue(); + } return 0; } -bool LinkBaseExtension::extensionHasChildElement() const { - if(!_getElementListValue().empty() - || (_getElementCountValue() && _getShowElementValue())) +bool LinkBaseExtension::extensionHasChildElement() const +{ + if (!_getElementListValue().empty() || (_getElementCountValue() && _getShowElementValue())) { return true; - if (getLinkClaimChildValue()) + } + if (getLinkClaimChildValue()) { return false; - DocumentObject *linked = getTrueLinkedObject(false); - if(linked) { - if(linked->hasChildElement()) + } + DocumentObject* linked = getTrueLinkedObject(false); + if (linked) { + if (linked->hasChildElement()) { return true; + } } return false; } -int LinkBaseExtension::extensionSetElementVisible(const char *element, bool visible) { - int index = _getShowElementValue()?getElementIndex(element):getArrayIndex(element); - if(index>=0) { +int LinkBaseExtension::extensionSetElementVisible(const char* element, bool visible) +{ + int index = _getShowElementValue() ? getElementIndex(element) : getArrayIndex(element); + if (index >= 0) { auto propElementVis = getVisibilityListProperty(); - if(!propElementVis || !element || !element[0]) + if (!propElementVis || !element || !element[0]) { return -1; - if(propElementVis->getSize()<=index) { - if(visible) - return 1; - propElementVis->setSize(index+1, true); } - propElementVis->setStatus(Property::User3,true); - propElementVis->set1Value(index,visible); - propElementVis->setStatus(Property::User3,false); - const auto &elements = _getElementListValue(); - if(index<(int)elements.size()) { - if(!visible) + if (propElementVis->getSize() <= index) { + if (visible) { + return 1; + } + propElementVis->setSize(index + 1, true); + } + propElementVis->setStatus(Property::User3, true); + propElementVis->set1Value(index, visible); + propElementVis->setStatus(Property::User3, false); + const auto& elements = _getElementListValue(); + if (index < (int)elements.size()) { + if (!visible) { myHiddenElements.insert(elements[index]); - else + } + else { myHiddenElements.erase(elements[index]); + } } return 1; } - DocumentObject *linked = getTrueLinkedObject(false); - if(linked) - return linked->setElementVisible(element,visible); + DocumentObject* linked = getTrueLinkedObject(false); + if (linked) { + return linked->setElementVisible(element, visible); + } return -1; } -int LinkBaseExtension::extensionIsElementVisible(const char *element) { - int index = _getShowElementValue()?getElementIndex(element):getArrayIndex(element); - if(index>=0) { +int LinkBaseExtension::extensionIsElementVisible(const char* element) +{ + int index = _getShowElementValue() ? getElementIndex(element) : getArrayIndex(element); + if (index >= 0) { auto propElementVis = getVisibilityListProperty(); - if(propElementVis) { - if(propElementVis->getSize()<=index || propElementVis->getValues()[index]) + if (propElementVis) { + if (propElementVis->getSize() <= index || propElementVis->getValues()[index]) { return 1; + } return 0; } return -1; } - DocumentObject *linked = getTrueLinkedObject(false); - if(linked) + DocumentObject* linked = getTrueLinkedObject(false); + if (linked) { return linked->isElementVisible(element); + } return -1; } -const DocumentObject *LinkBaseExtension::getContainer() const { +const DocumentObject* LinkBaseExtension::getContainer() const +{ auto ext = getExtendedContainer(); - if(!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) - LINK_THROW(Base::RuntimeError,"Link: container not derived from document object"); - return static_cast(ext); + if (!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) { + LINK_THROW(Base::RuntimeError, "Link: container not derived from document object"); + } + return static_cast(ext); } -DocumentObject *LinkBaseExtension::getContainer(){ +DocumentObject* LinkBaseExtension::getContainer() +{ auto ext = getExtendedContainer(); - if(!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) - LINK_THROW(Base::RuntimeError,"Link: container not derived from document object"); - return static_cast(ext); + if (!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) { + LINK_THROW(Base::RuntimeError, "Link: container not derived from document object"); + } + return static_cast(ext); } -DocumentObject *LinkBaseExtension::getLink(int depth) const{ - if (!GetApplication().checkLinkDepth(depth, MessageOption::Error)) +DocumentObject* LinkBaseExtension::getLink(int depth) const +{ + if (!GetApplication().checkLinkDepth(depth, MessageOption::Error)) { return nullptr; - if(getLinkedObjectProperty()) + } + if (getLinkedObjectProperty()) { return getLinkedObjectValue(); + } return nullptr; } -int LinkBaseExtension::getArrayIndex(const char *subname, const char **psubname) { - if(!subname || Data::isMappedElement(subname)) +int LinkBaseExtension::getArrayIndex(const char* subname, const char** psubname) +{ + if (!subname || Data::isMappedElement(subname)) { return -1; - const char *dot = strchr(subname,'.'); - if(!dot) dot= subname+strlen(subname); - if(dot == subname) - return -1; - int idx = 0; - for(const char *c=subname;c!=dot;++c) { - if(!isdigit(*c)) - return -1; - idx = idx*10 + *c -'0'; } - if(psubname) { - if(*dot) - *psubname = dot+1; - else + const char* dot = strchr(subname, '.'); + if (!dot) { + dot = subname + strlen(subname); + } + if (dot == subname) { + return -1; + } + int idx = 0; + for (const char* c = subname; c != dot; ++c) { + if (!isdigit(*c)) { + return -1; + } + idx = idx * 10 + *c - '0'; + } + if (psubname) { + if (*dot) { + *psubname = dot + 1; + } + else { *psubname = dot; + } } return idx; } -int LinkBaseExtension::getElementIndex(const char *subname, const char **psubname) const { - if(!subname || Data::isMappedElement(subname)) +int LinkBaseExtension::getElementIndex(const char* subname, const char** psubname) const +{ + if (!subname || Data::isMappedElement(subname)) { return -1; + } int idx = -1; - const char *dot = strchr(subname,'.'); - if(!dot) dot= subname+strlen(subname); + const char* dot = strchr(subname, '.'); + if (!dot) { + dot = subname + strlen(subname); + } - if(isdigit(subname[0])) { + if (isdigit(subname[0])) { // If the name start with digits, treat as index reference - idx = getArrayIndex(subname,nullptr); - if(idx<0) + idx = getArrayIndex(subname, nullptr); + if (idx < 0) { return -1; - if(_getElementCountProperty()) { - if(idx>=_getElementCountValue()) + } + if (_getElementCountProperty()) { + if (idx >= _getElementCountValue()) { return -1; - }else if(idx>=(int)_getElementListValue().size()) + } + } + else if (idx >= (int)_getElementListValue().size()) { return -1; - }else if(!_getShowElementValue() && _getElementCountValue()) { + } + } + else if (!_getShowElementValue() && _getElementCountValue()) { // If elements are collapsed, we check first for LinkElement naming // pattern, which is the owner object name + "_i" + index - const char *name = subname[0]=='$'?subname+1:subname; + const char* name = subname[0] == '$' ? subname + 1 : subname; auto owner = getContainer(); - if(owner && owner->isAttachedToDocument()) { + if (owner && owner->isAttachedToDocument()) { std::string ownerName(owner->getNameInDocument()); ownerName += '_'; - if(boost::algorithm::starts_with(name,ownerName.c_str())) { - for(const char *txt=dot-1;txt>=name+ownerName.size();--txt) { - if(*txt == 'i') { - idx = getArrayIndex(txt+1,nullptr); - if(idx<0 || idx>=_getElementCountValue()) + if (boost::algorithm::starts_with(name, ownerName.c_str())) { + for (const char* txt = dot - 1; txt >= name + ownerName.size(); --txt) { + if (*txt == 'i') { + idx = getArrayIndex(txt + 1, nullptr); + if (idx < 0 || idx >= _getElementCountValue()) { idx = -1; + } break; } - if(!isdigit(*txt)) + if (!isdigit(*txt)) { break; + } } } } - if(idx<0) { + if (idx < 0) { // Then check for the actual linked object's name or label, and // redirect that reference to the first array element auto linked = getTrueLinkedObject(false); - if(!linked || !linked->isAttachedToDocument()) + if (!linked || !linked->isAttachedToDocument()) { return -1; - if(subname[0]=='$') { - CharRange sub(subname+1, dot); - if (boost::equals(sub, linked->Label.getValue())) - idx = 0; - } else { - CharRange sub(subname, dot); - if (boost::equals(sub, linked->getNameInDocument())) - idx = 0; } - if(idx<0) { + if (subname[0] == '$') { + CharRange sub(subname + 1, dot); + if (boost::equals(sub, linked->Label.getValue())) { + idx = 0; + } + } + else { + CharRange sub(subname, dot); + if (boost::equals(sub, linked->getNameInDocument())) { + idx = 0; + } + } + if (idx < 0) { // Lastly, try to get sub object directly from the linked object - auto sobj = linked->getSubObject(std::string(subname, dot-subname+1).c_str()); - if(!sobj) + auto sobj = linked->getSubObject(std::string(subname, dot - subname + 1).c_str()); + if (!sobj) { return -1; - if(psubname) + } + if (psubname) { *psubname = subname; + } return 0; } } - }else if(subname[0]!='$') { + } + else if (subname[0] != '$') { // Try search by element objects' name - std::string name(subname,dot); - if(_ChildCache.getSize()) { - auto obj=_ChildCache.findUsingMap(name,&idx); - if(obj) { - auto group = obj->getExtensionByType(true,false); - if(group) { - int nidx = getElementIndex(dot+1,psubname); - if(nidx >= 0) + std::string name(subname, dot); + if (_ChildCache.getSize()) { + auto obj = _ChildCache.findUsingMap(name, &idx); + if (obj) { + auto group = obj->getExtensionByType(true, false); + if (group) { + int nidx = getElementIndex(dot + 1, psubname); + if (nidx >= 0) { return nidx; + } } } - } else if(getElementListProperty()) - getElementListProperty()->find(name.c_str(),&idx); - if(idx<0) + } + else if (getElementListProperty()) { + getElementListProperty()->find(name.c_str(), &idx); + } + if (idx < 0) { return -1; - }else { + } + } + else { // Try search by label if the reference name start with '$' ++subname; - std::string name(subname,dot-subname); - const auto &elements = _getElementListValue(); - if(enableLabelCache) { - if(myLabelCache.empty()) + std::string name(subname, dot - subname); + const auto& elements = _getElementListValue(); + if (enableLabelCache) { + if (myLabelCache.empty()) { cacheChildLabel(1); + } auto it = myLabelCache.find(name); - if(it == myLabelCache.end()) + if (it == myLabelCache.end()) { return -1; + } idx = it->second; - }else{ + } + else { idx = 0; - for(auto element : elements) { - if(element->Label.getStrValue() == name) + for (auto element : elements) { + if (element->Label.getStrValue() == name) { break; + } ++idx; } } - if(idx<0 || idx>=(int)elements.size()) + if (idx < 0 || idx >= (int)elements.size()) { return -1; + } auto obj = elements[idx]; - if(obj && _ChildCache.getSize()) { - auto group = obj->getExtensionByType(true,false); - if(group) { - int nidx = getElementIndex(dot+1,psubname); - if(nidx >= 0) + if (obj && _ChildCache.getSize()) { + auto group = obj->getExtensionByType(true, false); + if (group) { + int nidx = getElementIndex(dot + 1, psubname); + if (nidx >= 0) { return nidx; + } } } } - if(psubname) - *psubname = dot[0]?dot+1:dot; + if (psubname) { + *psubname = dot[0] ? dot + 1 : dot; + } return idx; } -void LinkBaseExtension::elementNameFromIndex(int idx, std::ostream &ss) const { - const auto &elements = _getElementListValue(); - if(idx < 0 || idx >= (int)elements.size()) +void LinkBaseExtension::elementNameFromIndex(int idx, std::ostream& ss) const +{ + const auto& elements = _getElementListValue(); + if (idx < 0 || idx >= (int)elements.size()) { return; + } auto obj = elements[idx]; - if(_ChildCache.getSize()) { + if (_ChildCache.getSize()) { auto group = GroupExtension::getGroupOfObject(obj); - if(group && _ChildCache.find(group->getNameInDocument(),&idx)) - elementNameFromIndex(idx,ss); + if (group && _ChildCache.find(group->getNameInDocument(), &idx)) { + elementNameFromIndex(idx, ss); + } } ss << obj->getNameInDocument() << '.'; } -Base::Vector3d LinkBaseExtension::getScaleVector() const { - if(getScaleVectorProperty()) +Base::Vector3d LinkBaseExtension::getScaleVector() const +{ + if (getScaleVectorProperty()) { return getScaleVectorValue(); + } double s = getScaleValue(); - return Base::Vector3d(s,s,s); + return Base::Vector3d(s, s, s); } -Base::Matrix4D LinkBaseExtension::getTransform(bool transform) const { +Base::Matrix4D LinkBaseExtension::getTransform(bool transform) const +{ Base::Matrix4D mat; - if(transform) { - if(getLinkPlacementProperty()) + if (transform) { + if (getLinkPlacementProperty()) { mat = getLinkPlacementValue().toMatrix(); - else if(getPlacementProperty()) + } + else if (getPlacementProperty()) { mat = getPlacementValue().toMatrix(); + } } - if(getScaleProperty() || getScaleVectorProperty()) { + if (getScaleProperty() || getScaleVectorProperty()) { Base::Matrix4D s; s.scale(getScaleVector()); mat *= s; @@ -1234,45 +1415,52 @@ Base::Matrix4D LinkBaseExtension::getTransform(bool transform) const { return mat; } -bool LinkBaseExtension::extensionGetSubObjects(std::vector &ret, int reason) const { - if(!getLinkedObjectProperty() && getElementListProperty()) { - for(auto obj : getElementListProperty()->getValues()) { - if(obj && obj->isAttachedToDocument()) { +bool LinkBaseExtension::extensionGetSubObjects(std::vector& ret, int reason) const +{ + if (!getLinkedObjectProperty() && getElementListProperty()) { + for (auto obj : getElementListProperty()->getValues()) { + if (obj && obj->isAttachedToDocument()) { std::string name(obj->getNameInDocument()); - name+='.'; + name += '.'; ret.push_back(name); } } return true; } - if(mySubElements.empty() || mySubElements[0].empty()) { - DocumentObject *linked = getTrueLinkedObject(true); - if(linked) { - if(!_getElementCountValue()) + if (mySubElements.empty() || mySubElements[0].empty()) { + DocumentObject* linked = getTrueLinkedObject(true); + if (linked) { + if (!_getElementCountValue()) { ret = linked->getSubObjects(reason); - else{ + } + else { char index[30]; - for(int i=0,count=_getElementCountValue();i1) { + } + else if (mySubElements.size() > 1) { ret = mySubElements; } return true; } -bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const +bool LinkBaseExtension::extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const { ret = nullptr; auto obj = getContainer(); - if(!subname || !subname[0]) { + if (!subname || !subname[0]) { ret = const_cast(obj); Base::Matrix4D _mat; - if(mat) { + if (mat) { // 'mat' here is used as an output to return the accumulated // transformation up until this object. Since 'subname' is empty // here, it means the we are at the end of the hierarchy. We shall @@ -1281,61 +1469,73 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * // Think of it this way, the transformation along object hierarchy // is public, while transformation through linkage is private to // link itself. - if(transform) { - if(getLinkPlacementProperty()) + if (transform) { + if (getLinkPlacementProperty()) { *mat *= getLinkPlacementValue().toMatrix(); - else if(getPlacementProperty()) + } + else if (getPlacementProperty()) { *mat *= getPlacementValue().toMatrix(); + } } _mat = *mat; } - if(pyObj && !_getElementCountValue() - && _getElementListValue().empty() && mySubElements.size()<=1) - { + if (pyObj && !_getElementCountValue() && _getElementListValue().empty() + && mySubElements.size() <= 1) { // Scale will be included here - if(getScaleProperty() || getScaleVectorProperty()) { + if (getScaleProperty() || getScaleVectorProperty()) { Base::Matrix4D s; s.scale(getScaleVector()); _mat *= s; } - auto linked = getTrueLinkedObject(false,&_mat,depth); - if(linked && linked!=obj) { - linked->getSubObject(mySubElements.empty()?nullptr:mySubElements.front().c_str(), - pyObj,&_mat,false,depth+1); - checkGeoElementMap(obj,linked,pyObj,nullptr); + auto linked = getTrueLinkedObject(false, &_mat, depth); + if (linked && linked != obj) { + linked->getSubObject(mySubElements.empty() ? nullptr + : mySubElements.front().c_str(), + pyObj, + &_mat, + false, + depth + 1); + checkGeoElementMap(obj, linked, pyObj, nullptr); } } return true; } - if(mat) *mat *= getTransform(transform); + if (mat) { + *mat *= getTransform(transform); + } - //DocumentObject *element = 0; + // DocumentObject *element = 0; bool isElement = false; - int idx = getElementIndex(subname,&subname); - if(idx>=0) { - const auto &elements = _getElementListValue(); - if(!elements.empty()) { - if(idx>=(int)elements.size() || !elements[idx] || !elements[idx]->isAttachedToDocument()) + int idx = getElementIndex(subname, &subname); + if (idx >= 0) { + const auto& elements = _getElementListValue(); + if (!elements.empty()) { + if (idx >= (int)elements.size() || !elements[idx] + || !elements[idx]->isAttachedToDocument()) { return true; - ret = elements[idx]->getSubObject(subname,pyObj,mat,true,depth+1); + } + ret = elements[idx]->getSubObject(subname, pyObj, mat, true, depth + 1); // do not resolve the link if this element is the last referenced object - if(!subname || Data::isMappedElement(subname) || !strchr(subname,'.')) + if (!subname || Data::isMappedElement(subname) || !strchr(subname, '.')) { ret = elements[idx]; + } return true; } int elementCount = _getElementCountValue(); - if(idx>=elementCount) + if (idx >= elementCount) { return true; + } isElement = true; - if(mat) { + if (mat) { auto placementList = getPlacementListProperty(); - if(placementList && placementList->getSize()>idx) + if (placementList && placementList->getSize() > idx) { *mat *= (*placementList)[idx].toMatrix(); + } auto scaleList = getScaleListProperty(); - if(scaleList && scaleList->getSize()>idx) { + if (scaleList && scaleList->getSize() > idx) { Base::Matrix4D s; s.scale((*scaleList)[idx]); *mat *= s; @@ -1343,9 +1543,10 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * } } - auto linked = getTrueLinkedObject(false,mat,depth); - if(!linked || linked==obj) + auto linked = getTrueLinkedObject(false, mat, depth); + if (!linked || linked == obj) { return true; + } Base::Matrix4D matNext; @@ -1353,20 +1554,25 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * // claimed as the first child. Regardless of the current value of // LinkClaimChild, we must accept sub-object path that contains the linked // object, because other link property may store such reference. - if (const char* dot=strchr(subname,'.')) { + if (const char* dot = strchr(subname, '.')) { auto group = getLinkCopyOnChangeGroupValue(); if (subname[0] == '$') { - CharRange sub(subname+1,dot); - if (group && boost::equals(sub, group->Label.getValue())) + CharRange sub(subname + 1, dot); + if (group && boost::equals(sub, group->Label.getValue())) { linked = group; - else if(!boost::equals(sub, linked->Label.getValue())) + } + else if (!boost::equals(sub, linked->Label.getValue())) { dot = nullptr; - } else { - CharRange sub(subname,dot); - if (group && boost::equals(sub, group->getNameInDocument())) + } + } + else { + CharRange sub(subname, dot); + if (group && boost::equals(sub, group->getNameInDocument())) { linked = group; - else if (!boost::equals(sub, linked->getNameInDocument())) + } + else if (!boost::equals(sub, linked->getNameInDocument())) { dot = nullptr; + } } if (dot) { // Because of external linked object, It is possible for and @@ -1374,127 +1580,153 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * // as the parent object. To resolve this potential ambiguity, // try assuming the current subname is referring to the parent // (i.e. the linked object), and if it fails, try again below. - if(mat) matNext = *mat; - ret = linked->getSubObject(dot+1,pyObj,mat?&matNext:nullptr,false,depth+1); - if (ret && dot[1]) - subname = dot+1; + if (mat) { + matNext = *mat; + } + ret = linked->getSubObject(dot + 1, pyObj, mat ? &matNext : nullptr, false, depth + 1); + if (ret && dot[1]) { + subname = dot + 1; + } } } if (!ret) { - if(mat) matNext = *mat; - ret = linked->getSubObject(subname,pyObj,mat?&matNext:nullptr,false,depth+1); + if (mat) { + matNext = *mat; + } + ret = linked->getSubObject(subname, pyObj, mat ? &matNext : nullptr, false, depth + 1); } std::string postfix; - if(ret) { + if (ret) { // do not resolve the link if we are the last referenced object - if(subname && !Data::isMappedElement(subname) && strchr(subname,'.')) { - if(mat) + if (subname && !Data::isMappedElement(subname) && strchr(subname, '.')) { + if (mat) { *mat = matNext; + } } // This is a useless check as 'element' is never set to a value other than null - //else if(element) { + // else if(element) { // ret = element; //} - else if(!isElement) { + else if (!isElement) { ret = const_cast(obj); } else { - if(idx) { + if (idx) { postfix = Data::POSTFIX_INDEX; postfix += std::to_string(idx); } - if(mat) + if (mat) { *mat = matNext; + } } } - checkGeoElementMap(obj,linked,pyObj,!postfix.empty()?postfix.c_str():nullptr); + checkGeoElementMap(obj, linked, pyObj, !postfix.empty() ? postfix.c_str() : nullptr); return true; } -void LinkBaseExtension::checkGeoElementMap(const App::DocumentObject *obj, - const App::DocumentObject *linked, PyObject **pyObj, const char *postfix) const +void LinkBaseExtension::checkGeoElementMap(const App::DocumentObject* obj, + const App::DocumentObject* linked, + PyObject** pyObj, + const char* postfix) const { - if(!pyObj || !*pyObj || (!postfix && obj->getDocument()==linked->getDocument()) || - !PyObject_TypeCheck(*pyObj, &Data::ComplexGeoDataPy::Type)) + if (!pyObj || !*pyObj || (!postfix && obj->getDocument() == linked->getDocument()) + || !PyObject_TypeCheck(*pyObj, &Data::ComplexGeoDataPy::Type)) { return; + } -// auto geoData = static_cast(*pyObj)->getComplexGeoDataPtr(); -// geoData->reTagElementMap(obj->getID(),obj->getDocument()->Hasher,postfix); + // auto geoData = static_cast(*pyObj)->getComplexGeoDataPtr(); + // geoData->reTagElementMap(obj->getID(),obj->getDocument()->Hasher,postfix); auto geoData = static_cast(*pyObj)->getComplexGeoDataPtr(); std::string _postfix; if (linked && obj && linked->getDocument() != obj->getDocument()) { _postfix = Data::POSTFIX_EXTERNAL_TAG; if (postfix) { - if (!boost::starts_with(postfix, Data::ComplexGeoData::elementMapPrefix())) + if (!boost::starts_with(postfix, Data::ComplexGeoData::elementMapPrefix())) { _postfix += Data::ComplexGeoData::elementMapPrefix(); + } _postfix += postfix; } postfix = _postfix.c_str(); } - geoData->reTagElementMap(obj->getID(),obj->getDocument()->getStringHasher(),postfix); - + geoData->reTagElementMap(obj->getID(), obj->getDocument()->getStringHasher(), postfix); } -void LinkBaseExtension::onExtendedUnsetupObject() { - if(!getElementListProperty()) +void LinkBaseExtension::onExtendedUnsetupObject() +{ + if (!getElementListProperty()) { return; + } detachElements(); if (auto obj = getLinkCopyOnChangeGroupValue()) { - if(obj->isAttachedToDocument() && !obj->isRemoving()) + if (obj->isAttachedToDocument() && !obj->isRemoving()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } -DocumentObject *LinkBaseExtension::getTrueLinkedObject( - bool recurse, Base::Matrix4D *mat, int depth, bool noElement) const +DocumentObject* LinkBaseExtension::getTrueLinkedObject(bool recurse, + Base::Matrix4D* mat, + int depth, + bool noElement) const { - if(noElement && extensionIsDerivedFrom(LinkElement::getExtensionClassTypeId()) - && !static_cast(this)->canDelete()) - { + if (noElement && extensionIsDerivedFrom(LinkElement::getExtensionClassTypeId()) + && !static_cast(this)->canDelete()) { return nullptr; } auto ret = getLink(depth); - if(!ret) + if (!ret) { return nullptr; + } bool transform = linkTransform(); - const char *subname = getSubName(); - if(subname || (mat && transform)) { - ret = ret->getSubObject(subname,nullptr,mat,transform,depth+1); + const char* subname = getSubName(); + if (subname || (mat && transform)) { + ret = ret->getSubObject(subname, nullptr, mat, transform, depth + 1); transform = false; } - if(ret && recurse) - ret = ret->getLinkedObject(recurse,mat,transform,depth+1); - if(ret && !ret->isAttachedToDocument()) + if (ret && recurse) { + ret = ret->getLinkedObject(recurse, mat, transform, depth + 1); + } + if (ret && !ret->isAttachedToDocument()) { return nullptr; + } return ret; } -bool LinkBaseExtension::extensionGetLinkedObject(DocumentObject *&ret, - bool recurse, Base::Matrix4D *mat, bool transform, int depth) const +bool LinkBaseExtension::extensionGetLinkedObject(DocumentObject*& ret, + bool recurse, + Base::Matrix4D* mat, + bool transform, + int depth) const { - if(mat) + if (mat) { *mat *= getTransform(transform); + } ret = nullptr; - if(!_getElementCountValue()) - ret = getTrueLinkedObject(recurse,mat,depth); - if(!ret) + if (!_getElementCountValue()) { + ret = getTrueLinkedObject(recurse, mat, depth); + } + if (!ret) { ret = const_cast(getContainer()); + } // always return true to indicate we've handled getLinkObject() call return true; } -void LinkBaseExtension::extensionOnChanged(const Property *prop) { +void LinkBaseExtension::extensionOnChanged(const Property* prop) +{ auto parent = getContainer(); - if(parent && !parent->isRestoring() && prop && !prop->testStatus(Property::User3)) - update(parent,prop); + if (parent && !parent->isRestoring() && prop && !prop->testStatus(Property::User3)) { + update(parent, prop); + } inherited::extensionOnChanged(prop); } -void LinkBaseExtension::parseSubName() const { +void LinkBaseExtension::parseSubName() const +{ // If user has ever linked to some sub-element, the Link shall always accept // sub-element linking in the future, which affects how ViewProviderLink // dropObjectEx() behave. So we will push an empty string later even if no @@ -1503,132 +1735,153 @@ void LinkBaseExtension::parseSubName() const { mySubElements.clear(); mySubName.clear(); auto xlink = freecad_dynamic_cast(getLinkedObjectProperty()); - if(!xlink || xlink->getSubValues().empty()) { - if(hasSubElement) + if (!xlink || xlink->getSubValues().empty()) { + if (hasSubElement) { mySubElements.emplace_back(""); + } return; } - const auto &subs = xlink->getSubValues(); + const auto& subs = xlink->getSubValues(); auto subname = subs.front().c_str(); auto element = Data::findElementName(subname); - if(!element || !element[0]) { + if (!element || !element[0]) { mySubName = subs[0]; - if(hasSubElement) + if (hasSubElement) { mySubElements.emplace_back(""); + } return; } mySubElements.emplace_back(element); - mySubName = std::string(subname,element-subname); - for(std::size_t i=1;i(true,false); - if(group && &prop == &group->Group) +void LinkBaseExtension::slotChangedPlainGroup(const App::DocumentObject& obj, + const App::Property& prop) +{ + auto group = obj.getExtensionByType(true, false); + if (group && &prop == &group->Group) { updateGroup(); + } } -void LinkBaseExtension::updateGroup() { +void LinkBaseExtension::updateGroup() +{ std::vector groups; std::unordered_set groupSet; auto group = linkedPlainGroup(); - if(group) { + if (group) { groups.push_back(group); groupSet.insert(group->getExtendedObject()); - }else{ - for(auto o : getElementListProperty()->getValues()) { - if(!o || !o->isAttachedToDocument()) + } + else { + for (auto o : getElementListProperty()->getValues()) { + if (!o || !o->isAttachedToDocument()) { continue; - auto ext = o->getExtensionByType(true,false); - if(ext) { + } + auto ext = o->getExtensionByType(true, false); + if (ext) { groups.push_back(ext); groupSet.insert(o); } } } std::vector children; - if(!groups.empty()) { + if (!groups.empty()) { children = getElementListValue(); - std::set childSet(children.begin(),children.end()); - for(auto ext : groups) { + std::set childSet(children.begin(), children.end()); + for (auto ext : groups) { auto group = ext->getExtendedObject(); - auto &conn = plainGroupConns[group]; - if(!conn.connected()) { - FC_LOG("new group connection " << getExtendedObject()->getFullName() - << " -> " << group->getFullName()); - //NOLINTBEGIN + auto& conn = plainGroupConns[group]; + if (!conn.connected()) { + FC_LOG("new group connection " << getExtendedObject()->getFullName() << " -> " + << group->getFullName()); + // NOLINTBEGIN conn = group->signalChanged.connect( - std::bind(&LinkBaseExtension::slotChangedPlainGroup,this,sp::_1,sp::_2)); - //NOLINTEND + std::bind(&LinkBaseExtension::slotChangedPlainGroup, this, sp::_1, sp::_2)); + // NOLINTEND } std::size_t count = children.size(); - ext->getAllChildren(children,childSet); - for(;countgetAllChildren(children, childSet); + for (; count < children.size(); ++count) { auto child = children[count]; - if(!child->getExtensionByType(true,false)) + if (!child->getExtensionByType(true, false)) { continue; + } groupSet.insert(child); - auto &conn = plainGroupConns[child]; - if(!conn.connected()) { - FC_LOG("new group connection " << getExtendedObject()->getFullName() - << " -> " << child->getFullName()); - //NOLINTBEGIN + auto& conn = plainGroupConns[child]; + if (!conn.connected()) { + FC_LOG("new group connection " << getExtendedObject()->getFullName() << " -> " + << child->getFullName()); + // NOLINTBEGIN conn = child->signalChanged.connect( - std::bind(&LinkBaseExtension::slotChangedPlainGroup,this,sp::_1,sp::_2)); - //NOLINTEND + std::bind(&LinkBaseExtension::slotChangedPlainGroup, this, sp::_1, sp::_2)); + // NOLINTEND } } } } - for(auto it=plainGroupConns.begin();it!=plainGroupConns.end();) { - if(!groupSet.count(it->first)) + for (auto it = plainGroupConns.begin(); it != plainGroupConns.end();) { + if (!groupSet.count(it->first)) { it = plainGroupConns.erase(it); - else + } + else { ++it; + } } - if(children != _ChildCache.getValues()) + if (children != _ChildCache.getValues()) { _ChildCache.setValue(children); + } } -void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop) { - if(!prop) +void LinkBaseExtension::update(App::DocumentObject* parent, const Property* prop) +{ + if (!prop) { return; + } - if(prop == getLinkPlacementProperty() || prop == getPlacementProperty()) { + if (prop == getLinkPlacementProperty() || prop == getPlacementProperty()) { auto src = getLinkPlacementProperty(); auto dst = getPlacementProperty(); - if(src!=prop) std::swap(src,dst); - if(src && dst) { - dst->setStatus(Property::User3,true); - dst->setValue(src->getValue()); - dst->setStatus(Property::User3,false); + if (src != prop) { + std::swap(src, dst); } - }else if(prop == getScaleProperty()) { - if(!prop->testStatus(Property::User3) && getScaleVectorProperty()) { + if (src && dst) { + dst->setStatus(Property::User3, true); + dst->setValue(src->getValue()); + dst->setStatus(Property::User3, false); + } + } + else if (prop == getScaleProperty()) { + if (!prop->testStatus(Property::User3) && getScaleVectorProperty()) { auto s = getScaleValue(); auto p = getScaleVectorProperty(); - p->setStatus(Property::User3,true); - p->setValue(s,s,s); - p->setStatus(Property::User3,false); + p->setStatus(Property::User3, true); + p->setValue(s, s, s); + p->setStatus(Property::User3, false); } - }else if(prop == getScaleVectorProperty()) { - if(!prop->testStatus(Property::User3) && getScaleProperty()) { - const auto &v = getScaleVectorValue(); - if(v.x == v.y && v.x == v.z) { + } + else if (prop == getScaleVectorProperty()) { + if (!prop->testStatus(Property::User3) && getScaleProperty()) { + const auto& v = getScaleVectorValue(); + if (v.x == v.y && v.x == v.z) { auto p = getScaleProperty(); - p->setStatus(Property::User3,true); + p->setStatus(Property::User3, true); p->setValue(v.x); - p->setStatus(Property::User3,false); + p->setStatus(Property::User3, false); } } - }else if(prop == _getShowElementProperty()) { - if(_getShowElementValue()) - update(parent,_getElementCountProperty()); + } + else if (prop == _getShowElementProperty()) { + if (_getShowElementValue()) { + update(parent, _getElementCountProperty()); + } else { auto objs = getElementListValue(); @@ -1637,14 +1890,15 @@ void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop placements.reserve(objs.size()); std::vector scales; scales.reserve(objs.size()); - for(auto obj : objs) { + for (auto obj : objs) { auto element = freecad_dynamic_cast(obj); - if(element) { + if (element) { placements.push_back(element->Placement.getValue()); scales.push_back(element->getScaleVector()); - }else{ + } + else { placements.emplace_back(); - scales.emplace_back(1,1,1); + scales.emplace_back(1, 1, 1); } } // touch the property again to make sure view provider has been @@ -1655,65 +1909,76 @@ void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop getElementListProperty()->setValues(std::vector()); - if(getPlacementListProperty()) { - getPlacementListProperty()->setStatus(Property::User3, getScaleListProperty() != nullptr); + if (getPlacementListProperty()) { + getPlacementListProperty()->setStatus(Property::User3, + getScaleListProperty() != nullptr); getPlacementListProperty()->setValue(placements); getPlacementListProperty()->setStatus(Property::User3, false); } - if(getScaleListProperty()) + if (getScaleListProperty()) { getScaleListProperty()->setValue(scales); + } - for(auto obj : objs) { - if(obj && obj->isAttachedToDocument()) + for (auto obj : objs) { + if (obj && obj->isAttachedToDocument()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } - }else if(prop == _getElementCountProperty()) { - size_t elementCount = getElementCountValue()<0?0:(size_t)getElementCountValue(); + } + else if (prop == _getElementCountProperty()) { + size_t elementCount = getElementCountValue() < 0 ? 0 : (size_t)getElementCountValue(); auto propVis = getVisibilityListProperty(); - if(propVis) { - if(propVis->getSize()>(int)elementCount) - propVis->setSize(getElementCountValue(),true); + if (propVis) { + if (propVis->getSize() > (int)elementCount) { + propVis->setSize(getElementCountValue(), true); + } } - if(!_getShowElementValue()) { - if(getScaleListProperty()) { + if (!_getShowElementValue()) { + if (getScaleListProperty()) { auto scales = getScaleListValue(); - scales.resize(elementCount,Base::Vector3d(1,1,1)); - getScaleListProperty()->setStatus(Property::User3,true); + scales.resize(elementCount, Base::Vector3d(1, 1, 1)); + getScaleListProperty()->setStatus(Property::User3, true); getScaleListProperty()->setValue(scales); - getScaleListProperty()->setStatus(Property::User3,false); + getScaleListProperty()->setStatus(Property::User3, false); } - if(getPlacementListProperty()) { + if (getPlacementListProperty()) { auto placements = getPlacementListValue(); - if(placements.size()setStatus(Property::User3,true); + } + getPlacementListProperty()->setStatus(Property::User3, true); getPlacementListProperty()->setValue(placements); - getPlacementListProperty()->setStatus(Property::User3,false); + getPlacementListProperty()->setStatus(Property::User3, false); } - }else if(getElementListProperty()) { + } + else if (getElementListProperty()) { auto objs = getElementListValue(); - if(elementCount>objs.size()) { + if (elementCount > objs.size()) { std::string name = parent->getNameInDocument(); auto doc = parent->getDocument(); name += "_i"; name = doc->getUniqueObjectName(name.c_str()); - if(name[name.size()-1] != 'i') + if (name[name.size() - 1] != 'i') { name += "_i"; + } auto offset = name.size(); auto placementProp = getPlacementListProperty(); auto scaleProp = getScaleListProperty(); - const auto &vis = getVisibilityListValue(); + const auto& vis = getVisibilityListValue(); auto owner = getContainer(); - long ownerID = owner?owner->getID():0; + long ownerID = owner ? owner->getID() : 0; - for(size_t i=objs.size();i(doc->getObject(name.c_str())); - if(obj && (!obj->_LinkOwner.getValue() || obj->_LinkOwner.getValue()==ownerID)) { + if (obj + && (!obj->_LinkOwner.getValue() || obj->_LinkOwner.getValue() == ownerID)) { obj->Visibility.setValue(false); - } else { + } + else { obj = new LinkElement; - parent->getDocument()->addObject(obj,name.c_str()); + parent->getDocument()->addObject(obj, name.c_str()); } - if(vis.size()>i && !vis[i]) + if (vis.size() > i && !vis[i]) { myHiddenElements.insert(obj); + } - if(placementProp && placementProp->getSize()>(int)i) + if (placementProp && placementProp->getSize() > (int)i) { obj->Placement.setValue(placementProp->getValues()[i]); - else{ - Base::Placement pla(Base::Vector3d(i%10,(i/10)%10,i/100),Base::Rotation()); + } + else { + Base::Placement pla(Base::Vector3d(i % 10, (i / 10) % 10, i / 100), + Base::Rotation()); obj->Placement.setValue(pla); } - if(scaleProp && scaleProp->getSize()>(int)i) + if (scaleProp && scaleProp->getSize() > (int)i) { obj->Scale.setValue(scaleProp->getValues()[i].x); - else + } + else { obj->Scale.setValue(1); + } objs.push_back(obj); } - if(getPlacementListProperty()) + if (getPlacementListProperty()) { getPlacementListProperty()->setSize(0); - if(getScaleListProperty()) + } + if (getScaleListProperty()) { getScaleListProperty()->setSize(0); + } getElementListProperty()->setValue(objs); - - }else if(elementCount tmpObjs; auto owner = getContainer(); - long ownerID = owner?owner->getID():0; - while(objs.size()>elementCount) { + long ownerID = owner ? owner->getID() : 0; + while (objs.size() > elementCount) { auto element = freecad_dynamic_cast(objs.back()); - if(element && element->_LinkOwner.getValue()==ownerID) + if (element && element->_LinkOwner.getValue() == ownerID) { tmpObjs.push_back(objs.back()); + } objs.pop_back(); } getElementListProperty()->setValue(objs); - for(auto obj : tmpObjs) { - if(obj && obj->isAttachedToDocument()) + for (auto obj : tmpObjs) { + if (obj && obj->isAttachedToDocument()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } } - }else if(prop == getVisibilityListProperty()) { - if(_getShowElementValue()) { - const auto &elements = _getElementListValue(); - const auto &vis = getVisibilityListValue(); + } + else if (prop == getVisibilityListProperty()) { + if (_getShowElementValue()) { + const auto& elements = _getElementListValue(); + const auto& vis = getVisibilityListValue(); myHiddenElements.clear(); - for(size_t i=0;i=elements.size()) + for (size_t i = 0; i < vis.size(); ++i) { + if (i >= elements.size()) { break; - if(!vis[i]) + } + if (!vis[i]) { myHiddenElements.insert(elements[i]); + } } } - }else if(prop == getElementListProperty() || prop == &_ChildCache) { + } + else if (prop == getElementListProperty() || prop == &_ChildCache) { - if(prop == getElementListProperty()) { - _ChildCache.setStatus(Property::User3,true); + if (prop == getElementListProperty()) { + _ChildCache.setStatus(Property::User3, true); updateGroup(); - _ChildCache.setStatus(Property::User3,false); + _ChildCache.setStatus(Property::User3, false); } - const auto &elements = _getElementListValue(); + const auto& elements = _getElementListValue(); - if(enableLabelCache) + if (enableLabelCache) { myLabelCache.clear(); + } // Element list changed, we need to sychrnoize VisibilityList. - if(_getShowElementValue() && getVisibilityListProperty()) { - if(parent->getDocument()->isPerformingTransaction()) { - update(parent,getVisibilityListProperty()); - }else{ + if (_getShowElementValue() && getVisibilityListProperty()) { + if (parent->getDocument()->isPerformingTransaction()) { + update(parent, getVisibilityListProperty()); + } + else { boost::dynamic_bitset<> vis; - vis.resize(elements.size(),true); - std::unordered_set hiddenElements; - for(size_t i=0;i hiddenElements; + for (size_t i = 0; i < elements.size(); ++i) { + if (myHiddenElements.find(elements[i]) != myHiddenElements.end()) { hiddenElements.insert(elements[i]); vis[i] = false; } } myHiddenElements.swap(hiddenElements); - if(vis != getVisibilityListValue()) { + if (vis != getVisibilityListValue()) { auto propVis = getVisibilityListProperty(); - propVis->setStatus(Property::User3,true); + propVis->setStatus(Property::User3, true); propVis->setValue(vis); - propVis->setStatus(Property::User3,false); + propVis->setStatus(Property::User3, false); } } } syncElementList(); - if(_getShowElementValue() - && _getElementCountProperty() - && getElementListProperty() - && getElementCountValue()!=getElementListProperty()->getSize()) - { - getElementCountProperty()->setValue( - getElementListProperty()->getSize()); + if (_getShowElementValue() && _getElementCountProperty() && getElementListProperty() + && getElementCountValue() != getElementListProperty()->getSize()) { + getElementCountProperty()->setValue(getElementListProperty()->getSize()); } - }else if(prop == getLinkedObjectProperty()) { + } + else if (prop == getLinkedObjectProperty()) { auto group = linkedPlainGroup(); - if(getShowElementProperty()) + if (getShowElementProperty()) { getShowElementProperty()->setStatus(Property::Hidden, !!group); - if(getElementCountProperty()) + } + if (getElementCountProperty()) { getElementCountProperty()->setStatus(Property::Hidden, !!group); - if(group) + } + if (group) { updateGroup(); - else if(_ChildCache.getSize()) + } + else if (_ChildCache.getSize()) { _ChildCache.setValue(); + } parseSubName(); syncElementList(); - if(getLinkCopyOnChangeValue()==CopyOnChangeOwned - && !pauseCopyOnChange - && !parent->getDocument()->isPerformingTransaction()) + if (getLinkCopyOnChangeValue() == CopyOnChangeOwned && !pauseCopyOnChange + && !parent->getDocument()->isPerformingTransaction()) { getLinkCopyOnChangeProperty()->setValue(CopyOnChangeEnabled); - else + } + else { setupCopyOnChange(parent, true); - - }else if(prop == getLinkCopyOnChangeProperty()) { + } + } + else if (prop == getLinkCopyOnChangeProperty()) { setupCopyOnChange(parent, getLinkCopyOnChangeSourceValue() == nullptr); - } else if (prop == getLinkCopyOnChangeSourceProperty()) { + } + else if (prop == getLinkCopyOnChangeSourceProperty()) { if (auto source = getLinkCopyOnChangeSourceValue()) { this->connCopyOnChangeSource = source->signalChanged.connect( - [this](const DocumentObject & obj, const Property &prop) { + [this](const DocumentObject& obj, const Property& prop) { auto src = getLinkCopyOnChangeSourceValue(); - if (src != &obj || getLinkCopyOnChangeValue()==CopyOnChangeDisabled) + if (src != &obj || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return; - if (App::Document::isAnyRestoring() - || obj.testStatus(ObjectStatus::NoTouch) - || (prop.getType() & Prop_Output) - || prop.testStatus(Property::Output)) + } + if (App::Document::isAnyRestoring() || obj.testStatus(ObjectStatus::NoTouch) + || (prop.getType() & Prop_Output) || prop.testStatus(Property::Output)) { return; - if (auto propTouch = getLinkCopyOnChangeTouchedProperty()) + } + if (auto propTouch = getLinkCopyOnChangeTouchedProperty()) { propTouch->setValue(true); + } }); - } else + } + else { this->connCopyOnChangeSource.disconnect(); - - }else if(prop == getLinkTransformProperty()) { + } + } + else if (prop == getLinkTransformProperty()) { auto linkPlacement = getLinkPlacementProperty(); auto placement = getPlacementProperty(); - if(linkPlacement && placement) { + if (linkPlacement && placement) { bool transform = getLinkTransformValue(); - placement->setStatus(Property::Hidden,transform); - linkPlacement->setStatus(Property::Hidden,!transform); + placement->setStatus(Property::Hidden, transform); + linkPlacement->setStatus(Property::Hidden, !transform); } syncElementList(); - - } else { + } + else { checkCopyOnChange(parent, *prop); } } -void LinkBaseExtension::cacheChildLabel(int enable) const { - enableLabelCache = enable?true:false; +void LinkBaseExtension::cacheChildLabel(int enable) const +{ + enableLabelCache = enable ? true : false; myLabelCache.clear(); - if(enable<=0) + if (enable <= 0) { return; + } int idx = 0; - for(auto child : _getElementListValue()) { - if(child && child->isAttachedToDocument()) + for (auto child : _getElementListValue()) { + if (child && child->isAttachedToDocument()) { myLabelCache[child->Label.getStrValue()] = idx; + } ++idx; } } -bool LinkBaseExtension::linkTransform() const { - if(!getLinkTransformProperty() && - !getLinkPlacementProperty() && - !getPlacementProperty()) +bool LinkBaseExtension::linkTransform() const +{ + if (!getLinkTransformProperty() && !getLinkPlacementProperty() && !getPlacementProperty()) { return true; + } return getLinkTransformValue(); } -void LinkBaseExtension::syncElementList() { +void LinkBaseExtension::syncElementList() +{ auto transform = getLinkTransformProperty(); auto link = getLinkedObjectProperty(); auto xlink = freecad_dynamic_cast(link); auto owner = getContainer(); - auto ownerID = owner?owner->getID():0; + auto ownerID = owner ? owner->getID() : 0; auto elements = getElementListValue(); for (auto i : elements) { auto element = freecad_dynamic_cast(i); if (!element - || (element->_LinkOwner.getValue() - && element->_LinkOwner.getValue() != ownerID)) + || (element->_LinkOwner.getValue() && element->_LinkOwner.getValue() != ownerID)) { continue; + } element->_LinkOwner.setValue(ownerID); element->LinkTransform.setStatus(Property::Hidden, transform != nullptr); element->LinkTransform.setStatus(Property::Immutable, transform != nullptr); - if (transform && element->LinkTransform.getValue() != transform->getValue()) + if (transform && element->LinkTransform.getValue() != transform->getValue()) { element->LinkTransform.setValue(transform->getValue()); + } element->LinkedObject.setStatus(Property::Hidden, link != nullptr); element->LinkedObject.setStatus(Property::Immutable, link != nullptr); - if (element->LinkCopyOnChange.getValue() == 2) + if (element->LinkCopyOnChange.getValue() == 2) { continue; + } if (xlink) { if (element->LinkedObject.getValue() != xlink->getValue() || element->LinkedObject.getSubValues() != xlink->getSubValues()) { @@ -1940,87 +2234,100 @@ void LinkBaseExtension::syncElementList() { } } -void LinkBaseExtension::onExtendedDocumentRestored() { +void LinkBaseExtension::onExtendedDocumentRestored() +{ inherited::onExtendedDocumentRestored(); myHiddenElements.clear(); auto parent = getContainer(); - if(!parent) + if (!parent) { return; - if(hasOldSubElement) { + } + if (hasOldSubElement) { hasOldSubElement = false; // SubElements was stored as a PropertyStringList. It is now migrated to be // stored inside PropertyXLink. auto xlink = freecad_dynamic_cast(getLinkedObjectProperty()); - if(!xlink) + if (!xlink) { FC_ERR("Failed to restore SubElements for " << parent->getFullName()); - else if(!xlink->getValue()) + } + else if (!xlink->getValue()) { FC_ERR("Discard SubElements of " << parent->getFullName() << " due to null link"); - else if(xlink->getSubValues().size() > 1) + } + else if (xlink->getSubValues().size() > 1) { FC_ERR("Failed to restore SubElements for " << parent->getFullName() - << " due to conflict subnames"); - else if(xlink->getSubValues().empty()) { + << " due to conflict subnames"); + } + else if (xlink->getSubValues().empty()) { auto subs = xlink->getSubValues(); xlink->setSubValues(std::move(subs)); - } else { - std::set subset(mySubElements.begin(),mySubElements.end()); + } + else { + std::set subset(mySubElements.begin(), mySubElements.end()); auto sub = xlink->getSubValues().front(); auto element = Data::findElementName(sub.c_str()); - if(element && element[0]) { + if (element && element[0]) { subset.insert(element); sub.resize(element - sub.c_str()); } std::vector subs; - for(const auto &s : subset) + for (const auto& s : subset) { subs.push_back(sub + s); + } xlink->setSubValues(std::move(subs)); } } - if(getScaleVectorProperty() && getScaleProperty()) { + if (getScaleVectorProperty() && getScaleProperty()) { // Scale vector is added later. The code here is for migration. - const auto &v = getScaleVectorValue(); + const auto& v = getScaleVectorValue(); double s = getScaleValue(); - if(v.x == v.y && v.x == v.z && v.x != s) - getScaleVectorProperty()->setValue(s,s,s); + if (v.x == v.y && v.x == v.z && v.x != s) { + getScaleVectorProperty()->setValue(s, s, s); + } } - update(parent,getVisibilityListProperty()); + update(parent, getVisibilityListProperty()); if (auto prop = getLinkedObjectProperty()) { Base::StateLocker guard(pauseCopyOnChange); - update(parent,prop); + update(parent, prop); } - update(parent,getLinkCopyOnChangeSourceProperty()); - update(parent,getElementListProperty()); - if (getLinkCopyOnChangeValue() != CopyOnChangeDisabled) + update(parent, getLinkCopyOnChangeSourceProperty()); + update(parent, getElementListProperty()); + if (getLinkCopyOnChangeValue() != CopyOnChangeDisabled) { monitorOnChangeCopyObjects(getOnChangeCopyObjects()); + } } -void LinkBaseExtension::_handleChangedPropertyName( - Base::XMLReader &reader, const char * TypeName, const char *PropName) +void LinkBaseExtension::_handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) { - if(strcmp(PropName,"SubElements")==0 - && strcmp(TypeName,PropertyStringList::getClassTypeId().getName())==0) - { + if (strcmp(PropName, "SubElements") == 0 + && strcmp(TypeName, PropertyStringList::getClassTypeId().getName()) == 0) { PropertyStringList prop; prop.setContainer(getContainer()); prop.Restore(reader); - if(prop.getSize()) { + if (prop.getSize()) { mySubElements = prop.getValues(); hasOldSubElement = true; } } } -void LinkBaseExtension::setLink(int index, DocumentObject *obj, - const char *subname, const std::vector &subElements) +void LinkBaseExtension::setLink(int index, + DocumentObject* obj, + const char* subname, + const std::vector& subElements) { auto parent = getContainer(); - if(!parent) - LINK_THROW(Base::RuntimeError,"No parent container"); + if (!parent) { + LINK_THROW(Base::RuntimeError, "No parent container"); + } - if(obj && !App::Document::isAnyRestoring()) { + if (obj && !App::Document::isAnyRestoring()) { auto inSet = parent->getInListEx(true); inSet.insert(parent); - if(inSet.find(obj)!=inSet.end()) - LINK_THROW(Base::RuntimeError,"Cyclic dependency"); + if (inSet.find(obj) != inSet.end()) { + LINK_THROW(Base::RuntimeError, "Cyclic dependency"); + } } auto linkProp = getLinkedObjectProperty(); @@ -2028,73 +2335,84 @@ void LinkBaseExtension::setLink(int index, DocumentObject *obj, // If we are a group (i.e. no LinkObject property), and the index is // negative with a non-zero 'obj' assignment, we treat this as group // expansion by changing the index to one pass the existing group size - if(index<0 && obj && !linkProp && getElementListProperty()) + if (index < 0 && obj && !linkProp && getElementListProperty()) { index = getElementListProperty()->getSize(); + } - if(index>=0) { + if (index >= 0) { // LinkGroup assignment - if(linkProp || !getElementListProperty()) - LINK_THROW(Base::RuntimeError,"Cannot set link element"); + if (linkProp || !getElementListProperty()) { + LINK_THROW(Base::RuntimeError, "Cannot set link element"); + } - DocumentObject *old = nullptr; - const auto &elements = getElementListProperty()->getValues(); - if(!obj) { - if(index>=(int)elements.size()) - LINK_THROW(Base::ValueError,"Link element index out of bound"); + DocumentObject* old = nullptr; + const auto& elements = getElementListProperty()->getValues(); + if (!obj) { + if (index >= (int)elements.size()) { + LINK_THROW(Base::ValueError, "Link element index out of bound"); + } std::vector objs; old = elements[index]; - for(int i=0;i<(int)elements.size();++i) { - if(i!=index) + for (int i = 0; i < (int)elements.size(); ++i) { + if (i != index) { objs.push_back(elements[i]); + } } getElementListProperty()->setValue(objs); - }else if(!obj->isAttachedToDocument()) - LINK_THROW(Base::ValueError,"Invalid object"); - else{ - if(index>(int)elements.size()) - LINK_THROW(Base::ValueError,"Link element index out of bound"); + } + else if (!obj->isAttachedToDocument()) { + LINK_THROW(Base::ValueError, "Invalid object"); + } + else { + if (index > (int)elements.size()) { + LINK_THROW(Base::ValueError, "Link element index out of bound"); + } - if(index < (int)elements.size()) + if (index < (int)elements.size()) { old = elements[index]; + } int idx = -1; - if(getLinkModeValue()>=LinkModeAutoLink || - (subname && subname[0]) || - !subElements.empty() || - obj->getDocument()!=parent->getDocument() || - (getElementListProperty()->find(obj->getNameInDocument(),&idx) && idx!=index)) - { + if (getLinkModeValue() >= LinkModeAutoLink || (subname && subname[0]) + || !subElements.empty() || obj->getDocument() != parent->getDocument() + || (getElementListProperty()->find(obj->getNameInDocument(), &idx) + && idx != index)) { std::string name = parent->getDocument()->getUniqueObjectName("Link"); auto link = new Link; link->_LinkOwner.setValue(parent->getID()); - parent->getDocument()->addObject(link,name.c_str()); - link->setLink(-1,obj,subname,subElements); + parent->getDocument()->addObject(link, name.c_str()); + link->setLink(-1, obj, subname, subElements); auto linked = link->getTrueLinkedObject(true); - if(linked) + if (linked) { link->Label.setValue(linked->Label.getValue()); - auto pla = freecad_dynamic_cast(obj->getPropertyByName("Placement")); - if(pla) + } + auto pla = + freecad_dynamic_cast(obj->getPropertyByName("Placement")); + if (pla) { link->Placement.setValue(pla->getValue()); + } link->Visibility.setValue(false); obj = link; } - if(old == obj) + if (old == obj) { return; + } - getElementListProperty()->set1Value(index,obj); + getElementListProperty()->set1Value(index, obj); } detachElement(old); return; } - if(!linkProp) { + if (!linkProp) { // Reaching here means, we are group (i.e. no LinkedObject), and // index<0, and 'obj' is zero. We shall clear the whole group - if(obj || !getElementListProperty()) - LINK_THROW(Base::RuntimeError,"No PropertyLink or PropertyLinkList configured"); + if (obj || !getElementListProperty()) { + LINK_THROW(Base::RuntimeError, "No PropertyLink or PropertyLinkList configured"); + } detachElements(); return; } @@ -2102,127 +2420,157 @@ void LinkBaseExtension::setLink(int index, DocumentObject *obj, // Here means we are assigning a Link auto xlink = freecad_dynamic_cast(linkProp); - if(obj) { - if(!obj->isAttachedToDocument()) - LINK_THROW(Base::ValueError,"Invalid document object"); - if(!xlink) { - if(parent && obj->getDocument()!=parent->getDocument()) - LINK_THROW(Base::ValueError,"Cannot link to external object without PropertyXLink"); + if (obj) { + if (!obj->isAttachedToDocument()) { + LINK_THROW(Base::ValueError, "Invalid document object"); + } + if (!xlink) { + if (parent && obj->getDocument() != parent->getDocument()) { + LINK_THROW(Base::ValueError, + "Cannot link to external object without PropertyXLink"); + } } } - if(!xlink) { - if(!subElements.empty() || (subname && subname[0])) - LINK_THROW(Base::RuntimeError,"SubName/SubElement link requires PropertyXLink"); + if (!xlink) { + if (!subElements.empty() || (subname && subname[0])) { + LINK_THROW(Base::RuntimeError, "SubName/SubElement link requires PropertyXLink"); + } linkProp->setValue(obj); return; } std::vector subs; - if(!subElements.empty()) { + if (!subElements.empty()) { subs.reserve(subElements.size()); - for(const auto &s : subElements) { - subs.emplace_back(subname?subname:""); + for (const auto& s : subElements) { + subs.emplace_back(subname ? subname : ""); subs.back() += s; } - } else if(subname && subname[0]) + } + else if (subname && subname[0]) { subs.emplace_back(subname); - xlink->setValue(obj,std::move(subs)); + } + xlink->setValue(obj, std::move(subs)); } void LinkBaseExtension::detachElements() { std::vector objs; - for (auto obj : getElementListValue()) + for (auto obj : getElementListValue()) { objs.emplace_back(obj); + } getElementListProperty()->setValue(); - for(const auto &objT : objs) + for (const auto& objT : objs) { detachElement(objT.getObject()); + } } -void LinkBaseExtension::detachElement(DocumentObject *obj) { - if(!obj || !obj->isAttachedToDocument() || obj->isRemoving()) +void LinkBaseExtension::detachElement(DocumentObject* obj) +{ + if (!obj || !obj->isAttachedToDocument() || obj->isRemoving()) { return; + } auto ext = obj->getExtensionByType(true); auto owner = getContainer(); - long ownerID = owner?owner->getID():0; - if(getLinkModeValue()==LinkModeAutoUnlink) { - if(!ext || ext->_LinkOwner.getValue()!=ownerID) + long ownerID = owner ? owner->getID() : 0; + if (getLinkModeValue() == LinkModeAutoUnlink) { + if (!ext || ext->_LinkOwner.getValue() != ownerID) { return; - }else if(getLinkModeValue()!=LinkModeAutoDelete) { - if(ext && ext->_LinkOwner.getValue()==ownerID) + } + } + else if (getLinkModeValue() != LinkModeAutoDelete) { + if (ext && ext->_LinkOwner.getValue() == ownerID) { ext->_LinkOwner.setValue(0); + } return; } obj->getDocument()->removeObject(obj->getNameInDocument()); } -std::vector LinkBaseExtension::getLinkedChildren(bool filter) const{ - if(!filter) +std::vector LinkBaseExtension::getLinkedChildren(bool filter) const +{ + if (!filter) { return _getElementListValue(); + } std::vector ret; - for(auto o : _getElementListValue()) { - if(!o->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) + for (auto o : _getElementListValue()) { + if (!o->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { ret.push_back(o); + } } return ret; } -const char *LinkBaseExtension::flattenSubname(const char *subname) const { - if(subname && _ChildCache.getSize()) { - const char *sub = subname; +const char* LinkBaseExtension::flattenSubname(const char* subname) const +{ + if (subname && _ChildCache.getSize()) { + const char* sub = subname; std::string s; - for(const char* dot=strchr(sub,'.');dot;sub=dot+1,dot=strchr(sub,'.')) { - DocumentObject *obj = nullptr; + for (const char* dot = strchr(sub, '.'); dot; sub = dot + 1, dot = strchr(sub, '.')) { + DocumentObject* obj = nullptr; s.clear(); - s.append(sub,dot+1); - extensionGetSubObject(obj,s.c_str()); - if(!obj) + s.append(sub, dot + 1); + extensionGetSubObject(obj, s.c_str()); + if (!obj) { break; - if(!obj->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) + } + if (!obj->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { return sub; + } } } return subname; } -void LinkBaseExtension::expandSubname(std::string &subname) const { - if(!_ChildCache.getSize()) +void LinkBaseExtension::expandSubname(std::string& subname) const +{ + if (!_ChildCache.getSize()) { return; + } - const char *pos = nullptr; - int index = getElementIndex(subname.c_str(),&pos); - if(index<0) + const char* pos = nullptr; + int index = getElementIndex(subname.c_str(), &pos); + if (index < 0) { return; + } std::ostringstream ss; - elementNameFromIndex(index,ss); + elementNameFromIndex(index, ss); ss << pos; subname = ss.str(); } -static bool isExcludedProperties(const char *name) { -#define CHECK_EXCLUDE_PROP(_name) if(strcmp(name,#_name)==0) return true; +static bool isExcludedProperties(const char* name) +{ +#define CHECK_EXCLUDE_PROP(_name) \ + if (strcmp(name, #_name) == 0) \ + return true; CHECK_EXCLUDE_PROP(Shape); CHECK_EXCLUDE_PROP(Proxy); CHECK_EXCLUDE_PROP(Placement); return false; } -Property *LinkBaseExtension::extensionGetPropertyByName(const char* name) const { - if (checkingProperty) +Property* LinkBaseExtension::extensionGetPropertyByName(const char* name) const +{ + if (checkingProperty) { return inherited::extensionGetPropertyByName(name); + } Base::StateLocker guard(checkingProperty); - if(isExcludedProperties(name)) + if (isExcludedProperties(name)) { return nullptr; + } auto owner = getContainer(); if (owner) { - App::Property *prop = owner->getPropertyByName(name); - if(prop) + App::Property* prop = owner->getPropertyByName(name); + if (prop) { return prop; - if(owner->canLinkProperties()) { + } + if (owner->canLinkProperties()) { auto linked = getTrueLinkedObject(true); - if(linked) + if (linked) { return linked->getPropertyByName(name); + } } } return nullptr; @@ -2230,21 +2578,21 @@ Property *LinkBaseExtension::extensionGetPropertyByName(const char* name) const bool LinkBaseExtension::isLinkMutated() const { - return getLinkCopyOnChangeValue() != CopyOnChangeDisabled - && getLinkedObjectValue() + return getLinkCopyOnChangeValue() != CopyOnChangeDisabled && getLinkedObjectValue() && (!getLinkCopyOnChangeSourceValue() || (getLinkedObjectValue() != getLinkCopyOnChangeSourceValue())); } /////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::LinkBaseExtensionPython, App::LinkBaseExtension) // explicit template instantiation template class AppExport ExtensionPythonT; -} +} // namespace App ////////////////////////////////////////////////////////////////////////////// @@ -2259,26 +2607,29 @@ LinkExtension::LinkExtension() /////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::LinkExtensionPython, App::LinkExtension) // explicit template instantiation template class AppExport ExtensionPythonT; -} +} // namespace App /////////////////////////////////////////////////////////////////////////////////////////// PROPERTY_SOURCE_WITH_EXTENSIONS(App::Link, App::DocumentObject) -Link::Link() { +Link::Link() +{ LINK_PROPS_ADD(LINK_PARAMS_LINK); LinkExtension::initExtension(this); - static const PropertyIntegerConstraint::Constraints s_constraints = {0,INT_MAX,1}; + static const PropertyIntegerConstraint::Constraints s_constraints = {0, INT_MAX, 1}; ElementCount.setConstraints(&s_constraints); } -bool Link::canLinkProperties() const { +bool Link::canLinkProperties() const +{ return true; } @@ -2294,26 +2645,32 @@ bool Link::isLinkGroup() const ////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::LinkPython, App::Link) -template<> const char* App::LinkPython::getViewProviderName() const { +template<> +const char* App::LinkPython::getViewProviderName() const +{ return "Gui::ViewProviderLinkPython"; } template class AppExport FeaturePythonT; -} +} // namespace App ////////////////////////////////////////////////////////////////////////////////////////// PROPERTY_SOURCE_WITH_EXTENSIONS(App::LinkElement, App::DocumentObject) -LinkElement::LinkElement() { +LinkElement::LinkElement() +{ LINK_PROPS_ADD(LINK_PARAMS_ELEMENT); LinkBaseExtension::initExtension(this); } -bool LinkElement::canDelete() const { - if(!_LinkOwner.getValue()) +bool LinkElement::canDelete() const +{ + if (!_LinkOwner.getValue()) { return true; + } auto owner = getContainer(); return !owner || !owner->getDocument()->getObjectByID(_LinkOwner.getValue()); @@ -2344,34 +2701,40 @@ App::Link* LinkElement::getLinkGroup() const ////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::LinkElementPython, App::LinkElement) -template<> const char* App::LinkElementPython::getViewProviderName() const { +template<> +const char* App::LinkElementPython::getViewProviderName() const +{ return "Gui::ViewProviderLinkPython"; } template class AppExport FeaturePythonT; -} +} // namespace App ////////////////////////////////////////////////////////////////////////////////////////// PROPERTY_SOURCE_WITH_EXTENSIONS(App::LinkGroup, App::DocumentObject) -LinkGroup::LinkGroup() { +LinkGroup::LinkGroup() +{ LINK_PROPS_ADD(LINK_PARAMS_GROUP); LinkBaseExtension::initExtension(this); } ////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::LinkGroupPython, App::LinkGroup) -template<> const char* App::LinkGroupPython::getViewProviderName() const { +template<> +const char* App::LinkGroupPython::getViewProviderName() const +{ return "Gui::ViewProviderLinkPython"; } template class AppExport FeaturePythonT; -} +} // namespace App #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif - diff --git a/src/App/Link.h b/src/App/Link.h index 7cb879f75a..2fbfeea8a0 100644 --- a/src/App/Link.h +++ b/src/App/Link.h @@ -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, App::PropertyPlacementList, std::vector(),\ - "The placement for each link element", ##__VA_ARGS__) +#define LINK_PARAM_PLACEMENTS(...) \ + (PlacementList, \ + std::vector, \ + App::PropertyPlacementList, \ + std::vector(), \ + "The placement for each link element", \ + ##__VA_ARGS__) -#define LINK_PARAM_SCALES(...) \ - (ScaleList, std::vector, App::PropertyVectorList, std::vector(),\ - "The scale factors for each link element", ##__VA_ARGS__) +#define LINK_PARAM_SCALES(...) \ + (ScaleList, \ + std::vector, \ + App::PropertyVectorList, \ + std::vector(), \ + "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::PropertyLinkList, std::vector(),\ - "The link element object list", ##__VA_ARGS__) +#define LINK_PARAM_ELEMENTS(...) \ + (ElementList, \ + std::vector, \ + App::PropertyLinkList, \ + std::vector(), \ + "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 &getPropertyInfo() const; + virtual const std::vector& getPropertyInfo() const; using PropInfoMap = std::map; - 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(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(prop);\ - }\ - LINK_PPTYPE(_param) *BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property)) () {\ - auto prop = props[LINK_PINDEX(_param)];\ - return static_cast(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(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(prop); \ + } \ + LINK_PPTYPE(_param) * BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property))() \ + { \ + auto prop = props[LINK_PINDEX(_param)]; \ + return static_cast(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 &_getElementListValue() const; + PropertyLinkList* _getElementListProperty() const; + const std::vector& _getElementListValue() const; - PropertyBool *_getShowElementProperty() const; + PropertyBool* _getShowElementProperty() const; bool _getShowElementValue() const; - PropertyInteger *_getElementCountProperty() const; + PropertyInteger* _getElementCountProperty() const; int _getElementCountValue() const; - std::vector getLinkedChildren(bool filter=true) const; + std::vector 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 &getSubElements() const { + const std::vector& 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&ret, int reason) const override; + bool extensionGetSubObjects(std::vector& 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 &subs = std::vector()); + void setLink(int index, + DocumentObject* obj, + const char* subname = nullptr, + const std::vector& subs = std::vector()); - 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 >; + using LinkPropMap = std::map>; - 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 *copyOnChangeConns, bool checkExisting); + static bool + setupCopyOnChange(App::DocumentObject* obj, + App::DocumentObject* linked, + std::vector* 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 getOnChangeCopyObjects( - std::vector *excludes = nullptr, - App::DocumentObject *src = nullptr); + std::vector + getOnChangeCopyObjects(std::vector* excludes = nullptr, + App::DocumentObject* src = nullptr); bool isLinkedToConfigurableObject() const; - void monitorOnChangeCopyObjects(const std::vector &objs); + void monitorOnChangeCopyObjects(const std::vector& 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 props; + std::vector props; std::unordered_set myHiddenElements; mutable std::vector mySubElements; mutable std::string mySubName; - std::unordered_map plainGroupConns; + std::unordered_map + plainGroupConns; long prevLinkedObjectID = 0; - mutable std::unordered_map myLabelCache; // for label based subname lookup - mutable bool enableLabelCache{false}; - bool hasOldSubElement{false}; + mutable std::unordered_map myLabelCache; // for label based subname lookup + mutable bool enableLabelCache {false}; + bool hasOldSubElement {false}; std::vector copyOnChangeConns; std::vector copyOnChangeSrcConns; - bool hasCopyOnChange{true}; + bool hasCopyOnChange {true}; mutable bool checkingProperty = false; bool pauseCopyOnChange = false; @@ -404,7 +506,7 @@ using LinkBaseExtensionPython = ExtensionPythonT; /////////////////////////////////////////////////////////////////////////// -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; /////////////////////////////////////////////////////////////////////////// -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; /////////////////////////////////////////////////////////////////////////// -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; /////////////////////////////////////////////////////////////////////////// -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; -} //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:onChanged() * @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 diff --git a/src/App/LinkBaseExtensionPyImp.cpp b/src/App/LinkBaseExtensionPyImp.cpp index 10819f2901..5cf44fea82 100644 --- a/src/App/LinkBaseExtensionPyImp.cpp +++ b/src/App/LinkBaseExtensionPyImp.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include "DocumentObjectPy.h" @@ -40,155 +40,167 @@ std::string LinkBaseExtensionPy::representation() const return str.str(); } -using PropTmpMap = std::map >; +using PropTmpMap = std::map>; using PropMap = std::map; -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;possetProperty(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(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(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;icacheChildLabel(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; } diff --git a/src/App/LinkParams.py b/src/App/LinkParams.py index ec02477535..2373152520 100644 --- a/src/App/LinkParams.py +++ b/src/App/LinkParams.py @@ -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) diff --git a/src/App/Metadata.h b/src/App/Metadata.h index fa5f14717c..868315e638 100644 --- a/src/App/Metadata.h +++ b/src/App/Metadata.h @@ -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 license() const; //< Must be at least one, and most licenses require including a license file. std::vector 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 author() const; //< Any number of authors may be specified, and email addresses are optional. std::vector diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index a8294d3d9a..92593f0a80 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -45,7 +45,7 @@ #include "Property.h" -FC_LOG_LEVEL_INIT("Expression",true,true) +FC_LOG_LEVEL_INIT("Expression", true, true) using namespace App; using namespace Base; @@ -60,43 +60,43 @@ using namespace Base; * @return */ -std::string App::quote(const std::string &input, bool toPython) +std::string App::quote(const std::string& input, bool toPython) { std::stringstream output; std::string::const_iterator cur = input.begin(); std::string::const_iterator end = input.end(); - output << (toPython?"'":"<<"); + output << (toPython ? "'" : "<<"); while (cur != end) { switch (*cur) { - case '\t': - output << "\\t"; - break; - case '\n': - output << "\\n"; - break; - case '\r': - output << "\\r"; - break; - case '\\': - output << "\\\\"; - break; - case '\'': - output << "\\'"; - break; - case '"': - output << "\\\""; - break; - case '>': - output << (toPython?">":"\\>"); - break; - default: - output << *cur; + case '\t': + output << "\\t"; + break; + case '\n': + output << "\\n"; + break; + case '\r': + output << "\\r"; + break; + case '\\': + output << "\\\\"; + break; + case '\'': + output << "\\'"; + break; + case '"': + output << "\\\""; + break; + case '>': + output << (toPython ? ">" : "\\>"); + break; + default: + output << *cur; } ++cur; } - output << (toPython?"'":">>"); + output << (toPython ? "'" : ">>"); return output.str(); } @@ -108,8 +108,9 @@ std::string App::quote(const std::string &input, bool toPython) * @param property Name of property. */ -ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, - const std::string & property, int index) +ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer* _owner, + const std::string& property, + int index) : owner(nullptr) , documentNameSet(false) , documentObjectNameSet(false) @@ -117,9 +118,10 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, , _hash(0) { if (_owner) { - const DocumentObject * docObj = freecad_dynamic_cast(_owner); - if (!docObj) - FC_THROWM(Base::RuntimeError,"Property must be owned by a document object."); + const DocumentObject* docObj = freecad_dynamic_cast(_owner); + if (!docObj) { + FC_THROWM(Base::RuntimeError, "Property must be owned by a document object."); + } owner = const_cast(docObj); if (!property.empty()) { @@ -128,12 +130,13 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, } if (!property.empty()) { addComponent(SimpleComponent(property)); - if(index!=INT_MAX) + if (index != INT_MAX) { addComponent(ArrayComponent(index)); + } } } -ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, bool localProperty) +ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer* _owner, bool localProperty) : owner(nullptr) , documentNameSet(false) , documentObjectNameSet(false) @@ -141,39 +144,44 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, bool l , _hash(0) { if (_owner) { - const DocumentObject * docObj = freecad_dynamic_cast(_owner); - if (!docObj) - FC_THROWM(Base::RuntimeError,"Property must be owned by a document object."); + const DocumentObject* docObj = freecad_dynamic_cast(_owner); + if (!docObj) { + FC_THROWM(Base::RuntimeError, "Property must be owned by a document object."); + } owner = const_cast(docObj); } } /** - * @brief Construct an ObjectIdentifier object given a property. The property is assumed to be single-valued. + * @brief Construct an ObjectIdentifier object given a property. The property is assumed to be + * single-valued. * @param prop Property to construct object identifier for. */ -ObjectIdentifier::ObjectIdentifier(const Property &prop, int index) +ObjectIdentifier::ObjectIdentifier(const Property& prop, int index) : owner(nullptr) , documentNameSet(false) , documentObjectNameSet(false) , localProperty(false) , _hash(0) { - DocumentObject * docObj = freecad_dynamic_cast(prop.getContainer()); + DocumentObject* docObj = freecad_dynamic_cast(prop.getContainer()); - if (!docObj) + if (!docObj) { FC_THROWM(Base::TypeError, "Property must be owned by a document object."); - if (!prop.hasName()) + } + if (!prop.hasName()) { FC_THROWM(Base::RuntimeError, "Property must have a name."); + } owner = const_cast(docObj); setDocumentObjectName(docObj); addComponent(SimpleComponent(String(prop.getName()))); - if(index!=INT_MAX) + if (index != INT_MAX) { addComponent(ArrayComponent(index)); + } } /** @@ -185,7 +193,8 @@ std::string App::ObjectIdentifier::getPropertyName() const { ResolveResults result(*this); - assert(result.propertyIndex >=0 && static_cast(result.propertyIndex) < components.size()); + assert(result.propertyIndex >= 0 + && static_cast(result.propertyIndex) < components.size()); return components[result.propertyIndex].getName(); } @@ -197,41 +206,48 @@ std::string App::ObjectIdentifier::getPropertyName() const * @return A component. */ -const App::ObjectIdentifier::Component &App::ObjectIdentifier::getPropertyComponent(int i, int *idx) const +const App::ObjectIdentifier::Component& App::ObjectIdentifier::getPropertyComponent(int i, + int* idx) const { ResolveResults result(*this); i += result.propertyIndex; - if (i < 0 || i >= static_cast(components.size())) + if (i < 0 || i >= static_cast(components.size())) { FC_THROWM(Base::ValueError, "Invalid property component index"); + } - if (idx) + if (idx) { *idx = i; + } return components[i]; } -void App::ObjectIdentifier::setComponent(int idx, Component &&comp) +void App::ObjectIdentifier::setComponent(int idx, Component&& comp) { - if (idx < 0 || idx >= static_cast(components.size())) + if (idx < 0 || idx >= static_cast(components.size())) { FC_THROWM(Base::ValueError, "Invalid component index"); + } components[idx] = std::move(comp); _cache.clear(); } -void App::ObjectIdentifier::setComponent(int idx, const Component &comp) +void App::ObjectIdentifier::setComponent(int idx, const Component& comp) { setComponent(idx, Component(comp)); } -std::vector ObjectIdentifier::getPropertyComponents() const { - if(components.size()<=1 || documentObjectName.getString().empty()) +std::vector ObjectIdentifier::getPropertyComponents() const +{ + if (components.size() <= 1 || documentObjectName.getString().empty()) { return components; + } ResolveResults result(*this); - if(result.propertyIndex==0) + if (result.propertyIndex == 0) { return components; + } std::vector res; - res.insert(res.end(),components.begin()+result.propertyIndex,components.end()); + res.insert(res.end(), components.begin() + result.propertyIndex, components.end()); return res; } @@ -241,9 +257,9 @@ std::vector ObjectIdentifier::getPropertyComponents * @return true if they are equal. */ -bool ObjectIdentifier::operator ==(const ObjectIdentifier &other) const +bool ObjectIdentifier::operator==(const ObjectIdentifier& other) const { - return owner==other.owner && toString() == other.toString(); + return owner == other.owner && toString() == other.toString(); } /** @@ -252,7 +268,7 @@ bool ObjectIdentifier::operator ==(const ObjectIdentifier &other) const * @return true if they differ from each other. */ -bool ObjectIdentifier::operator !=(const ObjectIdentifier &other) const +bool ObjectIdentifier::operator!=(const ObjectIdentifier& other) const { return !(operator==)(other); } @@ -263,12 +279,14 @@ bool ObjectIdentifier::operator !=(const ObjectIdentifier &other) const * @return true if this object is less than the other. */ -bool ObjectIdentifier::operator <(const ObjectIdentifier &other) const +bool ObjectIdentifier::operator<(const ObjectIdentifier& other) const { - if(owner < other.owner) + if (owner < other.owner) { return true; - if(owner > other.owner) + } + if (owner > other.owner) { return false; + } return toString() < other.toString(); } @@ -294,27 +312,30 @@ int ObjectIdentifier::numSubComponents() const return components.size() - result.propertyIndex; } -bool ObjectIdentifier::verify(const App::Property &prop, bool silent) const { +bool ObjectIdentifier::verify(const App::Property& prop, bool silent) const +{ ResolveResults result(*this); - if(components.size() - result.propertyIndex != 1) { - if(silent) + if (components.size() - result.propertyIndex != 1) { + if (silent) { return false; - FC_THROWM(Base::ValueError,"Invalid property path: single component expected"); + } + FC_THROWM(Base::ValueError, "Invalid property path: single component expected"); } - if(!components[result.propertyIndex].isSimple()) { - if(silent) + if (!components[result.propertyIndex].isSimple()) { + if (silent) { return false; - FC_THROWM(Base::ValueError,"Invalid property path: simple component expected"); + } + FC_THROWM(Base::ValueError, "Invalid property path: simple component expected"); } - const std::string &name = components[result.propertyIndex].getName(); + const std::string& name = components[result.propertyIndex].getName(); CellAddress addr; bool isAddress = addr.parseAbsoluteAddress(name.c_str()); - if((isAddress && addr.toString(CellAddress::Cell::ShowRowColumn) != prop.getName()) || - (!isAddress && name!=prop.getName())) - { - if(silent) + if ((isAddress && addr.toString(CellAddress::Cell::ShowRowColumn) != prop.getName()) + || (!isAddress && name != prop.getName())) { + if (silent) { return false; - FC_THROWM(Base::ValueError,"Invalid property path: name mismatch"); + } + FC_THROWM(Base::ValueError, "Invalid property path: name mismatch"); } return true; } @@ -323,143 +344,165 @@ bool ObjectIdentifier::verify(const App::Property &prop, bool silent) const { * @brief Create a string representation of this object identifier. * * An identifier is written as document#documentobject.property.subproperty1...subpropertyN - * document# may be dropped; it is assumed to be within owner's document. If documentobject is dropped, - * the property is assumed to be owned by the owner specified in the object identifiers constructor. + * document# may be dropped; it is assumed to be within owner's document. If documentobject is + * dropped, the property is assumed to be owned by the owner specified in the object identifiers + * constructor. * * @return A string */ -const std::string &ObjectIdentifier::toString() const +const std::string& ObjectIdentifier::toString() const { - if(!_cache.empty() || !owner) + if (!_cache.empty() || !owner) { return _cache; + } std::ostringstream s; ResolveResults result(*this); - if(result.propertyIndex >= (int)components.size()) + if (result.propertyIndex >= (int)components.size()) { return _cache; + } - if(localProperty || - (result.resolvedProperty && - result.resolvedDocumentObject==owner && - components.size()>1 && - components[1].isSimple() && - result.propertyIndex==0)) - { + if (localProperty + || (result.resolvedProperty && result.resolvedDocumentObject == owner + && components.size() > 1 && components[1].isSimple() && result.propertyIndex == 0)) { s << '.'; - }else if (documentNameSet && !documentName.getString().empty()) { - if(documentObjectNameSet && !documentObjectName.getString().empty()) - s << documentName.toString() << "#" - << documentObjectName.toString() << '.'; - else if(!result.resolvedDocumentObjectName.getString().empty()) - s << documentName.toString() << "#" - << result.resolvedDocumentObjectName.toString() << '.'; - } else if (documentObjectNameSet && !documentObjectName.getString().empty()) { + } + else if (documentNameSet && !documentName.getString().empty()) { + if (documentObjectNameSet && !documentObjectName.getString().empty()) { + s << documentName.toString() << "#" << documentObjectName.toString() << '.'; + } + else if (!result.resolvedDocumentObjectName.getString().empty()) { + s << documentName.toString() << "#" << result.resolvedDocumentObjectName.toString() + << '.'; + } + } + else if (documentObjectNameSet && !documentObjectName.getString().empty()) { s << documentObjectName.toString() << '.'; - } else if (result.propertyIndex > 0) { + } + else if (result.propertyIndex > 0) { components[0].toString(s); s << '.'; } - if(!subObjectName.getString().empty()) + if (!subObjectName.getString().empty()) { s << subObjectName.toString() << '.'; + } s << components[result.propertyIndex].getName(); - getSubPathStr(s,result); + getSubPathStr(s, result); const_cast(this)->_cache = s.str(); return _cache; } -std::string ObjectIdentifier::toPersistentString() const { +std::string ObjectIdentifier::toPersistentString() const +{ - if(!owner) + if (!owner) { return {}; + } std::ostringstream s; ResolveResults result(*this); - if(result.propertyIndex >= (int)components.size()) + if (result.propertyIndex >= (int)components.size()) { return {}; + } - if(localProperty || - (result.resolvedProperty && - result.resolvedDocumentObject==owner && - components.size()>1 && - components[1].isSimple() && - result.propertyIndex==0)) - { + if (localProperty + || (result.resolvedProperty && result.resolvedDocumentObject == owner + && components.size() > 1 && components[1].isSimple() && result.propertyIndex == 0)) { s << '.'; - }else if(result.resolvedDocumentObject && - result.resolvedDocumentObject!=owner && - result.resolvedDocumentObject->isExporting()) - { + } + else if (result.resolvedDocumentObject && result.resolvedDocumentObject != owner + && result.resolvedDocumentObject->isExporting()) { s << result.resolvedDocumentObject->getExportName(true); - if(documentObjectName.isRealString()) + if (documentObjectName.isRealString()) { s << '@'; + } s << '.'; - } else if (documentNameSet && !documentName.getString().empty()) { - if(documentObjectNameSet && !documentObjectName.getString().empty()) - s << documentName.toString() << "#" - << documentObjectName.toString() << '.'; - else if(!result.resolvedDocumentObjectName.getString().empty()) - s << documentName.toString() << "#" - << result.resolvedDocumentObjectName.toString() << '.'; - } else if (documentObjectNameSet && !documentObjectName.getString().empty()) { + } + else if (documentNameSet && !documentName.getString().empty()) { + if (documentObjectNameSet && !documentObjectName.getString().empty()) { + s << documentName.toString() << "#" << documentObjectName.toString() << '.'; + } + else if (!result.resolvedDocumentObjectName.getString().empty()) { + s << documentName.toString() << "#" << result.resolvedDocumentObjectName.toString() + << '.'; + } + } + else if (documentObjectNameSet && !documentObjectName.getString().empty()) { s << documentObjectName.toString() << '.'; - } else if (result.propertyIndex > 0) { + } + else if (result.propertyIndex > 0) { components[0].toString(s); s << '.'; } - if(!subObjectName.getString().empty()) { - const char *subname = subObjectName.getString().c_str(); + if (!subObjectName.getString().empty()) { + const char* subname = subObjectName.getString().c_str(); std::string exportName; s << String(PropertyLinkBase::exportSubName(exportName, - result.resolvedDocumentObject,subname),true).toString() << '.'; + result.resolvedDocumentObject, + subname), + true) + .toString() + << '.'; } s << components[result.propertyIndex].getName(); - getSubPathStr(s,result); + getSubPathStr(s, result); return s.str(); } std::size_t ObjectIdentifier::hash() const { - if(_hash && !_cache.empty()) + if (_hash && !_cache.empty()) { return _hash; + } const_cast(this)->_hash = boost::hash_value(toString()); return _hash; } -bool ObjectIdentifier::replaceObject(ObjectIdentifier &res, const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +bool ObjectIdentifier::replaceObject(ObjectIdentifier& res, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { ResolveResults result(*this); - if(!result.resolvedDocumentObject) + if (!result.resolvedDocumentObject) { return false; + } - auto r = PropertyLinkBase::tryReplaceLink(owner, result.resolvedDocumentObject, - parent, oldObj, newObj, subObjectName.getString().c_str()); + auto r = PropertyLinkBase::tryReplaceLink(owner, + result.resolvedDocumentObject, + parent, + oldObj, + newObj, + subObjectName.getString().c_str()); - if(!r.first) + if (!r.first) { return false; + } res = *this; - if(r.first != result.resolvedDocumentObject) { - if(r.first->getDocument()!=owner->getDocument()) { + if (r.first != result.resolvedDocumentObject) { + if (r.first->getDocument() != owner->getDocument()) { auto doc = r.first->getDocument(); bool useLabel = res.documentName.isRealString(); - const char *name = useLabel?doc->Label.getValue():doc->getName(); + const char* name = useLabel ? doc->Label.getValue() : doc->getName(); res.setDocumentName(String(name, useLabel), true); } - if(documentObjectName.isRealString()) - res.documentObjectName = String(r.first->Label.getValue(),true); - else - res.documentObjectName = String(r.first->getNameInDocument(),false,true); + if (documentObjectName.isRealString()) { + res.documentObjectName = String(r.first->Label.getValue(), true); + } + else { + res.documentObjectName = String(r.first->getNameInDocument(), false, true); + } } - res.subObjectName = String(r.second,true); + res.subObjectName = String(r.second, true); res._cache.clear(); res.shadowSub.newName.clear(); res.shadowSub.oldName.clear(); @@ -476,37 +519,46 @@ std::string ObjectIdentifier::toEscapedString() const return Base::Tools::escapedUnicodeFromUtf8(toString().c_str()); } -bool ObjectIdentifier::updateLabelReference( - App::DocumentObject *obj, const std::string &ref, const char *newLabel) +bool ObjectIdentifier::updateLabelReference(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) { - if(!owner) + if (!owner) { return false; + } ResolveResults result(*this); - if(!subObjectName.getString().empty() && result.resolvedDocumentObject) { - std::string sub = PropertyLinkBase::updateLabelReference( - result.resolvedDocumentObject, subObjectName.getString().c_str(), obj,ref,newLabel); - if(!sub.empty()) { - subObjectName = String(sub,true); + if (!subObjectName.getString().empty() && result.resolvedDocumentObject) { + std::string sub = PropertyLinkBase::updateLabelReference(result.resolvedDocumentObject, + subObjectName.getString().c_str(), + obj, + ref, + newLabel); + if (!sub.empty()) { + subObjectName = String(sub, true); _cache.clear(); return true; } } - if(result.resolvedDocument != obj->getDocument()) + if (result.resolvedDocument != obj->getDocument()) { return false; + } - if(!documentObjectName.getString().empty()) { - if(documentObjectName.isForceIdentifier()) + if (!documentObjectName.getString().empty()) { + if (documentObjectName.isForceIdentifier()) { return false; + } - if(!documentObjectName.isRealString() && - documentObjectName.getString()==obj->getNameInDocument()) + if (!documentObjectName.isRealString() + && documentObjectName.getString() == obj->getNameInDocument()) { return false; + } - if(documentObjectName.getString()!=obj->Label.getValue()) + if (documentObjectName.getString() != obj->Label.getValue()) { return false; + } documentObjectName = ObjectIdentifier::String(newLabel, true); @@ -514,11 +566,9 @@ bool ObjectIdentifier::updateLabelReference( return true; } - if (result.resolvedDocumentObject==obj && - result.propertyIndex == 1 && - result.resolvedDocumentObjectName.isRealString() && - result.resolvedDocumentObjectName.getString()==obj->Label.getValue()) - { + if (result.resolvedDocumentObject == obj && result.propertyIndex == 1 + && result.resolvedDocumentObjectName.isRealString() + && result.resolvedDocumentObjectName.getString() == obj->Label.getValue()) { components[0].name = ObjectIdentifier::String(newLabel, true); _cache.clear(); return true; @@ -526,7 +576,7 @@ bool ObjectIdentifier::updateLabelReference( // If object identifier uses the label then resolving the document object will fail. // So, it must be checked if using the new label will succeed - if (components.size()>1 && components[0].getName()==obj->Label.getValue()) { + if (components.size() > 1 && components[0].getName() == obj->Label.getValue()) { ObjectIdentifier id(*this); id.components[0].name.str = newLabel; @@ -542,12 +592,13 @@ bool ObjectIdentifier::updateLabelReference( return false; } -bool ObjectIdentifier::relabeledDocument(ExpressionVisitor &v, - const std::string &oldLabel, const std::string &newLabel) +bool ObjectIdentifier::relabeledDocument(ExpressionVisitor& v, + const std::string& oldLabel, + const std::string& newLabel) { - if (documentNameSet && documentName.isRealString() && documentName.getString()==oldLabel) { + if (documentNameSet && documentName.isRealString() && documentName.getString() == oldLabel) { v.aboutToChange(); - documentName = String(newLabel,true); + documentName = String(newLabel, true); _cache.clear(); return true; } @@ -559,20 +610,24 @@ bool ObjectIdentifier::relabeledDocument(ExpressionVisitor &v, * @return String representation of path. */ -void ObjectIdentifier::getSubPathStr(std::ostream &s, const ResolveResults &result, bool toPython) const +void ObjectIdentifier::getSubPathStr(std::ostream& s, + const ResolveResults& result, + bool toPython) const { std::vector::const_iterator i = components.begin() + result.propertyIndex + 1; while (i != components.end()) { - if(i->isSimple()) + if (i->isSimple()) { s << '.'; - i->toString(s,toPython); + } + i->toString(s, toPython); ++i; } } -std::string ObjectIdentifier::getSubPathStr(bool toPython) const { +std::string ObjectIdentifier::getSubPathStr(bool toPython) const +{ std::ostringstream ss; - getSubPathStr(ss,ResolveResults(*this),toPython); + getSubPathStr(ss, ResolveResults(*this), toPython); return ss.str(); } @@ -585,107 +640,143 @@ std::string ObjectIdentifier::getSubPathStr(bool toPython) const { * @param _end ending of a Range, or INT_MAX for other type. */ -ObjectIdentifier::Component::Component(const String &_name, - ObjectIdentifier::Component::typeEnum _type, int _begin, int _end, int _step) +ObjectIdentifier::Component::Component(const String& _name, + ObjectIdentifier::Component::typeEnum _type, + int _begin, + int _end, + int _step) : name(_name) , type(_type) , begin(_begin) , end(_end) , step(_step) -{ -} +{} -ObjectIdentifier::Component::Component(String &&_name, - ObjectIdentifier::Component::typeEnum _type, int _begin, int _end, int _step) +ObjectIdentifier::Component::Component(String&& _name, + ObjectIdentifier::Component::typeEnum _type, + int _begin, + int _end, + int _step) : name(std::move(_name)) , type(_type) , begin(_begin) , end(_end) , step(_step) +{} + + +size_t ObjectIdentifier::Component::getIndex(size_t count) const { -} - - -size_t ObjectIdentifier::Component::getIndex(size_t count) const { - if(begin>=0) { - if(begin<(int)count) + if (begin >= 0) { + if (begin < (int)count) { return begin; - }else { + } + } + else { int idx = begin + (int)count; - if(idx >= 0) + if (idx >= 0) { return idx; + } } FC_THROWM(Base::IndexError, "Array out of bound: " << begin << ", " << count); } -Py::Object ObjectIdentifier::Component::get(const Py::Object &pyobj) const { +Py::Object ObjectIdentifier::Component::get(const Py::Object& pyobj) const +{ Py::Object res; - if(isSimple()) { - if(!pyobj.hasAttr(getName())) + if (isSimple()) { + if (!pyobj.hasAttr(getName())) { FC_THROWM(Base::AttributeError, "No attribute named '" << getName() << "'"); + } res = pyobj.getAttr(getName()); - } else if(isArray()) { - if(pyobj.isMapping()) + } + else if (isArray()) { + if (pyobj.isMapping()) { res = Py::Mapping(pyobj).getItem(Py::Int(begin)); - else + } + else { res = Py::Sequence(pyobj).getItem(begin); - }else if(isMap()) + } + } + else if (isMap()) { res = Py::Mapping(pyobj).getItem(getName()); + } else { assert(isRange()); Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end!=INT_MAX?Py::Int(end).ptr():nullptr, - step!=1?Py::Int(step).ptr():nullptr),true); - PyObject *r = PyObject_GetItem(pyobj.ptr(),slice.ptr()); - if(!r) + end != INT_MAX ? Py::Int(end).ptr() : nullptr, + step != 1 ? Py::Int(step).ptr() : nullptr), + true); + PyObject* r = PyObject_GetItem(pyobj.ptr(), slice.ptr()); + if (!r) { Base::PyException::ThrowException(); + } res = Py::asObject(r); } - if(!res.ptr()) + if (!res.ptr()) { Base::PyException::ThrowException(); - if(PyModule_Check(res.ptr()) && !ExpressionParser::isModuleImported(res.ptr())) + } + if (PyModule_Check(res.ptr()) && !ExpressionParser::isModuleImported(res.ptr())) { FC_THROWM(Base::RuntimeError, "Module '" << getName() << "' access denied."); + } return res; } -void ObjectIdentifier::Component::set(Py::Object &pyobj, const Py::Object &value) const { - if(isSimple()) { - if(PyObject_SetAttrString(*pyobj, getName().c_str(), *value ) == -1) +void ObjectIdentifier::Component::set(Py::Object& pyobj, const Py::Object& value) const +{ + if (isSimple()) { + if (PyObject_SetAttrString(*pyobj, getName().c_str(), *value) == -1) { Base::PyException::ThrowException(); - } else if(isArray()) { - if(pyobj.isMapping()) - Py::Mapping(pyobj).setItem(Py::Int(begin),value); - else - Py::Sequence(pyobj).setItem(begin,value); - }else if(isMap()) - Py::Mapping(pyobj).setItem(getName(),value); + } + } + else if (isArray()) { + if (pyobj.isMapping()) { + Py::Mapping(pyobj).setItem(Py::Int(begin), value); + } + else { + Py::Sequence(pyobj).setItem(begin, value); + } + } + else if (isMap()) { + Py::Mapping(pyobj).setItem(getName(), value); + } else { assert(isRange()); Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end!=INT_MAX?Py::Int(end).ptr():nullptr, - step!=1?Py::Int(step).ptr():nullptr),true); - if(PyObject_SetItem(pyobj.ptr(),slice.ptr(),value.ptr())<0) + end != INT_MAX ? Py::Int(end).ptr() : nullptr, + step != 1 ? Py::Int(step).ptr() : nullptr), + true); + if (PyObject_SetItem(pyobj.ptr(), slice.ptr(), value.ptr()) < 0) { Base::PyException::ThrowException(); + } } } -void ObjectIdentifier::Component::del(Py::Object &pyobj) const { - if(isSimple()) +void ObjectIdentifier::Component::del(Py::Object& pyobj) const +{ + if (isSimple()) { pyobj.delAttr(getName()); - else if(isArray()) { - if(pyobj.isMapping()) + } + else if (isArray()) { + if (pyobj.isMapping()) { Py::Mapping(pyobj).delItem(Py::Int(begin)); - else - PySequence_DelItem(pyobj.ptr(),begin); - } else if(isMap()) + } + else { + PySequence_DelItem(pyobj.ptr(), begin); + } + } + else if (isMap()) { Py::Mapping(pyobj).delItem(getName()); + } else { assert(isRange()); Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end!=INT_MAX?Py::Int(end).ptr():nullptr, - step!=1?Py::Int(step).ptr():nullptr),true); - if(PyObject_DelItem(pyobj.ptr(),slice.ptr())<0) + end != INT_MAX ? Py::Int(end).ptr() : nullptr, + step != 1 ? Py::Int(step).ptr() : nullptr), + true); + if (PyObject_DelItem(pyobj.ptr(), slice.ptr()) < 0) { Base::PyException::ThrowException(); + } } } @@ -695,7 +786,7 @@ void ObjectIdentifier::Component::del(Py::Object &pyobj) const { * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const char *_component) +ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const char* _component) { return Component(String(_component)); } @@ -706,12 +797,14 @@ ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const c * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const ObjectIdentifier::String &_component) +ObjectIdentifier::Component +ObjectIdentifier::Component::SimpleComponent(const ObjectIdentifier::String& _component) { return Component(_component); } -ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String &&_component) +ObjectIdentifier::Component +ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String&& _component) { return Component(std::move(_component)); } @@ -735,12 +828,12 @@ ObjectIdentifier::Component ObjectIdentifier::Component::ArrayComponent(int _ind * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(const String & _key) +ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(const String& _key) { return Component(_key, Component::MAP); } -ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(String &&_key) +ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(String&& _key) { return Component(std::move(_key), Component::MAP); } @@ -753,7 +846,8 @@ ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(String &&_ * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::RangeComponent(int _begin, int _end, int _step) +ObjectIdentifier::Component +ObjectIdentifier::Component::RangeComponent(int _begin, int _end, int _step) { return Component(String(), Component::RANGE, _begin, _end, _step); } @@ -764,22 +858,23 @@ ObjectIdentifier::Component ObjectIdentifier::Component::RangeComponent(int _beg * @return true if they are equal, false if not. */ -bool ObjectIdentifier::Component::operator ==(const ObjectIdentifier::Component &other) const +bool ObjectIdentifier::Component::operator==(const ObjectIdentifier::Component& other) const { - if (type != other.type) + if (type != other.type) { return false; + } switch (type) { - case SIMPLE: - case MAP: - return name == other.name; - case ARRAY: - return begin == other.begin; - case RANGE: - return begin == other.begin && end == other.end && step==other.step; - default: - assert(0); - return false; + case SIMPLE: + case MAP: + return name == other.name; + case ARRAY: + return begin == other.begin; + case RANGE: + return begin == other.begin && end == other.end && step == other.step; + default: + assert(0); + return false; } } @@ -788,35 +883,39 @@ bool ObjectIdentifier::Component::operator ==(const ObjectIdentifier::Component * @return A string representing the component. */ -void ObjectIdentifier::Component::toString(std::ostream &ss, bool toPython) const +void ObjectIdentifier::Component::toString(std::ostream& ss, bool toPython) const { switch (type) { - case Component::SIMPLE: - ss << name.getString(); - break; - case Component::MAP: - ss << "[" << name.toString(toPython) << "]"; - break; - case Component::ARRAY: - ss << "[" << begin << "]"; - break; - case Component::RANGE: - ss << '['; - if(begin!=INT_MAX) - ss << begin; - ss << ':'; - if(end!=INT_MAX) - ss << end; - if(step!=1) - ss << ':' << step; - ss << ']'; - break; - default: - assert(0); + case Component::SIMPLE: + ss << name.getString(); + break; + case Component::MAP: + ss << "[" << name.toString(toPython) << "]"; + break; + case Component::ARRAY: + ss << "[" << begin << "]"; + break; + case Component::RANGE: + ss << '['; + if (begin != INT_MAX) { + ss << begin; + } + ss << ':'; + if (end != INT_MAX) { + ss << end; + } + if (step != 1) { + ss << ':' << step; + } + ss << ']'; + break; + default: + assert(0); } } -enum ResolveFlags { +enum ResolveFlags +{ ResolveByIdentifier, ResolveByLabel, ResolveAmbiguous, @@ -833,13 +932,14 @@ enum ResolveFlags { * @return Pointer to document object if a unique pointer is found, 0 otherwise. */ -App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * doc, - const String & name, std::bitset<32> &flags) +App::DocumentObject* ObjectIdentifier::getDocumentObject(const App::Document* doc, + const String& name, + std::bitset<32>& flags) { - DocumentObject * objectById = nullptr; - DocumentObject * objectByLabel = nullptr; + DocumentObject* objectById = nullptr; + DocumentObject* objectByLabel = nullptr; - if(!name.isRealString()) { + if (!name.isRealString()) { // No object found with matching label, try using name directly objectById = doc->getObject(static_cast(name)); @@ -847,40 +947,43 @@ App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * flags.set(ResolveByIdentifier); return objectById; } - if(name.isForceIdentifier()) + if (name.isForceIdentifier()) { return nullptr; + } } std::vector docObjects = doc->getObjects(); for (auto docObject : docObjects) { if (strcmp(docObject->Label.getValue(), static_cast(name)) == 0) { // Found object with matching label - if (objectByLabel) { - FC_WARN("duplicate object label " << doc->getName() << '#' << static_cast(name)); + if (objectByLabel) { + FC_WARN("duplicate object label " << doc->getName() << '#' + << static_cast(name)); return nullptr; } objectByLabel = docObject; } } - if (!objectByLabel && !objectById) // Not found at all + if (!objectByLabel && !objectById) { // Not found at all return nullptr; - else if (!objectByLabel) { // Found by name + } + else if (!objectByLabel) { // Found by name flags.set(ResolveByIdentifier); return objectById; } - else if (!objectById) { // Found by label + else if (!objectById) { // Found by label flags.set(ResolveByLabel); return objectByLabel; } - else if (objectByLabel == objectById) { // Found by both name and label, same object + else if (objectByLabel == objectById) { // Found by both name and label, same object flags.set(ResolveByIdentifier); flags.set(ResolveByLabel); return objectByLabel; } else { flags.set(ResolveAmbiguous); - return nullptr; // Found by both name and label, two different objects + return nullptr; // Found by both name and label, two different objects } } @@ -891,16 +994,17 @@ App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * * */ -void ObjectIdentifier::resolve(ResolveResults &results) const +void ObjectIdentifier::resolve(ResolveResults& results) const { - if(!owner) + if (!owner) { return; + } bool docAmbiguous = false; /* Document name specified? */ if (!documentName.getString().empty()) { - results.resolvedDocument = getDocument(documentName,&docAmbiguous); + results.resolvedDocument = getDocument(documentName, &docAmbiguous); results.resolvedDocumentName = documentName; } else { @@ -915,14 +1019,16 @@ void ObjectIdentifier::resolve(ResolveResults &results) const // Assume document name and object name from owner if not found if (!results.resolvedDocument) { if (!documentName.getString().empty()) { - if(docAmbiguous) + if (docAmbiguous) { results.flags.set(ResolveAmbiguous); + } return; } results.resolvedDocument = owner->getDocument(); - if (!results.resolvedDocument) + if (!results.resolvedDocument) { return; + } } results.resolvedDocumentName = String(results.resolvedDocument->getName(), false, true); @@ -930,24 +1036,27 @@ void ObjectIdentifier::resolve(ResolveResults &results) const /* Document object name specified? */ if (!documentObjectName.getString().empty()) { results.resolvedDocumentObjectName = documentObjectName; - results.resolvedDocumentObject = getDocumentObject( - results.resolvedDocument, documentObjectName, results.flags); - if (!results.resolvedDocumentObject) + results.resolvedDocumentObject = + getDocumentObject(results.resolvedDocument, documentObjectName, results.flags); + if (!results.resolvedDocumentObject) { return; + } - if (components.empty()) + if (components.empty()) { return; + } - results.propertyName = components[ 0 ].name.getString(); + results.propertyName = components[0].name.getString(); results.propertyIndex = 0; - results.getProperty( *this ); + results.getProperty(*this); } else { /* Document object name not specified, resolve from path */ /* One component? */ - if (components.size() == 1 || (components.size()>1 && !components[0].isSimple())) { - /* Yes -- then this must be a property, so we get the document object's name from the owner */ + if (components.size() == 1 || (components.size() > 1 && !components[0].isSimple())) { + /* Yes -- then this must be a property, so we get the document object's name from the + * owner */ results.resolvedDocumentObjectName = String(owner->getNameInDocument(), false, true); results.resolvedDocumentObject = owner; results.propertyName = components[0].name.getString(); @@ -956,36 +1065,39 @@ void ObjectIdentifier::resolve(ResolveResults &results) const } else if (components.size() >= 2) { /* No -- */ - if (!components[0].isSimple()) + if (!components[0].isSimple()) { return; + } - results.resolvedDocumentObject = getDocumentObject( - results.resolvedDocument, components[0].name, results.flags); + results.resolvedDocumentObject = + getDocumentObject(results.resolvedDocument, components[0].name, results.flags); /* Possible to resolve component to a document object? */ if (results.resolvedDocumentObject) { /* Yes */ - results.resolvedDocumentObjectName = String { - components[0].name.getString(), - false, - results.flags.test(ResolveByIdentifier)}; + results.resolvedDocumentObjectName = + String {components[0].name.getString(), + false, + results.flags.test(ResolveByIdentifier)}; results.propertyName = components[1].name.getString(); results.propertyIndex = 1; results.getProperty(*this); - if(!results.resolvedProperty) { + if (!results.resolvedProperty) { // If the second component is not a property name, try to // interpret the first component as the property name. - DocumentObject *sobj = nullptr; - results.resolvedProperty = resolveProperty( - owner, - components[0].name.toString().c_str(), - sobj, - results.propertyType); - if(results.resolvedProperty) { + DocumentObject* sobj = nullptr; + results.resolvedProperty = + resolveProperty(owner, + components[0].name.toString().c_str(), + sobj, + results.propertyType); + if (results.resolvedProperty) { results.propertyName = components[0].name.getString(); results.resolvedDocument = owner->getDocument(); - results.resolvedDocumentName = String(results.resolvedDocument->getName(), false, true); - results.resolvedDocumentObjectName = String(owner->getNameInDocument(), false, true); + results.resolvedDocumentName = + String(results.resolvedDocument->getName(), false, true); + results.resolvedDocumentObjectName = + String(owner->getNameInDocument(), false, true); results.resolvedDocumentObject = owner; results.resolvedSubObject = sobj; results.propertyIndex = 0; @@ -995,16 +1107,20 @@ void ObjectIdentifier::resolve(ResolveResults &results) const else if (documentName.getString().empty()) { /* No, assume component is a property, and get document object's name from owner */ results.resolvedDocument = owner->getDocument(); - results.resolvedDocumentName = String(results.resolvedDocument->getName(), false, true); - results.resolvedDocumentObjectName = String(owner->getNameInDocument(), false, true); - results.resolvedDocumentObject = owner->getDocument()->getObject(owner->getNameInDocument()); + results.resolvedDocumentName = + String(results.resolvedDocument->getName(), false, true); + results.resolvedDocumentObjectName = + String(owner->getNameInDocument(), false, true); + results.resolvedDocumentObject = + owner->getDocument()->getObject(owner->getNameInDocument()); results.propertyIndex = 0; results.propertyName = components[results.propertyIndex].name.getString(); results.getProperty(*this); } } - else + else { return; + } } } @@ -1014,27 +1130,31 @@ void ObjectIdentifier::resolve(ResolveResults &results) const * @return Pointer to document, or 0 if it is not found or not uniquely defined by name. */ -Document * ObjectIdentifier::getDocument(String name, bool *ambiguous) const +Document* ObjectIdentifier::getDocument(String name, bool* ambiguous) const { - if (name.getString().empty()) + if (name.getString().empty()) { name = getDocumentName(); - - App::Document * docById = nullptr; - - if(!name.isRealString()) { - docById = App::GetApplication().getDocument(name.toString().c_str()); - if (name.isForceIdentifier()) - return docById; } - App::Document * docByLabel = nullptr; + App::Document* docById = nullptr; + + if (!name.isRealString()) { + docById = App::GetApplication().getDocument(name.toString().c_str()); + if (name.isForceIdentifier()) { + return docById; + } + } + + App::Document* docByLabel = nullptr; const std::vector docs = App::GetApplication().getDocuments(); for (auto doc : docs) { if (doc->Label.getValue() == name.getString()) { /* Multiple hits for same label? */ if (docByLabel) { - if(ambiguous) *ambiguous = true; + if (ambiguous) { + *ambiguous = true; + } return nullptr; } docByLabel = doc; @@ -1042,18 +1162,22 @@ Document * ObjectIdentifier::getDocument(String name, bool *ambiguous) const } /* Not found on id? */ - if (!docById) - return docByLabel; // Either not found at all, or on label + if (!docById) { + return docByLabel; // Either not found at all, or on label + } else { /* Not found on label? */ - if (!docByLabel) /* Then return doc by id */ + if (!docByLabel) { /* Then return doc by id */ return docById; + } /* docByLabel and docById could be equal; that is ok */ - if (docByLabel == docById) + if (docByLabel == docById) { return docById; - if (ambiguous) + } + if (ambiguous) { *ambiguous = true; + } return nullptr; } } @@ -1063,13 +1187,14 @@ Document * ObjectIdentifier::getDocument(String name, bool *ambiguous) const * @return Pointer to document object, or 0 if not found or uniquely defined. */ -DocumentObject *ObjectIdentifier::getDocumentObject() const +DocumentObject* ObjectIdentifier::getDocumentObject() const { - const App::Document * doc = getDocument(); + const App::Document* doc = getDocument(); std::bitset<32> dummy; - if (!doc) + if (!doc) { return nullptr; + } ResolveResults result(*this); @@ -1077,7 +1202,8 @@ DocumentObject *ObjectIdentifier::getDocumentObject() const } -enum PseudoPropertyType { +enum PseudoPropertyType +{ PseudoNone, PseudoShape, PseudoPlacement, @@ -1095,47 +1221,57 @@ enum PseudoPropertyType { PseudoCadquery, }; -void ObjectIdentifier::getDepLabels(std::vector &labels) const { - getDepLabels(ResolveResults(*this),labels); -} - -void ObjectIdentifier::getDepLabels( - const ResolveResults &result, std::vector &labels) const +void ObjectIdentifier::getDepLabels(std::vector& labels) const { - if(!documentObjectName.getString().empty()) { - if(documentObjectName.isRealString()) - labels.push_back(documentObjectName.getString()); - } else if(result.propertyIndex == 1) - labels.push_back(components[0].name.getString()); - if(!subObjectName.getString().empty()) - PropertyLinkBase::getLabelReferences(labels,subObjectName.getString().c_str()); + getDepLabels(ResolveResults(*this), labels); } -ObjectIdentifier::Dependencies -ObjectIdentifier::getDep(bool needProps, std::vector *labels) const +void ObjectIdentifier::getDepLabels(const ResolveResults& result, + std::vector& labels) const +{ + if (!documentObjectName.getString().empty()) { + if (documentObjectName.isRealString()) { + labels.push_back(documentObjectName.getString()); + } + } + else if (result.propertyIndex == 1) { + labels.push_back(components[0].name.getString()); + } + if (!subObjectName.getString().empty()) { + PropertyLinkBase::getLabelReferences(labels, subObjectName.getString().c_str()); + } +} + +ObjectIdentifier::Dependencies ObjectIdentifier::getDep(bool needProps, + std::vector* labels) const { Dependencies deps; - getDep(deps,needProps,labels); + getDep(deps, needProps, labels); return deps; } -void ObjectIdentifier::getDep(Dependencies &deps, bool needProps, std::vector *labels) const +void ObjectIdentifier::getDep(Dependencies& deps, + bool needProps, + std::vector* labels) const { ResolveResults result(*this); - if(labels) - getDepLabels(result,*labels); + if (labels) { + getDepLabels(result, *labels); + } - if(!result.resolvedDocumentObject) - return; + if (!result.resolvedDocumentObject) { + return; + } - if(!needProps) { + if (!needProps) { deps[result.resolvedDocumentObject]; return; } - if(!result.resolvedProperty) { - if(!result.propertyName.empty()) + if (!result.resolvedProperty) { + if (!result.propertyName.empty()) { deps[result.resolvedDocumentObject].insert(result.propertyName); + } return; } @@ -1146,7 +1282,7 @@ void ObjectIdentifier::getDep(Dependencies &deps, bool needProps, std::vector ObjectIdentifier::getStringList() const std::vector l; ResolveResults result(*this); - if(!result.resolvedProperty || result.resolvedDocumentObject != owner) { - if (documentNameSet) + if (!result.resolvedProperty || result.resolvedDocumentObject != owner) { + if (documentNameSet) { l.push_back(documentName.toString()); + } - if (documentObjectNameSet) + if (documentObjectNameSet) { l.push_back(documentObjectName.toString()); + } } - if(!subObjectName.getString().empty()) { + if (!subObjectName.getString().empty()) { l.back() += subObjectName.toString(); } std::vector::const_iterator i = components.begin(); @@ -1187,20 +1325,24 @@ std::vector ObjectIdentifier::getStringList() const * @return A new simplified object identifier. */ -ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier &other) const +ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier& other) const { ObjectIdentifier result(other.getOwner()); ResolveResults thisresult(*this); ResolveResults otherresult(other); - if (otherresult.resolvedDocument != thisresult.resolvedDocument) + if (otherresult.resolvedDocument != thisresult.resolvedDocument) { result.setDocumentName(std::move(thisresult.resolvedDocumentName), true); - if (otherresult.resolvedDocumentObject != thisresult.resolvedDocumentObject) - result.setDocumentObjectName( - std::move(thisresult.resolvedDocumentObjectName), true, String(subObjectName)); + } + if (otherresult.resolvedDocumentObject != thisresult.resolvedDocumentObject) { + result.setDocumentObjectName(std::move(thisresult.resolvedDocumentObjectName), + true, + String(subObjectName)); + } - for (std::size_t i = thisresult.propertyIndex; i < components.size(); ++i) + for (std::size_t i = thisresult.propertyIndex; i < components.size(); ++i) { result << components[i]; + } return result; } @@ -1215,15 +1357,17 @@ ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier &other) con * @return A new object identifier. */ -ObjectIdentifier ObjectIdentifier::parse(const DocumentObject *docObj, const std::string &str) +ObjectIdentifier ObjectIdentifier::parse(const DocumentObject* docObj, const std::string& str) { std::unique_ptr expr(ExpressionParser::parse(docObj, str.c_str())); - VariableExpression * v = freecad_dynamic_cast(expr.get()); + VariableExpression* v = freecad_dynamic_cast(expr.get()); - if (v) + if (v) { return v->getPath(); - else - FC_THROWM(Base::RuntimeError,"Invalid property specification."); + } + else { + FC_THROWM(Base::RuntimeError, "Invalid property specification."); + } } std::string ObjectIdentifier::resolveErrorString() const @@ -1239,14 +1383,14 @@ std::string ObjectIdentifier::resolveErrorString() const * @return Reference to itself. */ -ObjectIdentifier &ObjectIdentifier::operator <<(const ObjectIdentifier::Component &value) +ObjectIdentifier& ObjectIdentifier::operator<<(const ObjectIdentifier::Component& value) { components.push_back(value); _cache.clear(); return *this; } -ObjectIdentifier &ObjectIdentifier::operator <<(ObjectIdentifier::Component &&value) +ObjectIdentifier& ObjectIdentifier::operator<<(ObjectIdentifier::Component&& value) { components.push_back(std::move(value)); _cache.clear(); @@ -1259,59 +1403,61 @@ ObjectIdentifier &ObjectIdentifier::operator <<(ObjectIdentifier::Component &&va * @return Point to property if it is uniquely defined, or 0 otherwise. */ -Property *ObjectIdentifier::getProperty(int *ptype) const +Property* ObjectIdentifier::getProperty(int* ptype) const { ResolveResults result(*this); - if(ptype) + if (ptype) { *ptype = result.propertyType; + } return result.resolvedProperty; } -Property *ObjectIdentifier::resolveProperty(const App::DocumentObject *obj, - const char *propertyName, App::DocumentObject *&sobj, int &ptype) const +Property* ObjectIdentifier::resolveProperty(const App::DocumentObject* obj, + const char* propertyName, + App::DocumentObject*& sobj, + int& ptype) const { - if(obj && !subObjectName.getString().empty()) { + if (obj && !subObjectName.getString().empty()) { sobj = obj->getSubObject(subObjectName.toString().c_str()); obj = sobj; } - if(!obj) + if (!obj) { return nullptr; + } - static std::unordered_map _props = { - {"_shape",PseudoShape}, - {"_pla",PseudoPlacement}, - {"_matrix",PseudoMatrix}, - {"__pla",PseudoLinkPlacement}, - {"__matrix",PseudoLinkMatrix}, - {"_self",PseudoSelf}, - {"_app",PseudoApp}, - {"_part",PseudoPart}, - {"_re",PseudoRegex}, + static std::unordered_map _props = { + {"_shape", PseudoShape}, + {"_pla", PseudoPlacement}, + {"_matrix", PseudoMatrix}, + {"__pla", PseudoLinkPlacement}, + {"__matrix", PseudoLinkMatrix}, + {"_self", PseudoSelf}, + {"_app", PseudoApp}, + {"_part", PseudoPart}, + {"_re", PseudoRegex}, {"_py", PseudoBuiltins}, {"_math", PseudoMath}, {"_coll", PseudoCollections}, - {"_gui",PseudoGui}, - {"_cq",PseudoCadquery}, + {"_gui", PseudoGui}, + {"_cq", PseudoCadquery}, }; auto it = _props.find(propertyName); - if(it == _props.end()) + if (it == _props.end()) { ptype = PseudoNone; + } else { ptype = it->second; - if(ptype != PseudoShape && - !subObjectName.getString().empty() && - !boost::ends_with(subObjectName.getString(),".")) - { + if (ptype != PseudoShape && !subObjectName.getString().empty() + && !boost::ends_with(subObjectName.getString(), ".")) { return nullptr; } - return &const_cast(obj)->Label; //fake the property + return &const_cast(obj)->Label; // fake the property } return obj->getPropertyByName(propertyName); } - /** * @brief Create a canonical representation of an object identifier. * @@ -1325,18 +1471,19 @@ ObjectIdentifier ObjectIdentifier::canonicalPath() const { ObjectIdentifier res(*this); ResolveResults result(res); - if(result.resolvedDocumentObject && result.resolvedDocumentObject!=owner) { + if (result.resolvedDocumentObject && result.resolvedDocumentObject != owner) { res.owner = result.resolvedDocumentObject; res._cache.clear(); } res.resolveAmbiguity(result); - if(!result.resolvedProperty || result.propertyType!=PseudoNone) + if (!result.resolvedProperty || result.propertyType != PseudoNone) { return res; + } return result.resolvedProperty->canonicalPath(res); } -static const std::map *_DocumentMap; -ObjectIdentifier::DocumentMapper::DocumentMapper(const std::map &map) +static const std::map* _DocumentMap; +ObjectIdentifier::DocumentMapper::DocumentMapper(const std::map& map) { assert(!_DocumentMap); _DocumentMap = ↦ @@ -1356,23 +1503,25 @@ ObjectIdentifier::DocumentMapper::~DocumentMapper() * @param force Force name to be set */ -void ObjectIdentifier::setDocumentName(ObjectIdentifier::String &&name, bool force) +void ObjectIdentifier::setDocumentName(ObjectIdentifier::String&& name, bool force) { - if(name.getString().empty()) + if (name.getString().empty()) { force = false; + } documentNameSet = force; _cache.clear(); - if(!name.getString().empty() && _DocumentMap) { - if(name.isRealString()) { + if (!name.getString().empty() && _DocumentMap) { + if (name.isRealString()) { auto iter = _DocumentMap->find(name.toString()); - if(iter!=_DocumentMap->end()) { - documentName = String(iter->second,true); + if (iter != _DocumentMap->end()) { + documentName = String(iter->second, true); return; } - }else{ + } + else { auto iter = _DocumentMap->find(name.getString()); - if(iter!=_DocumentMap->end()) { - documentName = String(iter->second,false,true); + if (iter != _DocumentMap->end()) { + documentName = String(iter->second, false, true); return; } } @@ -1403,12 +1552,14 @@ ObjectIdentifier::String ObjectIdentifier::getDocumentName() const * @param force Force name to be set. */ -void ObjectIdentifier::setDocumentObjectName(ObjectIdentifier::String &&name, bool force, - ObjectIdentifier::String &&subname, bool checkImport) +void ObjectIdentifier::setDocumentObjectName(ObjectIdentifier::String&& name, + bool force, + ObjectIdentifier::String&& subname, + bool checkImport) { - if(checkImport) { + if (checkImport) { name.checkImport(owner); - subname.checkImport(owner,nullptr,&name); + subname.checkImport(owner, nullptr, &name); } documentObjectName = std::move(name); @@ -1418,35 +1569,46 @@ void ObjectIdentifier::setDocumentObjectName(ObjectIdentifier::String &&name, bo _cache.clear(); } -void ObjectIdentifier::setDocumentObjectName(const App::DocumentObject *obj, bool force, - ObjectIdentifier::String &&subname, bool checkImport) +void ObjectIdentifier::setDocumentObjectName(const App::DocumentObject* obj, + bool force, + ObjectIdentifier::String&& subname, + bool checkImport) { - if(!owner || !obj || !obj->isAttachedToDocument() || !obj->getDocument()) - FC_THROWM(Base::RuntimeError,"invalid object"); + if (!owner || !obj || !obj->isAttachedToDocument() || !obj->getDocument()) { + FC_THROWM(Base::RuntimeError, "invalid object"); + } - if(checkImport) - subname.checkImport(owner,obj); + if (checkImport) { + subname.checkImport(owner, obj); + } - if(obj == owner) + if (obj == owner) { force = false; - else + } + else { localProperty = false; - if(obj->getDocument() == owner->getDocument()) + } + if (obj->getDocument() == owner->getDocument()) { setDocumentName(String()); - else if(!documentNameSet) { - if(obj->getDocument() == owner->getDocument()) + } + else if (!documentNameSet) { + if (obj->getDocument() == owner->getDocument()) { setDocumentName(String()); + } else { documentNameSet = true; - documentName = String(obj->getDocument()->getName(),false,true); + documentName = String(obj->getDocument()->getName(), false, true); } - }else if(documentName.isRealString()) - documentName = String(obj->getDocument()->Label.getStrValue(),true); - else - documentName = String(obj->getDocument()->getName(),false,true); + } + else if (documentName.isRealString()) { + documentName = String(obj->getDocument()->Label.getStrValue(), true); + } + else { + documentName = String(obj->getDocument()->getName(), false, true); + } documentObjectNameSet = force; - documentObjectName = String(obj->getNameInDocument(),false,true); + documentObjectName = String(obj->getNameInDocument(), false, true); subObjectName = std::move(subname); _cache.clear(); @@ -1465,7 +1627,8 @@ ObjectIdentifier::String ObjectIdentifier::getDocumentObjectName() const return result.resolvedDocumentObjectName; } -bool ObjectIdentifier::hasDocumentObjectName(bool forced) const { +bool ObjectIdentifier::hasDocumentObjectName(bool forced) const +{ return !documentObjectName.getString().empty() && (!forced || documentObjectNameSet); } @@ -1476,40 +1639,43 @@ bool ObjectIdentifier::hasDocumentObjectName(bool forced) const { std::string ObjectIdentifier::String::toString(bool toPython) const { - if (isRealString()) - return quote(str,toPython); - else + if (isRealString()) { + return quote(str, toPython); + } + else { return str; + } } -void ObjectIdentifier::String::checkImport(const App::DocumentObject *owner, - const App::DocumentObject *obj, String *objName) +void ObjectIdentifier::String::checkImport(const App::DocumentObject* owner, + const App::DocumentObject* obj, + String* objName) { - if(owner && owner->getDocument() && !str.empty() && - ExpressionParser::ExpressionImporter::reader()) { + if (owner && owner->getDocument() && !str.empty() + && ExpressionParser::ExpressionImporter::reader()) { auto reader = ExpressionParser::ExpressionImporter::reader(); if (obj || objName) { bool restoreLabel = false; - str = PropertyLinkBase::importSubName(*reader,str.c_str(),restoreLabel); + str = PropertyLinkBase::importSubName(*reader, str.c_str(), restoreLabel); if (restoreLabel) { if (!obj) { std::bitset<32> flags; - obj = getDocumentObject(owner->getDocument(),*objName,flags); + obj = getDocumentObject(owner->getDocument(), *objName, flags); if (!obj) { FC_ERR("Cannot find object " << objName->toString()); } } if (obj) { - PropertyLinkBase::restoreLabelReference(obj,str); + PropertyLinkBase::restoreLabelReference(obj, str); } } } - else if (str.back()!='@') { + else if (str.back() != '@') { str = reader->getName(str.c_str()); } else { - str.resize(str.size()-1); + str.resize(str.size() - 1); auto mapped = reader->getName(str.c_str()); auto objForMapped = owner->getDocument()->getObject(mapped); if (!objForMapped) { @@ -1524,14 +1690,12 @@ void ObjectIdentifier::String::checkImport(const App::DocumentObject *owner, } } -Py::Object ObjectIdentifier::access(const ResolveResults &result, - Py::Object *value, Dependencies *deps) const +Py::Object +ObjectIdentifier::access(const ResolveResults& result, Py::Object* value, Dependencies* deps) const { - if(!result.resolvedDocumentObject || !result.resolvedProperty || - (!subObjectName.getString().empty() && !result.resolvedSubObject)) - { - FC_THROWM(Base::RuntimeError, result.resolveErrorString() - << " in '" << toString() << "'"); + if (!result.resolvedDocumentObject || !result.resolvedProperty + || (!subObjectName.getString().empty() && !result.resolvedSubObject)) { + FC_THROWM(Base::RuntimeError, result.resolveErrorString() << " in '" << toString() << "'"); } Py::Object pyobj; @@ -1540,153 +1704,166 @@ Py::Object ObjectIdentifier::access(const ResolveResults &result, // NOTE! We do not keep reference of the imported module, assuming once // imported they'll live (because of sys.modules) till the application // dies. -#define GET_MODULE(_name) do {\ - static PyObject *pymod;\ - if(!pymod) {\ - pymod = PyImport_ImportModule(#_name);\ - if(!pymod)\ - Base::PyException::ThrowException();\ - else\ - Py_DECREF(pymod);\ - }\ - pyobj = Py::Object(pymod);\ - }while(0) +#define GET_MODULE(_name) \ + do { \ + static PyObject* pymod; \ + if (!pymod) { \ + pymod = PyImport_ImportModule(#_name); \ + if (!pymod) \ + Base::PyException::ThrowException(); \ + else \ + Py_DECREF(pymod); \ + } \ + pyobj = Py::Object(pymod); \ + } while (0) - size_t idx = result.propertyIndex+1; - switch(ptype) { - case PseudoApp: - GET_MODULE(FreeCAD); - break; - case PseudoGui: - GET_MODULE(FreeCADGui); - break; - case PseudoPart: - GET_MODULE(Part); - break; - case PseudoCadquery: - GET_MODULE(freecad.fc_cadquery); - break; - case PseudoRegex: - GET_MODULE(re); - break; - case PseudoBuiltins: - GET_MODULE(builtins); - break; - case PseudoMath: - GET_MODULE(math); - break; - case PseudoCollections: - GET_MODULE(collections); - break; - case PseudoShape: { - GET_MODULE(Part); - Py::Callable func(pyobj.getAttr("getShape")); - Py::Tuple tuple(1); - tuple.setItem(0,Py::Object(result.resolvedDocumentObject->getPyObject(),true)); - if(result.subObjectName.getString().empty()) - pyobj = func.apply(tuple); - else{ - Py::Dict dict; - dict.setItem("subname",Py::String(result.subObjectName.getString())); - dict.setItem("needSubElement",Py::True()); - pyobj = func.apply(tuple,dict); - } - break; - } default: { - Base::Matrix4D mat; - auto obj = result.resolvedDocumentObject; - switch(ptype) { - case PseudoPlacement: - case PseudoMatrix: - case PseudoLinkPlacement: - case PseudoLinkMatrix: - obj->getSubObject(result.subObjectName.getString().c_str(),nullptr,&mat); + size_t idx = result.propertyIndex + 1; + switch (ptype) { + case PseudoApp: + GET_MODULE(FreeCAD); break; - default: + case PseudoGui: + GET_MODULE(FreeCADGui); break; - } - if(result.resolvedSubObject) - obj = result.resolvedSubObject; - switch(ptype) { - case PseudoPlacement: - pyobj = Py::Placement(Base::Placement(mat)); + case PseudoPart: + GET_MODULE(Part); break; - case PseudoMatrix: - pyobj = Py::Matrix(mat); + case PseudoCadquery: + GET_MODULE(freecad.fc_cadquery); break; - case PseudoLinkPlacement: - case PseudoLinkMatrix: { - auto linked = obj->getLinkedObject(true,&mat,false); - if(!linked || linked==obj) { - auto ext = obj->getExtensionByType(true); - if(ext) - ext->getTrueLinkedObject(true,&mat); + case PseudoRegex: + GET_MODULE(re); + break; + case PseudoBuiltins: + GET_MODULE(builtins); + break; + case PseudoMath: + GET_MODULE(math); + break; + case PseudoCollections: + GET_MODULE(collections); + break; + case PseudoShape: { + GET_MODULE(Part); + Py::Callable func(pyobj.getAttr("getShape")); + Py::Tuple tuple(1); + tuple.setItem(0, Py::Object(result.resolvedDocumentObject->getPyObject(), true)); + if (result.subObjectName.getString().empty()) { + pyobj = func.apply(tuple); + } + else { + Py::Dict dict; + dict.setItem("subname", Py::String(result.subObjectName.getString())); + dict.setItem("needSubElement", Py::True()); + pyobj = func.apply(tuple, dict); } - if(ptype == PseudoLinkPlacement) - pyobj = Py::Placement(Base::Placement(mat)); - else - pyobj = Py::Matrix(mat); break; } - case PseudoSelf: - pyobj = Py::Object(obj->getPyObject(),true); - break; default: { - // NOTE! We cannot directly call Property::getPyObject(), but - // instead, must obtain the property's python object through - // DocumentObjectPy::getAttr(). Because, PyObjectBase has internal - // attribute tracking only if we obtain attribute through - // getAttr(). Without attribute tracking, we can't do things like - // - // obj.Placement.Base.x = 10. - // - // What happens is that the when Python interpreter calls - // - // Base.setAttr('x', 10), - // - // PyObjectBase will lookup Base's parent, i.e. Placement, and call - // - // Placement.setAttr('Base', Base), - // - // and in turn calls - // - // obj.setAttr('Placement',Placement) - // - // The tracking logic is implemented in PyObjectBase::__getattro/__setattro - - auto container = result.resolvedProperty->getContainer(); - if(container - && container!=result.resolvedDocumentObject - && container!=result.resolvedSubObject) - { - if(!container->isDerivedFrom(DocumentObject::getClassTypeId())) - FC_WARN("Invalid property container"); - else - obj = static_cast(container); + Base::Matrix4D mat; + auto obj = result.resolvedDocumentObject; + switch (ptype) { + case PseudoPlacement: + case PseudoMatrix: + case PseudoLinkPlacement: + case PseudoLinkMatrix: + obj->getSubObject(result.subObjectName.getString().c_str(), nullptr, &mat); + break; + default: + break; } - pyobj = Py::Object(obj->getPyObject(),true); - idx = result.propertyIndex; - break; - }}} + if (result.resolvedSubObject) { + obj = result.resolvedSubObject; + } + switch (ptype) { + case PseudoPlacement: + pyobj = Py::Placement(Base::Placement(mat)); + break; + case PseudoMatrix: + pyobj = Py::Matrix(mat); + break; + case PseudoLinkPlacement: + case PseudoLinkMatrix: { + auto linked = obj->getLinkedObject(true, &mat, false); + if (!linked || linked == obj) { + auto ext = obj->getExtensionByType(true); + if (ext) { + ext->getTrueLinkedObject(true, &mat); + } + } + if (ptype == PseudoLinkPlacement) { + pyobj = Py::Placement(Base::Placement(mat)); + } + else { + pyobj = Py::Matrix(mat); + } + break; + } + case PseudoSelf: + pyobj = Py::Object(obj->getPyObject(), true); + break; + default: { + // NOTE! We cannot directly call Property::getPyObject(), but + // instead, must obtain the property's python object through + // DocumentObjectPy::getAttr(). Because, PyObjectBase has internal + // attribute tracking only if we obtain attribute through + // getAttr(). Without attribute tracking, we can't do things like + // + // obj.Placement.Base.x = 10. + // + // What happens is that the when Python interpreter calls + // + // Base.setAttr('x', 10), + // + // PyObjectBase will lookup Base's parent, i.e. Placement, and call + // + // Placement.setAttr('Base', Base), + // + // and in turn calls + // + // obj.setAttr('Placement',Placement) + // + // The tracking logic is implemented in PyObjectBase::__getattro/__setattro + + auto container = result.resolvedProperty->getContainer(); + if (container && container != result.resolvedDocumentObject + && container != result.resolvedSubObject) { + if (!container->isDerivedFrom(DocumentObject::getClassTypeId())) { + FC_WARN("Invalid property container"); + } + else { + obj = static_cast(container); + } + } + pyobj = Py::Object(obj->getPyObject(), true); + idx = result.propertyIndex; + break; + } + } + } } - auto setPropDep = [deps](DocumentObject *obj, Property *prop, const char *propName) { - if(!deps || !obj) + auto setPropDep = [deps](DocumentObject* obj, Property* prop, const char* propName) { + if (!deps || !obj) { return; - if(prop && prop->getContainer()!=obj) { - auto linkTouched = Base::freecad_dynamic_cast( - obj->getPropertyByName("_LinkTouched")); - if(linkTouched) + } + if (prop && prop->getContainer() != obj) { + auto linkTouched = + Base::freecad_dynamic_cast(obj->getPropertyByName("_LinkTouched")); + if (linkTouched) { propName = linkTouched->getName(); + } else { auto propOwner = Base::freecad_dynamic_cast(prop->getContainer()); - if(propOwner) + if (propOwner) { obj = propOwner; - else + } + else { propName = nullptr; + } } } - auto &propset = (*deps)[obj]; + auto& propset = (*deps)[obj]; // inserting a blank name in the propset indicates the dependency is // on all properties of the corresponding object. if (propset.size() != 1 || !propset.begin()->empty()) { @@ -1701,37 +1878,43 @@ Py::Object ObjectIdentifier::access(const ResolveResults &result, return; }; - App::DocumentObject *lastObj = result.resolvedDocumentObject; - if(result.resolvedSubObject) { - setPropDep(lastObj,nullptr,nullptr); + App::DocumentObject* lastObj = result.resolvedDocumentObject; + if (result.resolvedSubObject) { + setPropDep(lastObj, nullptr, nullptr); lastObj = result.resolvedSubObject; } - if(ptype == PseudoNone) + if (ptype == PseudoNone) { setPropDep(lastObj, result.resolvedProperty, result.resolvedProperty->getName()); - else - setPropDep(lastObj,nullptr,nullptr); + } + else { + setPropDep(lastObj, nullptr, nullptr); + } lastObj = nullptr; - if(components.empty()) + if (components.empty()) { return pyobj; + } size_t count = components.size(); - if(value) --count; - assert(idx<=count); + if (value) { + --count; + } + assert(idx <= count); - for(;idx(*pyobj)->getDocumentObjectPtr(); - else if(lastObj) { - const char *attr = components[idx].getName().c_str(); + } + else if (lastObj) { + const char* attr = components[idx].getName().c_str(); auto prop = lastObj->getPropertyByName(attr); - setPropDep(lastObj,prop,attr); + setPropDep(lastObj, prop, attr); lastObj = nullptr; } pyobj = components[idx].get(pyobj); } - if(value) { - components[idx].set(pyobj,*value); + if (value) { + components[idx].set(pyobj, *value); return Py::Object(); } return pyobj; @@ -1750,57 +1933,57 @@ Py::Object ObjectIdentifier::access(const ResolveResults &result, * @return The value of the property or field. */ -App::any ObjectIdentifier::getValue(bool pathValue, bool *isPseudoProperty) const +App::any ObjectIdentifier::getValue(bool pathValue, bool* isPseudoProperty) const { ResolveResults rs(*this); - if(isPseudoProperty) { - *isPseudoProperty = rs.propertyType!=PseudoNone; - if(rs.propertyType == PseudoSelf - && isLocalProperty() - && rs.propertyIndex+1 < (int)components.size() - && owner->getPropertyByName(components[rs.propertyIndex+1].getName().c_str())) - { + if (isPseudoProperty) { + *isPseudoProperty = rs.propertyType != PseudoNone; + if (rs.propertyType == PseudoSelf && isLocalProperty() + && rs.propertyIndex + 1 < (int)components.size() + && owner->getPropertyByName(components[rs.propertyIndex + 1].getName().c_str())) { *isPseudoProperty = false; } } - if(rs.resolvedProperty && rs.propertyType==PseudoNone && pathValue) + if (rs.resolvedProperty && rs.propertyType == PseudoNone && pathValue) { return rs.resolvedProperty->getPathValue(*this); + } Base::PyGILStateLocker lock; try { return pyObjectToAny(access(rs)); - }catch(Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException::ThrowException(); } return {}; } -Py::Object ObjectIdentifier::getPyValue(bool pathValue, bool *isPseudoProperty) const +Py::Object ObjectIdentifier::getPyValue(bool pathValue, bool* isPseudoProperty) const { ResolveResults rs(*this); - if(isPseudoProperty) { - *isPseudoProperty = rs.propertyType!=PseudoNone; - if(rs.propertyType == PseudoSelf - && isLocalProperty() - && rs.propertyIndex+1 < (int)components.size() - && owner->getPropertyByName(components[rs.propertyIndex+1].getName().c_str())) - { + if (isPseudoProperty) { + *isPseudoProperty = rs.propertyType != PseudoNone; + if (rs.propertyType == PseudoSelf && isLocalProperty() + && rs.propertyIndex + 1 < (int)components.size() + && owner->getPropertyByName(components[rs.propertyIndex + 1].getName().c_str())) { *isPseudoProperty = false; } } - if(rs.resolvedProperty && rs.propertyType==PseudoNone && pathValue) { + if (rs.resolvedProperty && rs.propertyType == PseudoNone && pathValue) { Py::Object res; - if(rs.resolvedProperty->getPyPathValue(*this,res)) + if (rs.resolvedProperty->getPyPathValue(*this, res)) { return res; + } } try { return access(rs); - }catch(Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException::ThrowException(); } return Py::Object(); @@ -1816,79 +1999,95 @@ Py::Object ObjectIdentifier::getPyValue(bool pathValue, bool *isPseudoProperty) * @param value Value to set */ -void ObjectIdentifier::setValue(const App::any &value) const +void ObjectIdentifier::setValue(const App::any& value) const { std::stringstream ss; ResolveResults rs(*this); - if(rs.propertyType) - FC_THROWM(Base::RuntimeError,"Cannot set pseudo property"); + if (rs.propertyType) { + FC_THROWM(Base::RuntimeError, "Cannot set pseudo property"); + } Base::PyGILStateLocker lock; try { Py::Object pyvalue = pyObjectFromAny(value); - access(rs,&pyvalue); - }catch(Py::Exception &) { + access(rs, &pyvalue); + } + catch (Py::Exception&) { Base::PyException::ThrowException(); } } -const std::string &ObjectIdentifier::getSubObjectName(bool newStyle) const { - if(newStyle && !shadowSub.newName.empty()) - return shadowSub.newName; - if(!shadowSub.oldName.empty()) - return shadowSub.oldName; - return subObjectName.getString(); -} - -const std::string &ObjectIdentifier::getSubObjectName() const { - return subObjectName.getString(); -} - -void ObjectIdentifier::importSubNames(const ObjectIdentifier::SubNameMap &subNameMap) +const std::string& ObjectIdentifier::getSubObjectName(bool newStyle) const { - if(!owner || !owner->getDocument()) + if (newStyle && !shadowSub.newName.empty()) { + return shadowSub.newName; + } + if (!shadowSub.oldName.empty()) { + return shadowSub.oldName; + } + return subObjectName.getString(); +} + +const std::string& ObjectIdentifier::getSubObjectName() const +{ + return subObjectName.getString(); +} + +void ObjectIdentifier::importSubNames(const ObjectIdentifier::SubNameMap& subNameMap) +{ + if (!owner || !owner->getDocument()) { return; + } ResolveResults result(*this); - auto it = subNameMap.find(std::make_pair(result.resolvedDocumentObject,std::string())); - if(it!=subNameMap.end()) { + auto it = subNameMap.find(std::make_pair(result.resolvedDocumentObject, std::string())); + if (it != subNameMap.end()) { auto obj = owner->getDocument()->getObject(it->second.c_str()); - if(!obj) { + if (!obj) { FC_ERR("Failed to find import object " << it->second << " from " - << result.resolvedDocumentObject->getFullName()); + << result.resolvedDocumentObject->getFullName()); return; } documentNameSet = false; documentName.str.clear(); - if(documentObjectName.isRealString()) + if (documentObjectName.isRealString()) { documentObjectName.str = obj->Label.getValue(); - else + } + else { documentObjectName.str = obj->getNameInDocument(); + } _cache.clear(); } - if(subObjectName.getString().empty()) + if (subObjectName.getString().empty()) { return; - it = subNameMap.find(std::make_pair( - result.resolvedDocumentObject,subObjectName.str)); - if(it==subNameMap.end()) + } + it = subNameMap.find(std::make_pair(result.resolvedDocumentObject, subObjectName.str)); + if (it == subNameMap.end()) { return; - subObjectName = String(it->second,true); + } + subObjectName = String(it->second, true); _cache.clear(); shadowSub.newName.clear(); shadowSub.oldName.clear(); } -bool ObjectIdentifier::updateElementReference(ExpressionVisitor &v, - App::DocumentObject *feature, bool reverse) +bool ObjectIdentifier::updateElementReference(ExpressionVisitor& v, + App::DocumentObject* feature, + bool reverse) { assert(v.getPropertyLink()); - if(subObjectName.getString().empty()) + if (subObjectName.getString().empty()) { return false; + } ResolveResults result(*this); - if(!result.resolvedSubObject) + if (!result.resolvedSubObject) { return false; - if(v.getPropertyLink()->_updateElementReference( - feature,result.resolvedDocumentObject,subObjectName.str,shadowSub,reverse)) { + } + if (v.getPropertyLink()->_updateElementReference(feature, + result.resolvedDocumentObject, + subObjectName.str, + shadowSub, + reverse)) { _cache.clear(); v.aboutToChange(); return true; @@ -1896,17 +2095,20 @@ bool ObjectIdentifier::updateElementReference(ExpressionVisitor &v, return false; } -bool ObjectIdentifier::adjustLinks(ExpressionVisitor &v, const std::set &inList) { +bool ObjectIdentifier::adjustLinks(ExpressionVisitor& v, + const std::set& inList) +{ ResolveResults result(*this); - if(!result.resolvedDocumentObject) + if (!result.resolvedDocumentObject) { return false; - if(result.resolvedSubObject) { + } + if (result.resolvedSubObject) { PropertyLinkSub prop; prop.setValue(result.resolvedDocumentObject, {subObjectName.getString()}); - if(prop.adjustLink(inList)) { + if (prop.adjustLink(inList)) { v.aboutToChange(); - documentObjectName = String(prop.getValue()->getNameInDocument(),false,true); - subObjectName = String(prop.getSubValues().front(),true); + documentObjectName = String(prop.getValue()->getNameInDocument(), false, true); + subObjectName = String(prop.getSubValues().front(), true); _cache.clear(); return true; } @@ -1914,24 +2116,29 @@ bool ObjectIdentifier::adjustLinks(ExpressionVisitor &v, const std::setisTouched(); - else + } + else { return result.resolvedDocumentObject->isTouched(); + } } - }catch(...) {} + } + catch (...) { + } return false; } -void ObjectIdentifier::resolveAmbiguity() { - if(!owner || !owner->isAttachedToDocument() || isLocalProperty() || - (documentObjectNameSet && !documentObjectName.getString().empty() && - (documentObjectName.isRealString() || documentObjectName.isForceIdentifier()))) - { +void ObjectIdentifier::resolveAmbiguity() +{ + if (!owner || !owner->isAttachedToDocument() || isLocalProperty() + || (documentObjectNameSet && !documentObjectName.getString().empty() + && (documentObjectName.isRealString() || documentObjectName.isForceIdentifier()))) { return; } @@ -1939,33 +2146,43 @@ void ObjectIdentifier::resolveAmbiguity() { resolveAmbiguity(result); } -void ObjectIdentifier::resolveAmbiguity(ResolveResults &result) { +void ObjectIdentifier::resolveAmbiguity(ResolveResults& result) +{ - if(!result.resolvedDocumentObject) + if (!result.resolvedDocumentObject) { return; + } - if(result.propertyIndex==1) + if (result.propertyIndex == 1) { components.erase(components.begin()); + } String subname = subObjectName; - if(result.resolvedDocumentObject == owner) { - setDocumentObjectName(owner,false,std::move(subname)); - }else if(result.flags.test(ResolveByIdentifier)) - setDocumentObjectName(result.resolvedDocumentObject,true,std::move(subname)); - else + if (result.resolvedDocumentObject == owner) { + setDocumentObjectName(owner, false, std::move(subname)); + } + else if (result.flags.test(ResolveByIdentifier)) { + setDocumentObjectName(result.resolvedDocumentObject, true, std::move(subname)); + } + else { setDocumentObjectName( - String(result.resolvedDocumentObject->Label.getStrValue(),true,false),true,std::move(subname)); + String(result.resolvedDocumentObject->Label.getStrValue(), true, false), + true, + std::move(subname)); + } - if(result.resolvedDocumentObject->getDocument() == owner->getDocument()) + if (result.resolvedDocumentObject->getDocument() == owner->getDocument()) { setDocumentName(String()); + } } /** Construct and initialize a ResolveResults object, given an ObjectIdentifier instance. * - * The constructor will invoke the ObjectIdentifier's resolve() method to initialize the object's data. + * The constructor will invoke the ObjectIdentifier's resolve() method to initialize the object's + * data. */ -ObjectIdentifier::ResolveResults::ResolveResults(const ObjectIdentifier &oi) +ObjectIdentifier::ResolveResults::ResolveResults(const ObjectIdentifier& oi) : propertyType(PseudoNone) { oi.resolve(*this); @@ -1975,36 +2192,43 @@ std::string ObjectIdentifier::ResolveResults::resolveErrorString() const { std::ostringstream ss; if (!resolvedDocument) { - if(flags.test(ResolveAmbiguous)) - ss << "Ambiguous document name/label '" - << resolvedDocumentName.getString() << "'"; - else + if (flags.test(ResolveAmbiguous)) { + ss << "Ambiguous document name/label '" << resolvedDocumentName.getString() << "'"; + } + else { ss << "Document '" << resolvedDocumentName.toString() << "' not found"; - } else if (!resolvedDocumentObject) { - if(flags.test(ResolveAmbiguous)) - ss << "Ambiguous document object name '" - << resolvedDocumentObjectName.getString() << "'"; - else - ss << "Document object '" << resolvedDocumentObjectName.toString() - << "' not found"; - } else if (!subObjectName.getString().empty() && !resolvedSubObject) { - ss << "Sub-object '" << resolvedDocumentObjectName.getString() - << '.' << subObjectName.toString() << "' not found"; - } else if (!resolvedProperty) { - if(propertyType != PseudoShape && - !subObjectName.getString().empty() && - !boost::ends_with(subObjectName.getString(),".")) - { + } + } + else if (!resolvedDocumentObject) { + if (flags.test(ResolveAmbiguous)) { + ss << "Ambiguous document object name '" << resolvedDocumentObjectName.getString() + << "'"; + } + else { + ss << "Document object '" << resolvedDocumentObjectName.toString() << "' not found"; + } + } + else if (!subObjectName.getString().empty() && !resolvedSubObject) { + ss << "Sub-object '" << resolvedDocumentObjectName.getString() << '.' + << subObjectName.toString() << "' not found"; + } + else if (!resolvedProperty) { + if (propertyType != PseudoShape && !subObjectName.getString().empty() + && !boost::ends_with(subObjectName.getString(), ".")) { ss << "Non geometry subname reference must end with '.'"; - }else + } + else { ss << "Property '" << propertyName << "' not found"; + } } return ss.str(); } -void ObjectIdentifier::ResolveResults::getProperty(const ObjectIdentifier &oi) { - resolvedProperty = oi.resolveProperty( - resolvedDocumentObject,propertyName.c_str(),resolvedSubObject,propertyType); +void ObjectIdentifier::ResolveResults::getProperty(const ObjectIdentifier& oi) +{ + resolvedProperty = oi.resolveProperty(resolvedDocumentObject, + propertyName.c_str(), + resolvedSubObject, + propertyType); } - diff --git a/src/App/ObjectIdentifier.h b/src/App/ObjectIdentifier.h index 4cbe0b7cec..c62f69c47c 100644 --- a/src/App/ObjectIdentifier.h +++ b/src/App/ObjectIdentifier.h @@ -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 -inline const T &any_cast(const boost::any &value) { +inline const T& any_cast(const boost::any& value) +{ return boost::any_cast(value); } template -inline T &any_cast(boost::any &value) { +inline T& any_cast(boost::any& value) +{ return boost::any_cast(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 &); + explicit DocumentMapper(const std::map&); ~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 - 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 getPropertyComponents() const; - const std::vector &getComponents() const { return components; } + const std::vector& 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::string>; - void importSubNames(const SubNameMap &subNameMap); + using SubNameMap = std::map, 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 >; + using Dependencies = std::map>; /** 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 *labels=nullptr) const; + Dependencies getDep(bool needProps, std::vector* 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 *labels=nullptr) const; + void + getDep(Dependencies& deps, bool needProps, std::vector* labels = nullptr) const; /// Returns all label references - void getDepLabels(std::vector &labels) const; + void getDepLabels(std::vector& 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 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 &inList); + bool adjustLinks(ExpressionVisitor& v, const std::set& 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 &labels) const; + void getDepLabels(const ResolveResults& result, std::vector& labels) const; - App::DocumentObject * owner; - String documentName; - String documentObjectName; - String subObjectName; + App::DocumentObject* owner; + String documentName; + String documentObjectName; + String subObjectName; ElementNamePair shadowSub; std::vector 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 { +struct hash +{ 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 diff --git a/src/App/Property.cpp b/src/App/Property.cpp index 2db9e5ed36..2b20f8f166 100644 --- a/src/App/Property.cpp +++ b/src/App/Property.cpp @@ -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 _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 &paths) const +void Property::getPaths(std::vector& 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 _RemovedProps; static int _PropCleanerCounter; }; -} +} // namespace App std::vector 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 guard(StatusBits,Busy); + if (!testStatus(Busy)) { + Base::BitsetLocker 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<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 indices; - std::vector vals; + std::vector 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) diff --git a/src/App/Property.h b/src/App/Property.h index 3dd456428e..f222148d65 100644 --- a/src/App/Property.h +++ b/src/App/Property.h @@ -33,7 +33,8 @@ #include #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 & paths) const; + virtual void getPaths(std::vector& 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(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 signalChanged; + boost::signals2::signal 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 AtomicPropertyChangeInterface { +template +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 &getTouchList() const { + const std::set& getTouchList() const + { return _touchList; } - void clearTouchList() { + void clearTouchList() + { _touchList.clear(); } protected: - virtual void setPyValues(const std::vector &vals, const std::vector &indices) { + virtual void setPyValues(const std::vector& vals, const std::vector& indices) + { (void)vals; (void)indices; throw Base::NotImplementedError("not implemented"); } - void _setPyObject(PyObject *); + void _setPyObject(PyObject*); protected: std::set _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 ParentT = PropertyLists > -class PropertyListsT: public ParentT - , public AtomicPropertyChangeInterface > +template, class ParentT = PropertyLists> +class PropertyListsT: public ParentT, + public AtomicPropertyChangeInterface> { public: using const_reference = typename ListT::const_reference; using list_type = ListT; using parent_type = ParentT; using atomic_change = typename AtomicPropertyChangeInterface< - PropertyListsT >::AtomicPropertyChange; + PropertyListsT>::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(_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(&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& vals, const std::vector& 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 diff --git a/src/App/PropertyContainerPy.xml b/src/App/PropertyContainerPy.xml index 3ededf7d54..572e2ab145 100644 --- a/src/App/PropertyContainerPy.xml +++ b/src/App/PropertyContainerPy.xml @@ -1,13 +1,13 @@  - @@ -16,14 +16,14 @@ - getPropertyByName(name, checkOwner=0) -> object or Tuple + 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). @@ -31,44 +31,44 @@ checkOwner : int - getPropertyTouchList(name) -> tuple + 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. - getTypeOfProperty(name) -> list + 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. - getTypeIdOfProperty(name) -> str + 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. - setEditorMode(name, type) -> None + 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'. @@ -76,121 +76,121 @@ type : int, sequence of str - getEditorMode(name) -> list + 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. - getGroupOfProperty(name) -> str + 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. - setGroupOfProperty(name, group) -> None + 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. - setPropertyStatus(name, val) -> None + 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. - getPropertyStatus(name='') -> list + 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. - getDocumentationOfProperty(name) -> str + 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. - setDocumentationOfProperty(name, docstring) -> None + 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. - getEnumerationsOfProperty(name) -> list or None + 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. - dumpPropertyContent(Property, Compression=3) -> bytearray + 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. - restorePropertyContent(name, obj) -> None + 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. diff --git a/src/App/PropertyContainerPyImp.cpp b/src/App/PropertyContainerPyImp.cpp index 8e2196dbbf..4700b5a090 100644 --- a/src/App/PropertyContainerPyImp.cpp +++ b/src/App/PropertyContainerPyImp.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include "PropertyContainer.h" @@ -49,12 +49,13 @@ std::string PropertyContainerPy::representation() const return {""}; } -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(prop)->getTouchList(); + const auto& touched = static_cast(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(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 &getStatusMap() { - static std::map statusMap; - if(statusMap.empty()) { +static const std::map& getStatusMap() +{ + static std::map statusMap; + if (statusMap.empty()) { statusMap["Immutable"] = Property::Immutable; statusMap["ReadOnly"] = Property::ReadOnly; statusMap["Hidden"] = Property::Hidden; @@ -217,12 +233,13 @@ static const std::map &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(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(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(i)) { + for (auto& v : statusMap) { + if (v.second == static_cast(i)) { ret.append(Py::String(v.first.c_str())); found = true; break; } } - if (!found) + if (!found) { ret.append(Py::Int(static_cast(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(prop); - if (!enumProp) + PropertyEnumeration* enumProp = dynamic_cast(prop); + if (!enumProp) { Py_Return; + } std::vector 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 Map; + std::map Map; getPropertyContainerPtr()->getPropertyMap(Map); - for (std::map::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 kwds_def {"Property", "Compression", nullptr}; + const char* property {}; + static const std::array 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; boost::iostreams::stream 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 Map; + std::map 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(this))); + args.setItem(0, Py::Object(const_cast(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()); diff --git a/src/App/PropertyExpressionEngine.cpp b/src/App/PropertyExpressionEngine.cpp index 63fd2c40fb..7bc7182ee5 100644 --- a/src/App/PropertyExpressionEngine.cpp +++ b/src/App/PropertyExpressionEngine.cpp @@ -42,46 +42,52 @@ using namespace Base; using namespace boost; namespace sp = std::placeholders; -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyExpressionContainer , App::PropertyXLinkContainer) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyExpressionContainer, App::PropertyXLinkContainer) static std::set _ExprContainers; -PropertyExpressionContainer::PropertyExpressionContainer() { +PropertyExpressionContainer::PropertyExpressionContainer() +{ static bool inited; - if(!inited) { + if (!inited) { inited = true; - GetApplication().signalRelabelDocument.connect(PropertyExpressionContainer::slotRelabelDocument); + GetApplication().signalRelabelDocument.connect( + PropertyExpressionContainer::slotRelabelDocument); } _ExprContainers.insert(this); } -PropertyExpressionContainer::~PropertyExpressionContainer() { +PropertyExpressionContainer::~PropertyExpressionContainer() +{ _ExprContainers.erase(this); } -void PropertyExpressionContainer::slotRelabelDocument(const App::Document &doc) { +void PropertyExpressionContainer::slotRelabelDocument(const App::Document& doc) +{ // For use a private _ExprContainers to track all living // PropertyExpressionContainer including those inside undo/redo stack, // because document relabel is not undoable/redoable. - if(doc.getOldLabel() != doc.Label.getValue()) { - for(auto prop : _ExprContainers) + if (doc.getOldLabel() != doc.Label.getValue()) { + for (auto prop : _ExprContainers) { prop->onRelabeledDocument(doc); + } } } /////////////////////////////////////////////////////////////////////////////////////// -struct PropertyExpressionEngine::Private { +struct PropertyExpressionEngine::Private +{ // For some reason, MSVC has trouble with vector of scoped_connection if // defined in header, hence the private structure here. std::vector conns; - std::unordered_map > propMap; + std::unordered_map> propMap; }; /////////////////////////////////////////////////////////////////////////////////////// -TYPESYSTEM_SOURCE(App::PropertyExpressionEngine , App::PropertyExpressionContainer) +TYPESYSTEM_SOURCE(App::PropertyExpressionEngine, App::PropertyExpressionContainer) /** * @brief Construct a new PropertyExpressionEngine object. @@ -89,8 +95,7 @@ TYPESYSTEM_SOURCE(App::PropertyExpressionEngine , App::PropertyExpressionContain PropertyExpressionEngine::PropertyExpressionEngine() : validator(0) -{ -} +{} /** * @brief Destroy the PropertyExpressionEngine object. @@ -111,14 +116,15 @@ unsigned int PropertyExpressionEngine::getMemSize() const return 0; } -Property *PropertyExpressionEngine::Copy() const +Property* PropertyExpressionEngine::Copy() const { - PropertyExpressionEngine * engine = new PropertyExpressionEngine(); + PropertyExpressionEngine* engine = new PropertyExpressionEngine(); - for (const auto & it : expressions) { + for (const auto& it : expressions) { ExpressionInfo info; - if (it.second.expression) + if (it.second.expression) { info.expression = std::shared_ptr(it.second.expression->copy()); + } engine->expressions[it.first] = info; } @@ -129,68 +135,79 @@ Property *PropertyExpressionEngine::Copy() const void PropertyExpressionEngine::hasSetValue() { - App::DocumentObject *owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument() || owner->isRestoring() || testFlag(LinkDetached)) { + App::DocumentObject* owner = dynamic_cast(getContainer()); + if (!owner || !owner->isAttachedToDocument() || owner->isRestoring() + || testFlag(LinkDetached)) { PropertyExpressionContainer::hasSetValue(); return; } - std::map deps; + std::map deps; std::vector labels; unregisterElementReference(); UpdateElementReferenceExpressionVisitor v(*this); - for(auto &e : expressions) { + for (auto& e : expressions) { auto expr = e.second.expression; - if(expr) { - expr->getDepObjects(deps,&labels); - if(!restoring) + if (expr) { + expr->getDepObjects(deps, &labels); + if (!restoring) { expr->visit(v); + } } } registerLabelReferences(std::move(labels)); updateDeps(std::move(deps)); - if(pimpl) { + if (pimpl) { pimpl->conns.clear(); pimpl->propMap.clear(); } // check if there is any hidden references bool hasHidden = false; - for(auto &v : _Deps) { - if(v.second) { + for (auto& v : _Deps) { + if (v.second) { hasHidden = true; break; } } - if(hasHidden) { - if(!pimpl) { + if (hasHidden) { + if (!pimpl) { pimpl = std::make_unique(); } - for(auto &e : expressions) { + for (auto& e : expressions) { auto expr = e.second.expression; - if(!expr) continue; - for(auto &dep : expr->getIdentifiers()) { - if(!dep.second) + if (!expr) { + continue; + } + for (auto& dep : expr->getIdentifiers()) { + if (!dep.second) { continue; - const ObjectIdentifier &var = dep.first; - for(auto &vdep : var.getDep(true)) { + } + const ObjectIdentifier& var = dep.first; + for (auto& vdep : var.getDep(true)) { auto obj = vdep.first; auto objName = obj->getFullName() + "."; - for(auto &propName : vdep.second) { + for (auto& propName : vdep.second) { std::string key = objName + propName; - auto &propDeps = pimpl->propMap[key]; - if(propDeps.empty()) { - //NOLINTBEGIN - if(!propName.empty()) { - pimpl->conns.emplace_back(obj->signalChanged.connect(std::bind( - &PropertyExpressionEngine::slotChangedProperty,this,sp::_1,sp::_2))); + auto& propDeps = pimpl->propMap[key]; + if (propDeps.empty()) { + // NOLINTBEGIN + if (!propName.empty()) { + pimpl->conns.emplace_back(obj->signalChanged.connect( + std::bind(&PropertyExpressionEngine::slotChangedProperty, + this, + sp::_1, + sp::_2))); } else { - pimpl->conns.emplace_back(obj->signalChanged.connect(std::bind( - &PropertyExpressionEngine::slotChangedObject,this,sp::_1,sp::_2))); + pimpl->conns.emplace_back(obj->signalChanged.connect( + std::bind(&PropertyExpressionEngine::slotChangedObject, + this, + sp::_1, + sp::_2))); } - //NOLINTEND + // NOLINTEND } propDeps.push_back(e.first); } @@ -202,60 +219,73 @@ void PropertyExpressionEngine::hasSetValue() PropertyExpressionContainer::hasSetValue(); } -void PropertyExpressionEngine::updateHiddenReference(const std::string &key) { - if(!pimpl) +void PropertyExpressionEngine::updateHiddenReference(const std::string& key) +{ + if (!pimpl) { return; + } auto it = pimpl->propMap.find(key); - if(it == pimpl->propMap.end()) + if (it == pimpl->propMap.end()) { return; - for(auto &var : it->second) { + } + for (auto& var : it->second) { auto it = expressions.find(var); - if(it == expressions.end() || it->second.busy) + if (it == expressions.end() || it->second.busy) { continue; - Property *myProp = var.getProperty(); - if(!myProp) + } + Property* myProp = var.getProperty(); + if (!myProp) { continue; + } Base::StateLocker guard(it->second.busy); App::any value; try { value = it->second.expression->getValueAsAny(); - if(!isAnyEqual(value, myProp->getPathValue(var))) + if (!isAnyEqual(value, myProp->getPathValue(var))) { myProp->setPathValue(var, value); - }catch(Base::Exception &e) { + } + } + catch (Base::Exception& e) { e.ReportException(); - FC_ERR("Failed to evaluate property binding " - << myProp->getFullName() << " on change of " << key); - }catch(std::bad_cast &) { - FC_ERR("Invalid type '" << value.type().name() - << "' in property binding " << myProp->getFullName() - << " on change of " << key); - }catch(std::exception &e) { + FC_ERR("Failed to evaluate property binding " << myProp->getFullName() + << " on change of " << key); + } + catch (std::bad_cast&) { + FC_ERR("Invalid type '" << value.type().name() << "' in property binding " + << myProp->getFullName() << " on change of " << key); + } + catch (std::exception& e) { FC_ERR(e.what()); - FC_ERR("Failed to evaluate property binding " - << myProp->getFullName() << " on change of " << key); + FC_ERR("Failed to evaluate property binding " << myProp->getFullName() + << " on change of " << key); } } } -void PropertyExpressionEngine::slotChangedObject(const App::DocumentObject &obj, const App::Property &) { +void PropertyExpressionEngine::slotChangedObject(const App::DocumentObject& obj, + const App::Property&) +{ updateHiddenReference(obj.getFullName()); } -void PropertyExpressionEngine::slotChangedProperty(const App::DocumentObject &, const App::Property &prop) { +void PropertyExpressionEngine::slotChangedProperty(const App::DocumentObject&, + const App::Property& prop) +{ updateHiddenReference(prop.getFullName()); } -void PropertyExpressionEngine::Paste(const Property &from) +void PropertyExpressionEngine::Paste(const Property& from) { - const PropertyExpressionEngine &fromee = dynamic_cast(from); + const PropertyExpressionEngine& fromee = dynamic_cast(from); AtomicPropertyChange signaller(*this); expressions.clear(); - for(auto &e : fromee.expressions) { + for (auto& e : fromee.expressions) { ExpressionInfo info; - if (e.second.expression) + if (e.second.expression) { info.expression = std::shared_ptr(e.second.expression->copy()); + } expressions[e.first] = info; expressionChanged(e.first); } @@ -263,18 +293,19 @@ void PropertyExpressionEngine::Paste(const Property &from) signaller.tryInvoke(); } -void PropertyExpressionEngine::Save(Base::Writer &writer) const +void PropertyExpressionEngine::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; writer.incInd(); - } else { + } + else { writer.Stream() << R"(" xlink="1">)" << std::endl; writer.incInd(); PropertyExpressionContainer::Save(writer); } - for (const auto & it : expressions) { + for (const auto& it : expressions) { std::string expression, comment; if (it.second.expression) { expression = it.second.expression->toString(true); @@ -282,24 +313,25 @@ void PropertyExpressionEngine::Save(Base::Writer &writer) const } writer.Stream() << writer.ind() << "" << std::endl; } writer.decInd(); writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyExpressionEngine::Restore(Base::XMLReader &reader) +void PropertyExpressionEngine::Restore(Base::XMLReader& reader) { reader.readElement("ExpressionEngine"); int count = reader.getAttributeAsFloat("count"); - if(reader.hasAttribute("xlink") && reader.getAttributeAsInteger("xlink")) + if (reader.hasAttribute("xlink") && reader.getAttributeAsInteger("xlink")) { PropertyExpressionContainer::Restore(reader); + } restoredExpressions = std::make_unique>(); restoredExpressions->reserve(count); @@ -307,11 +339,12 @@ void PropertyExpressionEngine::Restore(Base::XMLReader &reader) reader.readElement("Expression"); restoredExpressions->emplace_back(); - auto &info = restoredExpressions->back(); + auto& info = restoredExpressions->back(); info.path = reader.getAttribute("path"); info.expr = reader.getAttribute("expression"); - if(reader.hasAttribute("comment")) + if (reader.hasAttribute("comment")) { info.comment = reader.getAttribute("comment"); + } } reader.readEndElement("ExpressionEngine"); @@ -326,11 +359,12 @@ void PropertyExpressionEngine::Restore(Base::XMLReader &reader) * @param edges Edges in graph */ -void PropertyExpressionEngine::buildGraphStructures(const ObjectIdentifier & path, - const std::shared_ptr expression, - boost::unordered_map & nodes, - boost::unordered_map & revNodes, - std::vector & edges) const +void PropertyExpressionEngine::buildGraphStructures( + const ObjectIdentifier& path, + const std::shared_ptr expression, + boost::unordered_map& nodes, + boost::unordered_map& revNodes, + std::vector& edges) const { /* Insert target property into nodes structure */ if (nodes.find(path) == nodes.end()) { @@ -345,14 +379,16 @@ void PropertyExpressionEngine::buildGraphStructures(const ObjectIdentifier & pat /* Insert dependencies into nodes structure */ ExpressionDeps deps; - if (expression) + if (expression) { deps = expression->getDeps(); + } - for(auto &dep : deps) { - for(auto &info : dep.second) { - if(info.first.empty()) + for (auto& dep : deps) { + for (auto& info : dep.second) { + if (info.first.empty()) { continue; - for(auto &oid : info.second) { + } + for (auto& oid : info.second) { ObjectIdentifier cPath(oid.canonicalPath()); if (nodes.find(cPath) == nodes.end()) { int s = nodes.size(); @@ -370,27 +406,31 @@ void PropertyExpressionEngine::buildGraphStructures(const ObjectIdentifier & pat * @return New ObjectIdentifier */ -ObjectIdentifier PropertyExpressionEngine::canonicalPath(const ObjectIdentifier &p) const +ObjectIdentifier PropertyExpressionEngine::canonicalPath(const ObjectIdentifier& p) const { - DocumentObject * docObj = freecad_dynamic_cast(getContainer()); + DocumentObject* docObj = freecad_dynamic_cast(getContainer()); // Am I owned by a DocumentObject? - if (!docObj) + if (!docObj) { throw Base::RuntimeError("PropertyExpressionEngine must be owned by a DocumentObject."); + } int ptype; - Property * prop = p.getProperty(&ptype); + Property* prop = p.getProperty(&ptype); // p pointing to a property...? - if (!prop) + if (!prop) { throw Base::RuntimeError(p.resolveErrorString().c_str()); + } - if(ptype || prop->getContainer()!=getContainer()) + if (ptype || prop->getContainer() != getContainer()) { return p; + } // In case someone calls this with p pointing to a PropertyExpressionEngine for some reason - if (prop->isDerivedFrom(PropertyExpressionEngine::classTypeId)) + if (prop->isDerivedFrom(PropertyExpressionEngine::classTypeId)) { return p; + } // Dispatch call to actual canonicalPath implementation return p.canonicalPath(); @@ -408,20 +448,22 @@ size_t PropertyExpressionEngine::numExpressions() const void PropertyExpressionEngine::afterRestore() { - DocumentObject * docObj = freecad_dynamic_cast(getContainer()); - if(restoredExpressions && docObj) { + DocumentObject* docObj = freecad_dynamic_cast(getContainer()); + if (restoredExpressions && docObj) { Base::FlagToggler flag(restoring); AtomicPropertyChange signaller(*this); PropertyExpressionContainer::afterRestore(); ObjectIdentifier::DocumentMapper mapper(this->_DocMap); - for(auto &info : *restoredExpressions) { + for (auto& info : *restoredExpressions) { ObjectIdentifier path = ObjectIdentifier::parse(docObj, info.path); if (!info.expr.empty()) { - std::shared_ptr expression(Expression::parse(docObj, info.expr.c_str())); - if(expression) + std::shared_ptr expression( + Expression::parse(docObj, info.expr.c_str())); + if (expression) { expression->comment = std::move(info.comment); + } setValue(path, expression); } } @@ -430,14 +472,16 @@ void PropertyExpressionEngine::afterRestore() restoredExpressions.reset(); } -void PropertyExpressionEngine::onContainerRestored() { +void PropertyExpressionEngine::onContainerRestored() +{ Base::FlagToggler flag(restoring); unregisterElementReference(); UpdateElementReferenceExpressionVisitor v(*this); - for(auto &e : expressions) { + for (auto& e : expressions) { auto expr = e.second.expression; - if(expr) + if (expr) { expr->visit(v); + } } } @@ -447,17 +491,17 @@ void PropertyExpressionEngine::onContainerRestored() { * @return Expression for \a path, or empty boost::any if not found. */ -const boost::any PropertyExpressionEngine::getPathValue(const App::ObjectIdentifier & path) const +const boost::any PropertyExpressionEngine::getPathValue(const App::ObjectIdentifier& path) const { // Get a canonical path ObjectIdentifier usePath(canonicalPath(path)); - ExpressionMap::const_iterator i = expressions.find(usePath); - - if (i != expressions.end()) + auto i = expressions.find(usePath); + if (i != expressions.end()) { return i->second; - else - return boost::any(); + } + + return boost::any(); } /** @@ -467,33 +511,36 @@ const boost::any PropertyExpressionEngine::getPathValue(const App::ObjectIdentif * @param comment Optional comment. */ -void PropertyExpressionEngine::setValue(const ObjectIdentifier & path, std::shared_ptr expr) +void PropertyExpressionEngine::setValue(const ObjectIdentifier& path, + std::shared_ptr expr) { ObjectIdentifier usePath(canonicalPath(path)); - const Property * prop = usePath.getProperty(); + const Property* prop = usePath.getProperty(); - // Try to access value; it should trigger an exception if it is not supported, or if the path is invalid + // Try to access value; it should trigger an exception if it is not supported, or if the path is + // invalid prop->getPathValue(usePath); - // Check if the current expression equals the new one and do nothing if so to reduce unneeded computations - ExpressionMap::iterator it = expressions.find(usePath); - if(it != expressions.end() - && (expr == it->second.expression || - (expr && it->second.expression - && expr->isSame(*it->second.expression)))) - { + // Check if the current expression equals the new one and do nothing if so to reduce unneeded + // computations + auto it = expressions.find(usePath); + if (it != expressions.end() + && (expr == it->second.expression + || (expr && it->second.expression && expr->isSame(*it->second.expression)))) { return; } if (expr) { std::string error = validateExpression(usePath, expr); - if (!error.empty()) + if (!error.empty()) { throw Base::RuntimeError(error.c_str()); + } AtomicPropertyChange signaller(*this); expressions[usePath] = ExpressionInfo(expr); expressionChanged(usePath); signaller.tryInvoke(); - } else if (it != expressions.end()) { + } + else if (it != expressions.end()) { AtomicPropertyChange signaller(*this); expressions.erase(it); expressionChanged(usePath); @@ -502,52 +549,63 @@ void PropertyExpressionEngine::setValue(const ObjectIdentifier & path, std::shar } /** - * @brief The cycle_detector struct is used by the boost graph routines to detect cycles in the graph. + * @brief The cycle_detector struct is used by the boost graph routines to detect cycles in the + * graph. */ -struct cycle_detector : public boost::dfs_visitor<> { - cycle_detector( bool& has_cycle, int & src) - : _has_cycle(has_cycle), _src(src) { } +struct cycle_detector: public boost::dfs_visitor<> +{ + cycle_detector(bool& has_cycle, int& src) + : _has_cycle(has_cycle) + , _src(src) + {} - template - void back_edge(Edge e, Graph&g) { - _has_cycle = true; - _src = source(e, g); + template + void back_edge(Edge e, Graph& g) + { + _has_cycle = true; + _src = source(e, g); } - protected: +protected: bool& _has_cycle; - int & _src; + int& _src; }; /** * @brief Build a graph of all expressions in \a exprs. * @param exprs Expressions to use in graph * @param revNodes Map from int[nodeid] to ObjectIndentifer. - * @param g Graph to update. May contain additional nodes than in revNodes, because of outside dependencies. + * @param g Graph to update. May contain additional nodes than in revNodes, because of outside + * dependencies. */ -void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, - boost::unordered_map & revNodes, - DiGraph & g, ExecuteOption option) const +void PropertyExpressionEngine::buildGraph(const ExpressionMap& exprs, + boost::unordered_map& revNodes, + DiGraph& g, + ExecuteOption option) const { boost::unordered_map nodes; std::vector edges; // Build data structure for graph - for (const auto & expr : exprs) { - if(option!=ExecuteAll) { + for (const auto& expr : exprs) { + if (option != ExecuteAll) { auto prop = expr.first.getProperty(); - if(!prop) + if (!prop) { throw Base::RuntimeError("Path does not resolve to a property."); - bool is_output = prop->testStatus(App::Property::Output)||(prop->getType()&App::Prop_Output); - if((is_output && option==ExecuteNonOutput) || (!is_output && option==ExecuteOutput)) + } + bool is_output = + prop->testStatus(App::Property::Output) || (prop->getType() & App::Prop_Output); + if ((is_output && option == ExecuteNonOutput) + || (!is_output && option == ExecuteOutput)) { continue; - if(option == ExecuteOnRestore - && !prop->testStatus(Property::Transient) - && !(prop->getType() & Prop_Transient) - && !prop->testStatus(Property::EvalOnRestore)) + } + if (option == ExecuteOnRestore && !prop->testStatus(Property::Transient) + && !(prop->getType() & Prop_Transient) + && !prop->testStatus(Property::EvalOnRestore)) { continue; + } } buildGraphStructures(expr.first, expr.second.expression, nodes, revNodes, edges); } @@ -556,8 +614,9 @@ void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, g = DiGraph(nodes.size()); // Add edges to graph - for (const auto & edge : edges) + for (const auto& edge : edges) { add_edge(edge.first, edge.second, g); + } // Check for cycles bool has_cycle = false; @@ -566,7 +625,7 @@ void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, depth_first_search(g, visitor(vis)); if (has_cycle) { - std::string s = revNodes[src].toString() + " reference creates a cyclic dependency."; + std::string s = revNodes[src].toString() + " reference creates a cyclic dependency."; throw Base::RuntimeError(s.c_str()); } @@ -578,7 +637,8 @@ void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, * order, in case properties depends on each other. */ -std::vector PropertyExpressionEngine::computeEvaluationOrder(ExecuteOption option) +std::vector +PropertyExpressionEngine::computeEvaluationOrder(ExecuteOption option) { std::vector evaluationOrder; boost::unordered_map revNodes; @@ -593,8 +653,9 @@ std::vector PropertyExpressionEngine::computeEvaluationOr for (int i : c) { // we return the evaluation order for our properties, not the dependencies // the topo sort will contain node ids for both our props and their deps - if (revNodes.find(i) != revNodes.end()) + if (revNodes.find(i) != revNodes.end()) { evaluationOrder.push_back(revNodes[i]); + } } return evaluationOrder; @@ -605,45 +666,57 @@ std::vector PropertyExpressionEngine::computeEvaluationOr * @return StdReturn on success. */ -DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption option, bool *touched) +DocumentObjectExecReturn* App::PropertyExpressionEngine::execute(ExecuteOption option, + bool* touched) { - DocumentObject * docObj = freecad_dynamic_cast(getContainer()); + DocumentObject* docObj = freecad_dynamic_cast(getContainer()); - if (!docObj) + if (!docObj) { throw Base::RuntimeError("PropertyExpressionEngine must be owned by a DocumentObject."); + } - if (running) + if (running) { return DocumentObject::StdReturn; + } - if(option == ExecuteOnRestore) { + if (option == ExecuteOnRestore) { bool found = false; - for(auto &e : expressions) { + for (auto& e : expressions) { auto prop = e.first.getProperty(); - if(!prop) + if (!prop) { continue; - if(prop->testStatus(App::Property::Transient) - || (prop->getType()&App::Prop_Transient) - || prop->testStatus(App::Property::EvalOnRestore)) - { + } + if (prop->testStatus(App::Property::Transient) + || (prop->getType() & App::Prop_Transient) + || prop->testStatus(App::Property::EvalOnRestore)) { found = true; break; } } - if(!found) + if (!found) { return DocumentObject::StdReturn; + } } /* Resetter class, to ensure that the "running" variable gets set to false, even if * an exception is thrown. */ - class resetter { + class resetter + { public: - explicit resetter(bool & b) : _b(b) { _b = true; } - ~resetter() { _b = false; } + explicit resetter(bool& b) + : _b(b) + { + _b = true; + } + ~resetter() + { + _b = false; + } private: - bool & _b; + bool& _b; }; resetter r(running); @@ -657,19 +730,21 @@ DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption o #endif /* Evaluate the expressions, and update properties */ - for (;it != evaluationOrder.end();++it) { + for (; it != evaluationOrder.end(); ++it) { // Get property to update - Property * prop = it->getProperty(); + Property* prop = it->getProperty(); - if (!prop) + if (!prop) { throw Base::RuntimeError("Path does not resolve to a property."); + } DocumentObject* parent = freecad_dynamic_cast(prop->getContainer()); /* Make sure property belongs to the same container as this PropertyExpressionEngine */ - if (parent != docObj) + if (parent != docObj) { throw Base::RuntimeError("Invalid property owner."); + } /* Set value of property */ App::any value; @@ -692,24 +767,29 @@ DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption o // // if (option == ExecuteOnRestore && prop->testStatus(Property::EvalOnRestore)) { - if (isAnyEqual(value, prop->getPathValue(*it))) + if (isAnyEqual(value, prop->getPathValue(*it))) { continue; - if (touched) + } + if (touched) { *touched = true; + } } prop->setPathValue(*it, value); } - }catch(Base::Exception &e) { + } + catch (Base::Exception& e) { std::ostringstream ss; ss << e.what() << std::endl << "in property binding '" << prop->getFullName() << "'"; e.setMessage(ss.str()); throw; - }catch(std::bad_cast &) { + } + catch (std::bad_cast&) { std::ostringstream ss; ss << "Invalid type '" << value.type().name() << "'"; ss << "\nin property binding '" << prop->getFullName() << "'"; throw Base::TypeError(ss.str().c_str()); - }catch(std::exception &e) { + } + catch (std::exception& e) { std::ostringstream ss; ss << e.what() << "\nin property binding '" << prop->getFullName() << "'"; throw Base::RuntimeError(ss.str().c_str()); @@ -724,23 +804,28 @@ DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption o * @param paths Object identifier */ -void PropertyExpressionEngine::getPathsToDocumentObject(DocumentObject* obj, - std::vector & paths) const +void PropertyExpressionEngine::getPathsToDocumentObject( + DocumentObject* obj, + std::vector& paths) const { - DocumentObject * owner = freecad_dynamic_cast(getContainer()); + DocumentObject* owner = freecad_dynamic_cast(getContainer()); - if (!owner || owner==obj) + if (!owner || owner == obj) { return; + } - for(auto &v : expressions) { - if (!v.second.expression) + for (auto& v : expressions) { + if (!v.second.expression) { continue; - const auto &deps = v.second.expression->getDeps(); + } + const auto& deps = v.second.expression->getDeps(); auto it = deps.find(obj); - if(it==deps.end()) + if (it == deps.end()) { continue; - for(auto &dep : it->second) - paths.insert(paths.end(),dep.second.begin(),dep.second.end()); + } + for (auto& dep : it->second) { + paths.insert(paths.end(), dep.second.begin(), dep.second.end()); + } } } @@ -751,10 +836,11 @@ void PropertyExpressionEngine::getPathsToDocumentObject(DocumentObject* obj, bool PropertyExpressionEngine::depsAreTouched() const { - for(auto &v : _Deps) { + for (auto& v : _Deps) { // v.second indicates if it is a hidden reference - if(!v.second && v.first->isTouched()) + if (!v.second && v.first->isTouched()) { return true; + } } return false; } @@ -766,25 +852,28 @@ bool PropertyExpressionEngine::depsAreTouched() const * @return Empty string on success, error message on failure. */ -std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier &path, std::shared_ptr expr) const +std::string +PropertyExpressionEngine::validateExpression(const ObjectIdentifier& path, + std::shared_ptr expr) const { std::string error; ObjectIdentifier usePath(canonicalPath(path)); if (validator) { error = validator(usePath, expr); - if (!error.empty()) + if (!error.empty()) { return error; + } } // Get document object - DocumentObject * pathDocObj = usePath.getDocumentObject(); + DocumentObject* pathDocObj = usePath.getDocumentObject(); assert(pathDocObj); auto inList = pathDocObj->getInListEx(true); - for(auto &v : expr->getDepObjects()) { + for (auto& v : expr->getDepObjects()) { auto docObj = v.first; - if(!v.second && inList.count(docObj)) { + if (!v.second && inList.count(docObj)) { std::stringstream ss; ss << "cyclic reference to " << docObj->getFullName(); return ss.str(); @@ -807,7 +896,7 @@ std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier buildGraph(newExpressions, revNodes, g); } - catch (const Base::Exception & e) { + catch (const Base::Exception& e) { return e.what(); } @@ -819,29 +908,34 @@ std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier * @param paths Map with current and new object identifier. */ -void PropertyExpressionEngine::renameExpressions(const std::map & paths) +void PropertyExpressionEngine::renameExpressions( + const std::map& paths) { ExpressionMap newExpressions; std::map canonicalPaths; /* ensure input map uses canonical paths */ - for (const auto & path : paths) + for (const auto& path : paths) { canonicalPaths[canonicalPath(path.first)] = path.second; + } - for (ExpressionMap::const_iterator i = expressions.begin(); i != expressions.end(); ++i) { - std::map::const_iterator j = canonicalPaths.find(i->first); + for (auto i = expressions.begin(); i != expressions.end(); ++i) { + auto j = canonicalPaths.find(i->first); // Renamed now? - if (j != canonicalPaths.end()) + if (j != canonicalPaths.end()) { newExpressions[j->second] = i->second; - else + } + else { newExpressions[i->first] = i->second; + } } aboutToSetValue(); expressions = newExpressions; - for (ExpressionMap::const_iterator i = expressions.begin(); i != expressions.end(); ++i) + for (auto i = expressions.begin(); i != expressions.end(); ++i) { expressionChanged(i->first); + } hasSetValue(); } @@ -851,18 +945,19 @@ void PropertyExpressionEngine::renameExpressions(const std::map &paths) +void PropertyExpressionEngine::renameObjectIdentifiers( + const std::map& paths) { - for (const auto & it : expressions) { + for (const auto& it : expressions) { RenameObjectIdentifierExpressionVisitor v(*this, paths, it.first); it.second.expression->visit(v); } } -PyObject *PropertyExpressionEngine::getPyObject() +PyObject* PropertyExpressionEngine::getPyObject() { Py::List list; - for (const auto & it : expressions) { + for (const auto& it : expressions) { Py::Tuple tuple(2); tuple.setItem(0, Py::String(it.first.toString())); auto expr = it.second.expression; @@ -872,7 +967,7 @@ PyObject *PropertyExpressionEngine::getPyObject() return Py::new_reference_to(list); } -void PropertyExpressionEngine::setPyObject(PyObject *) +void PropertyExpressionEngine::setPyObject(PyObject*) { throw Base::RuntimeError("Property is read-only"); } @@ -905,42 +1000,50 @@ void PropertyExpressionEngine::breakLink(App::DocumentObject *obj, bool clear) { } */ -bool PropertyExpressionEngine::adjustLink(const std::set &inList) { +bool PropertyExpressionEngine::adjustLink(const std::set& inList) +{ auto owner = dynamic_cast(getContainer()); - if(!owner) + if (!owner) { return false; + } bool found = false; - for(auto &v : _Deps) { - if(inList.count(v.first)) { + for (auto& v : _Deps) { + if (inList.count(v.first)) { found = true; break; } } - if(!found) + if (!found) { return false; + } AtomicPropertyChange signaler(*this); - for(auto &v : expressions) { + for (auto& v : expressions) { try { - if(v.second.expression && v.second.expression->adjustLinks(inList)) + if (v.second.expression && v.second.expression->adjustLinks(inList)) { expressionChanged(v.first); - }catch(Base::Exception &e) { + } + } + catch (Base::Exception& e) { std::ostringstream ss; ss << "Failed to adjust link for " << owner->getFullName() << " in expression " - << v.second.expression->toString() << ": " << e.what(); + << v.second.expression->toString() << ": " << e.what(); throw Base::RuntimeError(ss.str()); } } return true; } -void PropertyExpressionEngine::updateElementReference(DocumentObject *feature, bool reverse, bool notify) +void PropertyExpressionEngine::updateElementReference(DocumentObject* feature, + bool reverse, + bool notify) { (void)notify; - if(!feature) + if (!feature) { unregisterElementReference(); - UpdateElementReferenceExpressionVisitor v(*this,feature,reverse); - for(auto &e : expressions) { + } + UpdateElementReferenceExpressionVisitor v(*this, feature, reverse); + for (auto& e : expressions) { if (e.second.expression) { e.second.expression->visit(v); if (v.changed()) { @@ -949,103 +1052,123 @@ void PropertyExpressionEngine::updateElementReference(DocumentObject *feature, b } } } - if(feature && v.changed()) { + if (feature && v.changed()) { auto owner = dynamic_cast(getContainer()); - if(owner) + if (owner) { owner->onUpdateElementReference(this); + } } } -bool PropertyExpressionEngine::referenceChanged() const { +bool PropertyExpressionEngine::referenceChanged() const +{ return false; } -Property *PropertyExpressionEngine::CopyOnImportExternal( - const std::map &nameMap) const +Property* PropertyExpressionEngine::CopyOnImportExternal( + const std::map& nameMap) const { - std::unique_ptr engine; - for(auto it=expressions.begin();it!=expressions.end();++it) { + std::unique_ptr engine; + for (auto it = expressions.begin(); it != expressions.end(); ++it) { #ifdef BOOST_NO_CXX11_SMART_PTR std::shared_ptr expr(it->second.expression->importSubNames(nameMap).release()); #else std::shared_ptr expr(it->second.expression->importSubNames(nameMap)); #endif - if(!expr && !engine) + if (!expr && !engine) { continue; - if(!engine) { + } + if (!engine) { engine = std::make_unique(); - for(auto it2=expressions.begin();it2!=it;++it2) { - engine->expressions[it2->first] = ExpressionInfo( - std::shared_ptr(it2->second.expression->copy())); + for (auto it2 = expressions.begin(); it2 != it; ++it2) { + engine->expressions[it2->first] = + ExpressionInfo(std::shared_ptr(it2->second.expression->copy())); } - }else if(!expr) + } + else if (!expr) { expr = it->second.expression; + } engine->expressions[it->first] = ExpressionInfo(expr); } - if(!engine) + if (!engine) { return nullptr; + } engine->validator = validator; return engine.release(); } -Property *PropertyExpressionEngine::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyExpressionEngine::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { - std::unique_ptr engine; - for(auto it=expressions.begin();it!=expressions.end();++it) { + std::unique_ptr engine; + for (auto it = expressions.begin(); it != expressions.end(); ++it) { #ifdef BOOST_NO_CXX11_SMART_PTR - std::shared_ptr expr(it->second.expression->updateLabelReference(obj,ref,newLabel).release()); + std::shared_ptr expr( + it->second.expression->updateLabelReference(obj, ref, newLabel).release()); #else - std::shared_ptr expr(it->second.expression->updateLabelReference(obj,ref,newLabel)); + std::shared_ptr expr( + it->second.expression->updateLabelReference(obj, ref, newLabel)); #endif - if(!expr && !engine) + if (!expr && !engine) { continue; - if(!engine) { + } + if (!engine) { engine = std::make_unique(); - for(auto it2=expressions.begin();it2!=it;++it2) { + for (auto it2 = expressions.begin(); it2 != it; ++it2) { ExpressionInfo info; - if (it2->second.expression) + if (it2->second.expression) { info.expression = std::shared_ptr(it2->second.expression->copy()); + } engine->expressions[it2->first] = info; } - }else if(!expr) + } + else if (!expr) { expr = it->second.expression; + } engine->expressions[it->first] = ExpressionInfo(expr); } - if(!engine) + if (!engine) { return nullptr; + } engine->validator = validator; return engine.release(); } -Property *PropertyExpressionEngine::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyExpressionEngine::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - std::unique_ptr engine; - for(auto it=expressions.begin();it!=expressions.end();++it) { + std::unique_ptr engine; + for (auto it = expressions.begin(); it != expressions.end(); ++it) { #ifdef BOOST_NO_CXX11_SMART_PTR std::shared_ptr expr( - it->second.expression->replaceObject(parent,oldObj,newObj).release()); + it->second.expression->replaceObject(parent, oldObj, newObj).release()); #else std::shared_ptr expr( - it->second.expression->replaceObject(parent,oldObj,newObj)); + it->second.expression->replaceObject(parent, oldObj, newObj)); #endif - if(!expr && !engine) + if (!expr && !engine) { continue; - if(!engine) { + } + if (!engine) { engine = std::make_unique(); - for(auto it2=expressions.begin();it2!=it;++it2) { + for (auto it2 = expressions.begin(); it2 != it; ++it2) { ExpressionInfo info; - if (it2->second.expression) + if (it2->second.expression) { info.expression = std::shared_ptr(it2->second.expression->copy()); + } engine->expressions[it2->first] = info; } - }else if(!expr) + } + else if (!expr) { expr = it->second.expression; + } engine->expressions[it->first] = ExpressionInfo(expr); } - if(!engine) + if (!engine) { return nullptr; + } engine->validator = validator; return engine.release(); } @@ -1054,30 +1177,34 @@ std::map PropertyExpressionEngine::getExpressions() const { std::map res; - for(auto &v : expressions) + for (auto& v : expressions) { res[v.first] = v.second.expression.get(); + } return res; } void PropertyExpressionEngine::setExpressions( - std::map &&exprs) + std::map&& exprs) { AtomicPropertyChange signaller(*this); #ifdef BOOST_NO_CXX11_SMART_PTR - for(auto &v : exprs) - setValue(v.first,std::shared_ptr(v.second.release())); + for (auto& v : exprs) { + setValue(v.first, std::shared_ptr(v.second.release())); + } #else - for(auto &v : exprs) - setValue(v.first,std::move(v.second)); + for (auto& v : exprs) { + setValue(v.first, std::move(v.second)); + } #endif } -void PropertyExpressionEngine::onRelabeledDocument(const App::Document &doc) +void PropertyExpressionEngine::onRelabeledDocument(const App::Document& doc) { RelabelDocumentExpressionVisitor v(doc); - for(auto &e : expressions) { - if (e.second.expression) + for (auto& e : expressions) { + if (e.second.expression) { e.second.expression->visit(v); + } } } diff --git a/src/App/PropertyExpressionEngine.h b/src/App/PropertyExpressionEngine.h index 248a1c1323..98dd5ba6cb 100644 --- a/src/App/PropertyExpressionEngine.h +++ b/src/App/PropertyExpressionEngine.h @@ -31,12 +31,14 @@ #include #include -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; -class AppExport PropertyExpressionContainer : public App::PropertyXLinkContainer +class AppExport PropertyExpressionContainer: public App::PropertyXLinkContainer { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: PropertyExpressionContainer(); ~PropertyExpressionContainer() override; virtual std::map getExpressions() const = 0; - virtual void setExpressions(std::map &&exprs) = 0; + virtual void setExpressions(std::map&& 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 +class AppExport PropertyExpressionEngine + : public App::PropertyExpressionContainer, + private App::AtomicPropertyChangeInterface { 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 &inList) override; - Property *CopyOnImportExternal(const std::map &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& inList) override; + Property* + CopyOnImportExternal(const std::map& 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 expr)>; + using ValidatorFunc = std::function expr)>; /** * @brief The ExpressionInfo struct encapsulates an expression. */ - struct ExpressionInfo { + struct ExpressionInfo + { std::shared_ptr expression; /**< The actual expression tree */ bool busy; - explicit ExpressionInfo(std::shared_ptr expression = std::shared_ptr()) { + explicit ExpressionInfo( + std::shared_ptr expression = std::shared_ptr()) + { 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 getExpressions() const override; - void setExpressions(std::map &&exprs) override; - void onRelabeledDocument(const App::Document &doc) override; + void setExpressions(std::map&& 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 expr); + void setValue(const App::ObjectIdentifier& path, std::shared_ptr 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 & paths) const; + void getPathsToDocumentObject(DocumentObject*, std::vector& 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 expr) const; + std::string validateExpression(const App::ObjectIdentifier& path, + std::shared_ptr expr) const; - void renameExpressions(const std::map &paths); + void renameExpressions(const std::map& paths); - void renameObjectIdentifiers(const std::map & paths); + void + renameObjectIdentifiers(const std::map& 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 expressionChanged; + /// signal called when an expression was changed + boost::signals2::signal expressionChanged; void afterRestore() override; void onContainerRestored() override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& 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; using Edge = std::pair; - // 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; - #else +#else using ExpressionMap = std::map; - #endif +#endif std::vector computeEvaluationOrder(ExecuteOption option); - void buildGraphStructures(const App::ObjectIdentifier &path, - const std::shared_ptr expression, boost::unordered_map &nodes, - boost::unordered_map &revNodes, std::vector &edges) const; + void buildGraphStructures(const App::ObjectIdentifier& path, + const std::shared_ptr expression, + boost::unordered_map& nodes, + boost::unordered_map& revNodes, + std::vector& edges) const; - void buildGraph(const ExpressionMap &exprs, - boost::unordered_map &revNodes, - DiGraph &g, ExecuteOption option=ExecuteAll) const; + void buildGraph(const ExpressionMap& exprs, + boost::unordered_map& 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 > restoredExpressions; + /**< Expressions are read from file to this map first before they are validated and inserted + * into the actual map */ + std::unique_ptr> restoredExpressions; struct Private; std::unique_ptr pimpl; friend class AtomicPropertyChange; - }; -} +} // namespace App -#endif // EXPRESSIONENGINE_H +#endif // EXPRESSIONENGINE_H diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 9944d637fb..eec521f391 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -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(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() << "" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; // write the file in the XML stream writer.incInd(); writer.insertBinFile(_cValue.c_str()); writer.decInd(); - writer.Stream() << writer.ind() <<"" << endl; + writer.Stream() << writer.ind() << "" << endl; } else { writer.Stream() << writer.ind() << "" << 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() << "" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; } else { writer.Stream() << writer.ind() << "" << 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 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(from); + const PropertyFileIncluded& prop = dynamic_cast(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); } } - diff --git a/src/App/PropertyFile.h b/src/App/PropertyFile.h index 3806b09bf8..d36300fc92 100644 --- a/src/App/PropertyFile.h +++ b/src/App/PropertyFile.h @@ -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(&other)->_BaseFileName && _OriginalName == static_cast(&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 diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp index 29b075393e..aeb2454960 100644 --- a/src/App/PropertyGeo.cpp +++ b/src/App/PropertyGeo.cpp @@ -48,14 +48,12 @@ using namespace Base; using namespace std; - - //************************************************************************** //************************************************************************** // PropertyVector //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyVector , App::Property) +TYPESYSTEM_SOURCE(App::PropertyVector, App::Property) //************************************************************************** // Construction/Destruction @@ -63,72 +61,79 @@ TYPESYSTEM_SOURCE(App::PropertyVector , App::Property) PropertyVector::PropertyVector() = default; - PropertyVector::~PropertyVector() = default; //************************************************************************** // Base class implementer - -void PropertyVector::setValue(const Base::Vector3d &vec) +void PropertyVector::setValue(const Base::Vector3d& vec) { aboutToSetValue(); - _cVec=vec; + _cVec = vec; hasSetValue(); } void PropertyVector::setValue(double x, double y, double z) { aboutToSetValue(); - _cVec.Set(x,y,z); + _cVec.Set(x, y, z); hasSetValue(); } -const Base::Vector3d & PropertyVector::getValue()const +const Base::Vector3d& PropertyVector::getValue() const { return _cVec; } -PyObject *PropertyVector::getPyObject() +PyObject* PropertyVector::getPyObject() { return new Base::VectorPy(_cVec); } -void PropertyVector::setPyObject(PyObject *value) +void PropertyVector::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::VectorPy::Type))) { - Base::VectorPy *pcObject = static_cast(value); + Base::VectorPy* pcObject = static_cast(value); Base::Vector3d* val = pcObject->getVectorPtr(); setValue(*val); } - else if (PyTuple_Check(value)&&PyTuple_Size(value)==3) { - PyObject* item; + else if (PyTuple_Check(value) && PyTuple_Size(value) == 3) { + PyObject* item {}; Base::Vector3d cVec; // x - item = PyTuple_GetItem(value,0); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 0); + if (PyFloat_Check(item)) { cVec.x = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cVec.x = (double)PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Not allowed type used in tuple (float expected)..."); + } // y - item = PyTuple_GetItem(value,1); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 1); + if (PyFloat_Check(item)) { cVec.y = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cVec.y = (double)PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Not allowed type used in tuple (float expected)..."); + } // z - item = PyTuple_GetItem(value,2); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 2); + if (PyFloat_Check(item)) { cVec.z = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cVec.z = (double)PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Not allowed type used in tuple (float expected)..."); - setValue( cVec ); + } + setValue(cVec); } else { std::string error = std::string("type must be 'Vector' or tuple of three floats, not "); @@ -137,18 +142,19 @@ void PropertyVector::setPyObject(PyObject *value) } } -void PropertyVector::Save (Base::Writer &writer) const +void PropertyVector::Save(Base::Writer& writer) const { // clang-format off writer.Stream() << writer.ind() - << "" << endl; + << "\n"; // clang-format on } -void PropertyVector::Restore(Base::XMLReader &reader) +void PropertyVector::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("PropertyVector"); @@ -161,21 +167,21 @@ void PropertyVector::Restore(Base::XMLReader &reader) } -Property *PropertyVector::Copy() const +Property* PropertyVector::Copy() const { - PropertyVector *p= new PropertyVector(); + PropertyVector* p = new PropertyVector(); p->_cVec = _cVec; return p; } -void PropertyVector::Paste(const Property &from) +void PropertyVector::Paste(const Property& from) { aboutToSetValue(); _cVec = dynamic_cast(from)._cVec; hasSetValue(); } -void PropertyVector::getPaths(std::vector &paths) const +void PropertyVector::getPaths(std::vector& paths) const { paths.push_back(ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x"))); @@ -185,10 +191,10 @@ void PropertyVector::getPaths(std::vector &paths) const << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z"))); } -const boost::any PropertyVector::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyVector::getPathValue(const ObjectIdentifier& path) const { Base::Unit unit = getUnit(); - if(!unit.isEmpty()) { + if (!unit.isEmpty()) { std::string p = path.getSubPathStr(); if (p == ".x" || p == ".y" || p == ".z") { // Convert double to quantity @@ -198,21 +204,26 @@ const boost::any PropertyVector::getPathValue(const ObjectIdentifier &path) cons return Property::getPathValue(path); } -bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const +bool PropertyVector::getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const { Base::Unit unit = getUnit(); - if(unit.isEmpty()) + if (unit.isEmpty()) { return false; + } std::string p = path.getSubPathStr(); if (p == ".x") { - res = Py::asObject(new QuantityPy(new Quantity(getValue().x,unit))); - } else if(p == ".y") { - res = Py::asObject(new QuantityPy(new Quantity(getValue().y,unit))); - } else if(p == ".z") { - res = Py::asObject(new QuantityPy(new Quantity(getValue().z,unit))); - } else + res = Py::asObject(new QuantityPy(new Quantity(getValue().x, unit))); + } + else if (p == ".y") { + res = Py::asObject(new QuantityPy(new Quantity(getValue().y, unit))); + } + else if (p == ".z") { + res = Py::asObject(new QuantityPy(new Quantity(getValue().z, unit))); + } + else { return false; + } return true; } @@ -221,7 +232,7 @@ bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &re // PropertyVectorDistance //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyVectorDistance , App::PropertyVector) +TYPESYSTEM_SOURCE(App::PropertyVectorDistance, App::PropertyVector) //************************************************************************** // Construction/Destruction @@ -235,7 +246,7 @@ PropertyVectorDistance::~PropertyVectorDistance() = default; // PropertyPosition //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPosition , App::PropertyVector) +TYPESYSTEM_SOURCE(App::PropertyPosition, App::PropertyVector) //************************************************************************** // Construction/Destruction @@ -249,7 +260,7 @@ PropertyPosition::~PropertyPosition() = default; // PropertyPosition //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyDirection , App::PropertyVector) +TYPESYSTEM_SOURCE(App::PropertyDirection, App::PropertyVector) //************************************************************************** // Construction/Destruction @@ -263,7 +274,7 @@ PropertyDirection::~PropertyDirection() = default; // PropertyVectorList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyVectorList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyVectorList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -277,55 +288,58 @@ PropertyVectorList::~PropertyVectorList() = default; void PropertyVectorList::setValue(double x, double y, double z) { - setValue(Base::Vector3d(x,y,z)); + setValue(Base::Vector3d(x, y, z)); } -PyObject *PropertyVectorList::getPyObject() +PyObject* PropertyVectorList::getPyObject() { PyObject* list = PyList_New(getSize()); - for (int i = 0;i < getSize(); i++) + for (int i = 0; i < getSize(); i++) { PyList_SetItem(list, i, new VectorPy(_lValueList[i])); + } return list; } -Base::Vector3d PropertyVectorList::getPyValue(PyObject *item) const { +Base::Vector3d PropertyVectorList::getPyValue(PyObject* item) const +{ PropertyVector val; - val.setPyObject( item ); + val.setPyObject(item); return val.getValue(); } -void PropertyVectorList::Save (Base::Writer &writer) const +void PropertyVectorList::Save(Base::Writer& writer) const { if (!writer.isForceXML()) { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } } -void PropertyVectorList::Restore(Base::XMLReader &reader) +void PropertyVectorList::Restore(Base::XMLReader& reader) { reader.readElement("VectorList"); - std::string file (reader.getAttribute("file") ); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } -void PropertyVectorList::SaveDocFile (Base::Writer &writer) const +void PropertyVectorList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); str << uCt; if (!isSinglePrecision()) { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { str << it.x << it.y << it.z; } } else { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { float x = (float)it.x; float y = (float)it.y; float z = (float)it.z; @@ -334,40 +348,40 @@ void PropertyVectorList::SaveDocFile (Base::Writer &writer) const } } -void PropertyVectorList::RestoreDocFile(Base::Reader &reader) +void PropertyVectorList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); if (!isSinglePrecision()) { - for (auto & it : values) { + for (auto& it : values) { str >> it.x >> it.y >> it.z; } } else { - float x,y,z; - for (auto & it : values) { - str >> x >> y >> z; - it.Set(x, y, z); + Base::Vector3f vec; + for (auto& it : values) { + str >> vec.x >> vec.y >> vec.z; + it.Set(vec.x, vec.y, vec.z); } } setValues(values); } -Property *PropertyVectorList::Copy() const +Property* PropertyVectorList::Copy() const { - PropertyVectorList *p= new PropertyVectorList(); + PropertyVectorList* p = new PropertyVectorList(); p->_lValueList = _lValueList; return p; } -void PropertyVectorList::Paste(const Property &from) +void PropertyVectorList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyVectorList::getMemSize () const +unsigned int PropertyVectorList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(Base::Vector3d)); } @@ -377,7 +391,7 @@ unsigned int PropertyVectorList::getMemSize () const // PropertyMatrix //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyMatrix , App::Property) +TYPESYSTEM_SOURCE(App::PropertyMatrix, App::Property) //************************************************************************** // Construction/Destruction @@ -392,47 +406,52 @@ PropertyMatrix::~PropertyMatrix() = default; // Base class implementer -void PropertyMatrix::setValue(const Base::Matrix4D &mat) +void PropertyMatrix::setValue(const Base::Matrix4D& mat) { aboutToSetValue(); - _cMat=mat; + _cMat = mat; hasSetValue(); } -const Base::Matrix4D & PropertyMatrix::getValue()const +const Base::Matrix4D& PropertyMatrix::getValue() const { return _cMat; } -PyObject *PropertyMatrix::getPyObject() +PyObject* PropertyMatrix::getPyObject() { return new Base::MatrixPy(_cMat); } -void PropertyMatrix::setPyObject(PyObject *value) +void PropertyMatrix::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) { - Base::MatrixPy *pcObject = static_cast(value); - setValue( pcObject->value() ); + Base::MatrixPy* pcObject = static_cast(value); + setValue(pcObject->value()); } - else if (PyTuple_Check(value)&&PyTuple_Size(value)==16) { + else if (PyTuple_Check(value) && PyTuple_Size(value) == 16) { PyObject* item; Base::Matrix4D cMatrix; - for (int x=0; x<4;x++) { - for (int y=0; y<4;y++) { - item = PyTuple_GetItem(value,x+y*4); - if (PyFloat_Check(item)) + const int dim = 4; + for (int x = 0; x < dim; x++) { + for (int y = 0; y < dim; y++) { + item = PyTuple_GetItem(value, x + y * dim); + if (PyFloat_Check(item)) { cMatrix[x][y] = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cMatrix[x][y] = (double)PyLong_AsLong(item); - else - throw Base::TypeError("Not allowed type used in matrix tuple (a number expected)..."); + } + else { + throw Base::TypeError( + "Not allowed type used in matrix tuple (a number expected)..."); + } } } - setValue( cMatrix ); + setValue(cMatrix); } else { std::string error = std::string("type must be 'Matrix' or tuple of 16 float or int, not "); @@ -441,7 +460,7 @@ void PropertyMatrix::setPyObject(PyObject *value) } } -void PropertyMatrix::Save (Base::Writer &writer) const +void PropertyMatrix::Save(Base::Writer& writer) const { // clang-format off writer.Stream() << writer.ind() << "_cMat = _cMat; return p; } -void PropertyMatrix::Paste(const Property &from) +void PropertyMatrix::Paste(const Property& from) { aboutToSetValue(); _cMat = dynamic_cast(from)._cMat; @@ -501,7 +520,7 @@ void PropertyMatrix::Paste(const Property &from) // PropertyPlacement //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPlacement , App::Property) +TYPESYSTEM_SOURCE(App::PropertyPlacement, App::Property) //************************************************************************** // Construction/Destruction @@ -516,18 +535,17 @@ PropertyPlacement::~PropertyPlacement() = default; // Base class implementer -void PropertyPlacement::setValue(const Base::Placement &pos) +void PropertyPlacement::setValue(const Base::Placement& pos) { aboutToSetValue(); - _cPos=pos; + _cPos = pos; hasSetValue(); } -bool PropertyPlacement::setValueIfChanged(const Base::Placement &pos,double tol,double atol) +bool PropertyPlacement::setValueIfChanged(const Base::Placement& pos, double tol, double atol) { - if(_cPos.getPosition().IsEqual(pos.getPosition(),tol) - && _cPos.getRotation().isSame(pos.getRotation(),atol)) - { + if (_cPos.getPosition().IsEqual(pos.getPosition(), tol) + && _cPos.getRotation().isSame(pos.getRotation(), atol)) { return false; } setValue(pos); @@ -535,12 +553,12 @@ bool PropertyPlacement::setValueIfChanged(const Base::Placement &pos,double tol, } -const Base::Placement & PropertyPlacement::getValue()const +const Base::Placement& PropertyPlacement::getValue() const { return _cPos; } -void PropertyPlacement::getPaths(std::vector &paths) const +void PropertyPlacement::getPaths(std::vector& paths) const { paths.push_back(ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base")) @@ -568,34 +586,44 @@ void PropertyPlacement::getPaths(std::vector &paths) const << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z"))); } -namespace { -double toDouble(const boost::any &value) +namespace { - double avalue{}; +double toDouble(const boost::any& value) +{ + double avalue {}; - if (value.type() == typeid(Base::Quantity)) + if (value.type() == typeid(Base::Quantity)) { avalue = boost::any_cast(value).getValue(); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { avalue = boost::any_cast(value); - else if (value.type() == typeid(int)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(unsigned int)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(short)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(unsigned short)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(long)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(unsigned long)) - avalue = boost::any_cast(value); - else + } + else if (value.type() == typeid(int)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(unsigned int)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(short)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(unsigned short)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(long)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(unsigned long)) { + avalue = boost::any_cast(value); + } + else { throw std::bad_cast(); + } return avalue; } -} +} // namespace -void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyPlacement::setPathValue(const ObjectIdentifier& path, const boost::any& value) { auto updateAxis = [this](int index, double coord) { Base::Vector3d axis; @@ -615,18 +643,21 @@ void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost:: double yaw, pitch, roll; rot.getYawPitchRoll(yaw, pitch, roll); if (index == 0) { - if (angle < -180.0 || angle > 180.0) + if (angle < -180.0 || angle > 180.0) { throw Base::ValueError("Yaw angle is out of range [-180, +180]"); + } yaw = angle; } else if (index == 1) { - if (angle < -90.0 || angle > 90.0) + if (angle < -90.0 || angle > 90.0) { throw Base::ValueError("Pitch angle is out of range [-90, +90]"); + } pitch = angle; } else if (index == 2) { - if (angle < -180.0 || angle > 180.0) + if (angle < -180.0 || angle > 180.0) { throw Base::ValueError("Roll angle is out of range [-180, +180]"); + } roll = angle; } rot.setYawPitchRoll(yaw, pitch, roll); @@ -662,7 +693,7 @@ void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost:: } } -const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier& path) const { auto getAxis = [](const Base::Placement& plm) { Base::Vector3d axis; @@ -683,7 +714,9 @@ const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) c if (p == ".Rotation.Angle") { // Convert angle to degrees - return Base::Quantity(Base::toDegrees(boost::any_cast(Property::getPathValue(path))), Unit::Angle); + return Base::Quantity( + Base::toDegrees(boost::any_cast(Property::getPathValue(path))), + Unit::Angle); } else if (p == ".Base.x" || p == ".Base.y" || p == ".Base.z") { // Convert double to quantity @@ -712,7 +745,7 @@ const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) c } } -bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const +bool PropertyPlacement::getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const { auto getAxis = [](const Base::Placement& plm) { Base::Vector3d axis; @@ -731,21 +764,22 @@ bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object std::string p = path.getSubPathStr(); if (p == ".Rotation.Angle") { - Base::Vector3d axis; double angle; - _cPos.getRotation().getValue(axis,angle); - res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle))); + Base::Vector3d axis; + double angle; + _cPos.getRotation().getValue(axis, angle); + res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle), Unit::Angle))); return true; } else if (p == ".Base.x") { - res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length))); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().x, Unit::Length))); return true; } else if (p == ".Base.y") { - res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length))); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().y, Unit::Length))); return true; } else if (p == ".Base.z") { - res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length))); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().z, Unit::Length))); return true; } else if (p == ".Rotation.Axis.x") { @@ -776,15 +810,15 @@ bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object return false; } -PyObject *PropertyPlacement::getPyObject() +PyObject* PropertyPlacement::getPyObject() { return new Base::PlacementPy(new Base::Placement(_cPos)); } -void PropertyPlacement::setPyObject(PyObject *value) +void PropertyPlacement::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) { - Base::MatrixPy *pcObject = static_cast(value); + Base::MatrixPy* pcObject = static_cast(value); Base::Matrix4D mat = pcObject->value(); Base::Placement p; p.fromMatrix(mat); @@ -800,28 +834,30 @@ void PropertyPlacement::setPyObject(PyObject *value) } } -void PropertyPlacement::Save (Base::Writer &writer) const +void PropertyPlacement::Save(Base::Writer& writer) const { + // clang-format off writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << " A=\"" << rfAngle << "\"" + << " Ox=\"" << axis.x << "\"" + << " Oy=\"" << axis.y << "\"" + << " Oz=\"" << axis.z << "\""; + writer.Stream() << "/>" << std::endl; + // clang-format on } -void PropertyPlacement::Restore(Base::XMLReader &reader) +void PropertyPlacement::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("PropertyPlacement"); @@ -832,10 +868,10 @@ void PropertyPlacement::Restore(Base::XMLReader &reader) _cPos = Base::Placement(Vector3d(reader.getAttributeAsFloat("Px"), reader.getAttributeAsFloat("Py"), reader.getAttributeAsFloat("Pz")), - Rotation(Vector3d(reader.getAttributeAsFloat("Ox"), - reader.getAttributeAsFloat("Oy"), - reader.getAttributeAsFloat("Oz")), - reader.getAttributeAsFloat("A"))); + Rotation(Vector3d(reader.getAttributeAsFloat("Ox"), + reader.getAttributeAsFloat("Oy"), + reader.getAttributeAsFloat("Oz")), + reader.getAttributeAsFloat("A"))); } else { _cPos = Base::Placement(Vector3d(reader.getAttributeAsFloat("Px"), @@ -851,14 +887,14 @@ void PropertyPlacement::Restore(Base::XMLReader &reader) } -Property *PropertyPlacement::Copy() const +Property* PropertyPlacement::Copy() const { - PropertyPlacement *p= new PropertyPlacement(); + PropertyPlacement* p = new PropertyPlacement(); p->_cPos = _cPos; return p; } -void PropertyPlacement::Paste(const Property &from) +void PropertyPlacement::Paste(const Property& from) { aboutToSetValue(); _cPos = dynamic_cast(from)._cPos; @@ -870,7 +906,7 @@ void PropertyPlacement::Paste(const Property &from) // PropertyPlacementList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPlacementList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyPlacementList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -882,53 +918,57 @@ PropertyPlacementList::~PropertyPlacementList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyPlacementList::getPyObject() +PyObject* PropertyPlacementList::getPyObject() { - PyObject* list = PyList_New( getSize() ); + PyObject* list = PyList_New(getSize()); - for (int i = 0;i" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } } -void PropertyPlacementList::Restore(Base::XMLReader &reader) +void PropertyPlacementList::Restore(Base::XMLReader& reader) { reader.readElement("PlacementList"); - std::string file (reader.getAttribute("file") ); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } -void PropertyPlacementList::SaveDocFile (Base::Writer &writer) const +void PropertyPlacementList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); str << uCt; if (!isSinglePrecision()) { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { str << it.getPosition().x << it.getPosition().y << it.getPosition().z - << it.getRotation()[0] << it.getRotation()[1] << it.getRotation()[2] << it.getRotation()[3] ; + << it.getRotation()[0] << it.getRotation()[1] << it.getRotation()[2] + << it.getRotation()[3]; } } else { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { float x = (float)it.getPosition().x; float y = (float)it.getPosition().y; float z = (float)it.getPosition().z; @@ -941,28 +981,29 @@ void PropertyPlacementList::SaveDocFile (Base::Writer &writer) const } } -void PropertyPlacementList::RestoreDocFile(Base::Reader &reader) +void PropertyPlacementList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); if (!isSinglePrecision()) { - for (auto & it : values) { + for (auto& it : values) { Base::Vector3d pos; double q0, q1, q2, q3; str >> pos.x >> pos.y >> pos.z >> q0 >> q1 >> q2 >> q3; - Base::Rotation rot(q0,q1,q2,q3); + Base::Rotation rot(q0, q1, q2, q3); it.setPosition(pos); it.setRotation(rot); } } else { - float x,y,z,q0,q1,q2,q3; - for (auto & it : values) { + float x {}, y {}, z {}; + float q0 {}, q1 {}, q2 {}, q3 {}; + for (auto& it : values) { str >> x >> y >> z >> q0 >> q1 >> q2 >> q3; Base::Vector3d pos(x, y, z); - Base::Rotation rot(q0,q1,q2,q3); + Base::Rotation rot(q0, q1, q2, q3); it.setPosition(pos); it.setRotation(rot); } @@ -970,32 +1011,30 @@ void PropertyPlacementList::RestoreDocFile(Base::Reader &reader) setValues(values); } -Property *PropertyPlacementList::Copy() const +Property* PropertyPlacementList::Copy() const { - PropertyPlacementList *p= new PropertyPlacementList(); + PropertyPlacementList* p = new PropertyPlacementList(); p->_lValueList = _lValueList; return p; } -void PropertyPlacementList::Paste(const Property &from) +void PropertyPlacementList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyPlacementList::getMemSize () const +unsigned int PropertyPlacementList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(Base::Vector3d)); } - - //************************************************************************** //************************************************************************** // PropertyPlacement //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPlacementLink , App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyPlacementLink, App::PropertyLink) //************************************************************************** // Construction/Destruction @@ -1006,26 +1045,27 @@ PropertyPlacementLink::PropertyPlacementLink() = default; PropertyPlacementLink::~PropertyPlacementLink() = default; -App::Placement * PropertyPlacementLink::getPlacementObject() const +App::Placement* PropertyPlacementLink::getPlacementObject() const { - if (_pcLink->isDerivedFrom()) + if (_pcLink->isDerivedFrom()) { return dynamic_cast(_pcLink); - else + } + else { return nullptr; - + } } //************************************************************************** // Base class implementer -Property *PropertyPlacementLink::Copy() const +Property* PropertyPlacementLink::Copy() const { - PropertyPlacementLink *p= new PropertyPlacementLink(); + PropertyPlacementLink* p = new PropertyPlacementLink(); p->_pcLink = _pcLink; return p; } -void PropertyPlacementLink::Paste(const Property &from) +void PropertyPlacementLink::Paste(const Property& from) { aboutToSetValue(); _pcLink = dynamic_cast(from)._pcLink; @@ -1037,21 +1077,21 @@ void PropertyPlacementLink::Paste(const Property &from) // PropertyRotation //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyRotation , App::Property) +TYPESYSTEM_SOURCE(App::PropertyRotation, App::Property) PropertyRotation::PropertyRotation() = default; PropertyRotation::~PropertyRotation() = default; -void PropertyRotation::setValue(const Base::Rotation &rot) +void PropertyRotation::setValue(const Base::Rotation& rot) { aboutToSetValue(); _rot = rot; hasSetValue(); } -bool PropertyRotation::setValueIfChanged(const Base::Rotation &rot, double atol) +bool PropertyRotation::setValueIfChanged(const Base::Rotation& rot, double atol) { if (_rot.isSame(rot, atol)) { return false; @@ -1062,12 +1102,12 @@ bool PropertyRotation::setValueIfChanged(const Base::Rotation &rot, double atol) } -const Base::Rotation & PropertyRotation::getValue() const +const Base::Rotation& PropertyRotation::getValue() const { return _rot; } -void PropertyRotation::getPaths(std::vector &paths) const +void PropertyRotation::getPaths(std::vector& paths) const { paths.push_back(ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Angle"))); @@ -1082,7 +1122,7 @@ void PropertyRotation::getPaths(std::vector &paths) const << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z"))); } -void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyRotation::setPathValue(const ObjectIdentifier& path, const boost::any& value) { auto updateAxis = [this](int index, double coord) { Base::Vector3d axis; @@ -1090,7 +1130,7 @@ void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::a _rot.getRawValue(axis, angle); axis[index] = coord; - setValue(Base::Rotation{axis, angle}); + setValue(Base::Rotation {axis, angle}); }; std::string subpath = path.getSubPathStr(); @@ -1112,7 +1152,7 @@ void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::a } } -const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyRotation::getPathValue(const ObjectIdentifier& path) const { auto getAxis = [](const Base::Rotation& rot) { Base::Vector3d axis; @@ -1124,7 +1164,9 @@ const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) co if (p == ".Angle") { // Convert angle to degrees - return Base::Quantity(Base::toDegrees(boost::any_cast(Property::getPathValue(path))), Unit::Angle); + return Base::Quantity( + Base::toDegrees(boost::any_cast(Property::getPathValue(path))), + Unit::Angle); } else if (p == ".Axis.x") { return getAxis(_rot).x; @@ -1140,7 +1182,7 @@ const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) co } } -bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const +bool PropertyRotation::getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const { auto getAxis = [](const Base::Rotation& rot) { Base::Vector3d axis; @@ -1151,9 +1193,10 @@ bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object & std::string p = path.getSubPathStr(); if (p == ".Angle") { - Base::Vector3d axis; double angle; - _rot.getValue(axis,angle); - res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle))); + Base::Vector3d axis; + double angle; + _rot.getValue(axis, angle); + res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle), Unit::Angle))); return true; } else if (p == ".Axis.x") { @@ -1172,15 +1215,15 @@ bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object & return false; } -PyObject *PropertyRotation::getPyObject() +PyObject* PropertyRotation::getPyObject() { return new Base::RotationPy(new Base::Rotation(_rot)); } -void PropertyRotation::setPyObject(PyObject *value) +void PropertyRotation::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) { - Base::MatrixPy *object = static_cast(value); + Base::MatrixPy* object = static_cast(value); Base::Matrix4D mat = object->value(); Base::Rotation p; p.setValue(mat); @@ -1196,21 +1239,21 @@ void PropertyRotation::setPyObject(PyObject *value) } } -void PropertyRotation::Save (Base::Writer &writer) const +void PropertyRotation::Save(Base::Writer& writer) const { Vector3d axis; - double rfAngle; + double rfAngle {}; _rot.getRawValue(axis, rfAngle); writer.Stream() << writer.ind() << "\n"; } -void PropertyRotation::Restore(Base::XMLReader &reader) +void PropertyRotation::Restore(Base::XMLReader& reader) { reader.readElement("PropertyRotation"); aboutToSetValue(); @@ -1218,18 +1261,18 @@ void PropertyRotation::Restore(Base::XMLReader &reader) _rot = Rotation(Vector3d(reader.getAttributeAsFloat("Ox"), reader.getAttributeAsFloat("Oy"), reader.getAttributeAsFloat("Oz")), - reader.getAttributeAsFloat("A")); + reader.getAttributeAsFloat("A")); hasSetValue(); } -Property *PropertyRotation::Copy() const +Property* PropertyRotation::Copy() const { - PropertyRotation *p = new PropertyRotation(); + PropertyRotation* p = new PropertyRotation(); p->_rot = _rot; return p; } -void PropertyRotation::Paste(const Property &from) +void PropertyRotation::Paste(const Property& from) { aboutToSetValue(); _rot = dynamic_cast(from)._rot; @@ -1238,7 +1281,7 @@ void PropertyRotation::Paste(const Property &from) // ------------------------------------------------------------ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyGeometry , App::Property) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyGeometry, App::Property) PropertyGeometry::PropertyGeometry() = default; @@ -1246,43 +1289,49 @@ PropertyGeometry::~PropertyGeometry() = default; // ------------------------------------------------------------ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyComplexGeoData , App::PropertyGeometry) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyComplexGeoData, App::PropertyGeometry) PropertyComplexGeoData::PropertyComplexGeoData() = default; PropertyComplexGeoData::~PropertyComplexGeoData() = default; -std::string PropertyComplexGeoData::getElementMapVersion(bool) const { +std::string PropertyComplexGeoData::getElementMapVersion(bool) const +{ auto data = getComplexData(); - if(!data) + if (!data) { return std::string(); + } auto owner = Base::freecad_dynamic_cast(getContainer()); std::ostringstream ss; - if(owner && owner->getDocument() - && owner->getDocument()->getStringHasher()==data->Hasher) + if (owner && owner->getDocument() && owner->getDocument()->getStringHasher() == data->Hasher) { ss << "1."; - else + } + else { ss << "0."; + } ss << data->getElementMapVersion(); return ss.str(); } -bool PropertyComplexGeoData::checkElementMapVersion(const char * ver) const +bool PropertyComplexGeoData::checkElementMapVersion(const char* ver) const { auto data = getComplexData(); - if(!data) + if (!data) { return false; + } auto owner = Base::freecad_dynamic_cast(getContainer()); std::ostringstream ss; - const char *prefix; - if(owner && owner->getDocument() - && owner->getDocument()->getStringHasher() == data->Hasher) + const char* prefix; + if (owner && owner->getDocument() && owner->getDocument()->getStringHasher() == data->Hasher) { prefix = "1."; - else + } + else { prefix = "0."; - if (!boost::starts_with(ver, prefix)) + } + if (!boost::starts_with(ver, prefix)) { return true; - return data->checkElementMapVersion(ver+2); + } + return data->checkElementMapVersion(ver + 2); } @@ -1292,9 +1341,8 @@ void PropertyComplexGeoData::afterRestore() if (data && data->isRestoreFailed()) { data->resetRestoreFailure(); auto owner = Base::freecad_dynamic_cast(getContainer()); - if (owner && - owner->getDocument() && - !owner->getDocument()->testStatus(App::Document::PartialDoc)) { + if (owner && owner->getDocument() + && !owner->getDocument()->testStatus(App::Document::PartialDoc)) { owner->getDocument()->addRecomputeObject(owner); } } diff --git a/src/App/PropertyGeo.h b/src/App/PropertyGeo.h index d6c78f0a52..b335469f8d 100644 --- a/src/App/PropertyGeo.h +++ b/src/App/PropertyGeo.h @@ -34,11 +34,13 @@ #include -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 &paths) const override; + void getPaths(std::vector& 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(&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(&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 &paths) const override; + void getPaths(std::vector& 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(&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 &paths) const override; + void getPaths(std::vector& 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 diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 4fd812f8ce..3ba3b5984f 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -43,7 +43,7 @@ #include "GeoFeature.h" -FC_LOG_LEVEL_INIT("PropertyLinks",true,true) +FC_LOG_LEVEL_INIT("PropertyLinks", true, true) using namespace App; using namespace Base; @@ -55,45 +55,54 @@ namespace sp = std::placeholders; // PropertyLinkBase //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkBase , App::Property) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkBase, App::Property) -static std::unordered_map > _LabelMap; - -static std::unordered_map > _ElementRefMap; +// clang-format off +static std::unordered_map> _LabelMap; +static std::unordered_map> _ElementRefMap; +// clang-format on PropertyLinkBase::PropertyLinkBase() = default; -PropertyLinkBase::~PropertyLinkBase() { +PropertyLinkBase::~PropertyLinkBase() +{ unregisterLabelReferences(); unregisterElementReference(); } -void PropertyLinkBase::setAllowExternal(bool allow) { - setFlag(LinkAllowExternal,allow); +void PropertyLinkBase::setAllowExternal(bool allow) +{ + setFlag(LinkAllowExternal, allow); } -void PropertyLinkBase::setSilentRestore(bool allow) { +void PropertyLinkBase::setSilentRestore(bool allow) +{ setFlag(LinkSilentRestore, allow); } -void PropertyLinkBase::setReturnNewElement(bool enable) { +void PropertyLinkBase::setReturnNewElement(bool enable) +{ setFlag(LinkNewElement, enable); } -void PropertyLinkBase::hasSetValue() { +void PropertyLinkBase::hasSetValue() +{ auto owner = dynamic_cast(getContainer()); - if(owner) + if (owner) { owner->clearOutListCache(); + } Property::hasSetValue(); } -bool PropertyLinkBase::isSame(const Property &other) const +bool PropertyLinkBase::isSame(const Property& other) const { - if(&other == this) + if (&other == this) { return true; - if(other.isDerivedFrom(PropertyLinkBase::getClassTypeId()) - || getScope() != static_cast(&other)->getScope()) + } + if (other.isDerivedFrom(PropertyLinkBase::getClassTypeId()) + || getScope() != static_cast(&other)->getScope()) { return false; + } static std::vector ret; static std::vector subs; @@ -104,13 +113,14 @@ bool PropertyLinkBase::isSame(const Property &other) const subs.clear(); ret2.clear(); subs2.clear(); - getLinks(ret,true,&subs,false); - static_cast(&other)->getLinks(ret2,true,&subs2,true); + getLinks(ret, true, &subs, false); + static_cast(&other)->getLinks(ret2, true, &subs2, true); - return ret==ret2 && subs==subs2; + return ret == ret2 && subs == subs2; } -void PropertyLinkBase::unregisterElementReference() { +void PropertyLinkBase::unregisterElementReference() +{ for (auto obj : _ElementRefs) { auto it = _ElementRefMap.find(obj); if (it != _ElementRefMap.end()) { @@ -125,102 +135,123 @@ void PropertyLinkBase::unregisterElementReference() { void PropertyLinkBase::unregisterLabelReferences() { - for(auto &label : _LabelRefs) { + for (auto& label : _LabelRefs) { auto it = _LabelMap.find(label); - if(it!=_LabelMap.end()) { + if (it != _LabelMap.end()) { it->second.erase(this); - if(it->second.empty()) + if (it->second.empty()) { _LabelMap.erase(it); + } } } _LabelRefs.clear(); } -void PropertyLinkBase::getLabelReferences(std::vector &subs,const char *subname) { - const char *dot; +void PropertyLinkBase::getLabelReferences(std::vector& subs, const char* subname) +{ + const char* dot; for (; (subname = strchr(subname, '$')) != nullptr; subname = dot + 1) { ++subname; - dot = strchr(subname,'.'); - if(!dot) break; - subs.emplace_back(subname,dot-subname); + dot = strchr(subname, '.'); + if (!dot) { + break; + } + subs.emplace_back(subname, dot - subname); } } -void PropertyLinkBase::registerLabelReferences(std::vector &&labels, bool reset) { - if(reset) - unregisterLabelReferences(); - for(auto &label : labels) { - auto res = _LabelRefs.insert(std::move(label)); - if(res.second) - _LabelMap[*res.first].insert(this); - } -} - -void PropertyLinkBase::checkLabelReferences(const std::vector &subs, bool reset) { - if(reset) - unregisterLabelReferences(); - std::vector labels; - for(auto &sub : subs) { - labels.clear(); - getLabelReferences(labels,sub.c_str()); - registerLabelReferences(std::move(labels),false); - } -} - -std::string PropertyLinkBase::updateLabelReference(const App::DocumentObject *parent, - const char *subname, App::DocumentObject *obj, const std::string &ref, const char *newLabel) +void PropertyLinkBase::registerLabelReferences(std::vector&& labels, bool reset) { - if(!obj || !obj->isAttachedToDocument() || !parent || !parent->isAttachedToDocument()) + if (reset) { + unregisterLabelReferences(); + } + for (auto& label : labels) { + auto res = _LabelRefs.insert(std::move(label)); + if (res.second) { + _LabelMap[*res.first].insert(this); + } + } +} + +void PropertyLinkBase::checkLabelReferences(const std::vector& subs, bool reset) +{ + if (reset) { + unregisterLabelReferences(); + } + std::vector labels; + for (auto& sub : subs) { + labels.clear(); + getLabelReferences(labels, sub.c_str()); + registerLabelReferences(std::move(labels), false); + } +} + +std::string PropertyLinkBase::updateLabelReference(const App::DocumentObject* parent, + const char* subname, + App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) +{ + if (!obj || !obj->isAttachedToDocument() || !parent || !parent->isAttachedToDocument()) { return {}; + } // Because the label is allowed to be the same across different // hierarchies, we have to search for all occurrences, and make sure the // referenced sub-object at the found hierarchy is actually the given // object. - for (const char *pos = subname; ((pos = strstr(pos, ref.c_str())) != nullptr); pos += ref.size()) { - auto sub = std::string(subname,pos+ref.size()-subname); + for (const char* pos = subname; ((pos = strstr(pos, ref.c_str())) != nullptr); + pos += ref.size()) { + auto sub = std::string(subname, pos + ref.size() - subname); auto sobj = parent->getSubObject(sub.c_str()); - if(sobj == obj) { + if (sobj == obj) { sub = subname; - sub.replace(pos+1-subname,ref.size()-2,newLabel); + sub.replace(pos + 1 - subname, ref.size() - 2, newLabel); return sub; } } return {}; } -std::vector > > -PropertyLinkBase::updateLabelReferences(App::DocumentObject *obj, const char *newLabel) +std::vector>> +PropertyLinkBase::updateLabelReferences(App::DocumentObject* obj, const char* newLabel) { - std::vector > > ret; - if(!obj || !obj->isAttachedToDocument()) + std::vector>> ret; + if (!obj || !obj->isAttachedToDocument()) { return ret; + } auto it = _LabelMap.find(obj->Label.getStrValue()); - if(it == _LabelMap.end()) + if (it == _LabelMap.end()) { return ret; + } std::string ref("$"); ref += obj->Label.getValue(); ref += '.'; std::vector props; props.reserve(it->second.size()); - props.insert(props.end(),it->second.begin(),it->second.end()); - for(auto prop : props) { - if(!prop->getContainer()) + props.insert(props.end(), it->second.begin(), it->second.end()); + for (auto prop : props) { + if (!prop->getContainer()) { continue; - std::unique_ptr copy(prop->CopyOnLabelChange(obj,ref,newLabel)); - if(copy) - ret.emplace_back(prop,std::move(copy)); + } + std::unique_ptr copy(prop->CopyOnLabelChange(obj, ref, newLabel)); + if (copy) { + ret.emplace_back(prop, std::move(copy)); + } } return ret; } -static std::string propertyName(const Property *prop) { - if(!prop) +static std::string propertyName(const Property* prop) +{ + if (!prop) { return {}; - if(!prop->getContainer() || !prop->hasName()) { + } + if (!prop->getContainer() || !prop->hasName()) { auto xlink = Base::freecad_dynamic_cast(prop); - if(xlink) + if (xlink) { return propertyName(xlink->parent()); + } } return prop->getFullName(); } @@ -238,7 +269,8 @@ PropertyLinkBase::getElementReferences(DocumentObject* feature) return it->second; } -void PropertyLinkBase::updateElementReferences(DocumentObject *feature, bool reverse) { +void PropertyLinkBase::updateElementReferences(DocumentObject* feature, bool reverse) +{ if (!feature || !feature->getNameInDocument()) { return; } @@ -266,7 +298,9 @@ void PropertyLinkBase::updateElementReferences(DocumentObject *feature, bool rev } } -void PropertyLinkBase::_registerElementReference(App::DocumentObject *obj, std::string &sub, ShadowSub &shadow) +void PropertyLinkBase::_registerElementReference(App::DocumentObject* obj, + std::string& sub, + ShadowSub& shadow) { if (!obj || !obj->getNameInDocument() || sub.empty()) { return; @@ -295,10 +329,11 @@ void PropertyLinkBase::_registerElementReference(App::DocumentObject *obj, std:: } } -class StringGuard { +class StringGuard +{ public: - explicit StringGuard(char *c) - :c(c) + explicit StringGuard(char* c) + : c(c) { v1 = c[0]; v2 = c[1]; @@ -311,51 +346,60 @@ public: c[1] = v2; } - char *c; + char* c; char v1; char v2; }; -void PropertyLinkBase::restoreLabelReference(const DocumentObject *obj, - std::string &subname, ShadowSub *shadow) +void PropertyLinkBase::restoreLabelReference(const DocumentObject* obj, + std::string& subname, + ShadowSub* shadow) { std::ostringstream ss; - char *sub = &subname[0]; - char *next=sub; - for(char *dot=strchr(next,'.');dot;next=dot+1,dot=strchr(next,'.')) { - if(dot!=next && dot[-1]!='@') + char* sub = &subname[0]; + char* next = sub; + for (char* dot = strchr(next, '.'); dot; next = dot + 1, dot = strchr(next, '.')) { + if (dot != next && dot[-1] != '@') { continue; - DocumentObject *sobj; + } + DocumentObject* sobj; try { - StringGuard guard(dot-1); + StringGuard guard(dot - 1); sobj = obj->getSubObject(subname.c_str()); - if(!sobj) { - FC_ERR("Failed to restore label reference " << obj->getFullName() - << '.' << ss.str()); + if (!sobj) { + FC_ERR("Failed to restore label reference " << obj->getFullName() << '.' + << ss.str()); return; } - }catch(...){ + } + catch (...) { throw; } - ss.write(sub,next-sub); + ss.write(sub, next - sub); ss << '$' << sobj->Label.getStrValue() << '.'; - sub = dot+1; + sub = dot + 1; } - if(sub == subname.c_str()) + if (sub == subname.c_str()) { return; + } - size_t count = sub-subname.c_str(); - const auto &newSub = ss.str(); - if(shadow && shadow->oldName.size()>=count) - shadow->oldName = newSub + (shadow->oldName.c_str()+count); - if(shadow && shadow->newName.size()>=count) - shadow->newName = newSub + (shadow->newName.c_str()+count); + size_t count = sub - subname.c_str(); + const auto& newSub = ss.str(); + if (shadow && shadow->oldName.size() >= count) { + shadow->oldName = newSub + (shadow->oldName.c_str() + count); + } + if (shadow && shadow->newName.size() >= count) { + shadow->newName = newSub + (shadow->newName.c_str() + count); + } subname = newSub + sub; } -bool PropertyLinkBase::_updateElementReference(DocumentObject *feature, - App::DocumentObject *obj, std::string &sub, ShadowSub &shadow, - bool reverse, bool notify) +bool PropertyLinkBase::_updateElementReference(DocumentObject* feature, + App::DocumentObject* obj, + std::string& sub, + ShadowSub& shadow, + bool reverse, + bool notify) { if (!obj || !obj->getNameInDocument()) { return false; @@ -575,32 +619,38 @@ PropertyLinkBase::tryReplaceLink(const PropertyContainer* owner, return res; } -std::pair > -PropertyLinkBase::tryReplaceLinkSubs(const PropertyContainer *owner, - DocumentObject *obj, const DocumentObject *parent, DocumentObject *oldObj, - DocumentObject *newObj, const std::vector &subs) +std::pair> +PropertyLinkBase::tryReplaceLinkSubs(const PropertyContainer* owner, + DocumentObject* obj, + const DocumentObject* parent, + DocumentObject* oldObj, + DocumentObject* newObj, + const std::vector& subs) { - std::pair > res; + std::pair> res; res.first = 0; - if (!obj) + if (!obj) { return res; + } - auto r = tryReplaceLink(owner,obj,parent,oldObj,newObj); - if(r.first) { + auto r = tryReplaceLink(owner, obj, parent, oldObj, newObj); + if (r.first) { res.first = r.first; res.second = subs; return res; } - for(auto it=subs.begin();it!=subs.end();++it) { - auto r = tryReplaceLink(owner,obj,parent,oldObj,newObj,it->c_str()); - if(r.first) { - if(!res.first) { + for (auto it = subs.begin(); it != subs.end(); ++it) { + auto r = tryReplaceLink(owner, obj, parent, oldObj, newObj, it->c_str()); + if (r.first) { + if (!res.first) { res.first = r.first; - res.second.insert(res.second.end(),subs.begin(),it); + res.second.insert(res.second.end(), subs.begin(), it); } res.second.push_back(std::move(r.second)); - }else if(res.first) + } + else if (res.first) { res.second.push_back(*it); + } } return res; } @@ -610,7 +660,7 @@ PropertyLinkBase::tryReplaceLinkSubs(const PropertyContainer *owner, // PropertyLinkListBase //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkListBase , App::PropertyLinkBase) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkListBase, App::PropertyLinkBase) //************************************************************************** //************************************************************************** @@ -618,15 +668,16 @@ TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkListBase , App::PropertyLinkBase) //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TYPESYSTEM_SOURCE(App::PropertyLink, App::PropertyLinkBase) -TYPESYSTEM_SOURCE(App::PropertyLinkChild , App::PropertyLink) -TYPESYSTEM_SOURCE(App::PropertyLinkGlobal , App::PropertyLink) -TYPESYSTEM_SOURCE(App::PropertyLinkHidden , App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyLinkChild, App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyLinkGlobal, App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyLinkHidden, App::PropertyLink) //************************************************************************** // Construction/Destruction PropertyLink::PropertyLink() = default; + PropertyLink::~PropertyLink() { resetLink(); @@ -635,74 +686,79 @@ PropertyLink::~PropertyLink() //************************************************************************** // Base class implementer -void PropertyLink::resetLink() { - //in case this property gets dynamically removed +void PropertyLink::resetLink() +{ + // in case this property gets dynamically removed #ifndef USE_OLD_DAG // maintain the back link in the DocumentObject class if it is from a document object - if (_pcScope!=LinkScope::Hidden && - _pcLink && - getContainer() && - getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) - { + if (_pcScope != LinkScope::Hidden && _pcLink && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy)) { - if (_pcLink) + if (_pcLink) { _pcLink->_removeBackLink(parent); + } } } #endif _pcLink = nullptr; } -void PropertyLink::setValue(App::DocumentObject * lValue) +void PropertyLink::setValue(App::DocumentObject* lValue) { auto parent = dynamic_cast(getContainer()); - if(!testFlag(LinkAllowExternal) && parent && lValue && parent->getDocument()!=lValue->getDocument()) + if (!testFlag(LinkAllowExternal) && parent && lValue + && parent->getDocument() != lValue->getDocument()) { throw Base::ValueError("PropertyLink does not support external object"); + } aboutToSetValue(); #ifndef USE_OLD_DAG // maintain the back link in the DocumentObject class if it is from a document object - if (_pcScope!=LinkScope::Hidden && parent) { + if (_pcScope != LinkScope::Hidden && parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy)) { - if (_pcLink) + if (_pcLink) { _pcLink->_removeBackLink(parent); - if (lValue) + } + if (lValue) { lValue->_addBackLink(parent); + } } } #endif - _pcLink=lValue; + _pcLink = lValue; hasSetValue(); } -App::DocumentObject * PropertyLink::getValue() const +App::DocumentObject* PropertyLink::getValue() const { return _pcLink; } -App::DocumentObject * PropertyLink::getValue(Base::Type t) const +App::DocumentObject* PropertyLink::getValue(Base::Type t) const { return (_pcLink && _pcLink->getTypeId().isDerivedFrom(t)) ? _pcLink : nullptr; } -PyObject *PropertyLink::getPyObject() +PyObject* PropertyLink::getPyObject() { - if (_pcLink) + if (_pcLink) { return _pcLink->getPyObject(); - else + } + else { Py_Return; + } } -void PropertyLink::setPyObject(PyObject *value) +void PropertyLink::setPyObject(PyObject* value) { Base::PyTypeCheck(&value, &DocumentObjectPy::Type); if (value) { - DocumentObjectPy *pcObject = static_cast(value); + DocumentObjectPy* pcObject = static_cast(value); setValue(pcObject->getDocumentObjectPtr()); } else { @@ -710,12 +766,13 @@ void PropertyLink::setPyObject(PyObject *value) } } -void PropertyLink::Save (Base::Writer &writer) const +void PropertyLink::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "getExportName():"") <<"\"/>" << std::endl; + writer.Stream() << writer.ind() << "getExportName() : "") + << "\"/>" << std::endl; } -void PropertyLink::Restore(Base::XMLReader &reader) +void PropertyLink::Restore(Base::XMLReader& reader) { // read my element reader.readElement("Link"); @@ -723,7 +780,7 @@ void PropertyLink::Restore(Base::XMLReader &reader) std::string name = reader.getName(reader.getAttribute("value")); // Property not in a DocumentObject! - assert(getContainer()->isDerivedFrom() ); + assert(getContainer()->isDerivedFrom()); if (!name.empty()) { DocumentObject* parent = static_cast(getContainer()); @@ -733,12 +790,13 @@ void PropertyLink::Restore(Base::XMLReader &reader) if (!object) { if (reader.isVerbose()) { Base::Console().Warning("Lost link to '%s' while loading, maybe " - "an object was not loaded correctly\n",name.c_str()); + "an object was not loaded correctly\n", + name.c_str()); } } else if (parent == object) { if (reader.isVerbose()) { - Base::Console().Warning("Object '%s' links to itself, nullify it\n",name.c_str()); + Base::Console().Warning("Object '%s' links to itself, nullify it\n", name.c_str()); } object = nullptr; } @@ -750,58 +808,67 @@ void PropertyLink::Restore(Base::XMLReader &reader) } } -Property *PropertyLink::Copy() const +Property* PropertyLink::Copy() const { - PropertyLink *p= new PropertyLink(); + PropertyLink* p = new PropertyLink(); p->_pcLink = _pcLink; return p; } -void PropertyLink::Paste(const Property &from) +void PropertyLink::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyLink::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLink::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } setValue(static_cast(from)._pcLink); } -void PropertyLink::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLink::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { (void)newStyle; (void)subs; - if((all||_pcScope!=LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) + if ((all || _pcScope != LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) { objs.push_back(_pcLink); + } } -void PropertyLink::getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - bool all) const { - (void) subname; +void PropertyLink::getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + bool all) const +{ + (void)subname; if (!all && _pcScope == LinkScope::Hidden) { - return; // Don't get hidden links unless all is specified. + return; // Don't get hidden links unless all is specified. } if (obj && _pcLink == obj) { identifiers.emplace_back(*this); } } -void PropertyLink::breakLink(App::DocumentObject *obj, bool clear) { - if(_pcLink == obj || (clear && getContainer()==obj)) +void PropertyLink::breakLink(App::DocumentObject* obj, bool clear) +{ + if (_pcLink == obj || (clear && getContainer() == obj)) { setValue(nullptr); + } } -bool PropertyLink::adjustLink(const std::set &inList) { +bool PropertyLink::adjustLink(const std::set& inList) +{ (void)inList; return false; } -Property *PropertyLink::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLink::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - auto res = tryReplaceLink(getContainer(),_pcLink,parent,oldObj,newObj); - if(res.first) { + auto res = tryReplaceLink(getContainer(), _pcLink, parent, oldObj, newObj); + if (res.first) { auto p = new PropertyLink(); p->_pcLink = res.first; return p; @@ -826,60 +893,64 @@ PropertyLinkList::PropertyLinkList() = default; PropertyLinkList::~PropertyLinkList() { - //in case this property gety dynamically removed + // in case this property gety dynamically removed #ifndef USE_OLD_DAG - //maintain the back link in the DocumentObject class - if (_pcScope!=LinkScope::Hidden && - !_lValueList.empty() && - getContainer() && - getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) - { + // maintain the back link in the DocumentObject class + if (_pcScope != LinkScope::Hidden && !_lValueList.empty() && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy)) { - for(auto *obj : _lValueList) { - if (obj) + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } } } #endif - } void PropertyLinkList::setSize(int newSize) { - for(int i=newSize;i<(int)_lValueList.size();++i) { + for (int i = newSize; i < (int)_lValueList.size(); ++i) { auto obj = _lValueList[i]; - if (!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } _nameMap.erase(obj->getNameInDocument()); #ifndef USE_OLD_DAG - if (_pcScope!=LinkScope::Hidden) + if (_pcScope != LinkScope::Hidden) { obj->_removeBackLink(static_cast(getContainer())); + } #endif } _lValueList.resize(newSize); } -void PropertyLinkList::setSize(int newSize, const_reference def) { +void PropertyLinkList::setSize(int newSize, const_reference def) +{ auto oldSize = getSize(); setSize(newSize); - for(auto i=oldSize;i=0 && idx<(int)_lValueList.size()) { +void PropertyLinkList::set1Value(int idx, DocumentObject* const& value) +{ + DocumentObject* obj = nullptr; + if (idx >= 0 && idx < (int)_lValueList.size()) { obj = _lValueList[idx]; - if(obj == value) + if (obj == value) { return; + } } - if(!value || !value->isAttachedToDocument()) + if (!value || !value->isAttachedToDocument()) { throw Base::ValueError("invalid document object"); + } _nameMap.clear(); @@ -888,109 +959,121 @@ void PropertyLinkList::set1Value(int idx, DocumentObject* const &value) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - if(obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + if (obj) { obj->_removeBackLink(static_cast(getContainer())); - if(value) + } + if (value) { value->_addBackLink(static_cast(getContainer())); + } } } #endif - inherited::set1Value(idx,value); + inherited::set1Value(idx, value); } -void PropertyLinkList::setValues(const std::vector& lValue) { - if(lValue.size()==1 && !lValue[0]) { +void PropertyLinkList::setValues(const std::vector& value) +{ + if (value.size() == 1 && !value[0]) { // one null element means clear, as backward compatibility for old code setValues(std::vector()); return; } auto parent = Base::freecad_dynamic_cast(getContainer()); - for(auto obj : lValue) { - if(!obj || !obj->isAttachedToDocument()) + for (auto obj : value) { + if (!obj || !obj->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkList: invalid document object"); - if(!testFlag(LinkAllowExternal) && parent && parent->getDocument()!=obj->getDocument()) + } + if (!testFlag(LinkAllowExternal) && parent && parent->getDocument() != obj->getDocument()) { throw Base::ValueError("PropertyLinkList does not support external object"); + } } _nameMap.clear(); #ifndef USE_OLD_DAG - //maintain the back link in the DocumentObject class + // maintain the back link in the DocumentObject class if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - for(auto *obj : _lValueList) { - if (obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - for(auto *obj : lValue) { - if (obj) + for (auto* obj : value) { + if (obj) { obj->_addBackLink(parent); + } } } } #endif - inherited::setValues(lValue); + inherited::setValues(value); } -PyObject *PropertyLinkList::getPyObject() +PyObject* PropertyLinkList::getPyObject() { int count = getSize(); -#if 0//FIXME: Should switch to tuple +#if 0 // FIXME: Should switch to tuple Py::Tuple sequence(count); #else Py::List sequence(count); #endif - for (int i = 0; iisAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { sequence.setItem(i, Py::asObject(_lValueList[i]->getPyObject())); - else + } + else { sequence.setItem(i, Py::None()); + } } return Py::new_reference_to(sequence); } -DocumentObject *PropertyLinkList::getPyValue(PyObject *item) const +DocumentObject* PropertyLinkList::getPyValue(PyObject* item) const { Base::PyTypeCheck(&item, &DocumentObjectPy::Type); return item ? static_cast(item)->getDocumentObjectPtr() : nullptr; } -void PropertyLinkList::Save(Base::Writer &writer) const +void PropertyLinkList::Save(Base::Writer& writer) const { writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for (int i = 0; igetExportName() << "\"/>" << endl; - else + if (obj) { + writer.Stream() << writer.ind() << "getExportName() << "\"/>" + << endl; + } + else { writer.Stream() << writer.ind() << "" << endl; + } } writer.decInd(); writer.Stream() << writer.ind() << "" << endl; } -void PropertyLinkList::Restore(Base::XMLReader &reader) +void PropertyLinkList::Restore(Base::XMLReader& reader) { // read my element reader.readElement("LinkList"); // get the value of my attribute int count = reader.getAttributeAsInteger("count"); App::PropertyContainer* container = getContainer(); - if (!container) + if (!container) { throw Base::RuntimeError("Property is not part of a container"); + } if (!container->isDerivedFrom()) { std::stringstream str; - str << "Container is not a document object (" - << container->getTypeId().getName() << ")"; + str << "Container is not a document object (" << container->getTypeId().getName() << ")"; throw Base::TypeError(str.str()); } @@ -1006,11 +1089,13 @@ void PropertyLinkList::Restore(Base::XMLReader &reader) DocumentObject* father = static_cast(getContainer()); App::Document* document = father->getDocument(); DocumentObject* child = document ? document->getObject(name.c_str()) : nullptr; - if (child) + if (child) { values.push_back(child); - else if (reader.isVerbose()) - FC_WARN("Lost link to " << (document?document->getName():"") << " " << name - << " while loading, maybe an object was not loaded correctly"); + } + else if (reader.isVerbose()) { + FC_WARN("Lost link to " << (document ? document->getName() : "") << " " << name + << " while loading, maybe an object was not loaded correctly"); + } } reader.readEndElement("LinkList"); @@ -1019,114 +1104,133 @@ void PropertyLinkList::Restore(Base::XMLReader &reader) setValues(values); } -Property *PropertyLinkList::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLinkList::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { std::vector links; bool copied = false; bool found = false; - for(auto it=_lValueList.begin();it!=_lValueList.end();++it) { - auto res = tryReplaceLink(getContainer(),*it,parent,oldObj,newObj); - if(res.first) { + for (auto it = _lValueList.begin(); it != _lValueList.end(); ++it) { + auto res = tryReplaceLink(getContainer(), *it, parent, oldObj, newObj); + if (res.first) { found = true; - if(!copied) { + if (!copied) { copied = true; - links.insert(links.end(),_lValueList.begin(),it); + links.insert(links.end(), _lValueList.begin(), it); } links.push_back(res.first); - } else if(*it == newObj) { + } + else if (*it == newObj) { // in case newObj already exists here, we shall remove all existing // entry, and insert it to take over oldObj's position. - if(!copied) { + if (!copied) { copied = true; - links.insert(links.end(),_lValueList.begin(),it); + links.insert(links.end(), _lValueList.begin(), it); } - }else if(copied) + } + else if (copied) { links.push_back(*it); + } } - if(!found) + if (!found) { return nullptr; - auto p= new PropertyLinkList(); + } + auto p = new PropertyLinkList(); p->_lValueList = std::move(links); return p; } -Property *PropertyLinkList::Copy() const +Property* PropertyLinkList::Copy() const { - PropertyLinkList *p = new PropertyLinkList(); + PropertyLinkList* p = new PropertyLinkList(); p->_lValueList = _lValueList; return p; } -void PropertyLinkList::Paste(const Property &from) +void PropertyLinkList::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyLinkList::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLinkList::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } setValues(static_cast(from)._lValueList); } unsigned int PropertyLinkList::getMemSize() const { - return static_cast(_lValueList.size() * sizeof(App::DocumentObject *)); + return static_cast(_lValueList.size() * sizeof(App::DocumentObject*)); } -DocumentObject *PropertyLinkList::find(const char *name, int *pindex) const { +DocumentObject* PropertyLinkList::find(const char* name, int* pindex) const +{ const int DONT_MAP_UNDER = 10; - if (!name) + if (!name) { return nullptr; - if(_lValueList.size() <= DONT_MAP_UNDER ) { + } + if (_lValueList.size() <= DONT_MAP_UNDER) { int index = -1; for (auto obj : _lValueList) { ++index; - if(obj && obj->getNameInDocument() - && boost::equals(name, obj->getNameInDocument())) { - if(pindex) + if (obj && obj->getNameInDocument() && boost::equals(name, obj->getNameInDocument())) { + if (pindex) { *pindex = index; + } return obj; } } return nullptr; } // We're using a map. Do we need to (re)create it? - if(_nameMap.empty() || _nameMap.size()>_lValueList.size()) { + if (_nameMap.empty() || _nameMap.size() > _lValueList.size()) { _nameMap.clear(); - for(int i=0;i<(int)_lValueList.size();++i) { + for (int i = 0; i < (int)_lValueList.size(); ++i) { auto obj = _lValueList[i]; - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { _nameMap[obj->getNameInDocument()] = i; + } } } // Now lookup up in that map auto it = _nameMap.find(name); - if(it == _nameMap.end()) + if (it == _nameMap.end()) { return nullptr; - if(pindex) *pindex = it->second; + } + if (pindex) { + *pindex = it->second; + } return _lValueList[it->second]; } -DocumentObject *PropertyLinkList::findUsingMap(const std::string &name, int *pindex) const { +DocumentObject* PropertyLinkList::findUsingMap(const std::string& name, int* pindex) const +{ if (_nameMap.size() == _lValueList.size()) { auto it = _nameMap.find(name); - if(it == _nameMap.end()) + if (it == _nameMap.end()) { return nullptr; - if(pindex) *pindex = it->second; + } + if (pindex) { + *pindex = it->second; + } return _lValueList[it->second]; } return find(name.c_str(), pindex); } -void PropertyLinkList::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLinkList::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { (void)subs; (void)newStyle; - if(all||_pcScope!=LinkScope::Hidden) { - objs.reserve(objs.size()+_lValueList.size()); - for(auto obj : _lValueList) { - if(obj && obj->isAttachedToDocument()) + if (all || _pcScope != LinkScope::Hidden) { + objs.reserve(objs.size() + _lValueList.size()); + for (auto obj : _lValueList) { + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } } } @@ -1150,22 +1254,26 @@ void PropertyLinkList::getLinksTo(std::vector& identifier } } -void PropertyLinkList::breakLink(App::DocumentObject *obj, bool clear) { - if(clear && getContainer()==obj) { +void PropertyLinkList::breakLink(App::DocumentObject* obj, bool clear) +{ + if (clear && getContainer() == obj) { setValues({}); return; } std::vector values; values.reserve(_lValueList.size()); - for(auto o : _lValueList) { - if(o != obj) + for (auto o : _lValueList) { + if (o != obj) { values.push_back(o); + } } - if(values.size()!=_lValueList.size()) + if (values.size() != _lValueList.size()) { setValues(values); + } } -bool PropertyLinkList::adjustLink(const std::set &inList) { +bool PropertyLinkList::adjustLink(const std::set& inList) +{ (void)inList; return false; } @@ -1188,15 +1296,17 @@ PropertyLinkSub::PropertyLinkSub() = default; PropertyLinkSub::~PropertyLinkSub() { - //in case this property is dynamically removed + // in case this property is dynamically removed #ifndef USE_OLD_DAG - if (_pcLinkSub && getContainer() && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (_pcLinkSub && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - if (_pcLinkSub) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + if (_pcLinkSub) { _pcLinkSub->_removeBackLink(parent); + } } } #endif @@ -1207,22 +1317,26 @@ void PropertyLinkSub::setSyncSubObject(bool enable) _Flags.set((std::size_t)LinkSyncSubObject, enable); } -void PropertyLinkSub::setValue(App::DocumentObject * lValue, - const std::vector &SubList, std::vector &&shadows) +void PropertyLinkSub::setValue(App::DocumentObject* lValue, + const std::vector& SubList, + std::vector&& shadows) { - setValue(lValue,std::vector(SubList),std::move(shadows)); + setValue(lValue, std::vector(SubList), std::move(shadows)); } -void PropertyLinkSub::setValue(App::DocumentObject * lValue, - std::vector &&subs, std::vector &&shadows) +void PropertyLinkSub::setValue(App::DocumentObject* lValue, + std::vector&& subs, + std::vector&& shadows) { auto parent = Base::freecad_dynamic_cast(getContainer()); if (lValue) { - if (!lValue->isAttachedToDocument()) + if (!lValue->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkSub: invalid document object"); + } if (!testFlag(LinkAllowExternal) && parent - && parent->getDocument() != lValue->getDocument()) + && parent->getDocument() != lValue->getDocument()) { throw Base::ValueError("PropertyLinkSub does not support external object"); + } } aboutToSetValue(); #ifndef USE_OLD_DAG @@ -1230,10 +1344,12 @@ void PropertyLinkSub::setValue(App::DocumentObject * lValue, // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { - if (_pcLinkSub) + if (_pcLinkSub) { _pcLinkSub->_removeBackLink(parent); - if (lValue) + } + if (lValue) { lValue->_addBackLink(parent); + } } } #endif @@ -1242,13 +1358,15 @@ void PropertyLinkSub::setValue(App::DocumentObject * lValue, if (shadows.size() == _cSubList.size()) { _ShadowSubList = std::move(shadows); onContainerRestored(); // re-register element references - } else + } + else { updateElementReference(nullptr); + } checkLabelReferences(_cSubList); hasSetValue(); } -App::DocumentObject * PropertyLinkSub::getValue() const +App::DocumentObject* PropertyLinkSub::getValue() const { return _pcLinkSub; } @@ -1258,17 +1376,21 @@ const std::vector& PropertyLinkSub::getSubValues() const return _cSubList; } -static inline const std::string &getSubNameWithStyle(const std::string &subName, - const PropertyLinkBase::ShadowSub &shadow, bool newStyle, std::string &tmp) +static inline const std::string& getSubNameWithStyle(const std::string& subName, + const PropertyLinkBase::ShadowSub& shadow, + bool newStyle, + std::string& tmp) { - if(!newStyle) { - if(!shadow.oldName.empty()) + if (!newStyle) { + if (!shadow.oldName.empty()) { return shadow.oldName; - }else if(!shadow.newName.empty()) { + } + } + else if (!shadow.newName.empty()) { if (Data::hasMissingElement(shadow.oldName.c_str())) { auto pos = shadow.newName.rfind('.'); if (pos != std::string::npos) { - tmp = shadow.newName.substr(0, pos+1); + tmp = shadow.newName.substr(0, pos + 1); tmp += shadow.oldName; return tmp; } @@ -1278,44 +1400,49 @@ static inline const std::string &getSubNameWithStyle(const std::string &subName, return subName; } -std::vector PropertyLinkSub::getSubValues(bool newStyle) const { +std::vector PropertyLinkSub::getSubValues(bool newStyle) const +{ assert(_cSubList.size() == _ShadowSubList.size()); std::vector ret; ret.reserve(_cSubList.size()); std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) - ret.push_back(getSubNameWithStyle(_cSubList[i],_ShadowSubList[i],newStyle,tmp)); - return ret; -} - -std::vector PropertyLinkSub::getSubValuesStartsWith(const char* starter, bool newStyle) const -{ - assert(_cSubList.size() == _ShadowSubList.size()); - std::vector ret; - std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) { - const auto &sub = getSubNameWithStyle(_cSubList[i],_ShadowSubList[i],newStyle,tmp); - auto element = Data::findElementName(sub.c_str()); - if(element && boost::starts_with(element,starter)) - ret.emplace_back(element); + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + ret.push_back(getSubNameWithStyle(_cSubList[i], _ShadowSubList[i], newStyle, tmp)); } return ret; } -App::DocumentObject * PropertyLinkSub::getValue(Base::Type t) const +std::vector PropertyLinkSub::getSubValuesStartsWith(const char* starter, + bool newStyle) const +{ + assert(_cSubList.size() == _ShadowSubList.size()); + std::vector ret; + std::string tmp; + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + const auto& sub = getSubNameWithStyle(_cSubList[i], _ShadowSubList[i], newStyle, tmp); + auto element = Data::findElementName(sub.c_str()); + if (element && boost::starts_with(element, starter)) { + ret.emplace_back(element); + } + } + return ret; +} + +App::DocumentObject* PropertyLinkSub::getValue(Base::Type t) const { return (_pcLinkSub && _pcLinkSub->getTypeId().isDerivedFrom(t)) ? _pcLinkSub : nullptr; } -PyObject *PropertyLinkSub::getPyObject() +PyObject* PropertyLinkSub::getPyObject() { Py::Tuple tup(2); Py::List list(static_cast(_cSubList.size())); if (_pcLinkSub) { tup[0] = Py::asObject(_pcLinkSub->getPyObject()); int i = 0; - for (auto &sub : getSubValues(testFlag(LinkNewElement))) + for (auto& sub : getSubValues(testFlag(LinkNewElement))) { list[i++] = Py::String(sub); + } tup[1] = list; return Py::new_reference_to(tup); } @@ -1324,200 +1451,253 @@ PyObject *PropertyLinkSub::getPyObject() } } -void PropertyLinkSub::setPyObject(PyObject *value) +void PropertyLinkSub::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(DocumentObjectPy::Type))) { - DocumentObjectPy *pcObject = static_cast(value); + DocumentObjectPy* pcObject = static_cast(value); setValue(pcObject->getDocumentObjectPtr()); } else if (PyTuple_Check(value) || PyList_Check(value)) { Py::Sequence seq(value); - if(seq.size() == 0) + if (seq.size() == 0) { setValue(nullptr); - else if(seq.size()!=2) + } + else if (seq.size() != 2) { throw Base::ValueError("Expect input sequence of size 2"); + } else if (PyObject_TypeCheck(seq[0].ptr(), &(DocumentObjectPy::Type))) { - DocumentObjectPy *pcObj = static_cast(seq[0].ptr()); - static const char *errMsg = "type of second element in tuple must be str or sequence of str"; + DocumentObjectPy* pcObj = static_cast(seq[0].ptr()); + static const char* errMsg = + "type of second element in tuple must be str or sequence of str"; PropertyString propString; if (seq[1].isString()) { std::vector vals; propString.setPyObject(seq[1].ptr()); vals.emplace_back(propString.getValue()); - setValue(pcObj->getDocumentObjectPtr(),std::move(vals)); + setValue(pcObj->getDocumentObjectPtr(), std::move(vals)); } else if (seq[1].isSequence()) { Py::Sequence list(seq[1]); std::vector vals(list.size()); - unsigned int i=0; - for (Py::Sequence::iterator it = list.begin();it!=list.end();++it,++i) { - if(!(*it).isString()) + unsigned int i = 0; + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it, ++i) { + if (!(*it).isString()) { throw Base::TypeError(errMsg); + } propString.setPyObject((*it).ptr()); vals[i] = propString.getValue(); } - setValue(pcObj->getDocumentObjectPtr(),std::move(vals)); + setValue(pcObj->getDocumentObjectPtr(), std::move(vals)); } else { throw Base::TypeError(errMsg); } } else { - std::string error = std::string("type of first element in tuple must be 'DocumentObject', not "); + std::string error = + std::string("type of first element in tuple must be 'DocumentObject', not "); error += seq[0].ptr()->ob_type->tp_name; throw Base::TypeError(error); } } - else if(Py_None == value) { + else if (Py_None == value) { setValue(nullptr); } else { - std::string error = std::string("type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not "); + std::string error = std::string( + "type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } } -static bool updateLinkReference(App::PropertyLinkBase *prop, - App::DocumentObject *feature, bool reverse, bool notify, - App::DocumentObject *link, std::vector &subs, std::vector &mapped, - std::vector &shadows) +static bool updateLinkReference(App::PropertyLinkBase* prop, + App::DocumentObject* feature, + bool reverse, + bool notify, + App::DocumentObject* link, + std::vector& subs, + std::vector& mapped, + std::vector& shadows) { - if(!feature) { + if (!feature) { shadows.clear(); prop->unregisterElementReference(); } shadows.resize(subs.size()); - if(!link || !link->isAttachedToDocument()) + if (!link || !link->isAttachedToDocument()) { return false; - auto owner = dynamic_cast(prop->getContainer()); - if(owner && owner->isRestoring()) - return false; - int i=0; - bool touched = false; - for(auto &sub : subs) { - if(prop->_updateElementReference( - feature,link,sub,shadows[i++],reverse,notify&&!touched)) - touched = true; } - if(!touched) + auto owner = dynamic_cast(prop->getContainer()); + if (owner && owner->isRestoring()) { return false; - for(int idx : mapped) { - if(idx<(int)subs.size() && !shadows[idx].newName.empty()) + } + int i = 0; + bool touched = false; + for (auto& sub : subs) { + if (prop->_updateElementReference(feature, + link, + sub, + shadows[i++], + reverse, + notify && !touched)) { + touched = true; + } + } + if (!touched) { + return false; + } + for (int idx : mapped) { + if (idx < (int)subs.size() && !shadows[idx].newName.empty()) { subs[idx] = shadows[idx].newName; + } } mapped.clear(); - if(owner && feature) + if (owner && feature) { owner->onUpdateElementReference(prop); + } return true; } -void PropertyLinkSub::afterRestore() { +void PropertyLinkSub::afterRestore() +{ _ShadowSubList.resize(_cSubList.size()); - if(!testFlag(LinkRestoreLabel) ||!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + if (!testFlag(LinkRestoreLabel) || !_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return; - setFlag(LinkRestoreLabel,false); - for(std::size_t i=0;i<_cSubList.size();++i) - restoreLabelReference(_pcLinkSub,_cSubList[i],&_ShadowSubList[i]); + } + setFlag(LinkRestoreLabel, false); + for (std::size_t i = 0; i < _cSubList.size(); ++i) { + restoreLabelReference(_pcLinkSub, _cSubList[i], &_ShadowSubList[i]); + } } -void PropertyLinkSub::onContainerRestored() { +void PropertyLinkSub::onContainerRestored() +{ unregisterElementReference(); - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return; - for(std::size_t i=0;i<_cSubList.size();++i) - _registerElementReference(_pcLinkSub,_cSubList[i],_ShadowSubList[i]); + } + for (std::size_t i = 0; i < _cSubList.size(); ++i) { + _registerElementReference(_pcLinkSub, _cSubList[i], _ShadowSubList[i]); + } } -void PropertyLinkSub::updateElementReference(DocumentObject *feature, bool reverse, bool notify) { - if(!updateLinkReference(this,feature,reverse,notify,_pcLinkSub,_cSubList,_mapped,_ShadowSubList)) +void PropertyLinkSub::updateElementReference(DocumentObject* feature, bool reverse, bool notify) +{ + if (!updateLinkReference(this, + feature, + reverse, + notify, + _pcLinkSub, + _cSubList, + _mapped, + _ShadowSubList)) { return; - if(notify) + } + if (notify) { hasSetValue(); + } } -bool PropertyLinkSub::referenceChanged() const { +bool PropertyLinkSub::referenceChanged() const +{ return !_mapped.empty(); } -std::string PropertyLinkBase::importSubName(Base::XMLReader &reader, const char *sub, bool &restoreLabel) { - if(!reader.doNameMapping()) +std::string +PropertyLinkBase::importSubName(Base::XMLReader& reader, const char* sub, bool& restoreLabel) +{ + if (!reader.doNameMapping()) { return sub; + } std::ostringstream str; - for(const char *dot=strchr(sub,'.');dot;sub=dot+1,dot=strchr(sub,'.')) { - size_t count = dot-sub; - const char *tail = "."; - if(count && dot[-1] == '@') { + for (const char* dot = strchr(sub, '.'); dot; sub = dot + 1, dot = strchr(sub, '.')) { + size_t count = dot - sub; + const char* tail = "."; + if (count && dot[-1] == '@') { // tail=='@' means we are exporting a label reference. So retain // this marker so that the label can be restored in afterRestore(). tail = "@."; --count; restoreLabel = true; } - str << reader.getName(std::string(sub,count).c_str()) << tail; + str << reader.getName(std::string(sub, count).c_str()) << tail; } str << sub; return str.str(); } -const char *PropertyLinkBase::exportSubName(std::string &output, - const App::DocumentObject *obj, const char *sub, bool first_obj) +const char* PropertyLinkBase::exportSubName(std::string& output, + const App::DocumentObject* obj, + const char* sub, + bool first_obj) { std::ostringstream str; - const char *res = sub; + const char* res = sub; - if(!sub || !sub[0]) + if (!sub || !sub[0]) { return res; + } bool touched = false; - if(first_obj) { - auto dot = strchr(sub,'.'); - if(!dot) + if (first_obj) { + auto dot = strchr(sub, '.'); + if (!dot) { return res; - const char *hash; - for(hash=sub;hashisAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { doc = obj->getDocument(); + } } - if(!doc) { + if (!doc) { FC_ERR("Failed to get document for the first object in " << sub); return res; } - obj = doc->getObject(std::string(sub,dot-sub).c_str()); - if(!obj || !obj->isAttachedToDocument()) + obj = doc->getObject(std::string(sub, dot - sub).c_str()); + if (!obj || !obj->isAttachedToDocument()) { return res; - if(hash) { - if(!obj->isExporting()) - str << doc->getName() << '#'; - sub = hash+1; } - }else if(!obj || !obj->isAttachedToDocument()) + if (hash) { + if (!obj->isExporting()) { + str << doc->getName() << '#'; + } + sub = hash + 1; + } + } + else if (!obj || !obj->isAttachedToDocument()) { return res; + } - for(const char *dot=strchr(sub,'.');dot;sub=dot+1,dot=strchr(sub,'.')) { + for (const char* dot = strchr(sub, '.'); dot; sub = dot + 1, dot = strchr(sub, '.')) { // name with trailing '.' - auto name = std::string(sub,dot-sub+1); - if(first_obj) + auto name = std::string(sub, dot - sub + 1); + if (first_obj) { first_obj = false; - else + } + else { obj = obj->getSubObject(name.c_str()); - if(!obj || !obj->isAttachedToDocument()) { - FC_WARN("missing sub object '" << name << "' in '" << sub <<"'"); + } + if (!obj || !obj->isAttachedToDocument()) { + FC_WARN("missing sub object '" << name << "' in '" << sub << "'"); break; } - if(obj->isExporting()) { - if(name[0] == '$') { - if(name.compare(1,name.size()-2,obj->Label.getValue())!=0) { + if (obj->isExporting()) { + if (name[0] == '$') { + if (name.compare(1, name.size() - 2, obj->Label.getValue()) != 0) { str << obj->getExportName(true) << "@."; touched = true; continue; } - } else if(name.compare(0,name.size()-1,obj->getNameInDocument())==0) { + } + else if (name.compare(0, name.size() - 1, obj->getNameInDocument()) == 0) { str << obj->getExportName(true) << '.'; touched = true; continue; @@ -1525,66 +1705,79 @@ const char *PropertyLinkBase::exportSubName(std::string &output, } str << name; } - if(!touched) + if (!touched) { return res; + } str << sub; output = str.str(); return output.c_str(); } -App::DocumentObject *PropertyLinkBase::tryImport(const App::Document *doc, - const App::DocumentObject *obj, const std::map &nameMap) +App::DocumentObject* PropertyLinkBase::tryImport(const App::Document* doc, + const App::DocumentObject* obj, + const std::map& nameMap) { - if(doc && obj && obj->isAttachedToDocument()) { + if (doc && obj && obj->isAttachedToDocument()) { auto it = nameMap.find(obj->getExportName(true)); - if(it!=nameMap.end()) { + if (it != nameMap.end()) { obj = doc->getObject(it->second.c_str()); - if(!obj) - FC_THROWM(Base::RuntimeError,"Cannot find import object " << it->second); + if (!obj) { + FC_THROWM(Base::RuntimeError, "Cannot find import object " << it->second); + } } } return const_cast(obj); } -std::string PropertyLinkBase::tryImportSubName(const App::DocumentObject *obj, const char *_subname, - const App::Document *doc, const std::map &nameMap) +std::string PropertyLinkBase::tryImportSubName(const App::DocumentObject* obj, + const char* _subname, + const App::Document* doc, + const std::map& nameMap) { - if(!doc || !obj || !obj->isAttachedToDocument()) + if (!doc || !obj || !obj->isAttachedToDocument()) { return {}; + } std::ostringstream ss; std::string subname(_subname); - char *sub = &subname[0]; - char *next = sub; - for(char *dot=strchr(next,'.');dot;next=dot+1,dot=strchr(next,'.')) { + char* sub = &subname[0]; + char* next = sub; + for (char* dot = strchr(next, '.'); dot; next = dot + 1, dot = strchr(next, '.')) { StringGuard guard(dot); auto sobj = obj->getSubObject(subname.c_str()); - if(!sobj) { + if (!sobj) { FC_ERR("Failed to restore label reference " << obj->getFullName() << '.' << subname); return {}; } dot[0] = 0; - if(next[0] == '$') { - if(strcmp(next+1,sobj->Label.getValue())!=0) + if (next[0] == '$') { + if (strcmp(next + 1, sobj->Label.getValue()) != 0) { continue; - } else if(strcmp(next,sobj->getNameInDocument())!=0) { + } + } + else if (strcmp(next, sobj->getNameInDocument()) != 0) { continue; } auto it = nameMap.find(sobj->getExportName(true)); - if(it == nameMap.end()) + if (it == nameMap.end()) { continue; + } auto imported = doc->getObject(it->second.c_str()); - if(!imported) + if (!imported) { FC_THROWM(RuntimeError, "Failed to find imported object " << it->second); - ss.write(sub,next-sub); - if(next[0] == '$') + } + ss.write(sub, next - sub); + if (next[0] == '$') { ss << '$' << imported->Label.getStrValue() << '.'; - else + } + else { ss << it->second << '.'; - sub = dot+1; + } + sub = dot + 1; } - if(sub!=subname.c_str()) + if (sub != subname.c_str()) { return ss.str(); + } return {}; } @@ -1646,54 +1839,58 @@ void PropertyLinkBase::_getLinksTo(std::vector& identifie #define IGNORE_SHADOW false -void PropertyLinkSub::Save (Base::Writer &writer) const +void PropertyLinkSub::Save(Base::Writer& writer) const { assert(_cSubList.size() == _ShadowSubList.size()); std::string internal_name; // it can happen that the object is still alive but is not part of the document anymore and thus // returns 0 - if (_pcLinkSub && _pcLinkSub->isAttachedToDocument()) + if (_pcLinkSub && _pcLinkSub->isAttachedToDocument()) { internal_name = _pcLinkSub->getExportName(); - writer.Stream() << writer.ind() << "" << std::endl; writer.incInd(); auto owner = dynamic_cast(getContainer()); bool exporting = owner && owner->isExporting(); - for(unsigned int i = 0;i<_cSubList.size(); i++) { - const auto &shadow = _ShadowSubList[i]; + for (unsigned int i = 0; i < _cSubList.size(); i++) { + const auto& shadow = _ShadowSubList[i]; // shadow.oldName stores the old style element name. For backward // compatibility reason, we shall store the old name into attribute // 'value' whenever possible. - const auto &sub = shadow.oldName.empty()?_cSubList[i]:shadow.oldName; + const auto& sub = shadow.oldName.empty() ? _cSubList[i] : shadow.oldName; writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << "\"/>" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyLinkSub::Restore(Base::XMLReader &reader) +void PropertyLinkSub::Restore(Base::XMLReader& reader) { // read my element reader.readElement("LinkSub"); @@ -1702,16 +1899,16 @@ void PropertyLinkSub::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); // Property not in a DocumentObject! - assert(getContainer()->isDerivedFrom() ); + assert(getContainer()->isDerivedFrom()); App::Document* document = static_cast(getContainer())->getDocument(); - DocumentObject *pcObject = nullptr; + DocumentObject* pcObject = nullptr; if (!name.empty()) { pcObject = document ? document->getObject(name.c_str()) : nullptr; if (!pcObject) { if (reader.isVerbose()) { - FC_WARN("Lost link to " << name - << " while loading, maybe an object was not loaded correctly"); + FC_WARN("Lost link to " + << name << " while loading, maybe an object was not loaded correctly"); } } } @@ -1719,107 +1916,126 @@ void PropertyLinkSub::Restore(Base::XMLReader &reader) std::vector mapped; std::vector values(count); std::vector shadows(count); - bool restoreLabel=false; + bool restoreLabel = false; // Sub may store '.' separated object names, so be aware of the possible mapping when import for (int i = 0; i < count; i++) { reader.readElement("Sub"); - shadows[i].oldName = importSubName(reader,reader.getAttribute("value"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { + shadows[i].oldName = importSubName(reader, reader.getAttribute("value"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { values[i] = shadows[i].newName = - importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); - } else { - values[i] = shadows[i].oldName; - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadows[i].newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); } - if(reader.hasAttribute(ATTR_MAPPED)) + else { + values[i] = shadows[i].oldName; + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadows[i].newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } + } + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(i); + } } - setFlag(LinkRestoreLabel,restoreLabel); + setFlag(LinkRestoreLabel, restoreLabel); reader.readEndElement("LinkSub"); - if(pcObject) { - setValue(pcObject,std::move(values),std::move(shadows)); + if (pcObject) { + setValue(pcObject, std::move(values), std::move(shadows)); _mapped = std::move(mapped); } else { - setValue(nullptr); + setValue(nullptr); } } -template -std::vector updateLinkSubs(const App::DocumentObject *obj, - const std::vector &subs, Func *f, Args&&... args ) +template +std::vector updateLinkSubs(const App::DocumentObject* obj, + const std::vector& subs, + Func* f, + Args&&... args) { - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { return {}; + } std::vector res; - for(auto it=subs.begin();it!=subs.end();++it) { - const auto &sub = *it; - auto new_sub = (*f)(obj,sub.c_str(),std::forward(args)...); - if(new_sub.size()) { - if(res.empty()) { + for (auto it = subs.begin(); it != subs.end(); ++it) { + const auto& sub = *it; + auto new_sub = (*f)(obj, sub.c_str(), std::forward(args)...); + if (new_sub.size()) { + if (res.empty()) { res.reserve(subs.size()); - res.insert(res.end(),subs.begin(),it); + res.insert(res.end(), subs.begin(), it); } res.push_back(std::move(new_sub)); - }else if(!res.empty()) + } + else if (!res.empty()) { res.push_back(sub); + } } return res; } -Property *PropertyLinkSub::CopyOnImportExternal( - const std::map &nameMap) const +Property* +PropertyLinkSub::CopyOnImportExternal(const std::map& nameMap) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) + if (!owner || !owner->getDocument()) { return nullptr; - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + } + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return nullptr; + } - auto subs = updateLinkSubs(_pcLinkSub,_cSubList, - &tryImportSubName,owner->getDocument(),nameMap); - auto linked = tryImport(owner->getDocument(),_pcLinkSub,nameMap); - if(subs.empty() && linked==_pcLinkSub) + auto subs = + updateLinkSubs(_pcLinkSub, _cSubList, &tryImportSubName, owner->getDocument(), nameMap); + auto linked = tryImport(owner->getDocument(), _pcLinkSub, nameMap); + if (subs.empty() && linked == _pcLinkSub) { return nullptr; + } - PropertyLinkSub *p= new PropertyLinkSub(); + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = linked; - if(subs.empty()) + if (subs.empty()) { p->_cSubList = _cSubList; - else + } + else { p->_cSubList = std::move(subs); + } return p; } -Property *PropertyLinkSub::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyLinkSub::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) + if (!owner || !owner->getDocument()) { return nullptr; - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + } + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return nullptr; + } - auto subs = updateLinkSubs(_pcLinkSub,_cSubList,&updateLabelReference,obj,ref,newLabel); - if(subs.empty()) + auto subs = updateLinkSubs(_pcLinkSub, _cSubList, &updateLabelReference, obj, ref, newLabel); + if (subs.empty()) { return nullptr; + } - PropertyLinkSub *p= new PropertyLinkSub(); + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = _pcLinkSub; p->_cSubList = std::move(subs); return p; } -Property *PropertyLinkSub::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLinkSub::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - auto res = tryReplaceLinkSubs(getContainer(),_pcLinkSub,parent,oldObj,newObj,_cSubList); - if(res.first) { - PropertyLinkSub *p= new PropertyLinkSub(); + auto res = tryReplaceLinkSubs(getContainer(), _pcLinkSub, parent, oldObj, newObj, _cSubList); + if (res.first) { + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = res.first; p->_cSubList = std::move(res.second); return p; @@ -1827,32 +2043,35 @@ Property *PropertyLinkSub::CopyOnLinkReplace(const App::DocumentObject *parent, return nullptr; } -Property *PropertyLinkSub::Copy() const +Property* PropertyLinkSub::Copy() const { - PropertyLinkSub *p= new PropertyLinkSub(); + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = _pcLinkSub; p->_cSubList = _cSubList; p->_ShadowSubList = _ShadowSubList; return p; } -void PropertyLinkSub::Paste(const Property &from) +void PropertyLinkSub::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyLinkSub::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLinkSub::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); - auto &link = static_cast(from); - setValue(link._pcLinkSub, link._cSubList, - std::vector(link._ShadowSubList)); + } + auto& link = static_cast(from); + setValue(link._pcLinkSub, link._cSubList, std::vector(link._ShadowSubList)); } -void PropertyLinkSub::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLinkSub::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { - if(all||_pcScope!=LinkScope::Hidden) { - if(_pcLinkSub && _pcLinkSub->isAttachedToDocument()) { + if (all || _pcScope != LinkScope::Hidden) { + if (_pcLinkSub && _pcLinkSub->isAttachedToDocument()) { objs.push_back(_pcLinkSub); - if(subs) + if (subs) { *subs = getSubValues(newStyle); + } } } } @@ -1869,57 +2088,70 @@ void PropertyLinkSub::getLinksTo(std::vector& identifiers } } -void PropertyLinkSub::breakLink(App::DocumentObject *obj, bool clear) { - if(obj == _pcLinkSub || (clear && getContainer()==obj)) +void PropertyLinkSub::breakLink(App::DocumentObject* obj, bool clear) +{ + if (obj == _pcLinkSub || (clear && getContainer() == obj)) { setValue(nullptr); + } } -static App::DocumentObject *adjustLinkSubs(App::PropertyLinkBase *prop, - const std::set &inList, - App::DocumentObject *link, std::vector &subs, - std::map > *links=nullptr) +static App::DocumentObject* +adjustLinkSubs(App::PropertyLinkBase* prop, + const std::set& inList, + App::DocumentObject* link, + std::vector& subs, + std::map>* links = nullptr) { - App::DocumentObject *newLink = nullptr; - for(auto &sub : subs) { + App::DocumentObject* newLink = nullptr; + for (auto& sub : subs) { size_t pos = sub.find('.'); - for(;pos!=std::string::npos;pos=sub.find('.',pos+1)) { - auto sobj = link->getSubObject(sub.substr(0,pos+1).c_str()); - if(!sobj || - (!prop->testFlag(PropertyLinkBase::LinkAllowExternal) && - sobj->getDocument()!=link->getDocument())) - { + for (; pos != std::string::npos; pos = sub.find('.', pos + 1)) { + auto sobj = link->getSubObject(sub.substr(0, pos + 1).c_str()); + if (!sobj + || (!prop->testFlag(PropertyLinkBase::LinkAllowExternal) + && sobj->getDocument() != link->getDocument())) { pos = std::string::npos; break; } - if(!newLink) { - if(inList.count(sobj)) + if (!newLink) { + if (inList.count(sobj)) { continue; + } newLink = sobj; - if(links) - (*links)[sobj].push_back(sub.substr(pos+1)); - else - sub = sub.substr(pos+1); - }else if(links) - (*links)[sobj].push_back(sub.substr(pos+1)); - else if(sobj == newLink) - sub = sub.substr(pos+1); + if (links) { + (*links)[sobj].push_back(sub.substr(pos + 1)); + } + else { + sub = sub.substr(pos + 1); + } + } + else if (links) { + (*links)[sobj].push_back(sub.substr(pos + 1)); + } + else if (sobj == newLink) { + sub = sub.substr(pos + 1); + } break; } - if(pos == std::string::npos) + if (pos == std::string::npos) { return nullptr; + } } return newLink; } -bool PropertyLinkSub::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyLinkSub::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument() || !inList.count(_pcLinkSub)) + } + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument() || !inList.count(_pcLinkSub)) { return false; + } auto subs = _cSubList; - auto link = adjustLinkSubs(this,inList,_pcLinkSub,subs); - if(link) { - setValue(link,std::move(subs)); + auto link = adjustLinkSubs(this, inList, _pcLinkSub, subs); + if (link) { + setValue(link, std::move(subs)); return true; } return false; @@ -1942,17 +2174,19 @@ PropertyLinkSubList::PropertyLinkSubList() = default; PropertyLinkSubList::~PropertyLinkSubList() { - //in case this property is dynamically removed + // in case this property is dynamically removed #ifndef USE_OLD_DAG - //maintain backlinks - if (!_lValueList.empty() && getContainer() && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + // maintain backlinks + if (!_lValueList.empty() && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - for(auto *obj : _lValueList) { - if (obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } } } @@ -1967,17 +2201,19 @@ void PropertyLinkSubList::setSyncSubObject(bool enable) void PropertyLinkSubList::verifyObject(App::DocumentObject* obj, App::DocumentObject* parent) { if (obj) { - if (!obj->isAttachedToDocument()) + if (!obj->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkSubList: invalid document object"); - if (!testFlag(LinkAllowExternal) && parent && parent->getDocument() != obj->getDocument()) + } + if (!testFlag(LinkAllowExternal) && parent && parent->getDocument() != obj->getDocument()) { throw Base::ValueError("PropertyLinkSubList does not support external object"); + } } } void PropertyLinkSubList::setSize(int newSize) { _lValueList.resize(newSize); - _lSubList .resize(newSize); + _lSubList.resize(newSize); _ShadowSubList.resize(newSize); } @@ -1986,23 +2222,25 @@ int PropertyLinkSubList::getSize() const return static_cast(_lValueList.size()); } -void PropertyLinkSubList::setValue(DocumentObject* lValue,const char* SubName) +void PropertyLinkSubList::setValue(DocumentObject* lValue, const char* SubName) { auto parent = Base::freecad_dynamic_cast(getContainer()); verifyObject(lValue, parent); #ifndef USE_OLD_DAG - //maintain backlinks - if(parent) { + // maintain backlinks + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - for(auto *obj : _lValueList) { - if (obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - if (lValue) + if (lValue) { lValue->_addBackLink(parent); + } } } #endif @@ -2010,9 +2248,9 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue,const char* SubName) if (lValue) { aboutToSetValue(); _lValueList.resize(1); - _lValueList[0]=lValue; + _lValueList[0] = lValue; _lSubList.resize(1); - _lSubList[0]=SubName; + _lSubList[0] = SubName; } else { aboutToSetValue(); @@ -2024,34 +2262,39 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue,const char* SubName) hasSetValue(); } -void PropertyLinkSubList::setValues(const std::vector& lValue,const std::vector& lSubNames) +void PropertyLinkSubList::setValues(const std::vector& lValue, + const std::vector& lSubNames) { auto parent = Base::freecad_dynamic_cast(getContainer()); - for(auto obj : lValue) { + for (auto obj : lValue) { verifyObject(obj, parent); } - if (lValue.size() != lSubNames.size()) - throw Base::ValueError("PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + if (lValue.size() != lSubNames.size()) { + throw Base::ValueError( + "PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + } #ifndef USE_OLD_DAG - //maintain backlinks. - if(parent) { + // maintain backlinks. + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works - for(auto *obj : _lValueList) { - if (obj) + // object to ensure that this works + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - for(auto *obj : lValue) { - if (obj) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + for (auto* obj : lValue) { + if (obj) { obj->_addBackLink(parent); + } } } } @@ -2061,9 +2304,11 @@ void PropertyLinkSubList::setValues(const std::vector& lValue,c _lValueList = lValue; _lSubList.resize(lSubNames.size()); int i = 0; - for (std::vector::const_iterator it = lSubNames.begin();it!=lSubNames.end();++it,++i) { - if (*it) + for (std::vector::const_iterator it = lSubNames.begin(); it != lSubNames.end(); + ++it, ++i) { + if (*it) { _lSubList[i] = *it; + } } updateElementReference(nullptr); checkLabelReferences(_lSubList); @@ -2071,40 +2316,47 @@ void PropertyLinkSubList::setValues(const std::vector& lValue,c } void PropertyLinkSubList::setValues(const std::vector& lValue, - const std::vector& lSubNames, std::vector &&ShadowSubList) + const std::vector& lSubNames, + std::vector&& ShadowSubList) { setValues(std::vector(lValue), - std::vector(lSubNames),std::move(ShadowSubList)); + std::vector(lSubNames), + std::move(ShadowSubList)); } void PropertyLinkSubList::setValues(std::vector&& lValue, - std::vector&& lSubNames, std::vector &&ShadowSubList) + std::vector&& lSubNames, + std::vector&& ShadowSubList) { auto parent = Base::freecad_dynamic_cast(getContainer()); - for(auto obj : lValue) { + for (auto obj : lValue) { verifyObject(obj, parent); } - if (lValue.size() != lSubNames.size()) - throw Base::ValueError("PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + if (lValue.size() != lSubNames.size()) { + throw Base::ValueError( + "PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + } #ifndef USE_OLD_DAG - //maintain backlinks. - if(parent) { + // maintain backlinks. + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works - for(auto *obj : _lValueList) { - if (obj) + // object to ensure that this works + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - for(auto *obj : lValue) { - if (obj) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + for (auto* obj : lValue) { + if (obj) { obj->_addBackLink(parent); + } } } } @@ -2113,37 +2365,41 @@ void PropertyLinkSubList::setValues(std::vector&& lValue, aboutToSetValue(); _lValueList = std::move(lValue); _lSubList = std::move(lSubNames); - if(ShadowSubList.size()==_lSubList.size()) { + if (ShadowSubList.size() == _lSubList.size()) { _ShadowSubList = std::move(ShadowSubList); onContainerRestored(); // re-register element references - } else + } + else { updateElementReference(nullptr); + } checkLabelReferences(_lSubList); hasSetValue(); } -void PropertyLinkSubList::setValue(DocumentObject* lValue, const std::vector &SubList) +void PropertyLinkSubList::setValue(DocumentObject* lValue, const std::vector& SubList) { auto parent = dynamic_cast(getContainer()); verifyObject(lValue, parent); #ifndef USE_OLD_DAG - //maintain backlinks. - if(parent) { + // maintain backlinks. + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works - for(auto *obj : _lValueList) { - if (obj) + // object to ensure that this works + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - if (lValue) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + if (lValue) { lValue->_addBackLink(parent); + } } } #endif @@ -2167,39 +2423,43 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue, const std::vector &subs, bool reset) +void PropertyLinkSubList::addValue(App::DocumentObject* obj, + const std::vector& subs, + bool reset) { auto parent = Base::freecad_dynamic_cast(getContainer()); verifyObject(obj, parent); #ifndef USE_OLD_DAG - //maintain backlinks. + // maintain backlinks. if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works + // object to ensure that this works if (reset) { - for(auto* value : _lValueList) { - if (value && value == obj) + for (auto* value : _lValueList) { + if (value && value == obj) { value->_removeBackLink(parent); + } } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - if (obj) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + if (obj) { obj->_addBackLink(parent); + } } } #endif std::vector valueList; - std::vector subList; + std::vector subList; if (reset) { - for (std::size_t i=0; i<_lValueList.size(); i++) { + for (std::size_t i = 0; i < _lValueList.size(); i++) { if (_lValueList[i] != obj) { valueList.push_back(_lValueList[i]); subList.push_back(_lSubList[i]); @@ -2235,21 +2495,25 @@ const string PropertyLinkSubList::getPyReprString() const { assert(this->_lValueList.size() == this->_lSubList.size()); - if (this->_lValueList.empty()) + if (this->_lValueList.empty()) { return std::string("None"); + } std::stringstream strm; strm << "["; for (std::size_t i = 0; i < this->_lSubList.size(); i++) { - if (i>0) + if (i > 0) { strm << ",("; - else + } + else { strm << "("; + } App::DocumentObject* obj = this->_lValueList[i]; if (obj) { - strm << "App.getDocument('" << obj->getDocument()->getName() - << "').getObject('" << obj->getNameInDocument() << "')"; - } else { + strm << "App.getDocument('" << obj->getDocument()->getName() << "').getObject('" + << obj->getNameInDocument() << "')"; + } + else { strm << "None"; } strm << ","; @@ -2260,33 +2524,36 @@ const string PropertyLinkSubList::getPyReprString() const return strm.str(); } -DocumentObject *PropertyLinkSubList::getValue() const +DocumentObject* PropertyLinkSubList::getValue() const { App::DocumentObject* ret = nullptr; - //FIXME: cache this to avoid iterating each time, to improve speed + // FIXME: cache this to avoid iterating each time, to improve speed for (auto i : this->_lValueList) { - if (!ret) + if (!ret) { ret = i; - if (ret != i) + } + if (ret != i) { return nullptr; + } } return ret; } -int PropertyLinkSubList::removeValue(App::DocumentObject *lValue) +int PropertyLinkSubList::removeValue(App::DocumentObject* lValue) { assert(this->_lValueList.size() == this->_lSubList.size()); std::size_t num = std::count(this->_lValueList.begin(), this->_lValueList.end(), lValue); - if (num == 0) + if (num == 0) { return 0; + } std::vector links; std::vector subs; links.reserve(this->_lValueList.size() - num); subs.reserve(this->_lSubList.size() - num); - for (std::size_t i=0; i_lValueList.size(); ++i) { + for (std::size_t i = 0; i < this->_lValueList.size(); ++i) { if (this->_lValueList[i] != lValue) { links.push_back(this->_lValueList[i]); subs.push_back(this->_lSubList[i]); @@ -2301,13 +2568,17 @@ void PropertyLinkSubList::setSubListValues(const std::vector links; std::vector subs; - for (std::vector::const_iterator it = values.begin(); it != values.end(); ++it) { + for (std::vector::const_iterator it = values.begin(); + it != values.end(); + ++it) { if (it->second.empty()) { links.push_back(it->first); subs.emplace_back(); continue; } - for (std::vector::const_iterator jt = it->second.begin(); jt != it->second.end(); ++jt) { + for (std::vector::const_iterator jt = it->second.begin(); + jt != it->second.end(); + ++jt) { links.push_back(it->first); subs.push_back(*jt); } @@ -2318,22 +2589,27 @@ void PropertyLinkSubList::setSubListValues(const std::vector PropertyLinkSubList::getSubListValues(bool newStyle) const { std::vector values; - if (_lValueList.size() != _lSubList.size()) - throw Base::ValueError("PropertyLinkSubList::getSubListValues: size of subelements list != size of objects list"); + if (_lValueList.size() != _lSubList.size()) { + throw Base::ValueError("PropertyLinkSubList::getSubListValues: size of subelements list != " + "size of objects list"); + } assert(_ShadowSubList.size() == _lSubList.size()); for (std::size_t i = 0; i < _lValueList.size(); i++) { App::DocumentObject* link = _lValueList[i]; std::string sub; - if(newStyle && !_ShadowSubList[i].newName.empty()) + if (newStyle && !_ShadowSubList[i].newName.empty()) { sub = _ShadowSubList[i].newName; - else if(!newStyle && !_ShadowSubList[i].oldName.empty()) + } + else if (!newStyle && !_ShadowSubList[i].oldName.empty()) { sub = _ShadowSubList[i].oldName; - else + } + else { sub = _lSubList[i]; - if (values.empty() || values.back().first != link){ - //new object started, start a new subset. + } + if (values.empty() || values.back().first != link) { + // new object started, start a new subset. values.emplace_back(link, std::vector()); } values.back().second.push_back(sub); @@ -2341,16 +2617,16 @@ std::vector PropertyLinkSubList::getSubListValues(b return values; } -PyObject *PropertyLinkSubList::getPyObject() +PyObject* PropertyLinkSubList::getPyObject() { std::vector subLists = getSubListValues(); std::size_t count = subLists.size(); -#if 0//FIXME: Should switch to tuple +#if 0 // FIXME: Should switch to tuple Py::Tuple sequence(count); #else Py::List sequence(count); #endif - for (std::size_t i = 0; igetPyObject()); @@ -2367,164 +2643,199 @@ PyObject *PropertyLinkSubList::getPyObject() return Py::new_reference_to(sequence); } -void PropertyLinkSubList::setPyObject(PyObject *value) +void PropertyLinkSubList::setPyObject(PyObject* value) { - try { //try PropertyLinkSub syntax + try { // try PropertyLinkSub syntax PropertyLinkSub dummy; dummy.setPyObject(value); this->setValue(dummy.getValue(), dummy.getSubValues()); return; } - catch (...) {} + catch (...) { + } try { // try PropertyLinkList syntax PropertyLinkList dummy; dummy.setPyObject(value); - const auto &values = dummy.getValues(); + const auto& values = dummy.getValues(); std::vector subs(values.size()); - this->setValues(values,subs); + this->setValues(values, subs); return; - }catch(...) {} + } + catch (...) { + } - static const char *errMsg = + static const char* errMsg = "Expects sequence of items of type DocObj, (DocObj,SubName), or (DocObj, (SubName,...))"; - if (!PyTuple_Check(value) && !PyList_Check(value)) + if (!PyTuple_Check(value) && !PyList_Check(value)) { throw Base::TypeError(errMsg); + } Py::Sequence list(value); Py::Sequence::size_type size = list.size(); std::vector values; values.reserve(size); - std::vector SubNames; + std::vector SubNames; SubNames.reserve(size); - for (Py::Sequence::size_type i=0; i(seq[0].ptr())->getDocumentObjectPtr(); PropertyString propString; if (seq[1].isString()) { values.push_back(obj); propString.setPyObject(seq[1].ptr()); SubNames.emplace_back(propString.getValue()); - } else if (seq[1].isSequence()) { + } + else if (seq[1].isSequence()) { Py::Sequence list(seq[1]); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if(!(*it).isString()) + if (!(*it).isString()) { throw Base::TypeError(errMsg); + } values.push_back(obj); propString.setPyObject((*it).ptr()); SubNames.emplace_back(propString.getValue()); } - } else + } + else { throw Base::TypeError(errMsg); + } } - } else if (PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) { - DocumentObjectPy *pcObj; + } + else if (PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) { + DocumentObjectPy* pcObj; pcObj = static_cast(*item); values.push_back(pcObj->getDocumentObjectPtr()); SubNames.emplace_back(); - } else + } + else { throw Base::TypeError(errMsg); + } } - setValues(values,SubNames); + setValues(values, SubNames); } -void PropertyLinkSubList::afterRestore() { +void PropertyLinkSubList::afterRestore() +{ assert(_lSubList.size() == _ShadowSubList.size()); - if(!testFlag(LinkRestoreLabel)) + if (!testFlag(LinkRestoreLabel)) { return; - setFlag(LinkRestoreLabel,false); - for(size_t i=0;i<_lSubList.size();++i) - restoreLabelReference(_lValueList[i],_lSubList[i],&_ShadowSubList[i]); + } + setFlag(LinkRestoreLabel, false); + for (size_t i = 0; i < _lSubList.size(); ++i) { + restoreLabelReference(_lValueList[i], _lSubList[i], &_ShadowSubList[i]); + } } -void PropertyLinkSubList::onContainerRestored() { +void PropertyLinkSubList::onContainerRestored() +{ unregisterElementReference(); - for(size_t i=0;i<_lSubList.size();++i) - _registerElementReference(_lValueList[i],_lSubList[i],_ShadowSubList[i]); + for (size_t i = 0; i < _lSubList.size(); ++i) { + _registerElementReference(_lValueList[i], _lSubList[i], _ShadowSubList[i]); + } } -void PropertyLinkSubList::updateElementReference(DocumentObject *feature, bool reverse, bool notify) { - if(!feature) { +void PropertyLinkSubList::updateElementReference(DocumentObject* feature, bool reverse, bool notify) +{ + if (!feature) { _ShadowSubList.clear(); unregisterElementReference(); } _ShadowSubList.resize(_lSubList.size()); auto owner = freecad_dynamic_cast(getContainer()); - if(owner && owner->isRestoring()) + if (owner && owner->isRestoring()) { return; - int i=0; - bool touched = false; - for(auto &sub : _lSubList) { - auto obj = _lValueList[i]; - if(_updateElementReference(feature,obj,sub,_ShadowSubList[i++],reverse,notify&&!touched)) - touched = true; } - if(!touched) + int i = 0; + bool touched = false; + for (auto& sub : _lSubList) { + auto obj = _lValueList[i]; + if (_updateElementReference(feature, + obj, + sub, + _ShadowSubList[i++], + reverse, + notify && !touched)) { + touched = true; + } + } + if (!touched) { return; + } std::vector mapped; mapped.reserve(_mapped.size()); - for(int idx : _mapped) { - if(idx<(int)_lSubList.size()) { - if(!_ShadowSubList[idx].newName.empty()) + for (int idx : _mapped) { + if (idx < (int)_lSubList.size()) { + if (!_ShadowSubList[idx].newName.empty()) { _lSubList[idx] = _ShadowSubList[idx].newName; - else + } + else { mapped.push_back(idx); + } } } _mapped.swap(mapped); - if(owner && feature) + if (owner && feature) { owner->onUpdateElementReference(this); - if(notify) + } + if (notify) { hasSetValue(); + } } -bool PropertyLinkSubList::referenceChanged() const{ +bool PropertyLinkSubList::referenceChanged() const +{ return !_mapped.empty(); } -void PropertyLinkSubList::Save (Base::Writer &writer) const +void PropertyLinkSubList::Save(Base::Writer& writer) const { assert(_lSubList.size() == _ShadowSubList.size()); int count = 0; - for(auto obj : _lValueList) { - if(obj && obj->isAttachedToDocument()) + for (auto obj : _lValueList) { + if (obj && obj->isAttachedToDocument()) { ++count; + } } - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); auto owner = dynamic_cast(getContainer()); bool exporting = owner && owner->isExporting(); for (int i = 0; i < getSize(); i++) { auto obj = _lValueList[i]; - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - const auto &shadow = _ShadowSubList[i]; + } + const auto& shadow = _ShadowSubList[i]; // shadow.oldName stores the old style element name. For backward // compatibility reason, we shall store the old name into attribute // 'value' whenever possible. - const auto &sub = shadow.oldName.empty()?_lSubList[i]:shadow.oldName; + const auto& sub = shadow.oldName.empty() ? _lSubList[i] : shadow.oldName; writer.Stream() << writer.ind() << "getExportName() << "\" sub=\""; - if(exporting) { + if (exporting) { std::string exportName; - writer.Stream() << encodeAttribute(exportSubName(exportName,obj,sub.c_str())); - if(!shadow.oldName.empty() && _lSubList[i]==shadow.newName) + writer.Stream() << encodeAttribute(exportSubName(exportName, obj, sub.c_str())); + if (!shadow.oldName.empty() && _lSubList[i] == shadow.newName) { writer.Stream() << "\" " ATTR_MAPPED "=\"1"; - } else { + } + } + else { writer.Stream() << encodeAttribute(sub); - if(!_lSubList[i].empty()) { - if(sub!=_lSubList[i]) { + if (!_lSubList[i].empty()) { + if (sub != _lSubList[i]) { // Stores the actual value that is shadowed. For new version FC, // we will restore this shadowed value instead. writer.Stream() << "\" " ATTR_SHADOWED "=\"" << encodeAttribute(_lSubList[i]); - }else if(!shadow.newName.empty()) { + } + else if (!shadow.newName.empty()) { // Here means the user set value is old style element name. // We shall then store the shadow somewhere else. writer.Stream() << "\" " ATTR_SHADOW "=\"" << encodeAttribute(shadow.newName); @@ -2535,10 +2846,10 @@ void PropertyLinkSubList::Save (Base::Writer &writer) const } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyLinkSubList::Restore(Base::XMLReader &reader) +void PropertyLinkSubList::Restore(Base::XMLReader& reader) { // read my element reader.readElement("LinkSubList"); @@ -2554,7 +2865,7 @@ void PropertyLinkSubList::Restore(Base::XMLReader &reader) DocumentObject* father = dynamic_cast(getContainer()); App::Document* document = father ? father->getDocument() : nullptr; std::vector mapped; - bool restoreLabel=false; + bool restoreLabel = false; for (int i = 0; i < count; i++) { reader.readElement("Link"); std::string name = reader.getName(reader.getAttribute("obj")); @@ -2566,32 +2877,40 @@ void PropertyLinkSubList::Restore(Base::XMLReader &reader) if (child) { values.push_back(child); shadows.emplace_back(); - auto &shadow = shadows.back(); - shadow.oldName = importSubName(reader,reader.getAttribute("sub"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { - shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); + auto& shadow = shadows.back(); + shadow.oldName = importSubName(reader, reader.getAttribute("sub"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { + shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); SubNames.push_back(shadow.newName); - }else{ - SubNames.push_back(shadow.oldName); - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); } - if(reader.hasAttribute(ATTR_MAPPED)) + else { + SubNames.push_back(shadow.oldName); + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } + } + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(i); - } else if (reader.isVerbose()) + } + } + else if (reader.isVerbose()) { Base::Console().Warning("Lost link to '%s' while loading, maybe " - "an object was not loaded correctly\n",name.c_str()); + "an object was not loaded correctly\n", + name.c_str()); + } } - setFlag(LinkRestoreLabel,restoreLabel); + setFlag(LinkRestoreLabel, restoreLabel); reader.readEndElement("LinkSubList"); // assignment - setValues(values,SubNames,std::move(shadows)); + setValues(values, SubNames, std::move(shadows)); _mapped.swap(mapped); } -bool PropertyLinkSubList::upgrade(Base::XMLReader &reader, const char *typeName) +bool PropertyLinkSubList::upgrade(Base::XMLReader& reader, const char* typeName) { Base::Type type = Base::Type::fromName(typeName); if (type.isDerivedFrom(PropertyLink::getClassTypeId())) { @@ -2621,124 +2940,133 @@ bool PropertyLinkSubList::upgrade(Base::XMLReader &reader, const char *typeName) return false; } -Property *PropertyLinkSubList::CopyOnImportExternal( - const std::map &nameMap) const +Property* +PropertyLinkSubList::CopyOnImportExternal(const std::map& nameMap) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument() || _lValueList.size()!=_lSubList.size()) + if (!owner || !owner->getDocument() || _lValueList.size() != _lSubList.size()) { return nullptr; - std::vector values; + } + std::vector values; std::vector subs; auto itSub = _lSubList.begin(); - for(auto itValue=_lValueList.begin();itValue!=_lValueList.end();++itValue,++itSub) { + for (auto itValue = _lValueList.begin(); itValue != _lValueList.end(); ++itValue, ++itSub) { auto value = *itValue; - const auto &sub = *itSub; - if(!value || !value->isAttachedToDocument()) { - if(!values.empty()) { + const auto& sub = *itSub; + if (!value || !value->isAttachedToDocument()) { + if (!values.empty()) { values.push_back(value); subs.push_back(sub); } continue; } - auto linked = tryImport(owner->getDocument(),value,nameMap); - auto new_sub = tryImportSubName(value,sub.c_str(),owner->getDocument(),nameMap); - if(linked!=value || !new_sub.empty()) { - if(values.empty()) { + auto linked = tryImport(owner->getDocument(), value, nameMap); + auto new_sub = tryImportSubName(value, sub.c_str(), owner->getDocument(), nameMap); + if (linked != value || !new_sub.empty()) { + if (values.empty()) { values.reserve(_lValueList.size()); - values.insert(values.end(),_lValueList.begin(),itValue); + values.insert(values.end(), _lValueList.begin(), itValue); subs.reserve(_lSubList.size()); - subs.insert(subs.end(),_lSubList.begin(),itSub); + subs.insert(subs.end(), _lSubList.begin(), itSub); } values.push_back(linked); subs.push_back(std::move(new_sub)); - }else if(!values.empty()) { + } + else if (!values.empty()) { values.push_back(linked); subs.push_back(sub); } } - if(values.empty()) + if (values.empty()) { return nullptr; + } std::unique_ptr p(new PropertyLinkSubList); p->_lValueList = std::move(values); p->_lSubList = std::move(subs); return p.release(); } -Property *PropertyLinkSubList::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyLinkSubList::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) + if (!owner || !owner->getDocument()) { return nullptr; - std::vector values; + } + std::vector values; std::vector subs; auto itSub = _lSubList.begin(); - for(auto itValue=_lValueList.begin();itValue!=_lValueList.end();++itValue,++itSub) { + for (auto itValue = _lValueList.begin(); itValue != _lValueList.end(); ++itValue, ++itSub) { auto value = *itValue; - const auto &sub = *itSub; - if(!value || !value->isAttachedToDocument()) { - if(!values.empty()) { + const auto& sub = *itSub; + if (!value || !value->isAttachedToDocument()) { + if (!values.empty()) { values.push_back(value); subs.push_back(sub); } continue; } - auto new_sub = updateLabelReference(value,sub.c_str(),obj,ref,newLabel); - if(!new_sub.empty()) { - if(values.empty()) { + auto new_sub = updateLabelReference(value, sub.c_str(), obj, ref, newLabel); + if (!new_sub.empty()) { + if (values.empty()) { values.reserve(_lValueList.size()); - values.insert(values.end(),_lValueList.begin(),itValue); + values.insert(values.end(), _lValueList.begin(), itValue); subs.reserve(_lSubList.size()); - subs.insert(subs.end(),_lSubList.begin(),itSub); + subs.insert(subs.end(), _lSubList.begin(), itSub); } values.push_back(value); subs.push_back(std::move(new_sub)); - }else if(!values.empty()) { + } + else if (!values.empty()) { values.push_back(value); subs.push_back(sub); } } - if(values.empty()) + if (values.empty()) { return nullptr; + } std::unique_ptr p(new PropertyLinkSubList); p->_lValueList = std::move(values); p->_lSubList = std::move(subs); return p.release(); } -Property *PropertyLinkSubList::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLinkSubList::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - std::vector values; + std::vector values; std::vector subs; auto itSub = _lSubList.begin(); std::vector positions; - for(auto itValue=_lValueList.begin();itValue!=_lValueList.end();++itValue,++itSub) { + for (auto itValue = _lValueList.begin(); itValue != _lValueList.end(); ++itValue, ++itSub) { auto value = *itValue; - const auto &sub = *itSub; - if(!value || !value->isAttachedToDocument()) { - if(!values.empty()) { + const auto& sub = *itSub; + if (!value || !value->isAttachedToDocument()) { + if (!values.empty()) { values.push_back(value); subs.push_back(sub); } continue; } - auto res = tryReplaceLink(getContainer(),value,parent,oldObj,newObj,sub.c_str()); - if(res.first) { - if(values.empty()) { + auto res = tryReplaceLink(getContainer(), value, parent, oldObj, newObj, sub.c_str()); + if (res.first) { + if (values.empty()) { values.reserve(_lValueList.size()); - values.insert(values.end(),_lValueList.begin(),itValue); + values.insert(values.end(), _lValueList.begin(), itValue); subs.reserve(_lSubList.size()); - subs.insert(subs.end(),_lSubList.begin(),itSub); + subs.insert(subs.end(), _lSubList.begin(), itSub); } - if(res.first == newObj) { + if (res.first == newObj) { // check for duplication auto itS = subs.begin(); - for(auto itV=values.begin();itV!=values.end();) { - if(*itV == res.first && *itS == res.second) { + for (auto itV = values.begin(); itV != values.end();) { + if (*itV == res.first && *itS == res.second) { itV = values.erase(itV); itS = subs.erase(itS); - } else { + } + else { ++itV; ++itS; } @@ -2747,79 +3075,88 @@ Property *PropertyLinkSubList::CopyOnLinkReplace(const App::DocumentObject *pare } values.push_back(res.first); subs.push_back(std::move(res.second)); - }else if(!values.empty()) { + } + else if (!values.empty()) { bool duplicate = false; - if(value == newObj) { - for(auto pos : positions) { - if(sub == subs[pos]) { + if (value == newObj) { + for (auto pos : positions) { + if (sub == subs[pos]) { duplicate = true; break; } } } - if(!duplicate) { + if (!duplicate) { values.push_back(value); subs.push_back(sub); } } } - if(values.empty()) + if (values.empty()) { return nullptr; + } std::unique_ptr p(new PropertyLinkSubList); p->_lValueList = std::move(values); p->_lSubList = std::move(subs); return p.release(); } -Property *PropertyLinkSubList::Copy() const +Property* PropertyLinkSubList::Copy() const { - PropertyLinkSubList *p = new PropertyLinkSubList(); + PropertyLinkSubList* p = new PropertyLinkSubList(); p->_lValueList = _lValueList; - p->_lSubList = _lSubList; + p->_lSubList = _lSubList; p->_ShadowSubList = _ShadowSubList; return p; } -void PropertyLinkSubList::Paste(const Property &from) +void PropertyLinkSubList::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyLinkSubList::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLinkSubList::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); - auto &link = static_cast(from); - setValues(link._lValueList, link._lSubList, - std::vector(link._ShadowSubList)); + } + auto& link = static_cast(from); + setValues(link._lValueList, link._lSubList, std::vector(link._ShadowSubList)); } -unsigned int PropertyLinkSubList::getMemSize () const +unsigned int PropertyLinkSubList::getMemSize() const { - unsigned int size = static_cast(_lValueList.size() * sizeof(App::DocumentObject *)); - for(int i = 0;i(_lValueList.size() * sizeof(App::DocumentObject*)); + for (int i = 0; i < getSize(); i++) { + size += _lSubList[i].size(); + } + return size; } -std::vector PropertyLinkSubList::getSubValues(bool newStyle) const { +std::vector PropertyLinkSubList::getSubValues(bool newStyle) const +{ assert(_lSubList.size() == _ShadowSubList.size()); std::vector ret; ret.reserve(_ShadowSubList.size()); std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) - ret.push_back(getSubNameWithStyle(_lSubList[i],_ShadowSubList[i],newStyle,tmp)); + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + ret.push_back(getSubNameWithStyle(_lSubList[i], _ShadowSubList[i], newStyle, tmp)); + } return ret; } -void PropertyLinkSubList::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLinkSubList::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { - if(all||_pcScope!=LinkScope::Hidden) { - objs.reserve(objs.size()+_lValueList.size()); - for(auto obj : _lValueList) { - if(obj && obj->isAttachedToDocument()) + if (all || _pcScope != LinkScope::Hidden) { + objs.reserve(objs.size() + _lValueList.size()); + for (auto obj : _lValueList) { + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } - if(subs) { + if (subs) { auto _subs = getSubValues(newStyle); - subs->reserve(subs->size()+_subs.size()); - std::move(_subs.begin(),_subs.end(),std::back_inserter(*subs)); + subs->reserve(subs->size() + _subs.size()); + std::move(_subs.begin(), _subs.end(), std::back_inserter(*subs)); } } } @@ -2861,7 +3198,7 @@ void PropertyLinkSubList::getLinksTo(std::vector& identif const auto& shadow = _ShadowSubList[i]; App::SubObjectT sobjT(obj, shadow.newName.empty() ? shadow.oldName.c_str() - : shadow.newName.c_str()); + : shadow.newName.c_str()); if (sobjT.getSubObject() == subObject && sobjT.getOldElementName() == subElement) { identifiers.emplace_back(*this); continue; @@ -2870,62 +3207,70 @@ void PropertyLinkSubList::getLinksTo(std::vector& identif } } -void PropertyLinkSubList::breakLink(App::DocumentObject *obj, bool clear) { +void PropertyLinkSubList::breakLink(App::DocumentObject* obj, bool clear) +{ std::vector values; std::vector subs; - if(clear && getContainer()==obj) { - setValues(values,subs); + if (clear && getContainer() == obj) { + setValues(values, subs); return; } - assert(_lValueList.size()==_lSubList.size()); + assert(_lValueList.size() == _lSubList.size()); values.reserve(_lValueList.size()); subs.reserve(_lSubList.size()); - int i=-1; - for(auto o : _lValueList) { + int i = -1; + for (auto o : _lValueList) { ++i; - if(o==obj) + if (o == obj) { continue; + } values.push_back(o); subs.push_back(_lSubList[i]); } - if(values.size()!=_lValueList.size()) - setValues(values,subs); + if (values.size() != _lValueList.size()) { + setValues(values, subs); + } } -bool PropertyLinkSubList::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyLinkSubList::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; + } auto subs = _lSubList; auto links = _lValueList; int idx = -1; bool touched = false; - for(std::string &sub : subs) { + for (std::string& sub : subs) { ++idx; - auto &link = links[idx]; - if(!link || !link->isAttachedToDocument() || !inList.count(link)) + auto& link = links[idx]; + if (!link || !link->isAttachedToDocument() || !inList.count(link)) { continue; + } touched = true; size_t pos = sub.find('.'); - for(;pos!=std::string::npos;pos=sub.find('.',pos+1)) { - auto sobj = link->getSubObject(sub.substr(0,pos+1).c_str()); - if(!sobj || sobj->getDocument()!=link->getDocument()) { + for (; pos != std::string::npos; pos = sub.find('.', pos + 1)) { + auto sobj = link->getSubObject(sub.substr(0, pos + 1).c_str()); + if (!sobj || sobj->getDocument() != link->getDocument()) { pos = std::string::npos; break; } - if(!inList.count(sobj)) { + if (!inList.count(sobj)) { link = sobj; - sub = sub.substr(pos+1); + sub = sub.substr(pos + 1); break; } } - if(pos == std::string::npos) + if (pos == std::string::npos) { return false; + } + } + if (touched) { + setValues(links, subs); } - if(touched) - setValues(links,subs); return touched; } @@ -2942,8 +3287,7 @@ bool PropertyLinkSubList::adjustLink(const std::set &inLis using DocInfoMap = std::map; DocInfoMap _DocInfoMap; -class App::DocInfo : - public std::enable_shared_from_this +class App::DocInfo: public std::enable_shared_from_this { public: using Connection = boost::signals2::scoped_connection; @@ -2955,11 +3299,13 @@ public: DocInfoMap::iterator myPos; std::string myPath; - App::Document *pcDoc{nullptr}; + App::Document* pcDoc {nullptr}; std::set links; - static std::string getDocPath( - const char *filename, App::Document *pDoc, bool relative, QString *fullPath = nullptr) + static std::string getDocPath(const char* filename, + App::Document* pDoc, + bool relative, + QString* fullPath = nullptr) { bool absolute; // The path could be an URI, in that case @@ -2967,108 +3313,125 @@ public: QString path = QString::fromUtf8(filename); if (path.startsWith(QLatin1String("https://"))) { // We do have an URI - if (fullPath) + if (fullPath) { *fullPath = path; - return std::string(filename); + } + return std::string(filename); } // make sure the filename is absolute path path = QDir::cleanPath(path); - if((absolute = QFileInfo(path).isAbsolute())) { - if(fullPath) + if ((absolute = QFileInfo(path).isAbsolute())) { + if (fullPath) { *fullPath = path; - if(!relative) + } + if (!relative) { return std::string(path.toUtf8().constData()); + } } - const char *docPath = pDoc->getFileName(); - if(!docPath || *docPath==0) + const char* docPath = pDoc->getFileName(); + if (!docPath || *docPath == 0) { throw Base::RuntimeError("Owner document not saved"); + } QDir docDir(QFileInfo(QString::fromUtf8(docPath)).absoluteDir()); - if(!absolute) { + if (!absolute) { path = QDir::cleanPath(docDir.absoluteFilePath(path)); - if(fullPath) + if (fullPath) { *fullPath = path; + } } - if(relative) + if (relative) { return std::string(docDir.relativeFilePath(path).toUtf8().constData()); - else + } + else { return std::string(path.toUtf8().constData()); + } } - static DocInfoPtr get(const char *filename, - App::Document *pDoc,PropertyXLink *l, const char *objName) + static DocInfoPtr + get(const char* filename, App::Document* pDoc, PropertyXLink* l, const char* objName) { QString path; - l->filePath = getDocPath(filename,pDoc,true,&path); + l->filePath = getDocPath(filename, pDoc, true, &path); FC_LOG("finding doc " << filename); auto it = _DocInfoMap.find(path); DocInfoPtr info; - if(it != _DocInfoMap.end()) { + if (it != _DocInfoMap.end()) { info = it->second; - if(!info->pcDoc) { + if (!info->pcDoc) { QString fullpath(info->getFullPath()); - if(fullpath.size() && - App::GetApplication().addPendingDocument( - fullpath.toUtf8().constData(),objName, - l->testFlag(PropertyLinkBase::LinkAllowPartial))==0) - { - for(App::Document *doc : App::GetApplication().getDocuments()) { - if(getFullPath(doc->getFileName()) == fullpath) { + if (fullpath.size() + && App::GetApplication().addPendingDocument( + fullpath.toUtf8().constData(), + objName, + l->testFlag(PropertyLinkBase::LinkAllowPartial)) + == 0) { + for (App::Document* doc : App::GetApplication().getDocuments()) { + if (getFullPath(doc->getFileName()) == fullpath) { info->attach(doc); break; } } } } - } else { + } + else { info = std::make_shared(); - auto ret = _DocInfoMap.insert(std::make_pair(path,info)); - info->init(ret.first,objName,l); + auto ret = _DocInfoMap.insert(std::make_pair(path, info)); + info->init(ret.first, objName, l); } - if(info->pcDoc) { + if (info->pcDoc) { // make sure to attach only external object auto owner = Base::freecad_dynamic_cast(l->getContainer()); - if(owner && owner->getDocument() == info->pcDoc) + if (owner && owner->getDocument() == info->pcDoc) { return info; + } } info->links.insert(l); return info; } - static QString getFullPath(const char *p) { + static QString getFullPath(const char* p) + { QString path = QString::fromUtf8(p); - if (path.isEmpty()) + if (path.isEmpty()) { return path; + } - if (path.startsWith(QLatin1String("https://"))) + if (path.startsWith(QLatin1String("https://"))) { return path; + } else { return QFileInfo(path).absoluteFilePath(); } } - QString getFullPath() const { + QString getFullPath() const + { QString path = myPos->first; - if (path.startsWith(QLatin1String("https://"))) + if (path.startsWith(QLatin1String("https://"))) { return path; + } else { return QFileInfo(myPos->first).absoluteFilePath(); } } - const char *filePath() const { + const char* filePath() const + { return myPath.c_str(); } - void deinit() { - FC_LOG("deinit " << (pcDoc?pcDoc->getName():filePath())); + void deinit() + { + FC_LOG("deinit " << (pcDoc ? pcDoc->getName() : filePath())); assert(links.empty()); connFinishRestoreDocument.disconnect(); connPendingReloadDocument.disconnect(); @@ -3083,132 +3446,151 @@ public: pcDoc = nullptr; } - void init(DocInfoMap::iterator pos, const char *objName, PropertyXLink *l) { + void init(DocInfoMap::iterator pos, const char* objName, PropertyXLink* l) + { myPos = pos; myPath = myPos->first.toUtf8().constData(); - App::Application &app = App::GetApplication(); - //NOLINTBEGIN + App::Application& app = App::GetApplication(); + // NOLINTBEGIN connFinishRestoreDocument = app.signalFinishRestoreDocument.connect( - std::bind(&DocInfo::slotFinishRestoreDocument,this,sp::_1)); + std::bind(&DocInfo::slotFinishRestoreDocument, this, sp::_1)); connPendingReloadDocument = app.signalPendingReloadDocument.connect( - std::bind(&DocInfo::slotFinishRestoreDocument,this,sp::_1)); - connDeleteDocument = app.signalDeleteDocument.connect( - std::bind(&DocInfo::slotDeleteDocument,this,sp::_1)); - connSaveDocument = app.signalSaveDocument.connect( - std::bind(&DocInfo::slotSaveDocument,this,sp::_1)); - //NOLINTEND + std::bind(&DocInfo::slotFinishRestoreDocument, this, sp::_1)); + connDeleteDocument = + app.signalDeleteDocument.connect(std::bind(&DocInfo::slotDeleteDocument, this, sp::_1)); + connSaveDocument = + app.signalSaveDocument.connect(std::bind(&DocInfo::slotSaveDocument, this, sp::_1)); + // NOLINTEND QString fullpath(getFullPath()); - if(fullpath.isEmpty()) + if (fullpath.isEmpty()) { FC_ERR("document not found " << filePath()); - else{ - for(App::Document *doc : App::GetApplication().getDocuments()) { - if(getFullPath(doc->getFileName()) == fullpath) { - if(doc->testStatus(App::Document::PartialDoc) && !doc->getObject(objName)) + } + else { + for (App::Document* doc : App::GetApplication().getDocuments()) { + if (getFullPath(doc->getFileName()) == fullpath) { + if (doc->testStatus(App::Document::PartialDoc) && !doc->getObject(objName)) { break; + } attach(doc); return; } } FC_LOG("document pending " << filePath()); - app.addPendingDocument(fullpath.toUtf8().constData(),objName, - l->testFlag(PropertyLinkBase::LinkAllowPartial)); + app.addPendingDocument(fullpath.toUtf8().constData(), + objName, + l->testFlag(PropertyLinkBase::LinkAllowPartial)); } } - void attach(Document *doc) { + void attach(Document* doc) + { assert(!pcDoc); pcDoc = doc; FC_LOG("attaching " << doc->getName() << ", " << doc->getFileName()); - std::map > parentLinks; - for(auto it=links.begin(),itNext=it;it!=links.end();it=itNext) { + std::map> parentLinks; + for (auto it = links.begin(), itNext = it; it != links.end(); it = itNext) { ++itNext; auto link = *it; - if(link->_pcLink) + if (link->_pcLink) { continue; - if(link->parentProp) { + } + if (link->parentProp) { parentLinks[link->parentProp].push_back(link); continue; } auto obj = doc->getObject(link->objectName.c_str()); - if(obj) + if (obj) { link->restoreLink(obj); + } else if (doc->testStatus(App::Document::PartialDoc)) { - App::GetApplication().addPendingDocument( - doc->FileName.getValue(), - link->objectName.c_str(), - false); + App::GetApplication().addPendingDocument(doc->FileName.getValue(), + link->objectName.c_str(), + false); FC_WARN("reloading partial document '" << doc->FileName.getValue() - << "' due to object " << link->objectName); - } else + << "' due to object " << link->objectName); + } + else { FC_WARN("object '" << link->objectName << "' not found in document '" - << doc->getName() << "'"); + << doc->getName() << "'"); + } } - for(auto &v : parentLinks) { + for (auto& v : parentLinks) { v.first->setFlag(PropertyLinkBase::LinkRestoring); v.first->aboutToSetValue(); - for(auto link : v.second) { + for (auto link : v.second) { auto obj = doc->getObject(link->objectName.c_str()); - if(obj) + if (obj) { link->restoreLink(obj); + } else if (doc->testStatus(App::Document::PartialDoc)) { - App::GetApplication().addPendingDocument( - doc->FileName.getValue(), - link->objectName.c_str(), - false); - FC_WARN("reloading partial document '" << doc->FileName.getValue() - << "' due to object " << link->objectName); - } else + App::GetApplication().addPendingDocument(doc->FileName.getValue(), + link->objectName.c_str(), + false); + FC_WARN("reloading partial document '" + << doc->FileName.getValue() << "' due to object " << link->objectName); + } + else { FC_WARN("object '" << link->objectName << "' not found in document '" - << doc->getName() << "'"); + << doc->getName() << "'"); + } } v.first->hasSetValue(); - v.first->setFlag(PropertyLinkBase::LinkRestoring,false); + v.first->setFlag(PropertyLinkBase::LinkRestoring, false); } } - void remove(PropertyXLink *l) { + void remove(PropertyXLink* l) + { auto it = links.find(l); - if(it != links.end()) { + if (it != links.end()) { links.erase(it); - if(links.empty()) + if (links.empty()) { deinit(); + } } } - static void restoreDocument(const App::Document &doc) { + static void restoreDocument(const App::Document& doc) + { auto it = _DocInfoMap.find(getFullPath(doc.FileName.getValue())); - if(it==_DocInfoMap.end()) + if (it == _DocInfoMap.end()) { return; + } it->second->slotFinishRestoreDocument(doc); } - void slotFinishRestoreDocument(const App::Document &doc) { - if(pcDoc) + void slotFinishRestoreDocument(const App::Document& doc) + { + if (pcDoc) { return; + } QString fullpath(getFullPath()); - if(!fullpath.isEmpty() && getFullPath(doc.getFileName())==fullpath) + if (!fullpath.isEmpty() && getFullPath(doc.getFileName()) == fullpath) { attach(const_cast(&doc)); + } } - void slotSaveDocument(const App::Document &doc) { - if(!pcDoc) { + void slotSaveDocument(const App::Document& doc) + { + if (!pcDoc) { slotFinishRestoreDocument(doc); return; } - if(&doc!=pcDoc) + if (&doc != pcDoc) { return; + } QFileInfo info(myPos->first); QString path(info.absoluteFilePath()); - const char *filename = doc.getFileName(); + const char* filename = doc.getFileName(); QString docPath(getFullPath(filename)); - if(path.isEmpty() || path!=docPath) { + if (path.isEmpty() || path != docPath) { FC_LOG("document '" << doc.getName() << "' path changed"); auto me = shared_from_this(); - auto ret = _DocInfoMap.insert(std::make_pair(docPath,me)); - if(!ret.second) { + auto ret = _DocInfoMap.insert(std::make_pair(docPath, me)); + if (!ret.second) { // is that even possible? FC_WARN("document '" << doc.getName() << "' path exists, detach"); slotDeleteDocument(doc); @@ -3217,35 +3599,36 @@ public: _DocInfoMap.erase(myPos); myPos = ret.first; - std::set tmp; + std::set tmp; tmp.swap(links); - for(auto link : tmp) { + for (auto link : tmp) { auto owner = static_cast(link->getContainer()); // adjust file path for each PropertyXLink - DocInfo::get(filename,owner->getDocument(),link,link->objectName.c_str()); + DocInfo::get(filename, owner->getDocument(), link, link->objectName.c_str()); } } // time stamp changed, touch the linking document. std::set docs; - for(auto link : links) { + for (auto link : links) { auto linkdoc = static_cast(link->getContainer())->getDocument(); auto ret = docs.insert(linkdoc); - if(ret.second) { + if (ret.second) { // This will signal the Gui::Document to call setModified(); - FC_LOG("touch document " << linkdoc->getName() - << " on time stamp change of " << link->getFullName()); + FC_LOG("touch document " << linkdoc->getName() << " on time stamp change of " + << link->getFullName()); linkdoc->Comment.touch(); } } } - void slotDeleteDocument(const App::Document &doc) { - for(auto it=links.begin(),itNext=it;it!=links.end();it=itNext) { + void slotDeleteDocument(const App::Document& doc) + { + for (auto it = links.begin(), itNext = it; it != links.end(); it = itNext) { ++itNext; auto link = *it; auto obj = dynamic_cast(link->getContainer()); - if(obj && obj->getDocument() == &doc) { + if (obj && obj->getDocument() == &doc) { links.erase(it); // must call unlink here, so that PropertyLink::resetLink can // remove back link before the owner object is marked as being @@ -3253,102 +3636,119 @@ public: link->unlink(); } } - if(links.empty()) { + if (links.empty()) { deinit(); return; } - if(pcDoc!=&doc) + if (pcDoc != &doc) { return; - std::map > parentLinks; - for(auto link : links) { - link->setFlag(PropertyLinkBase::LinkDetached); - if(link->parentProp) - parentLinks[link->parentProp].push_back(link); - else - parentLinks[nullptr].push_back(link); } - for(auto &v : parentLinks) { - if(v.first) { + std::map> parentLinks; + for (auto link : links) { + link->setFlag(PropertyLinkBase::LinkDetached); + if (link->parentProp) { + parentLinks[link->parentProp].push_back(link); + } + else { + parentLinks[nullptr].push_back(link); + } + } + for (auto& v : parentLinks) { + if (v.first) { v.first->setFlag(PropertyLinkBase::LinkDetached); v.first->aboutToSetValue(); } - for(auto l : v.second) + for (auto l : v.second) { l->detach(); - if(v.first) { + } + if (v.first) { v.first->hasSetValue(); - v.first->setFlag(PropertyLinkBase::LinkDetached,false); + v.first->setFlag(PropertyLinkBase::LinkDetached, false); } } pcDoc = nullptr; } - bool hasXLink(const App::Document *doc) const{ - for(auto link : links) { + bool hasXLink(const App::Document* doc) const + { + for (auto link : links) { auto obj = dynamic_cast(link->getContainer()); - if(obj && obj->getDocument() == doc) + if (obj && obj->getDocument() == doc) { return true; + } } return false; } - static void breakLinks(App::DocumentObject *obj, bool clear) { + static void breakLinks(App::DocumentObject* obj, bool clear) + { auto doc = obj->getDocument(); - for(auto itD=_DocInfoMap.begin(),itDNext=itD;itD!=_DocInfoMap.end();itD=itDNext) { + for (auto itD = _DocInfoMap.begin(), itDNext = itD; itD != _DocInfoMap.end(); + itD = itDNext) { ++itDNext; auto docInfo = itD->second; - if(docInfo->pcDoc != doc) + if (docInfo->pcDoc != doc) { continue; - auto &links = docInfo->links; + } + auto& links = docInfo->links; std::set parentLinks; - for(auto it=links.begin(),itNext=it;it!=links.end();it=itNext) { + for (auto it = links.begin(), itNext = it; it != links.end(); it = itNext) { ++itNext; auto link = *it; - if(link->_pcLink!=obj && !(clear && link->getContainer()==obj)) + if (link->_pcLink != obj && !(clear && link->getContainer() == obj)) { continue; - if(link->parentProp) + } + if (link->parentProp) { parentLinks.insert(link->parentProp); - else - link->breakLink(obj,clear); + } + else { + link->breakLink(obj, clear); + } + } + for (auto link : parentLinks) { + link->breakLink(obj, clear); } - for(auto link : parentLinks) - link->breakLink(obj,clear); } } }; -void PropertyLinkBase::breakLinks(App::DocumentObject *link, - const std::vector &objs, bool clear) +void PropertyLinkBase::breakLinks(App::DocumentObject* link, + const std::vector& objs, + bool clear) { std::vector props; - for(auto obj : objs) { + for (auto obj : objs) { props.clear(); obj->getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { auto linkProp = dynamic_cast(prop); - if(linkProp) - linkProp->breakLink(link,clear); + if (linkProp) { + linkProp->breakLink(link, clear); + } } } - DocInfo::breakLinks(link,clear); + DocInfo::breakLinks(link, clear); } //************************************************************************** // PropertyXLink //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLink , App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyXLink, App::PropertyLink) -PropertyXLink::PropertyXLink(bool _allowPartial, PropertyLinkBase *parent) - :parentProp(parent) +PropertyXLink::PropertyXLink(bool _allowPartial, PropertyLinkBase* parent) + : parentProp(parent) { setAllowPartial(_allowPartial); setAllowExternal(true); setSyncSubObject(true); - if(parent) + if (parent) { setContainer(parent->getContainer()); + } } -PropertyXLink::~PropertyXLink() { +PropertyXLink::~PropertyXLink() +{ unlink(); } @@ -3357,8 +3757,9 @@ void PropertyXLink::setSyncSubObject(bool enable) _Flags.set((std::size_t)LinkSyncSubObject, enable); } -void PropertyXLink::unlink() { - if(docInfo) { +void PropertyXLink::unlink() +{ + if (docInfo) { docInfo->remove(this); docInfo.reset(); } @@ -3366,8 +3767,9 @@ void PropertyXLink::unlink() { resetLink(); } -void PropertyXLink::detach() { - if(docInfo && _pcLink) { +void PropertyXLink::detach() +{ + if (docInfo && _pcLink) { aboutToSetValue(); resetLink(); updateElementReference(nullptr); @@ -3375,214 +3777,245 @@ void PropertyXLink::detach() { } } -void PropertyXLink::aboutToSetValue() { - if(parentProp) +void PropertyXLink::aboutToSetValue() +{ + if (parentProp) { parentProp->aboutToSetChildValue(*this); - else + } + else { PropertyLinkBase::aboutToSetValue(); + } } -void PropertyXLink::hasSetValue() { - if(parentProp) +void PropertyXLink::hasSetValue() +{ + if (parentProp) { parentProp->hasSetChildValue(*this); - else + } + else { PropertyLinkBase::hasSetValue(); + } } -void PropertyXLink::setSubName(const char *subname) +void PropertyXLink::setSubName(const char* subname) { std::vector subs; - if(subname && subname[0]) + if (subname && subname[0]) { subs.emplace_back(subname); + } aboutToSetValue(); setSubValues(std::move(subs)); hasSetValue(); } -void PropertyXLink::setSubValues(std::vector &&subs, - std::vector &&shadows) +void PropertyXLink::setSubValues(std::vector&& subs, std::vector&& shadows) { _SubList = std::move(subs); _ShadowSubList.clear(); - if(shadows.size() == _SubList.size()) { + if (shadows.size() == _SubList.size()) { _ShadowSubList = std::move(shadows); - onContainerRestored(); // re-register element references - } else + onContainerRestored(); // re-register element references + } + else { updateElementReference(nullptr); + } checkLabelReferences(_SubList); } -void PropertyXLink::setValue(App::DocumentObject * lValue) { - setValue(lValue,nullptr); +void PropertyXLink::setValue(App::DocumentObject* lValue) +{ + setValue(lValue, nullptr); } -void PropertyXLink::setValue(App::DocumentObject * lValue, const char *subname) +void PropertyXLink::setValue(App::DocumentObject* lValue, const char* subname) { std::vector subs; - if(subname && subname[0]) + if (subname && subname[0]) { subs.emplace_back(subname); - setValue(lValue,std::move(subs)); + } + setValue(lValue, std::move(subs)); } -void PropertyXLink::restoreLink(App::DocumentObject *lValue) { +void PropertyXLink::restoreLink(App::DocumentObject* lValue) +{ assert(!_pcLink && lValue && docInfo); auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { throw Base::RuntimeError("invalid container"); + } bool touched = owner->isTouched(); - setFlag(LinkDetached,false); + setFlag(LinkDetached, false); setFlag(LinkRestoring); aboutToSetValue(); #ifndef USE_OLD_DAG - if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) + if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { lValue->_addBackLink(owner); + } #endif - _pcLink=lValue; + _pcLink = lValue; updateElementReference(nullptr); hasSetValue(); - setFlag(LinkRestoring,false); + setFlag(LinkRestoring, false); - if(!touched && - owner->isTouched() && - docInfo && - docInfo->pcDoc && - stamp==docInfo->pcDoc->LastModifiedDate.getValue()) - { + if (!touched && owner->isTouched() && docInfo && docInfo->pcDoc + && stamp == docInfo->pcDoc->LastModifiedDate.getValue()) { owner->purgeTouched(); } } -void PropertyXLink::setValue(App::DocumentObject *lValue, - std::vector &&subs, std::vector &&shadows) +void PropertyXLink::setValue(App::DocumentObject* lValue, + std::vector&& subs, + std::vector&& shadows) { - if(_pcLink==lValue && _SubList==subs) - return; - - if(lValue && (!lValue->isAttachedToDocument() || !lValue->getDocument())) { - throw Base::ValueError("Invalid object"); + if (_pcLink == lValue && _SubList == subs) { return; } - auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) - throw Base::RuntimeError("invalid container"); + if (lValue && (!lValue->isAttachedToDocument() || !lValue->getDocument())) { + throw Base::ValueError("Invalid object"); + } - if(lValue == owner) + auto owner = dynamic_cast(getContainer()); + if (!owner || !owner->isAttachedToDocument()) { + throw Base::RuntimeError("invalid container"); + } + + if (lValue == owner) { throw Base::ValueError("self linking"); + } aboutToSetValue(); DocInfoPtr info; - const char *name = ""; - if(lValue) { + const char* name = ""; + if (lValue) { name = lValue->getNameInDocument(); - if(lValue->getDocument() != owner->getDocument()) { - if(!docInfo || lValue->getDocument()!=docInfo->pcDoc) - { - const char *filename = lValue->getDocument()->getFileName(); - if(!filename || *filename==0) + if (lValue->getDocument() != owner->getDocument()) { + if (!docInfo || lValue->getDocument() != docInfo->pcDoc) { + const char* filename = lValue->getDocument()->getFileName(); + if (!filename || *filename == 0) { throw Base::RuntimeError("Linked document not saved"); + } FC_LOG("xlink set to new document " << lValue->getDocument()->getName()); - info = DocInfo::get(filename,owner->getDocument(),this,name); + info = DocInfo::get(filename, owner->getDocument(), this, name); assert(info && info->pcDoc == lValue->getDocument()); - }else + } + else { info = docInfo; + } } } - setFlag(LinkDetached,false); + setFlag(LinkDetached, false); #ifndef USE_OLD_DAG - if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - if(_pcLink) + if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + if (_pcLink) { _pcLink->_removeBackLink(owner); - if(lValue) + } + if (lValue) { lValue->_addBackLink(owner); + } } #endif - if(docInfo!=info) { + if (docInfo != info) { unlink(); docInfo = info; } - if(!docInfo) + if (!docInfo) { filePath.clear(); - _pcLink=lValue; - if(docInfo && docInfo->pcDoc) - stamp=docInfo->pcDoc->LastModifiedDate.getValue(); + } + _pcLink = lValue; + if (docInfo && docInfo->pcDoc) { + stamp = docInfo->pcDoc->LastModifiedDate.getValue(); + } objectName = name; - setSubValues(std::move(subs),std::move(shadows)); + setSubValues(std::move(subs), std::move(shadows)); hasSetValue(); } -void PropertyXLink::setValue(std::string &&filename, std::string &&name, - std::vector &&subs, std::vector &&shadows) +void PropertyXLink::setValue(std::string&& filename, + std::string&& name, + std::vector&& subs, + std::vector&& shadows) { - if(name.empty()) { - setValue(nullptr,std::move(subs),std::move(shadows)); + if (name.empty()) { + setValue(nullptr, std::move(subs), std::move(shadows)); return; } auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { throw Base::RuntimeError("invalid container"); + } - DocumentObject *pObject=nullptr; + DocumentObject* pObject = nullptr; DocInfoPtr info; - if(!filename.empty()) { + if (!filename.empty()) { owner->getDocument()->signalLinkXsetValue(filename); - info = DocInfo::get(filename.c_str(),owner->getDocument(),this,name.c_str()); - if(info->pcDoc) + info = DocInfo::get(filename.c_str(), owner->getDocument(), this, name.c_str()); + if (info->pcDoc) { pObject = info->pcDoc->getObject(name.c_str()); - }else + } + } + else { pObject = owner->getDocument()->getObject(name.c_str()); + } - if(pObject) { - setValue(pObject,std::move(subs),std::move(shadows)); + if (pObject) { + setValue(pObject, std::move(subs), std::move(shadows)); return; } - setFlag(LinkDetached,false); + setFlag(LinkDetached, false); aboutToSetValue(); #ifndef USE_OLD_DAG - if (_pcLink && !owner->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) + if (_pcLink && !owner->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { _pcLink->_removeBackLink(owner); + } #endif _pcLink = nullptr; - if(docInfo!=info) { + if (docInfo != info) { unlink(); docInfo = info; } - if(!docInfo) + if (!docInfo) { filePath.clear(); - if(docInfo && docInfo->pcDoc) - stamp=docInfo->pcDoc->LastModifiedDate.getValue(); + } + if (docInfo && docInfo->pcDoc) { + stamp = docInfo->pcDoc->LastModifiedDate.getValue(); + } objectName = std::move(name); - setSubValues(std::move(subs),std::move(shadows)); + setSubValues(std::move(subs), std::move(shadows)); hasSetValue(); } -void PropertyXLink::setValue(App::DocumentObject *link, - const std::vector &subs, std::vector &&shadows) +void PropertyXLink::setValue(App::DocumentObject* link, + const std::vector& subs, + std::vector&& shadows) { - setValue(link,std::vector(subs),std::move(shadows)); + setValue(link, std::vector(subs), std::move(shadows)); } -App::Document *PropertyXLink::getDocument() const { - return docInfo?docInfo->pcDoc:nullptr; +App::Document* PropertyXLink::getDocument() const +{ + return docInfo ? docInfo->pcDoc : nullptr; } -const char *PropertyXLink::getDocumentPath() const { - return docInfo?docInfo->filePath():filePath.c_str(); +const char* PropertyXLink::getDocumentPath() const +{ + return docInfo ? docInfo->filePath() : filePath.c_str(); } -const char *PropertyXLink::getObjectName() const { +const char* PropertyXLink::getObjectName() const +{ return objectName.c_str(); } -bool PropertyXLink::upgrade(Base::XMLReader &reader, const char *typeName) { - if(strcmp(typeName,App::PropertyLinkGlobal::getClassTypeId().getName())==0 || - strcmp(typeName,App::PropertyLink::getClassTypeId().getName())==0 || - strcmp(typeName,App::PropertyLinkChild::getClassTypeId().getName())==0) - { +bool PropertyXLink::upgrade(Base::XMLReader& reader, const char* typeName) +{ + if (strcmp(typeName, App::PropertyLinkGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, App::PropertyLink::getClassTypeId().getName()) == 0 + || strcmp(typeName, App::PropertyLinkChild::getClassTypeId().getName()) == 0) { PropertyLink::Restore(reader); return true; } @@ -3590,209 +4023,256 @@ bool PropertyXLink::upgrade(Base::XMLReader &reader, const char *typeName) { return false; } -int PropertyXLink::checkRestore(std::string *msg) const { - if(!docInfo) { - if(!_pcLink && !objectName.empty()) { +int PropertyXLink::checkRestore(std::string* msg) const +{ + if (!docInfo) { + if (!_pcLink && !objectName.empty()) { // this condition means linked object not found - if(msg) { + if (msg) { std::ostringstream ss; ss << "Link not restored" << std::endl; ss << "Object: " << objectName; - if(!filePath.empty()) + if (!filePath.empty()) { ss << std::endl << "File: " << filePath; + } *msg = ss.str(); } return 2; } return 0; } - if(!_pcLink) { - if (testFlag(LinkSilentRestore)) - return 0; - if(testFlag(LinkAllowPartial) && - (!docInfo->pcDoc || - docInfo->pcDoc->testStatus(App::Document::PartialDoc))) - { + if (!_pcLink) { + if (testFlag(LinkSilentRestore)) { return 0; } - if(msg) { + if (testFlag(LinkAllowPartial) + && (!docInfo->pcDoc || docInfo->pcDoc->testStatus(App::Document::PartialDoc))) { + return 0; + } + if (msg) { std::ostringstream ss; ss << "Link not restored" << std::endl; ss << "Linked object: " << objectName; - if(docInfo->pcDoc) + if (docInfo->pcDoc) { ss << std::endl << "Linked document: " << docInfo->pcDoc->Label.getValue(); - else if(!filePath.empty()) + } + else if (!filePath.empty()) { ss << std::endl << "Linked file: " << filePath; + } *msg = ss.str(); } return 2; } - if(!docInfo->pcDoc || stamp==docInfo->pcDoc->LastModifiedDate.getValue()) + if (!docInfo->pcDoc || stamp == docInfo->pcDoc->LastModifiedDate.getValue()) { return 0; + } - if(msg) { + if (msg) { std::ostringstream ss; - ss << "Time stamp changed on link " - << _pcLink->getFullName(); + ss << "Time stamp changed on link " << _pcLink->getFullName(); *msg = ss.str(); } return 1; } -void PropertyXLink::afterRestore() { +void PropertyXLink::afterRestore() +{ assert(_SubList.size() == _ShadowSubList.size()); - if(!testFlag(LinkRestoreLabel) || !_pcLink || !_pcLink->isAttachedToDocument()) + if (!testFlag(LinkRestoreLabel) || !_pcLink || !_pcLink->isAttachedToDocument()) { return; - setFlag(LinkRestoreLabel,false); - for(size_t i=0;i<_SubList.size();++i) - restoreLabelReference(_pcLink,_SubList[i],&_ShadowSubList[i]); + } + setFlag(LinkRestoreLabel, false); + for (size_t i = 0; i < _SubList.size(); ++i) { + restoreLabelReference(_pcLink, _SubList[i], &_ShadowSubList[i]); + } } -void PropertyXLink::onContainerRestored() { - if(!_pcLink || !_pcLink->isAttachedToDocument()) +void PropertyXLink::onContainerRestored() +{ + if (!_pcLink || !_pcLink->isAttachedToDocument()) { return; - for(size_t i=0;i<_SubList.size();++i) - _registerElementReference(_pcLink,_SubList[i],_ShadowSubList[i]); + } + for (size_t i = 0; i < _SubList.size(); ++i) { + _registerElementReference(_pcLink, _SubList[i], _ShadowSubList[i]); + } } -void PropertyXLink::updateElementReference(DocumentObject *feature,bool reverse,bool notify) { - if(!updateLinkReference(this,feature,reverse,notify,_pcLink,_SubList,_mapped,_ShadowSubList)) +void PropertyXLink::updateElementReference(DocumentObject* feature, bool reverse, bool notify) +{ + if (!updateLinkReference(this, + feature, + reverse, + notify, + _pcLink, + _SubList, + _mapped, + _ShadowSubList)) { return; - if(notify) + } + if (notify) { hasSetValue(); + } } -bool PropertyXLink::referenceChanged() const{ +bool PropertyXLink::referenceChanged() const +{ return !_mapped.empty(); } -void PropertyXLink::Save (Base::Writer &writer) const { - auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) +void PropertyXLink::Save(Base::Writer& writer) const +{ + auto owner = dynamic_cast(getContainer()); + if (!owner || !owner->getDocument()) { return; + } assert(_SubList.size() == _ShadowSubList.size()); auto exporting = owner->isExporting(); - if(_pcLink && exporting && _pcLink->isExporting()) { + if (_pcLink && exporting && _pcLink->isExporting()) { // this means, we are exporting the owner and the linked object together. // Lets save the export name writer.Stream() << writer.ind() << "getExportName(); - }else { - const char *path = filePath.c_str(); + } + else { + const char* path = filePath.c_str(); std::string _path; - if(exporting) { + if (exporting) { // Here means we are exporting the owner but not exporting the // linked object. Try to use absolute file path for easy transition // into document at different directory - if(docInfo) + if (docInfo) { _path = docInfo->filePath(); + } else { auto pDoc = owner->getDocument(); - const char *docPath = pDoc->getFileName(); - if(docPath && docPath[0]) { - if(!filePath.empty()) - _path = DocInfo::getDocPath(filePath.c_str(),pDoc,false); - else + const char* docPath = pDoc->getFileName(); + if (docPath && docPath[0]) { + if (!filePath.empty()) { + _path = DocInfo::getDocPath(filePath.c_str(), pDoc, false); + } + else { _path = docPath; - }else + } + } + else { FC_WARN("PropertyXLink export without saving the document"); + } } - if(!_path.empty()) + if (!_path.empty()) { path = _path.c_str(); + } } - writer.Stream() << writer.ind() - << "pcDoc?docInfo->pcDoc->LastModifiedDate.getValue():"") - << "\" name=\"" << objectName; - + writer.Stream() << writer.ind() << "pcDoc ? docInfo->pcDoc->LastModifiedDate.getValue() + : "") + << "\" name=\"" << objectName; } - if(testFlag(LinkAllowPartial)) + if (testFlag(LinkAllowPartial)) { writer.Stream() << "\" partial=\"1"; + } - if(_SubList.empty()) { + if (_SubList.empty()) { writer.Stream() << "\"/>" << std::endl; - } else if(_SubList.size() == 1) { - const auto &subName = _SubList[0]; - const auto &shadowSub = _ShadowSubList[0]; - const auto &sub = shadowSub.oldName.empty()?subName:shadowSub.oldName; - if(exporting) { + } + else if (_SubList.size() == 1) { + const auto& subName = _SubList[0]; + const auto& shadowSub = _ShadowSubList[0]; + const auto& sub = shadowSub.oldName.empty() ? subName : shadowSub.oldName; + if (exporting) { std::string exportName; - writer.Stream() << "\" sub=\"" << - encodeAttribute(exportSubName(exportName,_pcLink,sub.c_str())); - if(!shadowSub.oldName.empty() && shadowSub.newName==subName) + writer.Stream() << "\" sub=\"" + << encodeAttribute(exportSubName(exportName, _pcLink, sub.c_str())); + if (!shadowSub.oldName.empty() && shadowSub.newName == subName) { writer.Stream() << "\" " ATTR_MAPPED "=\"1"; - }else{ + } + } + else { writer.Stream() << "\" sub=\"" << encodeAttribute(sub); - if(!sub.empty()) { - if(sub!=subName) + if (!sub.empty()) { + if (sub != subName) { writer.Stream() << "\" " ATTR_SHADOWED "=\"" << encodeAttribute(subName); - else if(!shadowSub.newName.empty()) - writer.Stream() << "\" " ATTR_SHADOW "=\"" << encodeAttribute(shadowSub.newName); + } + else if (!shadowSub.newName.empty()) { + writer.Stream() + << "\" " ATTR_SHADOW "=\"" << encodeAttribute(shadowSub.newName); + } } } writer.Stream() << "\"/>" << std::endl; - }else { - writer.Stream() <<"\" count=\"" << _SubList.size() << "\">" << std::endl; + } + else { + writer.Stream() << "\" count=\"" << _SubList.size() << "\">" << std::endl; writer.incInd(); - for(unsigned int i = 0;i<_SubList.size(); i++) { - const auto &shadow = _ShadowSubList[i]; + for (unsigned int i = 0; i < _SubList.size(); i++) { + const auto& shadow = _ShadowSubList[i]; // shadow.oldName stores the old style element name. For backward // compatibility reason, we shall store the old name into attribute // 'value' whenever possible. - const auto &sub = shadow.oldName.empty()?_SubList[i]:shadow.oldName; + const auto& sub = shadow.oldName.empty() ? _SubList[i] : shadow.oldName; writer.Stream() << writer.ind() << "" << endl; + else { + writer.Stream() << encodeAttribute(sub); + if (!_SubList[i].empty()) { + if (sub != _SubList[i]) { + writer.Stream() + << "\" " ATTR_SHADOWED "=\"" << encodeAttribute(_SubList[i]); + } + else if (!shadow.newName.empty()) { + writer.Stream() + << "\" " ATTR_SHADOW "=\"" << encodeAttribute(shadow.newName); + } + } + } + writer.Stream() << "\"/>" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } } -void PropertyXLink::Restore(Base::XMLReader &reader) +void PropertyXLink::Restore(Base::XMLReader& reader) { // read my element reader.readElement("XLink"); - std::string stampAttr,file; - if(reader.hasAttribute("stamp")) + std::string stampAttr, file; + if (reader.hasAttribute("stamp")) { stampAttr = reader.getAttribute("stamp"); - if(reader.hasAttribute("file")) + } + if (reader.hasAttribute("file")) { file = reader.getAttribute("file"); + } setFlag(LinkAllowPartial, - reader.hasAttribute("partial") && - reader.getAttributeAsInteger("partial")); + reader.hasAttribute("partial") && reader.getAttributeAsInteger("partial")); std::string name; - if(file.empty()) + if (file.empty()) { name = reader.getName(reader.getAttribute("name")); - else + } + else { name = reader.getAttribute("name"); + } assert(getContainer()->isDerivedFrom()); - DocumentObject *object = nullptr; - if(!name.empty() && file.empty()) { + DocumentObject* object = nullptr; + if (!name.empty() && file.empty()) { DocumentObject* parent = static_cast(getContainer()); - Document *document = parent->getDocument(); + Document* document = parent->getDocument(); object = document ? document->getObject(name.c_str()) : nullptr; - if(!object) { - if(reader.isVerbose()) { - FC_WARN("Lost link to '" << name << "' while loading, maybe " - "an object was not loaded correctly"); + if (!object) { + if (reader.isVerbose()) { + FC_WARN("Lost link to '" << name + << "' while loading, maybe " + "an object was not loaded correctly"); } } } @@ -3801,117 +4281,139 @@ void PropertyXLink::Restore(Base::XMLReader &reader) std::vector shadows; std::vector mapped; bool restoreLabel = false; - if(reader.hasAttribute("sub")) { - if(reader.hasAttribute(ATTR_MAPPED)) + if (reader.hasAttribute("sub")) { + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(0); + } subs.emplace_back(); - auto &subname = subs.back(); + auto& subname = subs.back(); shadows.emplace_back(); - auto &shadow = shadows.back(); - shadow.oldName = importSubName(reader,reader.getAttribute("sub"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) - subname = shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); + auto& shadow = shadows.back(); + shadow.oldName = importSubName(reader, reader.getAttribute("sub"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { + subname = shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); + } else { subname = shadow.oldName; - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } } - }else if(reader.hasAttribute("count")) { + } + else if (reader.hasAttribute("count")) { int count = reader.getAttributeAsInteger("count"); subs.resize(count); shadows.resize(count); for (int i = 0; i < count; i++) { reader.readElement("Sub"); - shadows[i].oldName = importSubName(reader,reader.getAttribute("value"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) + shadows[i].oldName = importSubName(reader, reader.getAttribute("value"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { subs[i] = shadows[i].newName = - importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); + } else { subs[i] = shadows[i].oldName; - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadows[i].newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadows[i].newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } } - if(reader.hasAttribute(ATTR_MAPPED)) + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(i); + } } reader.readEndElement("XLink"); } - setFlag(LinkRestoreLabel,restoreLabel); + setFlag(LinkRestoreLabel, restoreLabel); if (name.empty()) { setValue(nullptr); return; } - if(!file.empty() || (!object && !name.empty())) { + if (!file.empty() || (!object && !name.empty())) { this->stamp = stampAttr; - setValue(std::move(file),std::move(name),std::move(subs),std::move(shadows)); - }else - setValue(object,std::move(subs),std::move(shadows)); + setValue(std::move(file), std::move(name), std::move(subs), std::move(shadows)); + } + else { + setValue(object, std::move(subs), std::move(shadows)); + } _mapped = std::move(mapped); } -Property *PropertyXLink::CopyOnImportExternal( - const std::map &nameMap) const +Property* +PropertyXLink::CopyOnImportExternal(const std::map& nameMap) const { auto owner = Base::freecad_dynamic_cast(getContainer()); - if(!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) + if (!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) { return nullptr; + } - auto subs = updateLinkSubs(_pcLink,_SubList, - &tryImportSubName,owner->getDocument(),nameMap); - auto linked = tryImport(owner->getDocument(),_pcLink,nameMap); - if(subs.empty() && linked==_pcLink) + auto subs = updateLinkSubs(_pcLink, _SubList, &tryImportSubName, owner->getDocument(), nameMap); + auto linked = tryImport(owner->getDocument(), _pcLink, nameMap); + if (subs.empty() && linked == _pcLink) { return nullptr; + } std::unique_ptr p(new PropertyXLink); - copyTo(*p,linked,&subs); + copyTo(*p, linked, &subs); return p.release(); } -Property *PropertyXLink::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyXLink::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - auto res = tryReplaceLinkSubs(getContainer(),_pcLink,parent,oldObj,newObj,_SubList); - if(!res.first) + auto res = tryReplaceLinkSubs(getContainer(), _pcLink, parent, oldObj, newObj, _SubList); + if (!res.first) { return nullptr; + } std::unique_ptr p(new PropertyXLink); - copyTo(*p,res.first,&res.second); + copyTo(*p, res.first, &res.second); return p.release(); } -Property *PropertyXLink::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyXLink::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) + if (!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) { return nullptr; - auto subs = updateLinkSubs(_pcLink,_SubList,&updateLabelReference,obj,ref,newLabel); - if(subs.empty()) + } + auto subs = updateLinkSubs(_pcLink, _SubList, &updateLabelReference, obj, ref, newLabel); + if (subs.empty()) { return nullptr; + } std::unique_ptr p(new PropertyXLink); - copyTo(*p,_pcLink,&subs); + copyTo(*p, _pcLink, &subs); return p.release(); } -void PropertyXLink::copyTo(PropertyXLink &other, - DocumentObject *linked, std::vector *subs) const +void PropertyXLink::copyTo(PropertyXLink& other, + DocumentObject* linked, + std::vector* subs) const { - if(!linked) + if (!linked) { linked = _pcLink; - if(linked && linked->isAttachedToDocument()) { + } + if (linked && linked->isAttachedToDocument()) { other.docName = linked->getDocument()->getName(); other.objectName = linked->getNameInDocument(); other.docInfo.reset(); other.filePath.clear(); - }else{ + } + else { other.objectName = objectName; other.docName.clear(); other.docInfo = docInfo; other.filePath = filePath; } - if(subs) + if (subs) { other._SubList = std::move(*subs); + } else { other._SubList = _SubList; other._ShadowSubList = _ShadowSubList; @@ -3919,136 +4421,157 @@ void PropertyXLink::copyTo(PropertyXLink &other, other._Flags = _Flags; } -Property *PropertyXLink::Copy() const +Property* PropertyXLink::Copy() const { std::unique_ptr p(new PropertyXLink); copyTo(*p); return p.release(); } -void PropertyXLink::Paste(const Property &from) +void PropertyXLink::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyXLink::getClassTypeId())) + if (!from.isDerivedFrom(PropertyXLink::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } - const auto &other = static_cast(from); - if(!other.docName.empty()) { + const auto& other = static_cast(from); + if (!other.docName.empty()) { auto doc = GetApplication().getDocument(other.docName.c_str()); - if(!doc) { + if (!doc) { FC_WARN("Document '" << other.docName << "' not found"); return; } auto obj = doc->getObject(other.objectName.c_str()); - if(!obj) { + if (!obj) { FC_WARN("Object '" << other.docName << '#' << other.objectName << "' not found"); return; } - setValue(obj,std::vector(other._SubList), - std::vector(other._ShadowSubList)); - } else - setValue(std::string(other.filePath),std::string(other.objectName), + setValue(obj, std::vector(other._SubList), std::vector(other._ShadowSubList)); - setFlag(LinkAllowPartial,other.testFlag(LinkAllowPartial)); + } + else { + setValue(std::string(other.filePath), + std::string(other.objectName), + std::vector(other._SubList), + std::vector(other._ShadowSubList)); + } + setFlag(LinkAllowPartial, other.testFlag(LinkAllowPartial)); } -bool PropertyXLink::supportXLink(const App::Property *prop) { - return prop->isDerivedFrom(PropertyXLink::getClassTypeId()) || - prop->isDerivedFrom(PropertyXLinkSubList::getClassTypeId()) || - prop->isDerivedFrom(PropertyXLinkContainer::getClassTypeId()); +bool PropertyXLink::supportXLink(const App::Property* prop) +{ + return prop->isDerivedFrom(PropertyXLink::getClassTypeId()) + || prop->isDerivedFrom(PropertyXLinkSubList::getClassTypeId()) + || prop->isDerivedFrom(PropertyXLinkContainer::getClassTypeId()); } -bool PropertyXLink::hasXLink(const App::Document *doc) { - for(auto &v : _DocInfoMap) { - if(v.second->hasXLink(doc)) +bool PropertyXLink::hasXLink(const App::Document* doc) +{ + for (auto& v : _DocInfoMap) { + if (v.second->hasXLink(doc)) { return true; + } } return false; } -bool PropertyXLink::hasXLink( - const std::vector &objs, std::vector *unsaved) +bool PropertyXLink::hasXLink(const std::vector& objs, + std::vector* unsaved) { std::set docs; bool ret = false; - for(auto o : objs) { - if(o && o->isAttachedToDocument() && docs.insert(o->getDocument()).second) { - if(!hasXLink(o->getDocument())) + for (auto o : objs) { + if (o && o->isAttachedToDocument() && docs.insert(o->getDocument()).second) { + if (!hasXLink(o->getDocument())) { continue; - if(!unsaved) + } + if (!unsaved) { return true; + } ret = true; - if(!o->getDocument()->isSaved()) + if (!o->getDocument()->isSaved()) { unsaved->push_back(o->getDocument()); + } } } return ret; } -void PropertyXLink::restoreDocument(const App::Document &doc) { +void PropertyXLink::restoreDocument(const App::Document& doc) +{ DocInfo::restoreDocument(doc); } -std::map > -PropertyXLink::getDocumentOutList(App::Document *doc) { - std::map > ret; - for(auto &v : _DocInfoMap) { - for(auto link : v.second->links) { - if(!v.second->pcDoc - || link->getScope() == LinkScope::Hidden - || link->testStatus(Property::PropTransient) - || link->testStatus(Property::Transient) - || link->testStatus(Property::PropNoPersist)) +std::map> +PropertyXLink::getDocumentOutList(App::Document* doc) +{ + std::map> ret; + for (auto& v : _DocInfoMap) { + for (auto link : v.second->links) { + if (!v.second->pcDoc || link->getScope() == LinkScope::Hidden + || link->testStatus(Property::PropTransient) + || link->testStatus(Property::Transient) + || link->testStatus(Property::PropNoPersist)) { continue; + } auto obj = dynamic_cast(link->getContainer()); - if(!obj || !obj->isAttachedToDocument() || !obj->getDocument()) + if (!obj || !obj->isAttachedToDocument() || !obj->getDocument()) { continue; - if(doc && obj->getDocument()!=doc) + } + if (doc && obj->getDocument() != doc) { continue; + } ret[obj->getDocument()].insert(v.second->pcDoc); } } return ret; } -std::map > -PropertyXLink::getDocumentInList(App::Document *doc) { - std::map > ret; - for(auto &v : _DocInfoMap) { - if(!v.second->pcDoc || (doc && doc!=v.second->pcDoc)) +std::map> +PropertyXLink::getDocumentInList(App::Document* doc) +{ + std::map> ret; + for (auto& v : _DocInfoMap) { + if (!v.second->pcDoc || (doc && doc != v.second->pcDoc)) { continue; - auto &docs = ret[v.second->pcDoc]; - for(auto link : v.second->links) { - if(link->getScope() == LinkScope::Hidden - || link->testStatus(Property::PropTransient) - || link->testStatus(Property::Transient) - || link->testStatus(Property::PropNoPersist)) + } + auto& docs = ret[v.second->pcDoc]; + for (auto link : v.second->links) { + if (link->getScope() == LinkScope::Hidden || link->testStatus(Property::PropTransient) + || link->testStatus(Property::Transient) + || link->testStatus(Property::PropNoPersist)) { continue; + } auto obj = dynamic_cast(link->getContainer()); - if(obj && obj->isAttachedToDocument() && obj->getDocument()) + if (obj && obj->isAttachedToDocument() && obj->getDocument()) { docs.insert(obj->getDocument()); + } } } return ret; } -PyObject *PropertyXLink::getPyObject() +PyObject* PropertyXLink::getPyObject() { - if(!_pcLink) + if (!_pcLink) { Py_Return; - const auto &subs = getSubValues(false); - if(subs.empty()) + } + const auto& subs = getSubValues(false); + if (subs.empty()) { return _pcLink->getPyObject(); + } Py::Tuple ret(2); - ret.setItem(0,Py::Object(_pcLink->getPyObject(),true)); + ret.setItem(0, Py::Object(_pcLink->getPyObject(), true)); PropertyString propString; if (subs.size() == 1) { propString.setValue(subs.front()); - ret.setItem(1,Py::asObject(propString.getPyObject())); - } else { + ret.setItem(1, Py::asObject(propString.getPyObject())); + } + else { Py::List list(subs.size()); int i = 0; - for (auto &sub : subs) { + for (auto& sub : subs) { propString.setValue(sub); list[i++] = Py::asObject(propString.getPyObject()); } @@ -4057,66 +4580,85 @@ PyObject *PropertyXLink::getPyObject() return Py::new_reference_to(ret); } -void PropertyXLink::setPyObject(PyObject *value) { - if(PySequence_Check(value)) { +void PropertyXLink::setPyObject(PyObject* value) +{ + if (PySequence_Check(value)) { Py::Sequence seq(value); - if(seq.size()!=2) + if (seq.size() != 2) { throw Base::ValueError("Expect input sequence of size 2"); + } std::vector subs; Py::Object pyObj(seq[0].ptr()); Py::Object pySub(seq[1].ptr()); - if(pyObj.isNone()) { + if (pyObj.isNone()) { setValue(nullptr); return; - } else if(!PyObject_TypeCheck(pyObj.ptr(), &DocumentObjectPy::Type)) + } + else if (!PyObject_TypeCheck(pyObj.ptr(), &DocumentObjectPy::Type)) { throw Base::TypeError("Expect the first element to be of 'DocumentObject'"); + } PropertyString propString; - if(pySub.isString()) { + if (pySub.isString()) { propString.setPyObject(pySub.ptr()); subs.push_back(propString.getStrValue()); - } else if (pySub.isSequence()) { + } + else if (pySub.isSequence()) { Py::Sequence seq(pySub); subs.reserve(seq.size()); - for(Py_ssize_t i=0;i(pyObj.ptr())->getDocumentObjectPtr(), std::move(subs)); - } else if(PyObject_TypeCheck(value, &(DocumentObjectPy::Type))) { + } + setValue(static_cast(pyObj.ptr())->getDocumentObjectPtr(), + std::move(subs)); + } + else if (PyObject_TypeCheck(value, &(DocumentObjectPy::Type))) { setValue(static_cast(value)->getDocumentObjectPtr()); - } else if (Py_None == value) { + } + else if (Py_None == value) { setValue(nullptr); - } else { - throw Base::TypeError("type must be 'DocumentObject', 'None', or '(DocumentObject, SubName)' or " - "'DocumentObject, [SubName..])"); + } + else { + throw Base::TypeError( + "type must be 'DocumentObject', 'None', or '(DocumentObject, SubName)' or " + "'DocumentObject, [SubName..])"); } } -const char *PropertyXLink::getSubName(bool newStyle) const { - if(_SubList.empty() || _ShadowSubList.empty()) - return ""; - return getSubNameWithStyle(_SubList[0],_ShadowSubList[0],newStyle,tmpShadow).c_str(); -} - -void PropertyXLink::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +const char* PropertyXLink::getSubName(bool newStyle) const { - if((all||_pcScope!=LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) { + if (_SubList.empty() || _ShadowSubList.empty()) { + return ""; + } + return getSubNameWithStyle(_SubList[0], _ShadowSubList[0], newStyle, tmpShadow).c_str(); +} + +void PropertyXLink::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const +{ + if ((all || _pcScope != LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) { objs.push_back(_pcLink); - if(subs && _SubList.size()==_ShadowSubList.size()) + if (subs && _SubList.size() == _ShadowSubList.size()) { *subs = getSubValues(newStyle); + } } } -void PropertyXLink::getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - bool all) const { +void PropertyXLink::getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + bool all) const +{ if (all || _pcScope != LinkScope::Hidden) { if (obj && obj == _pcLink) { _getLinksTo(identifiers, obj, subname, _SubList, _ShadowSubList); @@ -4124,58 +4666,66 @@ void PropertyXLink::getLinksTo(std::vector &identifiers, } } -bool PropertyXLink::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyXLink::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; - if(!_pcLink || !_pcLink->isAttachedToDocument() || !inList.count(_pcLink)) + } + if (!_pcLink || !_pcLink->isAttachedToDocument() || !inList.count(_pcLink)) { return false; + } auto subs = _SubList; - auto link = adjustLinkSubs(this,inList,_pcLink,subs); - if(link) { - setValue(link,std::move(subs)); + auto link = adjustLinkSubs(this, inList, _pcLink, subs); + if (link) { + setValue(link, std::move(subs)); return true; } return false; } -std::vector PropertyXLink::getSubValues(bool newStyle) const { +std::vector PropertyXLink::getSubValues(bool newStyle) const +{ assert(_SubList.size() == _ShadowSubList.size()); std::vector ret; ret.reserve(_SubList.size()); std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) - ret.push_back(getSubNameWithStyle(_SubList[i],_ShadowSubList[i],newStyle,tmp)); + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + ret.push_back(getSubNameWithStyle(_SubList[i], _ShadowSubList[i], newStyle, tmp)); + } return ret; } -std::vector PropertyXLink::getSubValuesStartsWith(const char* starter, bool newStyle) const +std::vector PropertyXLink::getSubValuesStartsWith(const char* starter, + bool newStyle) const { (void)newStyle; std::vector temp; - for(const auto & it : _SubList) { - if(strncmp(starter, it.c_str(), strlen(starter)) == 0) { + for (const auto& it : _SubList) { + if (strncmp(starter, it.c_str(), strlen(starter)) == 0) { temp.push_back(it); } } return temp; } -void PropertyXLink::setAllowPartial(bool enable) { - setFlag(LinkAllowPartial,enable); - if(enable) +void PropertyXLink::setAllowPartial(bool enable) +{ + setFlag(LinkAllowPartial, enable); + if (enable) { return; + } auto owner = dynamic_cast(getContainer()); - if(!owner) + if (!owner) { return; - if(!App::GetApplication().isRestoring() && - !owner->getDocument()->isPerformingTransaction() && - !_pcLink && docInfo && !filePath.empty() && !objectName.empty() && - (!docInfo->pcDoc || docInfo->pcDoc->testStatus(Document::PartialDoc))) - { - auto path = docInfo->getDocPath(filePath.c_str(),owner->getDocument(),false); - if(!path.empty()) + } + if (!App::GetApplication().isRestoring() && !owner->getDocument()->isPerformingTransaction() + && !_pcLink && docInfo && !filePath.empty() && !objectName.empty() + && (!docInfo->pcDoc || docInfo->pcDoc->testStatus(Document::PartialDoc))) { + auto path = docInfo->getDocPath(filePath.c_str(), owner->getDocument(), false); + if (!path.empty()) { App::GetApplication().openDocument(path.c_str()); + } } } @@ -4183,42 +4733,41 @@ void PropertyXLink::setAllowPartial(bool enable) { // PropertyXLinkSub //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLinkSub , App::PropertyXLink) +TYPESYSTEM_SOURCE(App::PropertyXLinkSub, App::PropertyXLink) TYPESYSTEM_SOURCE(App::PropertyXLinkSubHidden, App::PropertyXLinkSub) -PropertyXLinkSub::PropertyXLinkSub(bool allowPartial, PropertyLinkBase *parent) - :PropertyXLink(allowPartial,parent) -{ - -} +PropertyXLinkSub::PropertyXLinkSub(bool allowPartial, PropertyLinkBase* parent) + : PropertyXLink(allowPartial, parent) +{} PropertyXLinkSub::~PropertyXLinkSub() = default; -bool PropertyXLinkSub::upgrade(Base::XMLReader &reader, const char *typeName) { - if(strcmp(typeName, PropertyLinkSubGlobal::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSub::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSubChild::getClassTypeId().getName())==0) - { +bool PropertyXLinkSub::upgrade(Base::XMLReader& reader, const char* typeName) +{ + if (strcmp(typeName, PropertyLinkSubGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSub::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSubChild::getClassTypeId().getName()) == 0) { App::PropertyLinkSub linkProp; linkProp.setContainer(getContainer()); linkProp.Restore(reader); - setValue(linkProp.getValue(),linkProp.getSubValues()); + setValue(linkProp.getValue(), linkProp.getSubValues()); return true; } - return PropertyXLink::upgrade(reader,typeName); + return PropertyXLink::upgrade(reader, typeName); } -PyObject *PropertyXLinkSub::getPyObject() +PyObject* PropertyXLinkSub::getPyObject() { - if(!_pcLink) + if (!_pcLink) { Py_Return; + } Py::Tuple ret(2); - ret.setItem(0,Py::Object(_pcLink->getPyObject(),true)); - const auto &subs = getSubValues(false); + ret.setItem(0, Py::Object(_pcLink->getPyObject(), true)); + const auto& subs = getSubValues(false); Py::List list(subs.size()); int i = 0; PropertyString propString; - for (auto &sub : subs) { + for (auto& sub : subs) { propString.setValue(sub); list[i++] = Py::asObject(propString.getPyObject()); } @@ -4230,7 +4779,7 @@ PyObject *PropertyXLinkSub::getPyObject() // PropertyXLinkSubList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLinkSubList , App::PropertyLinkBase) +TYPESYSTEM_SOURCE(App::PropertyXLinkSubList, App::PropertyLinkBase) //************************************************************************** // Construction/Destruction @@ -4254,32 +4803,34 @@ int PropertyXLinkSubList::getSize() const return static_cast(_Links.size()); } -void PropertyXLinkSubList::setValue(DocumentObject* lValue,const char* SubName) +void PropertyXLinkSubList::setValue(DocumentObject* lValue, const char* SubName) { - std::map > values; - if(lValue) { - auto &subs = values[lValue]; - if(SubName) + std::map> values; + if (lValue) { + auto& subs = values[lValue]; + if (SubName) { subs.emplace_back(SubName); + } } setValues(std::move(values)); } -void PropertyXLinkSubList::setValues( - const std::vector& lValue, - const std::vector& lSubNames) +void PropertyXLinkSubList::setValues(const std::vector& lValue, + const std::vector& lSubNames) { -#define CHECK_SUB_SIZE(_l,_r) do{\ - if(_l.size()!=_r.size())\ - FC_THROWM(Base::ValueError, "object and subname size mismatch");\ - }while(0) - CHECK_SUB_SIZE(lValue,lSubNames); - std::map > values; - int i=0; - for(auto &obj : lValue) { - const char *sub = lSubNames[i++]; - if(sub) +#define CHECK_SUB_SIZE(_l, _r) \ + do { \ + if (_l.size() != _r.size()) \ + FC_THROWM(Base::ValueError, "object and subname size mismatch"); \ + } while (0) + CHECK_SUB_SIZE(lValue, lSubNames); + std::map> values; + int i = 0; + for (auto& obj : lValue) { + const char* sub = lSubNames[i++]; + if (sub) { values[obj].emplace_back(sub); + } } setValues(std::move(values)); } @@ -4287,44 +4838,47 @@ void PropertyXLinkSubList::setValues( void PropertyXLinkSubList::setValues(const std::vector& lValue, const std::vector& lSubNames) { - CHECK_SUB_SIZE(lValue,lSubNames); - std::map > values; - int i=0; - for(auto &obj : lValue) + CHECK_SUB_SIZE(lValue, lSubNames); + std::map> values; + int i = 0; + for (auto& obj : lValue) { values[obj].push_back(lSubNames[i++]); + } setValues(std::move(values)); } -void PropertyXLinkSubList::setSubListValues(const std::vector &svalues) { - std::map > values; - for(auto &v : svalues) { - auto &s = values[v.first]; - s.reserve(s.size()+v.second.size()); - s.insert(s.end(),v.second.begin(),v.second.end()); +void PropertyXLinkSubList::setSubListValues(const std::vector& svalues) +{ + std::map> values; + for (auto& v : svalues) { + auto& s = values[v.first]; + s.reserve(s.size() + v.second.size()); + s.insert(s.end(), v.second.begin(), v.second.end()); } setValues(std::move(values)); } void PropertyXLinkSubList::setValues( - const std::map > &values) + const std::map>& values) { - setValues(std::map >(values)); + setValues(std::map>(values)); } void PropertyXLinkSubList::setValues( - std::map > &&values) + std::map>&& values) { - for(auto &v : values) { - if(!v.first || !v.first->isAttachedToDocument()) - FC_THROWM(Base::ValueError,"invalid document object"); + for (auto& v : values) { + if (!v.first || !v.first->isAttachedToDocument()) { + FC_THROWM(Base::ValueError, "invalid document object"); + } } atomic_change guard(*this); - for(auto it=_Links.begin(),itNext=it;it!=_Links.end();it=itNext) { + for (auto it = _Links.begin(), itNext = it; it != _Links.end(); it = itNext) { ++itNext; auto iter = values.find(it->getValue()); - if(iter == values.end()) { + if (iter == values.end()) { _Links.erase(it); continue; } @@ -4332,105 +4886,118 @@ void PropertyXLinkSubList::setValues( values.erase(iter); } - for(auto &v : values) { - _Links.emplace_back(testFlag(LinkAllowPartial),this); - _Links.back().setValue(v.first,std::move(v.second)); + for (auto& v : values) { + _Links.emplace_back(testFlag(LinkAllowPartial), this); + _Links.back().setValue(v.first, std::move(v.second)); } guard.tryInvoke(); } -void PropertyXLinkSubList::addValue(App::DocumentObject *obj, - const std::vector &subs, bool reset) +void PropertyXLinkSubList::addValue(App::DocumentObject* obj, + const std::vector& subs, + bool reset) { - addValue(obj,std::vector(subs),reset); + addValue(obj, std::vector(subs), reset); } -void PropertyXLinkSubList::addValue(App::DocumentObject *obj, - std::vector &&subs, bool reset) { +void PropertyXLinkSubList::addValue(App::DocumentObject* obj, + std::vector&& subs, + bool reset) +{ - if(!obj || !obj->isAttachedToDocument()) - FC_THROWM(Base::ValueError,"invalid document object"); + if (!obj || !obj->isAttachedToDocument()) { + FC_THROWM(Base::ValueError, "invalid document object"); + } - for(auto &l : _Links) { - if(l.getValue() == obj) { + for (auto& l : _Links) { + if (l.getValue() == obj) { auto s = l.getSubValues(); - if(s.empty() || reset) + if (s.empty() || reset) { l.setSubValues(std::move(subs)); + } else { - s.reserve(s.size()+subs.size()); - std::move(subs.begin(),subs.end(),std::back_inserter(s)); + s.reserve(s.size() + subs.size()); + std::move(subs.begin(), subs.end(), std::back_inserter(s)); l.setSubValues(std::move(s)); } return; } } atomic_change guard(*this); - _Links.emplace_back(testFlag(LinkAllowPartial),this); - _Links.back().setValue(obj,std::move(subs)); + _Links.emplace_back(testFlag(LinkAllowPartial), this); + _Links.back().setValue(obj, std::move(subs)); guard.tryInvoke(); } -void PropertyXLinkSubList::setValue(DocumentObject *lValue, const std::vector &SubList) +void PropertyXLinkSubList::setValue(DocumentObject* lValue, const std::vector& SubList) { - std::map > values; - if(lValue) + std::map> values; + if (lValue) { values[lValue] = SubList; + } setValues(std::move(values)); } -void PropertyXLinkSubList::setValues(const std::vector &values) { +void PropertyXLinkSubList::setValues(const std::vector& values) +{ atomic_change guard(*this); _Links.clear(); - for(auto obj : values) { - _Links.emplace_back(testFlag(LinkAllowPartial),this); + for (auto obj : values) { + _Links.emplace_back(testFlag(LinkAllowPartial), this); _Links.back().setValue(obj); } guard.tryInvoke(); } void PropertyXLinkSubList::set1Value(int idx, - DocumentObject *value, - const std::vector &SubList) + DocumentObject* value, + const std::vector& SubList) { - if(idx < -1 || idx > getSize()) + if (idx < -1 || idx > getSize()) { throw Base::RuntimeError("index out of bound"); + } - if(idx < 0 || idx+1 == getSize()) { - if(SubList.empty()) { - addValue(value,SubList); + if (idx < 0 || idx + 1 == getSize()) { + if (SubList.empty()) { + addValue(value, SubList); return; } atomic_change guard(*this); - _Links.emplace_back(testFlag(LinkAllowPartial),this); + _Links.emplace_back(testFlag(LinkAllowPartial), this); _Links.back().setValue(value); guard.tryInvoke(); return; } auto it = _Links.begin(); - for(;idx;--idx) + for (; idx; --idx) { ++it; - it->setValue(value,SubList); + } + it->setValue(value, SubList); } const string PropertyXLinkSubList::getPyReprString() const { - if (_Links.empty()) + if (_Links.empty()) { return std::string("None"); + } std::ostringstream ss; ss << '['; - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - ss << "(App.getDocument('" << obj->getDocument()->getName() - << "').getObject('" << obj->getNameInDocument() << "'), ("; - const auto &subs = link.getSubValues(); - if(subs.empty()) + } + ss << "(App.getDocument('" << obj->getDocument()->getName() << "').getObject('" + << obj->getNameInDocument() << "'), ("; + const auto& subs = link.getSubValues(); + if (subs.empty()) { ss << "''"; - else{ - for(auto &sub : subs) + } + else { + for (auto& sub : subs) { ss << "'" << sub << "',"; + } } ss << ")), "; } @@ -4438,20 +5005,22 @@ const string PropertyXLinkSubList::getPyReprString() const return ss.str(); } -DocumentObject *PropertyXLinkSubList::getValue() const +DocumentObject* PropertyXLinkSubList::getValue() const { - if(!_Links.empty()) + if (!_Links.empty()) { return _Links.begin()->getValue(); + } return nullptr; } -int PropertyXLinkSubList::removeValue(App::DocumentObject *lValue) +int PropertyXLinkSubList::removeValue(App::DocumentObject* lValue) { - atomic_change guard(*this,false); + atomic_change guard(*this, false); int ret = 0; - for(auto it=_Links.begin();it!=_Links.end();) { - if(it->getValue() != lValue) + for (auto it = _Links.begin(); it != _Links.end();) { + if (it->getValue() != lValue) { ++it; + } else { guard.aboutToChange(); it = _Links.erase(it); @@ -4462,18 +5031,19 @@ int PropertyXLinkSubList::removeValue(App::DocumentObject *lValue) return ret; } -PyObject *PropertyXLinkSubList::getPyObject() +PyObject* PropertyXLinkSubList::getPyObject() { Py::List list; - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } Py::Tuple tup(2); tup[0] = Py::asObject(obj->getPyObject()); - const auto &subs = link.getSubValues(); + const auto& subs = link.getSubValues(); Py::Tuple items(subs.size()); for (std::size_t j = 0; j < subs.size(); j++) { items[j] = Py::String(subs[j]); @@ -4484,178 +5054,209 @@ PyObject *PropertyXLinkSubList::getPyObject() return Py::new_reference_to(list); } -void PropertyXLinkSubList::setPyObject(PyObject *value) +void PropertyXLinkSubList::setPyObject(PyObject* value) { - try { //try PropertyLinkSub syntax + try { // try PropertyLinkSub syntax PropertyLinkSub dummy; dummy.setAllowExternal(true); dummy.setPyObject(value); this->setValue(dummy.getValue(), dummy.getSubValues()); return; } - catch (Base::Exception&) {} + catch (Base::Exception&) { + } - if (!PyTuple_Check(value) && !PyList_Check(value)) - throw Base::TypeError("Invalid type. Accepts (DocumentObject, (subname...)) or sequence of such type."); + if (!PyTuple_Check(value) && !PyList_Check(value)) { + throw Base::TypeError( + "Invalid type. Accepts (DocumentObject, (subname...)) or sequence of such type."); + } Py::Sequence seq(value); - std::map > values; + std::map> values; try { - for(Py_ssize_t i=0;i" << endl; + } + writer.Stream() << "\">" << endl; writer.incInd(); - for(auto &l : _Links) + for (auto& l : _Links) { l.Save(writer); + } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyXLinkSubList::Restore(Base::XMLReader &reader) +void PropertyXLinkSubList::Restore(Base::XMLReader& reader) { reader.readElement("XLinkSubList"); setFlag(LinkAllowPartial, - reader.hasAttribute("partial") && - reader.getAttributeAsInteger("partial")); + reader.hasAttribute("partial") && reader.getAttributeAsInteger("partial")); int count = reader.getAttributeAsInteger("count"); - atomic_change guard(*this,false); + atomic_change guard(*this, false); _Links.clear(); - for(int i=0;i &nameMap) const +Property* +PropertyXLinkSubList::CopyOnImportExternal(const std::map& nameMap) const { std::unique_ptr copy; auto it = _Links.begin(); - for(;it!=_Links.end();++it) { + for (; it != _Links.end(); ++it) { copy.reset(it->CopyOnImportExternal(nameMap)); - if(copy) break; + if (copy) { + break; + } } - if(!copy) + if (!copy) { return nullptr; + } std::unique_ptr p(new PropertyXLinkSubList); - for(auto iter=_Links.begin();iter!=it;++iter) { + for (auto iter = _Links.begin(); iter != it; ++iter) { p->_Links.emplace_back(); iter->copyTo(p->_Links.back()); } p->_Links.emplace_back(); static_cast(*copy).copyTo(p->_Links.back()); - for(++it;it!=_Links.end();++it) { + for (++it; it != _Links.end(); ++it) { p->_Links.emplace_back(); copy.reset(it->CopyOnImportExternal(nameMap)); - if(copy) + if (copy) { static_cast(*copy).copyTo(p->_Links.back()); - else + } + else { it->copyTo(p->_Links.back()); + } } return p.release(); } -Property *PropertyXLinkSubList::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyXLinkSubList::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { std::unique_ptr copy; auto it = _Links.begin(); - for(;it!=_Links.end();++it) { - copy.reset(it->CopyOnLabelChange(obj,ref,newLabel)); - if(copy) break; + for (; it != _Links.end(); ++it) { + copy.reset(it->CopyOnLabelChange(obj, ref, newLabel)); + if (copy) { + break; + } } - if(!copy) + if (!copy) { return nullptr; + } std::unique_ptr p(new PropertyXLinkSubList); - for(auto iter=_Links.begin();iter!=it;++iter) { + for (auto iter = _Links.begin(); iter != it; ++iter) { p->_Links.emplace_back(); iter->copyTo(p->_Links.back()); } p->_Links.emplace_back(); static_cast(*copy).copyTo(p->_Links.back()); - for(++it;it!=_Links.end();++it) { + for (++it; it != _Links.end(); ++it) { p->_Links.emplace_back(); - copy.reset(it->CopyOnLabelChange(obj,ref,newLabel)); - if(copy) + copy.reset(it->CopyOnLabelChange(obj, ref, newLabel)); + if (copy) { static_cast(*copy).copyTo(p->_Links.back()); - else + } + else { it->copyTo(p->_Links.back()); + } } return p.release(); } -Property *PropertyXLinkSubList::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyXLinkSubList::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { std::unique_ptr copy; - PropertyXLinkSub *copied = nullptr; + PropertyXLinkSub* copied = nullptr; std::set subs; auto it = _Links.begin(); - for(;it!=_Links.end();++it) { - copy.reset(it->CopyOnLinkReplace(parent,oldObj,newObj)); - if(copy) { + for (; it != _Links.end(); ++it) { + copy.reset(it->CopyOnLinkReplace(parent, oldObj, newObj)); + if (copy) { copied = static_cast(copy.get()); - if(copied->getValue() == newObj) { - for(auto &sub : copied->getSubValues()) + if (copied->getValue() == newObj) { + for (auto& sub : copied->getSubValues()) { subs.insert(sub); + } } break; } } - if(!copy) + if (!copy) { return nullptr; + } std::unique_ptr p(new PropertyXLinkSubList); - for(auto iter=_Links.begin();iter!=it;++iter) { - if(iter->getValue()==newObj && copied->getValue()==newObj) { + for (auto iter = _Links.begin(); iter != it; ++iter) { + if (iter->getValue() == newObj && copied->getValue() == newObj) { // merge subnames in case new object already exists - for(auto &sub : iter->getSubValues()) { - if(subs.insert(sub).second) + for (auto& sub : iter->getSubValues()) { + if (subs.insert(sub).second) { copied->_SubList.push_back(sub); + } } - } else { + } + else { p->_Links.emplace_back(); iter->copyTo(p->_Links.back()); } @@ -4663,113 +5264,128 @@ Property *PropertyXLinkSubList::CopyOnLinkReplace(const App::DocumentObject *par p->_Links.emplace_back(); copied->copyTo(p->_Links.back()); copied = &p->_Links.back(); - for(++it;it!=_Links.end();++it) { - if((it->getValue()==newObj||it->getValue()==oldObj) - && copied->getValue()==newObj) - { + for (++it; it != _Links.end(); ++it) { + if ((it->getValue() == newObj || it->getValue() == oldObj) + && copied->getValue() == newObj) { // merge subnames in case new object already exists - for(auto &sub : it->getSubValues()) { - if(subs.insert(sub).second) + for (auto& sub : it->getSubValues()) { + if (subs.insert(sub).second) { copied->_SubList.push_back(sub); + } } continue; } p->_Links.emplace_back(); - copy.reset(it->CopyOnLinkReplace(parent,oldObj,newObj)); - if(copy) + copy.reset(it->CopyOnLinkReplace(parent, oldObj, newObj)); + if (copy) { static_cast(*copy).copyTo(p->_Links.back()); - else + } + else { it->copyTo(p->_Links.back()); + } } return p.release(); } -Property *PropertyXLinkSubList::Copy() const +Property* PropertyXLinkSubList::Copy() const { - PropertyXLinkSubList *p = new PropertyXLinkSubList(); - for(auto &l : _Links) { - p->_Links.emplace_back(testFlag(LinkAllowPartial),p); + PropertyXLinkSubList* p = new PropertyXLinkSubList(); + for (auto& l : _Links) { + p->_Links.emplace_back(testFlag(LinkAllowPartial), p); l.copyTo(p->_Links.back()); } return p; } -void PropertyXLinkSubList::Paste(const Property &from) +void PropertyXLinkSubList::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyXLinkSubList::getClassTypeId())) + if (!from.isDerivedFrom(PropertyXLinkSubList::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } aboutToSetValue(); _Links.clear(); - for(auto &l : static_cast(from)._Links) { - _Links.emplace_back(testFlag(LinkAllowPartial),this); + for (auto& l : static_cast(from)._Links) { + _Links.emplace_back(testFlag(LinkAllowPartial), this); _Links.back().Paste(l); } hasSetValue(); } -unsigned int PropertyXLinkSubList::getMemSize () const +unsigned int PropertyXLinkSubList::getMemSize() const { - unsigned int size=0; - for(auto &l : _Links) + unsigned int size = 0; + for (auto& l : _Links) { size += l.getMemSize(); - return size; + } + return size; } -const std::vector &PropertyXLinkSubList::getSubValues(App::DocumentObject *obj) const { - for(auto &l : _Links) { - if(l.getValue() == obj) +const std::vector& PropertyXLinkSubList::getSubValues(App::DocumentObject* obj) const +{ + for (auto& l : _Links) { + if (l.getValue() == obj) { return l.getSubValues(); + } } FC_THROWM(Base::RuntimeError, "object not found"); } -std::vector PropertyXLinkSubList::getSubValues(App::DocumentObject *obj, bool newStyle) const { - for(auto &l : _Links) { - if(l.getValue() == obj) +std::vector PropertyXLinkSubList::getSubValues(App::DocumentObject* obj, + bool newStyle) const +{ + for (auto& l : _Links) { + if (l.getValue() == obj) { return l.getSubValues(newStyle); + } } return {}; } -void PropertyXLinkSubList::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyXLinkSubList::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { - if(all||_pcScope!=LinkScope::Hidden) { - if(!subs) { - objs.reserve(objs.size()+_Links.size()); - for(auto &l : _Links) { + if (all || _pcScope != LinkScope::Hidden) { + if (!subs) { + objs.reserve(objs.size() + _Links.size()); + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } return; } - size_t count=0; - for(auto &l : _Links) { + size_t count = 0; + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { count += std::max((int)l.getSubValues().size(), 1); + } } - if(!count) { - objs.reserve(objs.size()+_Links.size()); - for(auto &l : _Links) { + if (!count) { + objs.reserve(objs.size() + _Links.size()); + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } return; } - objs.reserve(objs.size()+count); - subs->reserve(subs->size()+count); - for(auto &l : _Links) { + objs.reserve(objs.size() + count); + subs->reserve(subs->size() + count); + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) { + if (obj && obj->isAttachedToDocument()) { auto subnames = l.getSubValues(newStyle); - if (subnames.empty()) + if (subnames.empty()) { subnames.emplace_back(""); - for(auto &sub : subnames) { + } + for (auto& sub : subnames) { objs.push_back(obj); subs->push_back(std::move(sub)); } @@ -4837,7 +5453,7 @@ void PropertyXLinkSubList::getLinksTo(std::vector& identi const char* subname, bool all) const { - if ( ! all && _pcScope != LinkScope::Hidden) { + if (!all && _pcScope != LinkScope::Hidden) { return; } for (auto& l : _Links) { @@ -4847,14 +5463,15 @@ void PropertyXLinkSubList::getLinksTo(std::vector& identi } } -void PropertyXLinkSubList::breakLink(App::DocumentObject *obj, bool clear) { - if(clear && getContainer()==obj) { +void PropertyXLinkSubList::breakLink(App::DocumentObject* obj, bool clear) +{ + if (clear && getContainer() == obj) { setValue(nullptr); return; } - atomic_change guard(*this,false); - for(auto &l : _Links) { - if(l.getValue() == obj) { + atomic_change guard(*this, false); + for (auto& l : _Links) { + if (l.getValue() == obj) { guard.aboutToChange(); l.setValue(nullptr); } @@ -4862,98 +5479,111 @@ void PropertyXLinkSubList::breakLink(App::DocumentObject *obj, bool clear) { guard.tryInvoke(); } -bool PropertyXLinkSubList::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyXLinkSubList::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; - std::map > values; + } + std::map> values; bool touched = false; - int count=0; - for(auto &l : _Links) { + int count = 0; + for (auto& l : _Links) { auto obj = l.getValue(); - if(!obj || !obj->isAttachedToDocument()) { + if (!obj || !obj->isAttachedToDocument()) { ++count; continue; } - if(inList.count(obj) && adjustLinkSubs(this,inList,obj,l._SubList,&values)) + if (inList.count(obj) && adjustLinkSubs(this, inList, obj, l._SubList, &values)) { touched = true; + } } - if(touched) { + if (touched) { decltype(_Links) tmp; - if(count) { + if (count) { // XLink allows detached state, i.e. with closed external document. So // we need to preserve empty link - for(auto it=_Links.begin(),itNext=it;it!=_Links.end();it=itNext) { + for (auto it = _Links.begin(), itNext = it; it != _Links.end(); it = itNext) { ++itNext; - if(!it->getValue()) - tmp.splice(tmp.end(),_Links,it); + if (!it->getValue()) { + tmp.splice(tmp.end(), _Links, it); + } } } setValues(std::move(values)); - _Links.splice(_Links.end(),tmp); + _Links.splice(_Links.end(), tmp); } return touched; } -int PropertyXLinkSubList::checkRestore(std::string *msg) const { - for(auto &l : _Links) { +int PropertyXLinkSubList::checkRestore(std::string* msg) const +{ + for (auto& l : _Links) { int res; - if((res = l.checkRestore(msg))) + if ((res = l.checkRestore(msg))) { return res; + } } return 0; } -bool PropertyXLinkSubList::upgrade(Base::XMLReader &reader, const char *typeName) { - if(strcmp(typeName, PropertyLinkListGlobal::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkList::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkListChild::getClassTypeId().getName())==0) - { +bool PropertyXLinkSubList::upgrade(Base::XMLReader& reader, const char* typeName) +{ + if (strcmp(typeName, PropertyLinkListGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkList::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkListChild::getClassTypeId().getName()) == 0) { PropertyLinkList linkProp; linkProp.setContainer(getContainer()); linkProp.Restore(reader); setValues(linkProp.getValues()); return true; - } else if (strcmp(typeName, PropertyLinkSubListGlobal::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSubList::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSubListChild::getClassTypeId().getName())==0) - { + } + else if (strcmp(typeName, PropertyLinkSubListGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSubList::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSubListChild::getClassTypeId().getName()) == 0) { PropertyLinkSubList linkProp; linkProp.setContainer(getContainer()); linkProp.Restore(reader); - std::map > values; - const auto &objs = linkProp.getValues(); - const auto &subs = linkProp.getSubValues(); + std::map> values; + const auto& objs = linkProp.getValues(); + const auto& subs = linkProp.getSubValues(); assert(objs.size() == subs.size()); - for(size_t i=0;i PropertyXLinkSubList::getValues() const { std::vector xLinks; getLinks(xLinks); - return(xLinks); + return (xLinks); } //************************************************************************** // PropertyXLinkList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLinkList , App::PropertyXLinkSubList) +TYPESYSTEM_SOURCE(App::PropertyXLinkList, App::PropertyXLinkSubList) //************************************************************************** // Construction/Destruction @@ -4977,36 +5607,40 @@ PropertyXLinkList::PropertyXLinkList() = default; PropertyXLinkList::~PropertyXLinkList() = default; -PyObject *PropertyXLinkList::getPyObject() +PyObject* PropertyXLinkList::getPyObject() { - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - if(link.hasSubName()) + } + if (link.hasSubName()) { return PropertyXLinkSubList::getPyObject(); + } } Py::List list; - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } list.append(Py::asObject(obj->getPyObject())); } return Py::new_reference_to(list); } -void PropertyXLinkList::setPyObject(PyObject *value) +void PropertyXLinkList::setPyObject(PyObject* value) { - try { //try PropertyLinkList syntax + try { // try PropertyLinkList syntax PropertyLinkList dummy; dummy.setAllowExternal(true); dummy.setPyObject(value); this->setValues(dummy.getValues()); return; } - catch (Base::Exception&) {} + catch (Base::Exception&) { + } PropertyXLinkSubList::setPyObject(value); } @@ -5014,31 +5648,37 @@ void PropertyXLinkList::setPyObject(PyObject *value) //************************************************************************** // PropertyXLinkContainer //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyXLinkContainer , App::PropertyLinkBase) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyXLinkContainer, App::PropertyLinkBase) -PropertyXLinkContainer::PropertyXLinkContainer() { +PropertyXLinkContainer::PropertyXLinkContainer() +{ _pcScope = LinkScope::Global; _LinkRestored = false; } PropertyXLinkContainer::~PropertyXLinkContainer() = default; -void PropertyXLinkContainer::afterRestore() { +void PropertyXLinkContainer::afterRestore() +{ _DocMap.clear(); - if(!_XLinkRestores) + if (!_XLinkRestores) { return; + } _Deps.clear(); - for(auto &info : *_XLinkRestores) { + for (auto& info : *_XLinkRestores) { auto obj = info.xlink->getValue(); - if(!obj) + if (!obj) { continue; - if(!info.docName.empty()) { - if(info.docName != obj->getDocument()->getName()) - _DocMap[info.docName] = obj->getDocument()->getName(); - if(info.docLabel != obj->getDocument()->Label.getValue()) - _DocMap[App::quote(info.docLabel)] = obj->getDocument()->Label.getValue(); } - if(_Deps.insert(std::make_pair(obj,info.xlink->getScope()==LinkScope::Hidden)).second) { + if (!info.docName.empty()) { + if (info.docName != obj->getDocument()->getName()) { + _DocMap[info.docName] = obj->getDocument()->getName(); + } + if (info.docLabel != obj->getDocument()->Label.getValue()) { + _DocMap[App::quote(info.docLabel)] = obj->getDocument()->Label.getValue(); + } + } + if (_Deps.insert(std::make_pair(obj, info.xlink->getScope() == LinkScope::Hidden)).second) { _XLinks[obj->getFullName()] = std::move(info.xlink); onAddDep(obj); } @@ -5046,253 +5686,292 @@ void PropertyXLinkContainer::afterRestore() { _XLinkRestores.reset(); } -void PropertyXLinkContainer::breakLink(App::DocumentObject *obj, bool clear) { - if(!obj || !obj->isAttachedToDocument()) +void PropertyXLinkContainer::breakLink(App::DocumentObject* obj, bool clear) +{ + if (!obj || !obj->isAttachedToDocument()) { return; + } auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { return; - if(!clear || obj!=owner) { + } + if (!clear || obj != owner) { auto it = _Deps.find(obj); - if(it == _Deps.end()) + if (it == _Deps.end()) { return; + } aboutToSetValue(); onBreakLink(obj); - if (obj->getDocument() != owner->getDocument()) + if (obj->getDocument() != owner->getDocument()) { _XLinks.erase(obj->getFullName()); - else if (!it->second) + } + else if (!it->second) { obj->_removeBackLink(owner); + } _Deps.erase(it); onRemoveDep(obj); hasSetValue(); return; } - if(obj!=owner) + if (obj != owner) { return; - for(auto &v : _Deps) { + } + for (auto& v : _Deps) { auto key = v.first; - if(!key || !key->isAttachedToDocument()) + if (!key || !key->isAttachedToDocument()) { continue; + } onBreakLink(key); - if(!v.second && key->getDocument()==owner->getDocument()) + if (!v.second && key->getDocument() == owner->getDocument()) { key->_removeBackLink(owner); + } } _XLinks.clear(); _Deps.clear(); } -int PropertyXLinkContainer::checkRestore(std::string *msg) const { - if(_LinkRestored) { - for(auto &v : _XLinks) { +int PropertyXLinkContainer::checkRestore(std::string* msg) const +{ + if (_LinkRestored) { + for (auto& v : _XLinks) { int res = v.second->checkRestore(msg); - if(res) + if (res) { return res; + } } } return 0; } -void PropertyXLinkContainer::Save (Base::Writer &writer) const { +void PropertyXLinkContainer::Save(Base::Writer& writer) const +{ writer.Stream() << writer.ind() << " docSet; + std::map docSet; auto owner = Base::freecad_dynamic_cast(getContainer()); - if(owner && !owner->isExporting()) { + if (owner && !owner->isExporting()) { // Document name and label can change on restore, we shall record the // current document name and label and pair it with the associated // xlink, so that we can restore them correctly. - int i=-1; - for(auto &v : _XLinks) { + int i = -1; + for (auto& v : _XLinks) { ++i; auto obj = v.second->getValue(); - if(obj && obj->getDocument()) - docSet.insert(std::make_pair(obj->getDocument(),i)); + if (obj && obj->getDocument()) { + docSet.insert(std::make_pair(obj->getDocument(), i)); + } } - if(!docSet.empty()) + if (!docSet.empty()) { writer.Stream() << "\" docs=\"" << docSet.size(); + } } std::ostringstream ss; int hidden = 0; - int i=-1; - for(auto &v : _XLinks) { + int i = -1; + for (auto& v : _XLinks) { ++i; - if(v.second->getScope() == LinkScope::Hidden) { + if (v.second->getScope() == LinkScope::Hidden) { ss << i << ' '; ++hidden; } } - if(hidden) + if (hidden) { writer.Stream() << "\" hidden=\"" << ss.str(); + } writer.Stream() << "\">" << std::endl; writer.incInd(); - for(auto &v : docSet) { + for (auto& v : docSet) { writer.Stream() << writer.ind() << "getName() - << "\" label=\"" << encodeAttribute(v.first->Label.getValue()) - << "\" index=\"" << v.second << "\"/>" << std::endl; + << "name=\"" << v.first->getName() << "\" label=\"" + << encodeAttribute(v.first->Label.getValue()) << "\" index=\"" << v.second + << "\"/>" << std::endl; } - for(auto &v : _XLinks) + for (auto& v : _XLinks) { v.second->Save(writer); + } writer.decInd(); writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyXLinkContainer::Restore(Base::XMLReader &reader) { +void PropertyXLinkContainer::Restore(Base::XMLReader& reader) +{ reader.readElement("XLinks"); auto count = reader.getAttributeAsUnsigned("count"); _XLinkRestores = std::make_unique>(count); - if(reader.hasAttribute("hidden")) { + if (reader.hasAttribute("hidden")) { std::istringstream iss(reader.getAttribute("hidden")); int index; - while(iss >> index) { - if(index>=0 && index(count)) + while (iss >> index) { + if (index >= 0 && index < static_cast(count)) { _XLinkRestores->at(index).hidden = true; + } } } - if(reader.hasAttribute("docs")) { + if (reader.hasAttribute("docs")) { auto docCount = reader.getAttributeAsUnsigned("docs"); _DocMap.clear(); - for(unsigned i=0;i=count) { + if (index >= count) { FC_ERR(propertyName(this) << " invalid document map entry"); continue; } - auto &info = _XLinkRestores->at(index); + auto& info = _XLinkRestores->at(index); info.docName = reader.getAttribute("name"); info.docLabel = reader.getAttribute("label"); } } - for(auto &info : *_XLinkRestores) { + for (auto& info : *_XLinkRestores) { info.xlink.reset(createXLink()); - if(info.hidden) + if (info.hidden) { info.xlink->setScope(LinkScope::Hidden); + } info.xlink->Restore(reader); } reader.readEndElement("XLinks"); } -void PropertyXLinkContainer::aboutToSetChildValue(App::Property &prop) { +void PropertyXLinkContainer::aboutToSetChildValue(App::Property& prop) +{ auto xlink = dynamic_cast(&prop); - if(xlink && xlink->testFlag(LinkDetached)) { + if (xlink && xlink->testFlag(LinkDetached)) { auto obj = const_cast(xlink->getValue()); - if(_Deps.erase(obj)) { + if (_Deps.erase(obj)) { _onBreakLink(xlink->getValue()); onRemoveDep(obj); } } } -void PropertyXLinkContainer::onBreakLink(DocumentObject *) { -} +void PropertyXLinkContainer::onBreakLink(DocumentObject*) +{} -void PropertyXLinkContainer::_onBreakLink(DocumentObject *obj) { +void PropertyXLinkContainer::_onBreakLink(DocumentObject* obj) +{ try { onBreakLink(obj); - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); FC_ERR("Exception on breaking link property " << getFullName()); - } catch (std::exception &e) { + } + catch (std::exception& e) { FC_ERR("Exception on breaking link property " << getFullName() << ": " << e.what()); - } catch (...) { + } + catch (...) { FC_ERR("Exception on breaking link property " << getFullName()); } } -PropertyXLink *PropertyXLinkContainer::createXLink() { - return new PropertyXLink(false,this); +PropertyXLink* PropertyXLinkContainer::createXLink() +{ + return new PropertyXLink(false, this); } -bool PropertyXLinkContainer::isLinkedToDocument(const App::Document &doc) const { +bool PropertyXLinkContainer::isLinkedToDocument(const App::Document& doc) const +{ auto iter = _XLinks.lower_bound(doc.getName()); - if(iter != _XLinks.end()) { + if (iter != _XLinks.end()) { size_t len = strlen(doc.getName()); - return iter->first.size()>len - && iter->first[len] == '#' - && boost::starts_with(iter->first,doc.getName()); + return iter->first.size() > len && iter->first[len] == '#' + && boost::starts_with(iter->first, doc.getName()); } return false; } -void PropertyXLinkContainer::updateDeps(std::map &&newDeps) { +void PropertyXLinkContainer::updateDeps(std::map&& newDeps) +{ auto owner = Base::freecad_dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { return; + } newDeps.erase(owner); - for(auto &v : newDeps) { + for (auto& v : newDeps) { auto obj = v.first; - if(obj && obj->isAttachedToDocument()) { + if (obj && obj->isAttachedToDocument()) { auto it = _Deps.find(obj); - if(it != _Deps.end()) { - if(v.second != it->second) { - if(v.second) + if (it != _Deps.end()) { + if (v.second != it->second) { + if (v.second) { obj->_removeBackLink(owner); - else + } + else { obj->_addBackLink(owner); + } } _Deps.erase(it); continue; } - if(owner->getDocument()!=obj->getDocument()) { - auto &xlink = _XLinks[obj->getFullName()]; - if(!xlink) { + if (owner->getDocument() != obj->getDocument()) { + auto& xlink = _XLinks[obj->getFullName()]; + if (!xlink) { xlink.reset(createXLink()); xlink->setValue(obj); } - xlink->setScope(v.second?LinkScope::Hidden:LinkScope::Global); + xlink->setScope(v.second ? LinkScope::Hidden : LinkScope::Global); } - else if(!v.second) + else if (!v.second) { obj->_addBackLink(owner); + } onAddDep(obj); } } - for(auto &v : _Deps) { + for (auto& v : _Deps) { auto obj = v.first; - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - if(obj->getDocument()==owner->getDocument()) { - if(!v.second) + } + if (obj->getDocument() == owner->getDocument()) { + if (!v.second) { obj->_removeBackLink(owner); - }else + } + } + else { _XLinks.erase(obj->getFullName()); + } onRemoveDep(obj); } _Deps = std::move(newDeps); _LinkRestored = testFlag(LinkRestoring); - if(!_LinkRestored && !testFlag(LinkDetached)) { - for(auto it=_XLinks.begin(),itNext=it;it!=_XLinks.end();it=itNext) { + if (!_LinkRestored && !testFlag(LinkDetached)) { + for (auto it = _XLinks.begin(), itNext = it; it != _XLinks.end(); it = itNext) { ++itNext; - if(!it->second->getValue()) + if (!it->second->getValue()) { _XLinks.erase(it); + } } } } -void PropertyXLinkContainer::clearDeps() { +void PropertyXLinkContainer::clearDeps() +{ auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { return; + } #ifndef USE_OLD_DAG if (!owner->testStatus(ObjectStatus::Destroy)) { - for(auto &v : _Deps) { + for (auto& v : _Deps) { auto obj = v.first; - if(!v.second && obj && obj->isAttachedToDocument() && obj->getDocument()==owner->getDocument()) + if (!v.second && obj && obj->isAttachedToDocument() + && obj->getDocument() == owner->getDocument()) { obj->_removeBackLink(owner); + } } } #endif @@ -5301,11 +5980,14 @@ void PropertyXLinkContainer::clearDeps() { _LinkRestored = false; } -void PropertyXLinkContainer::getLinks(std::vector &objs, - bool all, std::vector * /*subs*/, bool /*newStyle*/) const +void PropertyXLinkContainer::getLinks(std::vector& objs, + bool all, + std::vector* /*subs*/, + bool /*newStyle*/) const { - for(auto &v : _Deps) { - if(all || !v.second) + for (auto& v : _Deps) { + if (all || !v.second) { objs.push_back(v.first); + } } } diff --git a/src/App/PropertyLinks.h b/src/App/PropertyLinks.h index 63f8a71dc8..edf2d6b098 100644 --- a/src/App/PropertyLinks.h +++ b/src/App/PropertyLinks.h @@ -33,7 +33,8 @@ #include "Property.h" -namespace Base { +namespace Base +{ class Writer; } @@ -51,13 +52,13 @@ class PropertyXLink; /** * @brief Defines different scopes for which a link can be valid - * The scopes defined in this enum describe the different possibilities of where a link can point to. - * Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in none. - * Child: links are valid within the same or any sub GeoFeatureGroup - * Global: all possible links are valid - * Hidden: links are not included in dependency calculation + * The scopes defined in this enum describe the different possibilities of where a link can point + * to. Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in + * none. Child: links are valid within the same or any sub GeoFeatureGroup Global: all possible + * links are valid Hidden: links are not included in dependency calculation */ -enum class LinkScope { +enum class LinkScope +{ Local, Child, Global, @@ -66,43 +67,51 @@ enum class LinkScope { /** * @brief Enables scope handling for links - * This class is a base for all link properties and enables them to handle scopes of the linked objects. - * The possible scopes are defined by LinkScope enum class. The default value is Local. - * The scope of a property is not saved in the document. It is a value that needs to be fixed when - * the object holding the property is loaded. That is possible with two methods: + * This class is a base for all link properties and enables them to handle scopes of the linked + * objects. The possible scopes are defined by LinkScope enum class. The default value is Local. The + * scope of a property is not saved in the document. It is a value that needs to be fixed when the + * object holding the property is loaded. That is possible with two methods: * 1. Set the scope value in the constructor of the link property * 2. Use setScope to change the scope in the constructor of the link property * * The second option is only available in c++, not in python, as setscope is not exposed. It would - * not make sense to expose it there, as restoring python objects does not call the constructor again. - * Hence in python the only way to create a LinkProperty with different scope than local is to use a - * specialized property for that. In c++ existing properties can simply be changed via setScope in the - * objects constructor. + * not make sense to expose it there, as restoring python objects does not call the constructor + * again. Hence in python the only way to create a LinkProperty with different scope than local is + * to use a specialized property for that. In c++ existing properties can simply be changed via + * setScope in the objects constructor. */ -class AppExport ScopedLink { +class AppExport ScopedLink +{ public: /** * @brief Set the links scope - * Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and - * all Childs or to all objects within the Glocal scope. + * Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this + * and all Childs or to all objects within the Glocal scope. */ - void setScope(LinkScope scope) {_pcScope = scope;}; + void setScope(LinkScope scope) + { + _pcScope = scope; + } /** * @brief Get the links scope * Retrieve what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and * all Childs or to all objects within the Glocal scope. */ - LinkScope getScope() const {return _pcScope;}; - + LinkScope getScope() const + { + return _pcScope; + } + protected: LinkScope _pcScope = LinkScope::Local; }; /// Parent class of all link type properties -class AppExport PropertyLinkBase : public Property, public ScopedLink +class AppExport PropertyLinkBase: public Property, public ScopedLink { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: using ShadowSub = ElementNamePair; @@ -121,8 +130,8 @@ public: * * @sa _updateElementReference() */ - virtual void updateElementReference(App::DocumentObject *feature, - bool reverse=false, bool notify=false) + virtual void + updateElementReference(App::DocumentObject* feature, bool reverse = false, bool notify = false) { (void)feature; (void)reverse; @@ -138,7 +147,7 @@ public: * @param reset: if true, then calls unregisterLabelReference() before * registering */ - void registerLabelReferences(std::vector &&labels, bool reset=true); + void registerLabelReferences(std::vector&& labels, bool reset = true); /** Check subnames for label registration * @@ -149,13 +158,14 @@ public: * Check the give subname references and extract any label reference * inside (by calling getLabelReferences()), and register them. */ - void checkLabelReferences(const std::vector &subs, bool reset=true); + void checkLabelReferences(const std::vector& subs, bool reset = true); /// Clear internal label references registration void unregisterLabelReferences(); /// Test if the element reference has changed after restore - virtual bool referenceChanged() const { + virtual bool referenceChanged() const + { return false; } @@ -166,7 +176,8 @@ public: * @return For external linked object, return 2 in case the link is * missing, and 1 if the time stamp has changed. */ - virtual int checkRestore(std::string *msg=nullptr) const { + virtual int checkRestore(std::string* msg = nullptr) const + { (void)msg; return 0; } @@ -180,8 +191,10 @@ public: * @param sub: if given, then return subname references. * @param newStyle: whether to return new or old style subname reference */ - virtual void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const = 0; + virtual void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const = 0; /** Obtain identifiers from this link property that link to a given object * @param identifiers: holds the returned identifier to reference the given object @@ -191,10 +204,10 @@ public: * this LinkScope. If false, then return only if the LinkScope * is not hidden. */ - virtual void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const = 0; + virtual void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const = 0; /** Called to reset this link property * @@ -203,7 +216,7 @@ public: * * @sa breakLinks() */ - virtual void breakLink(App::DocumentObject *obj, bool clear) = 0; + virtual void breakLink(App::DocumentObject* obj, bool clear) = 0; /** Called to adjust the link to avoid potential cyclic dependency * @@ -214,7 +227,7 @@ public: * This function tries to correct the link to avoid any (sub)object inside * in-list. If the adjustment is impossible, exception will be raised */ - virtual bool adjustLink(const std::set &inList) = 0; + virtual bool adjustLink(const std::set& inList) = 0; /** Return a copy of the property if the link replacement affects this property * @@ -228,8 +241,9 @@ public: * @return Return a copy of the property that is adjusted for the link * replacement operation. */ - virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const = 0; + virtual Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const = 0; /** Return a copy of the property if any changes caused by importing external linked object * @@ -240,7 +254,8 @@ public: * affected. The copy will later be assgiend to this property by calling its * Paste(). */ - virtual Property *CopyOnImportExternal(const std::map &nameMap) const { + virtual Property* CopyOnImportExternal(const std::map& nameMap) const + { (void)nameMap; return nullptr; } @@ -254,8 +269,8 @@ public: * @return Returns a copy of the property if its link reference is affected. * The copy will later be assgiend to this property by calling its Paste(). */ - virtual Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const + virtual Property* + CopyOnLabelChange(App::DocumentObject* obj, const std::string& ref, const char* newLabel) const { (void)obj; (void)ref; @@ -264,44 +279,48 @@ public: } /// Helper function to return all linked objects of this property - std::vector linkedObjects(bool all=false) const { + std::vector linkedObjects(bool all = false) const + { std::vector ret; - getLinks(ret,all); + getLinks(ret, all); return ret; } /// Helper function to return linked objects using an std::inserter template - void getLinkedObjects(T &inserter, bool all=false) const { + void getLinkedObjects(T& inserter, bool all = false) const + { std::vector ret; - getLinks(ret,all); - std::copy(ret.begin(),ret.end(),inserter); + getLinks(ret, all); + std::copy(ret.begin(), ret.end(), inserter); } /// Helper function to return a map of linked object and its subname references - void getLinkedElements(std::map > &elements, - bool newStyle=true, bool all=false) const + void getLinkedElements(std::map>& elements, + bool newStyle = true, + bool all = false) const { std::vector ret; std::vector subs; - getLinks(ret,all,&subs,newStyle); - assert(ret.size()==subs.size()); - int i=0; - for(auto obj : ret) + getLinks(ret, all, &subs, newStyle); + assert(ret.size() == subs.size()); + int i = 0; + for (auto obj : ret) { elements[obj].push_back(subs[i++]); + } } /// Helper function to return a map of linked object and its subname references - std::map > - linkedElements(bool newStyle=true, bool all=false) const + std::map> linkedElements(bool newStyle = true, + bool all = false) const { - std::map > ret; - getLinkedElements(ret,newStyle,all); + std::map> ret; + getLinkedElements(ret, newStyle, all); return ret; } //@} - bool isSame(const Property &other) const override; + bool isSame(const Property& other) const override; /** Enable/disable temporary holding external object without throwing exception * @@ -334,10 +353,13 @@ public: * through the group will be broken. This helper function is used to check * and correct any link sub reference. */ - static std::pair tryReplaceLink( - const App::PropertyContainer *owner, App::DocumentObject *obj, - const App::DocumentObject *parent, App::DocumentObject *oldObj, - App::DocumentObject *newObj, const char *sub=nullptr); + static std::pair + tryReplaceLink(const App::PropertyContainer* owner, + App::DocumentObject* obj, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj, + const char* sub = nullptr); /** Helper function to check and replace a link with multiple subname references * @@ -353,19 +375,19 @@ public: * pair.first will be NULL * @sa tryReplaceLink() */ - static std::pair > - tryReplaceLinkSubs( const App::PropertyContainer *owner, - App::DocumentObject *obj, - const App::DocumentObject *parent, - App::DocumentObject *oldObj, - App::DocumentObject *newObj, - const std::vector &subs); + static std::pair> + tryReplaceLinkSubs(const App::PropertyContainer* owner, + App::DocumentObject* obj, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj, + const std::vector& subs); /// Update all element references in all link properties of \a feature - static void updateElementReferences(DocumentObject *feature, bool reverse=false); + static void updateElementReferences(DocumentObject* feature, bool reverse = false); /// Obtain link properties that contain element references to a given object - static const std::unordered_set& getElementReferences(DocumentObject *); + static const std::unordered_set& getElementReferences(DocumentObject*); /** Helper function for update individual element reference * @@ -383,9 +405,12 @@ public: * This helper function is to be called by each link property in the event of * geometry element reference change due to geometry model changes. */ - bool _updateElementReference(App::DocumentObject *feature, - App::DocumentObject *obj, std::string &sub, ShadowSub &shadow, - bool reverse, bool notify=false); + bool _updateElementReference(App::DocumentObject* feature, + App::DocumentObject* obj, + std::string& sub, + ShadowSub& shadow, + bool reverse, + bool notify = false); /** Helper function to register geometry element reference * @@ -396,7 +421,7 @@ public: * Search for any geometry element reference inside the subname, and * register for future update in case of geometry model update. */ - void _registerElementReference(App::DocumentObject *obj, std::string &sub, ShadowSub &shadow); + void _registerElementReference(App::DocumentObject* obj, std::string& sub, ShadowSub& shadow); /** Helper function for breaking link properties * @@ -406,7 +431,9 @@ public: * * App::Document::breakDependency() calls this function to break the link property */ - static void breakLinks(App::DocumentObject *link, const std::vector &objs, bool clear); + static void breakLinks(App::DocumentObject* link, + const std::vector& objs, + bool clear); /** Helper function for link import operation * @@ -423,8 +450,10 @@ public: * the API CopyOnImportExternal(). This function helps to rewrite subname * reference to point to the correct sub objects that are imported. */ - static std::string tryImportSubName(const App::DocumentObject *obj, const char *sub, - const App::Document *doc, const std::map &nameMap); + static std::string tryImportSubName(const App::DocumentObject* obj, + const char* sub, + const App::Document* doc, + const std::map& nameMap); /** Helper function for link import operation * @@ -438,8 +467,9 @@ public: * This function searches for the name map and tries to find the imported * object from the given source object. */ - static App::DocumentObject *tryImport(const App::Document *doc, const App::DocumentObject *obj, - const std::map &nameMap); + static App::DocumentObject* tryImport(const App::Document* doc, + const App::DocumentObject* obj, + const std::map& nameMap); /** Helper function to export a subname reference * @@ -463,8 +493,10 @@ public: * restoreLabelReference() can be used together to restore the reference * during import. */ - static const char *exportSubName(std::string &output, - const App::DocumentObject *obj, const char *subname, bool first_obj=false); + static const char* exportSubName(std::string& output, + const App::DocumentObject* obj, + const char* subname, + bool first_obj = false); /** Helper function to import a subname reference * @@ -481,7 +513,7 @@ public: * after restore, by calling restoreLabelReference() in property's * afterRestore(). */ - static std::string importSubName(Base::XMLReader &reader, const char *sub, bool &restoreLabel); + static std::string importSubName(Base::XMLReader& reader, const char* sub, bool& restoreLabel); /** Helper function to restore label references during import * @@ -503,7 +535,9 @@ public: * afterRestore() function, which calls this function to do the string * parsing. */ - static void restoreLabelReference(const App::DocumentObject *obj, std::string &sub, ShadowSub *shadow=nullptr); + static void restoreLabelReference(const App::DocumentObject* obj, + std::string& sub, + ShadowSub* shadow = nullptr); /** Helper function to extract labels from a subname reference * @@ -515,7 +549,7 @@ public: * This function is used to extract label from subname reference for * registering of label changes. */ - static void getLabelReferences(std::vector &labels, const char *subname); + static void getLabelReferences(std::vector& labels, const char* subname); /** Helper function to collect changed property when an object re-label * @@ -525,8 +559,8 @@ public: * @return return a map from the affected property to a copy of it with * updated subname references */ - static std::vector > > updateLabelReferences( - App::DocumentObject *obj, const char *newLabel); + static std::vector>> + updateLabelReferences(App::DocumentObject* obj, const char* newLabel); /** Helper function to update subname reference on label change * @@ -547,47 +581,56 @@ public: * called, the sub object can still be reached using the original label * references, but not the new labels. */ - static std::string updateLabelReference(const App::DocumentObject *linked, const char *subname, - App::DocumentObject *obj, const std::string &ref, const char *newLabel); + static std::string updateLabelReference(const App::DocumentObject* linked, + const char* subname, + App::DocumentObject* obj, + const std::string& ref, + const char* newLabel); //@} - enum LinkFlags { + enum LinkFlags + { LinkAllowExternal, LinkDetached, LinkRestoring, LinkAllowPartial, LinkRestoreLabel, - LinkSyncSubObject, // used by DlgPropertyLink - LinkNewElement, // return new element name in getPyObject - LinkSilentRestore, // do not report error on restore (e.g. missing external link) + LinkSyncSubObject, // used by DlgPropertyLink + LinkNewElement, // return new element name in getPyObject + LinkSilentRestore, // do not report error on restore (e.g. missing external link) }; - inline bool testFlag(int flag) const { + inline bool testFlag(int flag) const + { return _Flags.test((std::size_t)flag); } - virtual void setAllowPartial(bool enable) { (void)enable; } + virtual void setAllowPartial(bool enable) + { + (void)enable; + } void setReturnNewElement(bool enable); void setSilentRestore(bool enable); - boost::signals2::signal signalUpdateElementReference; + boost::signals2::signal + signalUpdateElementReference; protected: void hasSetValue() override; protected: std::bitset<32> _Flags; - inline void setFlag(int flag, bool value=true) { - _Flags.set((std::size_t)flag,value); + inline void setFlag(int flag, bool value = true) + { + _Flags.set((std::size_t)flag, value); } - void _getLinksTo( - std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - const std::vector &subs, - const std::vector &shadows) const; + void _getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + const std::vector& subs, + const std::vector& shadows) const; private: std::set _LabelRefs; @@ -599,10 +642,10 @@ private: * property is scope aware, meaning it does define which objects are allowed to be linked depending * of the GeoFeatureGroup where it is in. Default is Local. * - * @note Links that are invalid in respect to the scope of this property is set to are not rejected. - * They are only detected to be invalid and prevent the feature from recomputing. + * @note Links that are invalid in respect to the scope of this property is set to are not + * rejected. They are only detected to be invalid and prevent the feature from recomputing. */ -class AppExport PropertyLink : public PropertyLinkBase +class AppExport PropertyLink: public PropertyLinkBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -623,98 +666,121 @@ public: /** Sets the property */ - virtual void setValue(App::DocumentObject *); + virtual void setValue(App::DocumentObject*); /** This method returns the linked DocumentObject */ - App::DocumentObject * getValue() const; + App::DocumentObject* getValue() const; /** Returns the link type checked */ - App::DocumentObject * getValue(Base::Type t) const; + App::DocumentObject* getValue(Base::Type t) const; - /** Returns the link type checked + /** Returns the link type checked */ - template - inline _type getValue() const { + template + inline _type getValue() const + { return _pcLink ? dynamic_cast<_type>(_pcLink) : 0; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject* value) 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(App::DocumentObject *); + unsigned int getMemSize() const override + { + return sizeof(App::DocumentObject*); } const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkItem"; } + { + return "Gui::PropertyEditor::PropertyLinkItem"; + } - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; + + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; protected: - App::DocumentObject *_pcLink{nullptr}; + App::DocumentObject* _pcLink {nullptr}; }; /** The general Link Property with Child scope */ -class AppExport PropertyLinkChild : public PropertyLink +class AppExport PropertyLinkChild: public PropertyLink { TYPESYSTEM_HEADER(); + public: - PropertyLinkChild() {_pcScope = LinkScope::Child;} + PropertyLinkChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkGlobal : public PropertyLink +class AppExport PropertyLinkGlobal: public PropertyLink { TYPESYSTEM_HEADER(); + public: - PropertyLinkGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkHidden : public PropertyLink +class AppExport PropertyLinkHidden: public PropertyLink { TYPESYSTEM_HEADER(); + public: - PropertyLinkHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkHidden() + { + _pcScope = LinkScope::Hidden; + } }; class AppExport PropertyLinkListBase: public PropertyLinkBase, public PropertyListsBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - void setPyObject(PyObject *obj) override { + void setPyObject(PyObject* obj) override + { _setPyObject(obj); } }; -class AppExport PropertyLinkList : - public PropertyListsT, PropertyLinkListBase> +class AppExport PropertyLinkList + : public PropertyListsT, PropertyLinkListBase> { TYPESYSTEM_HEADER_WITH_OVERRIDE(); - using inherited = PropertyListsT,PropertyLinkListBase>; + using inherited = + PropertyListsT, PropertyLinkListBase>; public: /** @@ -733,43 +799,48 @@ public: void setSize(int newSize, const_reference def) override; /** Sets the property - */ - void setValues(const std::vector&) override; + */ + void setValues(const std::vector& value) override; - void set1Value(int idx, DocumentObject * const &value) override; + void set1Value(int idx, DocumentObject* const& value) 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; - 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 - { return "Gui::PropertyEditor::PropertyLinkListItem"; } + { + return "Gui::PropertyEditor::PropertyLinkListItem"; + } - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - DocumentObject *findUsingMap(const std::string &, int *pindex=nullptr) const; - DocumentObject *find(const char *sub, int *pindex=nullptr) const; + DocumentObject* findUsingMap(const std::string&, int* pindex = nullptr) const; + DocumentObject* find(const char* sub, int* pindex = nullptr) const; protected: - DocumentObject *getPyValue(PyObject *item) const override; + DocumentObject* getPyValue(PyObject* item) const override; protected: mutable std::map _nameMap; @@ -777,29 +848,41 @@ protected: /** The general Link Property with Child scope */ -class AppExport PropertyLinkListChild : public PropertyLinkList +class AppExport PropertyLinkListChild: public PropertyLinkList { TYPESYSTEM_HEADER(); + public: - PropertyLinkListChild() {_pcScope = LinkScope::Child;} + PropertyLinkListChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkListGlobal : public PropertyLinkList +class AppExport PropertyLinkListGlobal: public PropertyLinkList { TYPESYSTEM_HEADER(); + public: - PropertyLinkListGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkListGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkListHidden : public PropertyLinkList +class AppExport PropertyLinkListHidden: public PropertyLinkList { TYPESYSTEM_HEADER(); + public: - PropertyLinkListHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkListHidden() + { + _pcScope = LinkScope::Hidden; + } }; /** the Link Property with sub elements @@ -808,7 +891,7 @@ public: * are stored as names, which can be resolved by the * ComplexGeoDataType interface to concrete sub objects. */ -class AppExport PropertyLinkSub : public PropertyLinkBase +class AppExport PropertyLinkSub: public PropertyLinkBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -830,123 +913,149 @@ public: /** Sets the property */ - void setValue(App::DocumentObject *,const std::vector &SubList, - std::vector &&ShadowSubList={}); - void setValue(App::DocumentObject *,std::vector &&SubList={}, - std::vector &&ShadowSubList={}); + void setValue(App::DocumentObject*, + const std::vector& SubList, + std::vector&& ShadowSubList = {}); + void setValue(App::DocumentObject*, + std::vector&& SubList = {}, + std::vector&& ShadowSubList = {}); /** This method returns the linked DocumentObject */ - App::DocumentObject * getValue() const; + App::DocumentObject* getValue() const; /// return the list of sub elements const std::vector& getSubValues() const; /// return the list of sub elements with mapped names - const std::vector &getShadowSubs() const { + const std::vector& getShadowSubs() const + { return _ShadowSubList; } std::vector getSubValues(bool newStyle) const; /// return the list of sub elements starts with a special string - std::vector getSubValuesStartsWith(const char*, bool newStyle=false) const; + std::vector getSubValuesStartsWith(const char*, bool newStyle = false) const; /** Returns the link type checked */ - App::DocumentObject * getValue(Base::Type t) const; + App::DocumentObject* getValue(Base::Type t) const; - /** Returns the link type checked + /** Returns the link type checked */ - template - inline _type getValue() const { + template + inline _type getValue() const + { return _pcLinkSub ? dynamic_cast<_type>(_pcLinkSub) : 0; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject* value) 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; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkItem"; } - - /// Return a copy of the property if any changes caused by importing external object - Property *CopyOnImportExternal(const std::map &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; - - unsigned int getMemSize () const override { - return sizeof(App::DocumentObject *); + { + return "Gui::PropertyEditor::PropertyLinkItem"; } - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + /// Return a copy of the property if any changes caused by importing external object + Property* + CopyOnImportExternal(const std::map& 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; + + unsigned int getMemSize() const override + { + return sizeof(App::DocumentObject*); + } + + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; void setSyncSubObject(bool enable); + protected: - App::DocumentObject* _pcLinkSub{nullptr}; + App::DocumentObject* _pcLinkSub {nullptr}; std::vector _cSubList; std::vector _ShadowSubList; std::vector _mapped; - bool _restoreLabel{false}; + bool _restoreLabel {false}; }; /** The general Link Property with Child scope */ -class AppExport PropertyLinkSubChild : public PropertyLinkSub +class AppExport PropertyLinkSubChild: public PropertyLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubChild() {_pcScope = LinkScope::Child;} + PropertyLinkSubChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkSubGlobal : public PropertyLinkSub +class AppExport PropertyLinkSubGlobal: public PropertyLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkSubGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkSubHidden : public PropertyLinkSub +class AppExport PropertyLinkSubHidden: public PropertyLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkSubHidden() + { + _pcScope = LinkScope::Hidden; + } }; -class AppExport PropertyLinkSubList : public PropertyLinkBase +class AppExport PropertyLinkSubList: public PropertyLinkBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - using SubSet = std::pair >; + using SubSet = std::pair>; /** * A constructor. * A more elaborate description of the constructor. @@ -968,22 +1077,28 @@ public: /** Sets the property. * setValue(0, whatever) clears the property */ - void setValue(DocumentObject*,const char*); - void setValues(const std::vector&,const std::vector&); - void setValues(const std::vector&,const std::vector&, - std::vector &&ShadowSubList={}); - void setValues(std::vector&&, std::vector &&subs, - std::vector &&ShadowSubList={}); + void setValue(DocumentObject*, const char*); + void setValues(const std::vector&, const std::vector&); + void setValues(const std::vector&, + const std::vector&, + std::vector&& ShadowSubList = {}); + void setValues(std::vector&&, + std::vector&& subs, + std::vector&& ShadowSubList = {}); /** * @brief setValue: PropertyLinkSub-compatible overload * @param SubList */ - void setValue(App::DocumentObject *lValue, const std::vector &SubList=std::vector()); + void setValue(App::DocumentObject* lValue, + const std::vector& SubList = std::vector()); - void addValue(App::DocumentObject *obj, const std::vector &SubList={}, bool reset = false); + void addValue(App::DocumentObject* obj, + const std::vector& SubList = {}, + bool reset = false); - const std::vector &getValues() const { + const std::vector& getValues() const + { return _lValueList; } @@ -997,13 +1112,15 @@ public: */ DocumentObject* getValue() const; - const std::vector &getSubValues() const { + const std::vector& getSubValues() const + { return _lSubList; } std::vector getSubValues(bool newStyle) const; - const std::vector &getShadowSubs() const { + const std::vector& getShadowSubs() const + { return _ShadowSubList; } @@ -1011,194 +1128,236 @@ public: * @brief Removes all occurrences of \a lValue in the property * together with its sub-elements and returns the number of entries removed. */ - int removeValue(App::DocumentObject *lValue); + int removeValue(App::DocumentObject* lValue); void setSubListValues(const std::vector&); - std::vector getSubListValues(bool newStyle=false) const; + std::vector getSubListValues(bool newStyle = false) const; - 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; - bool upgrade(Base::XMLReader &reader, const char *typeName); + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; + bool upgrade(Base::XMLReader& reader, const char* typeName); - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkListItem"; } + { + return "Gui::PropertyEditor::PropertyLinkListItem"; + } /// Return a copy of the property if any changes caused by importing external object - Property *CopyOnImportExternal(const std::map &nameMap) const override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) 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; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; void setSyncSubObject(bool enable); private: - void verifyObject(App::DocumentObject *, App::DocumentObject *); + void verifyObject(App::DocumentObject*, App::DocumentObject*); private: - //FIXME: Do not make two independent lists because this will lead to some inconsistencies! + // FIXME: Do not make two independent lists because this will lead to some inconsistencies! std::vector _lValueList; - std::vector _lSubList; + std::vector _lSubList; std::vector _ShadowSubList; std::vector _mapped; }; /** The general Link Property with Child scope */ -class AppExport PropertyLinkSubListChild : public PropertyLinkSubList +class AppExport PropertyLinkSubListChild: public PropertyLinkSubList { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubListChild() {_pcScope = LinkScope::Child;} + PropertyLinkSubListChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkSubListGlobal : public PropertyLinkSubList +class AppExport PropertyLinkSubListGlobal: public PropertyLinkSubList { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubListGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkSubListGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkSubListHidden : public PropertyLinkSubList +class AppExport PropertyLinkSubListHidden: public PropertyLinkSubList { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubListHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkSubListHidden() + { + _pcScope = LinkScope::Hidden; + } }; class PropertyXLinkSubList; /** Link to an (sub)object in the same or different document */ -class AppExport PropertyXLink : public PropertyLinkGlobal +class AppExport PropertyXLink: public PropertyLinkGlobal { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - explicit PropertyXLink(bool allowPartial=false, PropertyLinkBase *parent=nullptr); + explicit PropertyXLink(bool allowPartial = false, PropertyLinkBase* parent = nullptr); ~PropertyXLink() override; - PropertyLinkBase *parent() const { return parentProp; } + PropertyLinkBase* parent() const + { + return parentProp; + } void afterRestore() override; void onContainerRestored() override; - void setValue(App::DocumentObject *) override; - void setValue(App::DocumentObject *, const char *subname); + void setValue(App::DocumentObject*) override; + void setValue(App::DocumentObject*, const char* subname); - void setValue(std::string &&filePath, std::string &&objectName, std::vector &&SubList, - std::vector &&ShadowSubList = {}); + void setValue(std::string&& filePath, + std::string&& objectName, + std::vector&& SubList, + std::vector&& ShadowSubList = {}); - void setValue(App::DocumentObject *,std::vector &&SubList, - std::vector &&ShadowSubList = {}); + void setValue(App::DocumentObject*, + std::vector&& SubList, + std::vector&& ShadowSubList = {}); - void setValue(App::DocumentObject *,const std::vector &SubList, - std::vector &&ShadowSubList={}); + void setValue(App::DocumentObject*, + const std::vector& SubList, + std::vector&& ShadowSubList = {}); - void setSubValues(std::vector &&SubList, - std::vector &&ShadowSubList = {}); + void setSubValues(std::vector&& SubList, + std::vector&& ShadowSubList = {}); - const char *getSubName(bool newStyle=true) const; - void setSubName(const char *subname); + const char* getSubName(bool newStyle = true) const; + void setSubName(const char* subname); - bool hasSubName() const {return !_SubList.empty();} + bool hasSubName() const + { + return !_SubList.empty(); + } - App::Document *getDocument() const; - const char *getDocumentPath() const; - const char *getObjectName() const; + App::Document* getDocument() const; + const char* getDocumentPath() const; + const char* getObjectName() const; - int checkRestore(std::string *msg=nullptr) const override; + int checkRestore(std::string* msg = nullptr) const 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; /// Return a copy of the property if any changes caused by importing external object - Property *CopyOnImportExternal(const std::map &nameMap) const override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) 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; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; friend class DocInfo; - static bool supportXLink(const App::Property *prop); - static bool hasXLink(const App::Document *doc); - static bool hasXLink(const std::vector &objs, std::vector *unsaved=nullptr); - static std::map > getDocumentOutList(App::Document *doc=nullptr); - static std::map > getDocumentInList(App::Document *doc=nullptr); - static void restoreDocument(const App::Document &doc); + static bool supportXLink(const App::Property* prop); + static bool hasXLink(const App::Document* doc); + static bool hasXLink(const std::vector& objs, + std::vector* unsaved = nullptr); + static std::map> + getDocumentOutList(App::Document* doc = nullptr); + static std::map> + getDocumentInList(App::Document* doc = nullptr); + static void restoreDocument(const App::Document& doc); - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; - const std::vector& getSubValues() const { + const std::vector& getSubValues() const + { return _SubList; } - const std::vector &getShadowSubs() const { + const std::vector& getShadowSubs() const + { return _ShadowSubList; } std::vector getSubValues(bool newStyle) const; - std::vector getSubValuesStartsWith(const char*, bool newStyle=false) const; + std::vector getSubValuesStartsWith(const char*, bool newStyle = false) const; void setAllowPartial(bool enable) override; - const char *getFilePath() const { + const char* getFilePath() const + { return filePath.c_str(); } - virtual bool upgrade(Base::XMLReader &reader, const char *typeName); + virtual bool upgrade(Base::XMLReader& reader, const char* typeName); void setSyncSubObject(bool enable); @@ -1206,9 +1365,11 @@ protected: void unlink(); void detach(); - void restoreLink(App::DocumentObject *); + void restoreLink(App::DocumentObject*); - void copyTo(PropertyXLink &other, App::DocumentObject *linked=nullptr, std::vector *subs=nullptr) const; + void copyTo(PropertyXLink& other, + App::DocumentObject* linked = nullptr, + std::vector* subs = nullptr) const; void aboutToSetValue() override; @@ -1225,47 +1386,55 @@ protected: std::vector _SubList; std::vector _ShadowSubList; std::vector _mapped; - PropertyLinkBase *parentProp; + PropertyLinkBase* parentProp; mutable std::string tmpShadow; }; /** Link to one or more (sub)object from the same or different document */ -class AppExport PropertyXLinkSub: public PropertyXLink { +class AppExport PropertyXLinkSub: public PropertyXLink +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - explicit PropertyXLinkSub(bool allowPartial=false, PropertyLinkBase *parent=nullptr); + explicit PropertyXLinkSub(bool allowPartial = false, PropertyLinkBase* parent = nullptr); ~PropertyXLinkSub() override; - bool upgrade(Base::XMLReader &reader, const char *typeName) override; + bool upgrade(Base::XMLReader& reader, const char* typeName) override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkItem"; } + { + return "Gui::PropertyEditor::PropertyLinkItem"; + } }; /** The PropertyXLinkSub that is hidden from dependency checking */ -class AppExport PropertyXLinkSubHidden : public PropertyXLinkSub +class AppExport PropertyXLinkSubHidden: public PropertyXLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyXLinkSubHidden() { _pcScope = LinkScope::Hidden; } + PropertyXLinkSubHidden() + { + _pcScope = LinkScope::Hidden; + } }; /** Link to one or more (sub)object(s) of one or more object(s) from the same or different document */ -class AppExport PropertyXLinkSubList: public PropertyLinkBase - , public AtomicPropertyChangeInterface +class AppExport PropertyXLinkSubList: public PropertyLinkBase, + public AtomicPropertyChangeInterface { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - using atomic_change = typename AtomicPropertyChangeInterface::AtomicPropertyChange; + using atomic_change = + typename AtomicPropertyChangeInterface::AtomicPropertyChange; friend atomic_change; PropertyXLinkSubList(); @@ -1279,23 +1448,26 @@ public: /** Sets the property. * setValue(0, whatever) clears the property */ - void setValue(DocumentObject*,const char*); + void setValue(DocumentObject*, const char*); void setValues(const std::vector&); - void set1Value(int idx, DocumentObject *value, const std::vector &SubList={}); + void set1Value(int idx, DocumentObject* value, const std::vector& SubList = {}); - void setValues(const std::vector&,const std::vector&); - void setValues(const std::vector&,const std::vector&); - void setValues(std::map > &&); - void setValues(const std::map > &); + void setValues(const std::vector&, const std::vector&); + void setValues(const std::vector&, const std::vector&); + void setValues(std::map>&&); + void setValues(const std::map>&); - void addValue(App::DocumentObject *obj, const std::vector &SubList={}, bool reset=false); - void addValue(App::DocumentObject *obj, std::vector &&SubList={}, bool reset=false); + void addValue(App::DocumentObject* obj, + const std::vector& SubList = {}, + bool reset = false); + void + addValue(App::DocumentObject* obj, std::vector&& SubList = {}, bool reset = false); /** * @brief setValue: PropertyLinkSub-compatible overload * @param SubList */ - void setValue(App::DocumentObject *lValue, const std::vector &SubList={}); + void setValue(App::DocumentObject* lValue, const std::vector& SubList = {}); std::vector getValues() const; @@ -1303,81 +1475,89 @@ public: DocumentObject* getValue() const; - const std::vector &getSubValues(App::DocumentObject *obj) const; + const std::vector& getSubValues(App::DocumentObject* obj) const; - std::vector getSubValues(App::DocumentObject *obj, bool newStyle) const; + std::vector getSubValues(App::DocumentObject* obj, bool newStyle) const; - const std::vector &getShadowSubs(App::DocumentObject *obj) const; + const std::vector& getShadowSubs(App::DocumentObject* obj) const; /** * @brief Removes all occurrences of \a lValue in the property * together with its sub-elements and returns the number of entries removed. */ - int removeValue(App::DocumentObject *lValue); + int removeValue(App::DocumentObject* lValue); void setSubListValues(const std::vector&); - const std::list &getSubListValues() const { + const std::list& getSubListValues() const + { return _Links; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject* value) 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; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkListItem"; } + { + return "Gui::PropertyEditor::PropertyLinkListItem"; + } - Property *CopyOnImportExternal(const std::map &nameMap) const override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) 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; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; - bool upgrade(Base::XMLReader &reader, const char *typeName); + bool upgrade(Base::XMLReader& reader, const char* typeName); - int checkRestore(std::string *msg=nullptr) const override; + int checkRestore(std::string* msg = nullptr) const override; void setAllowPartial(bool enable) override; - void hasSetChildValue(Property &) override; - void aboutToSetChildValue(Property &) override; + void hasSetChildValue(Property&) override; + void aboutToSetChildValue(Property&) override; void setSyncSubObject(bool enable); protected: - void _getLinksToList( - std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - const std::vector &subs, - const std::vector &shadows) const; + void _getLinksToList(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + const std::vector& subs, + const std::vector& shadows) const; protected: std::list _Links; @@ -1390,15 +1570,16 @@ protected: * their getPyObject(). PropertyXLinkList will return a list of object is * there is no sub-object/sub-elements in the property. */ -class AppExport PropertyXLinkList: public PropertyXLinkSubList { +class AppExport PropertyXLinkList: public PropertyXLinkSubList +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: PropertyXLinkList(); ~PropertyXLinkList() override; - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; }; @@ -1406,50 +1587,57 @@ public: * * @sa See PropertyExpressionEngine for example usage */ -class AppExport PropertyXLinkContainer : public PropertyLinkBase { +class AppExport PropertyXLinkContainer: public PropertyLinkBase +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: PropertyXLinkContainer(); ~PropertyXLinkContainer() override; void afterRestore() override; - int checkRestore(std::string *msg=nullptr) const override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; - void breakLink(App::DocumentObject *obj, bool clear) override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + int checkRestore(std::string* msg = nullptr) const override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; + void breakLink(App::DocumentObject* obj, bool clear) override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - bool isLinkedToDocument(const App::Document &doc) const; + bool isLinkedToDocument(const App::Document& doc) const; protected: - void aboutToSetChildValue(App::Property &prop) override; - virtual PropertyXLink *createXLink(); - virtual void onBreakLink(App::DocumentObject *obj); - virtual void onAddDep(App::DocumentObject *) {} - virtual void onRemoveDep(App::DocumentObject *) {} - void updateDeps(std::map &&newDeps); + void aboutToSetChildValue(App::Property& prop) override; + virtual PropertyXLink* createXLink(); + virtual void onBreakLink(App::DocumentObject* obj); + virtual void onAddDep(App::DocumentObject*) + {} + virtual void onRemoveDep(App::DocumentObject*) + {} + void updateDeps(std::map&& newDeps); void clearDeps(); - void _onBreakLink(App::DocumentObject *obj); + void _onBreakLink(App::DocumentObject* obj); protected: - std::map _Deps; - std::map > _XLinks; + std::map _Deps; + std::map> _XLinks; std::map _DocMap; bool _LinkRestored; private: - struct RestoreInfo { + struct RestoreInfo + { std::unique_ptr xlink; std::string docName; std::string docLabel; - bool hidden=false; + bool hidden = false; }; - std::unique_ptr > _XLinkRestores; + std::unique_ptr> _XLinkRestores; }; -} // namespace App +} // namespace App -#endif // APP_PROPERTYLINKS_H +#endif // APP_PROPERTYLINKS_H diff --git a/src/App/PropertyPythonObject.cpp b/src/App/PropertyPythonObject.cpp index 63ac957b10..4141c022d6 100644 --- a/src/App/PropertyPythonObject.cpp +++ b/src/App/PropertyPythonObject.cpp @@ -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 += "<"; - else if (it == '"') + } + else if (it == '"') { tmp += """; - else if (it == '&') + } + else if (it == '&') { tmp += "&"; - else if (it == '>') + } + else if (it == '>') { tmp += ">"; - 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() << "toString(); + repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size()); + std::string val = /*encodeValue*/ (repr); + writer.Stream() << writer.ind() << "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() << "" << 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()) { Base::PyGILStateLocker lock; diff --git a/src/App/PropertyPythonObject.h b/src/App/PropertyPythonObject.h index cf1357a234..fb2a7a6dad 100644 --- a/src/App/PropertyPythonObject.h +++ b/src/App/PropertyPythonObject.h @@ -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 diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 2618506f2d..696afa0ec4 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -48,14 +48,12 @@ using namespace Base; using namespace std; - - //************************************************************************** //************************************************************************** // PropertyInteger //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyInteger , App::Property) +TYPESYSTEM_SOURCE(App::PropertyInteger, App::Property) //************************************************************************** // Construction/Destruction @@ -76,7 +74,7 @@ PropertyInteger::~PropertyInteger() = default; void PropertyInteger::setValue(long lValue) { aboutToSetValue(); - _lValue=lValue; + _lValue = lValue; hasSetValue(); } @@ -85,12 +83,12 @@ long PropertyInteger::getValue() const return _lValue; } -PyObject *PropertyInteger::getPyObject() +PyObject* PropertyInteger::getPyObject() { return Py_BuildValue("l", _lValue); } -void PropertyInteger::setPyObject(PyObject *value) +void PropertyInteger::setPyObject(PyObject* value) { if (PyLong_Check(value)) { aboutToSetValue(); @@ -104,12 +102,12 @@ void PropertyInteger::setPyObject(PyObject *value) } } -void PropertyInteger::Save (Base::Writer &writer) const +void PropertyInteger::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyInteger::Restore(Base::XMLReader &reader) +void PropertyInteger::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Integer"); @@ -117,36 +115,42 @@ void PropertyInteger::Restore(Base::XMLReader &reader) setValue(reader.getAttributeAsInteger("value")); } -Property *PropertyInteger::Copy() const +Property* PropertyInteger::Copy() const { - PropertyInteger *p= new PropertyInteger(); + PropertyInteger* p = new PropertyInteger(); p->_lValue = _lValue; return p; } -void PropertyInteger::Paste(const Property &from) +void PropertyInteger::Paste(const Property& from) { aboutToSetValue(); _lValue = dynamic_cast(from)._lValue; hasSetValue(); } -void PropertyInteger::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyInteger::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(long)) + if (value.type() == typeid(long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(int)) + } + else if (value.type() == typeid(int)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue(boost::math::round(boost::any_cast(value).getValue())); - else + } + else { throw bad_cast(); + } } @@ -155,7 +159,7 @@ void PropertyInteger::setPathValue(const ObjectIdentifier &path, const boost::an // PropertyPath //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPath , App::Property) +TYPESYSTEM_SOURCE(App::PropertyPath, App::Property) //************************************************************************** // Construction/Destruction @@ -172,32 +176,30 @@ PropertyPath::~PropertyPath() = default; //************************************************************************** // Setter/getter for the property -void PropertyPath::setValue(const boost::filesystem::path &Path) +void PropertyPath::setValue(const boost::filesystem::path& Path) { aboutToSetValue(); _cValue = Path; hasSetValue(); } -void PropertyPath::setValue(const char * Path) +void PropertyPath::setValue(const char* Path) { aboutToSetValue(); #if (BOOST_FILESYSTEM_VERSION == 2) - _cValue = boost::filesystem::path(Path,boost::filesystem::no_check ); - //_cValue = boost::filesystem::path(Path,boost::filesystem::native ); - //_cValue = boost::filesystem::path(Path,boost::filesystem::windows_name ); + _cValue = boost::filesystem::path(Path, boost::filesystem::no_check); #else _cValue = boost::filesystem::path(Path); #endif hasSetValue(); } -const boost::filesystem::path &PropertyPath::getValue() const +const boost::filesystem::path& PropertyPath::getValue() const { return _cValue; } -PyObject *PropertyPath::getPyObject() +PyObject* PropertyPath::getPyObject() { #if (BOOST_FILESYSTEM_VERSION == 2) std::string str = _cValue.native_file_string(); @@ -206,12 +208,14 @@ PyObject *PropertyPath::getPyObject() #endif // Returns a new reference, don't increment it! - PyObject *p = PyUnicode_DecodeUTF8(str.c_str(),str.size(),nullptr); - if (!p) throw Base::UnicodeError("UTF8 conversion failure at PropertyPath::getPyObject()"); + PyObject* p = PyUnicode_DecodeUTF8(str.c_str(), str.size(), nullptr); + if (!p) { + throw Base::UnicodeError("UTF8 conversion failure at PropertyPath::getPyObject()"); + } return p; } -void PropertyPath::setPyObject(PyObject *value) +void PropertyPath::setPyObject(PyObject* value) { std::string path; if (PyUnicode_Check(value)) { @@ -228,13 +232,13 @@ void PropertyPath::setPyObject(PyObject *value) } -void PropertyPath::Save (Base::Writer &writer) const +void PropertyPath::Save(Base::Writer& writer) const { std::string val = encodeAttribute(_cValue.string()); - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyPath::Restore(Base::XMLReader &reader) +void PropertyPath::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Path"); @@ -242,21 +246,21 @@ void PropertyPath::Restore(Base::XMLReader &reader) setValue(reader.getAttribute("value")); } -Property *PropertyPath::Copy() const +Property* PropertyPath::Copy() const { - PropertyPath *p= new PropertyPath(); + PropertyPath* p = new PropertyPath(); p->_cValue = _cValue; return p; } -void PropertyPath::Paste(const Property &from) +void PropertyPath::Paste(const Property& from) { aboutToSetValue(); _cValue = dynamic_cast(from)._cValue; hasSetValue(); } -unsigned int PropertyPath::getMemSize () const +unsigned int PropertyPath::getMemSize() const { return static_cast(_cValue.string().size()); } @@ -277,32 +281,34 @@ PropertyEnumeration::PropertyEnumeration() _editorTypeName = "Gui::PropertyEditor::PropertyEnumItem"; } -PropertyEnumeration::PropertyEnumeration(const App::Enumeration &e) +PropertyEnumeration::PropertyEnumeration(const App::Enumeration& e) { _enum = e; } PropertyEnumeration::~PropertyEnumeration() = default; -void PropertyEnumeration::setEnums(const char **plEnums) +void PropertyEnumeration::setEnums(const char** plEnums) { // For backward compatibility, if the property container is not attached to // any document (i.e. its full name starts with '?'), do not notify, or // else existing code may crash. bool notify = !boost::starts_with(getFullName(), "?"); - if (notify) + if (notify) { aboutToSetValue(); + } _enum.setEnums(plEnums); - if (notify) + if (notify) { hasSetValue(); + } } -void PropertyEnumeration::setEnums(const std::vector &Enums) +void PropertyEnumeration::setEnums(const std::vector& Enums) { setEnumVector(Enums); } -void PropertyEnumeration::setValue(const char *value) +void PropertyEnumeration::setValue(const char* value) { aboutToSetValue(); _enum.setValue(value); @@ -316,7 +322,7 @@ void PropertyEnumeration::setValue(long value) hasSetValue(); } -void PropertyEnumeration::setValue(const Enumeration &source) +void PropertyEnumeration::setValue(const Enumeration& source) { aboutToSetValue(); _enum = source; @@ -328,24 +334,25 @@ long PropertyEnumeration::getValue() const return _enum.getInt(); } -bool PropertyEnumeration::isValue(const char *value) const +bool PropertyEnumeration::isValue(const char* value) const { return _enum.isValue(value); } -bool PropertyEnumeration::isPartOf(const char *value) const +bool PropertyEnumeration::isPartOf(const char* value) const { return _enum.contains(value); } -const char * PropertyEnumeration::getValueAsString() const +const char* PropertyEnumeration::getValueAsString() const { - if (!_enum.isValid()) + if (!_enum.isValid()) { throw Base::RuntimeError("Cannot get value from invalid enumeration"); + } return _enum.getCStr(); } -const Enumeration & PropertyEnumeration::getEnum() const +const Enumeration& PropertyEnumeration::getEnum() const { return _enum; } @@ -355,17 +362,19 @@ std::vector PropertyEnumeration::getEnumVector() const return _enum.getEnumVector(); } -void PropertyEnumeration::setEnumVector(const std::vector &values) +void PropertyEnumeration::setEnumVector(const std::vector& values) { // For backward compatibility, if the property container is not attached to // any document (i.e. its full name starts with '?'), do not notify, or // else existing code may crash. bool notify = !boost::starts_with(getFullName(), "?"); - if (notify) + if (notify) { aboutToSetValue(); + } _enum.setEnums(values); - if (notify) + if (notify) { hasSetValue(); + } } bool PropertyEnumeration::hasEnums() const @@ -378,26 +387,28 @@ bool PropertyEnumeration::isValid() const return _enum.isValid(); } -void PropertyEnumeration::Save(Base::Writer &writer) const +void PropertyEnumeration::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; if (_enum.isCustom()) { std::vector items = getEnumVector(); - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" + << endl; writer.incInd(); - for(auto & item : items) { + for (auto& item : items) { std::string val = encodeAttribute(item); - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; } writer.decInd(); writer.Stream() << writer.ind() << "" << endl; } } -void PropertyEnumeration::Restore(Base::XMLReader &reader) +void PropertyEnumeration::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Integer"); @@ -411,7 +422,7 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::vector values(count); - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("Enum"); values[i] = reader.getAttribute("value"); } @@ -424,7 +435,9 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader) if (val < 0) { // If the enum is empty at this stage do not print a warning if (_enum.hasEnums()) { - Base::Console().DeveloperWarning(std::string("PropertyEnumeration"), "Enumeration index %d is out of range, ignore it\n", val); + Base::Console().DeveloperWarning(std::string("PropertyEnumeration"), + "Enumeration index %d is out of range, ignore it\n", + val); } val = getValue(); } @@ -433,7 +446,7 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader) hasSetValue(); } -PyObject * PropertyEnumeration::getPyObject() +PyObject* PropertyEnumeration::getPyObject() { if (!_enum.isValid()) { Py_Return; @@ -442,7 +455,7 @@ PyObject * PropertyEnumeration::getPyObject() return Py_BuildValue("s", getValueAsString()); } -void PropertyEnumeration::setPyObject(PyObject *value) +void PropertyEnumeration::setPyObject(PyObject* value) { if (PyLong_Check(value)) { long val = PyLong_AsLong(value); @@ -461,9 +474,8 @@ void PropertyEnumeration::setPyObject(PyObject *value) hasSetValue(); } else { - FC_THROWM(Base::ValueError, "'" << str - << "' is not part of the enumeration in " - << getFullName()); + FC_THROWM(Base::ValueError, + "'" << str << "' is not part of the enumeration in " << getFullName()); } return; } @@ -475,9 +487,9 @@ void PropertyEnumeration::setPyObject(PyObject *value) int idx = -1; Py::Sequence seq(value); - if(seq.size() == 2) { + if (seq.size() == 2) { Py::Object v(seq[0].ptr()); - if(!v.isString() && v.isSequence()) { + if (!v.isString() && v.isSequence()) { idx = Py::Int(seq[1].ptr()); seq = v; } @@ -485,54 +497,67 @@ void PropertyEnumeration::setPyObject(PyObject *value) values.resize(seq.size()); - for (int i = 0; i < seq.size(); ++i) + for (int i = 0; i < seq.size(); ++i) { values[i] = Py::Object(seq[i].ptr()).as_string(); + } aboutToSetValue(); _enum.setEnums(values); - if (idx>=0) - _enum.setValue(idx,true); + if (idx >= 0) { + _enum.setValue(idx, true); + } hasSetValue(); return; - } catch (Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException e; e.ReportException(); } } - FC_THROWM(Base::TypeError, "PropertyEnumeration " << getFullName() - << " expects type to be int, string, or list(string), or list(list, int)"); + FC_THROWM(Base::TypeError, + "PropertyEnumeration " + << getFullName() + << " expects type to be int, string, or list(string), or list(list, int)"); } -Property * PropertyEnumeration::Copy() const +Property* PropertyEnumeration::Copy() const { return new PropertyEnumeration(_enum); } -void PropertyEnumeration::Paste(const Property &from) +void PropertyEnumeration::Paste(const Property& from) { const PropertyEnumeration& prop = dynamic_cast(from); setValue(prop._enum); } -void PropertyEnumeration::setPathValue(const ObjectIdentifier &, const boost::any &value) +void PropertyEnumeration::setPathValue(const ObjectIdentifier&, const boost::any& value) { - if (value.type() == typeid(int)) + if (value.type() == typeid(int)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(long)) + } + else if (value.type() == typeid(long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(short)) + } + else if (value.type() == typeid(short)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(std::string)) + } + else if (value.type() == typeid(std::string)) { setValue(boost::any_cast(value).c_str()); - else if (value.type() == typeid(char*)) + } + else if (value.type() == typeid(char*)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(const char*)) + } + else if (value.type() == typeid(const char*)) { setValue(boost::any_cast(value)); + } else { Base::PyGILStateLocker lock; Py::Object pyValue = pyObjectFromAny(value); @@ -540,53 +565,59 @@ void PropertyEnumeration::setPathValue(const ObjectIdentifier &, const boost::an } } -bool PropertyEnumeration::setPyPathValue(const ObjectIdentifier &, const Py::Object &value) +bool PropertyEnumeration::setPyPathValue(const ObjectIdentifier&, const Py::Object& value) { setPyObject(value.ptr()); return true; } -const boost::any PropertyEnumeration::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyEnumeration::getPathValue(const ObjectIdentifier& path) const { std::string p = path.getSubPathStr(); if (p == ".Enum" || p == ".All") { Base::PyGILStateLocker lock; Py::Object res; getPyPathValue(path, res); - return pyObjectToAny(res,false); + return pyObjectToAny(res, false); } else if (p == ".String") { auto v = getValueAsString(); - return std::string(v?v:""); - } else + return std::string(v ? v : ""); + } + else { return getValue(); + } } -bool PropertyEnumeration::getPyPathValue(const ObjectIdentifier &path, Py::Object &r) const +bool PropertyEnumeration::getPyPathValue(const ObjectIdentifier& path, Py::Object& r) const { std::string p = path.getSubPathStr(); if (p == ".Enum" || p == ".All") { Base::PyGILStateLocker lock; - Py::Tuple res(_enum.maxValue()+1); + Py::Tuple res(_enum.maxValue() + 1); std::vector enums = _enum.getEnumVector(); PropertyString tmp; - for(int i=0;i< int(enums.size());++i) { + for (int i = 0; i < int(enums.size()); ++i) { tmp.setValue(enums[i]); - res.setItem(i,Py::asObject(tmp.getPyObject())); + res.setItem(i, Py::asObject(tmp.getPyObject())); } - if (p == ".Enum") + if (p == ".Enum") { r = res; + } else { Py::Tuple tuple(2); tuple.setItem(0, res); tuple.setItem(1, Py::Int(getValue())); r = tuple; } - } else if (p == ".String") { + } + else if (p == ".String") { auto v = getValueAsString(); - r = Py::String(v?v:""); - } else + r = Py::String(v ? v : ""); + } + else { r = Py::Int(getValue()); + } return true; } @@ -605,57 +636,64 @@ PropertyIntegerConstraint::PropertyIntegerConstraint() = default; PropertyIntegerConstraint::~PropertyIntegerConstraint() { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } void PropertyIntegerConstraint::setConstraints(const Constraints* sConstrain) { if (_ConstStruct != sConstrain) { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } _ConstStruct = sConstrain; } -const PropertyIntegerConstraint::Constraints* PropertyIntegerConstraint::getConstraints() const +const PropertyIntegerConstraint::Constraints* PropertyIntegerConstraint::getConstraints() const { return _ConstStruct; } long PropertyIntegerConstraint::getMinimum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->LowerBound; + } // return the min of int, not long return std::numeric_limits::min(); } long PropertyIntegerConstraint::getMaximum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->UpperBound; + } // return the max of int, not long return std::numeric_limits::max(); } long PropertyIntegerConstraint::getStepSize() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->StepSize; + } return 1; } -void PropertyIntegerConstraint::setPyObject(PyObject *value) +void PropertyIntegerConstraint::setPyObject(PyObject* value) { if (PyLong_Check(value)) { long temp = PyLong_AsLong(value); 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; + } } aboutToSetValue(); @@ -664,13 +702,15 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value) } else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) { long values[4]; - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) { PyObject* item; - item = PyTuple_GetItem(value,i); - if (PyLong_Check(item)) + item = PyTuple_GetItem(value, i); + if (PyLong_Check(item)) { values[i] = PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Type in tuple must be int"); + } } Constraints* c = new Constraints(); @@ -678,10 +718,12 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value) c->LowerBound = values[1]; c->UpperBound = values[2]; c->StepSize = std::max(1, values[3]); - if (values[0] > c->UpperBound) + if (values[0] > c->UpperBound) { values[0] = c->UpperBound; - else if (values[0] < c->LowerBound) + } + else if (values[0] < c->LowerBound) { values[0] = c->LowerBound; + } setConstraints(c); aboutToSetValue(); @@ -700,9 +742,9 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value) // PropertyPercent //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPercent , App::PropertyIntegerConstraint) +TYPESYSTEM_SOURCE(App::PropertyPercent, App::PropertyIntegerConstraint) -const PropertyIntegerConstraint::Constraints percent = {0,100,1}; +const PropertyIntegerConstraint::Constraints percent = {0, 100, 1}; //************************************************************************** // Construction/Destruction @@ -720,7 +762,7 @@ PropertyPercent::~PropertyPercent() = default; // PropertyIntegerList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyIntegerList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyIntegerList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -733,33 +775,37 @@ PropertyIntegerList::~PropertyIntegerList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyIntegerList::getPyObject() +PyObject* PropertyIntegerList::getPyObject() { PyObject* list = PyList_New(getSize()); - for(int i = 0;iob_type->tp_name; throw Base::TypeError(error); } -void PropertyIntegerList::Save (Base::Writer &writer) const +void PropertyIntegerList::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(int i = 0;i" << endl; ; + for (int i = 0; i < getSize(); i++) { + writer.Stream() << writer.ind() << "" << endl; + }; writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyIntegerList::Restore(Base::XMLReader &reader) +void PropertyIntegerList::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("IntegerList"); @@ -767,43 +813,41 @@ void PropertyIntegerList::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::vector values(count); - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("I"); values[i] = reader.getAttributeAsInteger("v"); } reader.readEndElement("IntegerList"); - //assignment + // assignment setValues(values); } -Property *PropertyIntegerList::Copy() const +Property* PropertyIntegerList::Copy() const { - PropertyIntegerList *p= new PropertyIntegerList(); + PropertyIntegerList* p = new PropertyIntegerList(); p->_lValueList = _lValueList; return p; } -void PropertyIntegerList::Paste(const Property &from) +void PropertyIntegerList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyIntegerList::getMemSize () const +unsigned int PropertyIntegerList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(long)); } - - //************************************************************************** //************************************************************************** // PropertyIntegerSet //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyIntegerSet , App::Property) +TYPESYSTEM_SOURCE(App::PropertyIntegerSet, App::Property) //************************************************************************** // Construction/Destruction @@ -832,15 +876,16 @@ void PropertyIntegerSet::setValues(const std::set& values) hasSetValue(); } -PyObject *PropertyIntegerSet::getPyObject() +PyObject* PropertyIntegerSet::getPyObject() { PyObject* set = PySet_New(nullptr); - for(long it : _lValueSet) - PySet_Add(set,PyLong_FromLong(it)); + for (long it : _lValueSet) { + PySet_Add(set, PyLong_FromLong(it)); + } return set; } -void PropertyIntegerSet::setPyObject(PyObject *value) +void PropertyIntegerSet::setPyObject(PyObject* value) { if (PySequence_Check(value)) { @@ -848,7 +893,7 @@ void PropertyIntegerSet::setPyObject(PyObject *value) Py_ssize_t nSize = sequence.size(); std::set values; - for (Py_ssize_t i=0; i" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(long it : _lValueSet) - writer.Stream() << writer.ind() << "" << endl; ; + for (long it : _lValueSet) { + writer.Stream() << writer.ind() << "" << endl; + }; writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyIntegerSet::Restore(Base::XMLReader &reader) +void PropertyIntegerSet::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("IntegerSet"); @@ -888,44 +934,43 @@ void PropertyIntegerSet::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::set values; - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("I"); values.insert(reader.getAttributeAsInteger("v")); } reader.readEndElement("IntegerSet"); - //assignment + // assignment setValues(values); } -Property *PropertyIntegerSet::Copy() const +Property* PropertyIntegerSet::Copy() const { - PropertyIntegerSet *p= new PropertyIntegerSet(); + PropertyIntegerSet* p = new PropertyIntegerSet(); p->_lValueSet = _lValueSet; return p; } -void PropertyIntegerSet::Paste(const Property &from) +void PropertyIntegerSet::Paste(const Property& from) { aboutToSetValue(); _lValueSet = dynamic_cast(from)._lValueSet; hasSetValue(); } -unsigned int PropertyIntegerSet::getMemSize () const +unsigned int PropertyIntegerSet::getMemSize() const { return static_cast(_lValueSet.size() * sizeof(long)); } - //************************************************************************** //************************************************************************** // PropertyFloat //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFloat , App::Property) +TYPESYSTEM_SOURCE(App::PropertyFloat, App::Property) //************************************************************************** // Construction/Destruction @@ -944,7 +989,7 @@ PropertyFloat::~PropertyFloat() = default; void PropertyFloat::setValue(double lValue) { aboutToSetValue(); - _dValue=lValue; + _dValue = lValue; hasSetValue(); } @@ -953,19 +998,19 @@ double PropertyFloat::getValue() const return _dValue; } -PyObject *PropertyFloat::getPyObject() +PyObject* PropertyFloat::getPyObject() { return Py_BuildValue("d", _dValue); } -void PropertyFloat::setPyObject(PyObject *value) +void PropertyFloat::setPyObject(PyObject* value) { if (PyFloat_Check(value)) { aboutToSetValue(); _dValue = PyFloat_AsDouble(value); hasSetValue(); } - else if(PyLong_Check(value)) { + else if (PyLong_Check(value)) { aboutToSetValue(); _dValue = PyLong_AsLong(value); hasSetValue(); @@ -977,12 +1022,12 @@ void PropertyFloat::setPyObject(PyObject *value) } } -void PropertyFloat::Save (Base::Writer &writer) const +void PropertyFloat::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyFloat::Restore(Base::XMLReader &reader) +void PropertyFloat::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Float"); @@ -990,41 +1035,48 @@ void PropertyFloat::Restore(Base::XMLReader &reader) setValue(reader.getAttributeAsFloat("value")); } -Property *PropertyFloat::Copy() const +Property* PropertyFloat::Copy() const { - PropertyFloat *p= new PropertyFloat(); + PropertyFloat* p = new PropertyFloat(); p->_dValue = _dValue; return p; } -void PropertyFloat::Paste(const Property &from) +void PropertyFloat::Paste(const Property& from) { aboutToSetValue(); _dValue = dynamic_cast(from)._dValue; hasSetValue(); } -void PropertyFloat::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyFloat::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(long)) + if (value.type() == typeid(long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(unsigned long)) + } + else if (value.type() == typeid(unsigned long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(int)) + } + else if (value.type() == typeid(int)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue((boost::any_cast(value)).getValue()); - else + } + else { throw bad_cast(); + } } -const boost::any PropertyFloat::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyFloat::getPathValue(const ObjectIdentifier& path) const { verifyPath(path); return _dValue; @@ -1045,54 +1097,61 @@ PropertyFloatConstraint::PropertyFloatConstraint() = default; PropertyFloatConstraint::~PropertyFloatConstraint() { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } void PropertyFloatConstraint::setConstraints(const Constraints* sConstrain) { if (_ConstStruct != sConstrain) { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } _ConstStruct = sConstrain; } -const PropertyFloatConstraint::Constraints* PropertyFloatConstraint::getConstraints() const +const PropertyFloatConstraint::Constraints* PropertyFloatConstraint::getConstraints() const { return _ConstStruct; } double PropertyFloatConstraint::getMinimum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->LowerBound; + } return std::numeric_limits::min(); } double PropertyFloatConstraint::getMaximum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->UpperBound; + } return std::numeric_limits::max(); } double PropertyFloatConstraint::getStepSize() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->StepSize; + } return 1.0; } -void PropertyFloatConstraint::setPyObject(PyObject *value) +void PropertyFloatConstraint::setPyObject(PyObject* value) { if (PyFloat_Check(value)) { double temp = PyFloat_AsDouble(value); 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; + } } aboutToSetValue(); @@ -1102,10 +1161,12 @@ void PropertyFloatConstraint::setPyObject(PyObject *value) else if (PyLong_Check(value)) { double temp = (double)PyLong_AsLong(value); 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; + } } aboutToSetValue(); @@ -1114,31 +1175,37 @@ void PropertyFloatConstraint::setPyObject(PyObject *value) } else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) { double values[4]; - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) { PyObject* item; - item = PyTuple_GetItem(value,i); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, i); + if (PyFloat_Check(item)) { values[i] = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { values[i] = PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Type in tuple must be float or int"); + } } double stepSize = values[3]; // need a value > 0 - if (stepSize < DBL_EPSILON) + if (stepSize < DBL_EPSILON) { throw Base::ValueError("Step size must be greater than zero"); + } Constraints* c = new Constraints(); c->setDeletable(true); c->LowerBound = values[1]; c->UpperBound = values[2]; c->StepSize = stepSize; - if (values[0] > c->UpperBound) + if (values[0] > c->UpperBound) { values[0] = c->UpperBound; - else if (values[0] < c->LowerBound) + } + else if (values[0] < c->LowerBound) { values[0] = c->LowerBound; + } setConstraints(c); aboutToSetValue(); @@ -1161,7 +1228,7 @@ TYPESYSTEM_SOURCE(App::PropertyPrecision, App::PropertyFloatConstraint) //************************************************************************** // Construction/Destruction // -const PropertyFloatConstraint::Constraints PrecisionStandard = {0.0,DBL_MAX,0.001}; +const PropertyFloatConstraint::Constraints PrecisionStandard = {0.0, DBL_MAX, 0.001}; PropertyPrecision::PropertyPrecision() { @@ -1175,7 +1242,7 @@ PropertyPrecision::~PropertyPrecision() = default; // PropertyFloatList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFloatList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyFloatList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -1188,54 +1255,60 @@ PropertyFloatList::~PropertyFloatList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyFloatList::getPyObject() +PyObject* PropertyFloatList::getPyObject() { PyObject* list = PyList_New(getSize()); - for (int i = 0;i(PyLong_AsLong(item)); - } else { + } + else { std::string error = std::string("type in list must be float, not "); error += item->ob_type->tp_name; throw Base::TypeError(error); } } -void PropertyFloatList::Save (Base::Writer &writer) const +void PropertyFloatList::Save(Base::Writer& writer) const { if (writer.isForceXML()) { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(int i = 0;i" << endl; ; + for (int i = 0; i < getSize(); i++) { + writer.Stream() << writer.ind() << "" << endl; + }; writer.decInd(); - writer.Stream() << writer.ind() <<"" << endl ; + writer.Stream() << writer.ind() << "" << endl; } else { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; } } -void PropertyFloatList::Restore(Base::XMLReader &reader) +void PropertyFloatList::Restore(Base::XMLReader& reader) { reader.readElement("FloatList"); - 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); } } -void PropertyFloatList::SaveDocFile (Base::Writer &writer) const +void PropertyFloatList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); @@ -1253,19 +1326,19 @@ void PropertyFloatList::SaveDocFile (Base::Writer &writer) const } } -void PropertyFloatList::RestoreDocFile(Base::Reader &reader) +void PropertyFloatList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); if (!isSinglePrecision()) { - for (double & it : values) { + for (double& it : values) { str >> it; } } else { - for (double & it : values) { + for (double& it : values) { float val; str >> val; it = val; @@ -1274,19 +1347,19 @@ void PropertyFloatList::RestoreDocFile(Base::Reader &reader) setValues(values); } -Property *PropertyFloatList::Copy() const +Property* PropertyFloatList::Copy() const { - PropertyFloatList *p= new PropertyFloatList(); + PropertyFloatList* p = new PropertyFloatList(); p->_lValueList = _lValueList; return p; } -void PropertyFloatList::Paste(const Property &from) +void PropertyFloatList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyFloatList::getMemSize () const +unsigned int PropertyFloatList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(double)); } @@ -1296,7 +1369,7 @@ unsigned int PropertyFloatList::getMemSize () const // PropertyString //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyString , App::Property) +TYPESYSTEM_SOURCE(App::PropertyString, App::Property) PropertyString::PropertyString() = default; @@ -1304,43 +1377,46 @@ PropertyString::~PropertyString() = default; void PropertyString::setValue(const char* newLabel) { - if(!newLabel) + if (!newLabel) { return; + } - if(_cValue == newLabel) + if (_cValue == newLabel) { return; + } std::string _newLabel; - std::vector > > propChanges; + std::vector>> propChanges; std::string label; auto obj = dynamic_cast(getContainer()); bool commit = false; - if(obj && obj->isAttachedToDocument() && this==&obj->Label && - (!obj->getDocument()->testStatus(App::Document::Restoring)|| - obj->getDocument()->testStatus(App::Document::Importing)) && - !obj->getDocument()->isPerformingTransaction()) - { + if (obj && obj->isAttachedToDocument() && this == &obj->Label + && (!obj->getDocument()->testStatus(App::Document::Restoring) + || obj->getDocument()->testStatus(App::Document::Importing)) + && !obj->getDocument()->isPerformingTransaction()) { // allow object to control label change static ParameterGrp::handle _hPGrp; - if(!_hPGrp) { + if (!_hPGrp) { _hPGrp = GetApplication().GetUserParameter().GetGroup("BaseApp"); _hPGrp = _hPGrp->GetGroup("Preferences")->GetGroup("Document"); } App::Document* doc = obj->getDocument(); - if(doc && !_hPGrp->GetBool("DuplicateLabels") && !obj->allowDuplicateLabel()) { + if (doc && !_hPGrp->GetBool("DuplicateLabels") && !obj->allowDuplicateLabel()) { std::vector objectLabels; std::vector::const_iterator it; std::vector objs = doc->getObjects(); bool match = false; - for (it = objs.begin();it != objs.end();++it) { - if (*it == obj) - continue; // don't compare object with itself + for (it = objs.begin(); it != objs.end(); ++it) { + if (*it == obj) { + continue; // don't compare object with itself + } std::string objLabel = (*it)->Label.getValue(); - if (!match && objLabel == newLabel) + if (!match && objLabel == newLabel) { match = true; + } objectLabels.push_back(objLabel); } @@ -1348,48 +1424,52 @@ void PropertyString::setValue(const char* newLabel) if (match && *newLabel) { label = newLabel; // remove number from end to avoid lengthy names - size_t lastpos = label.length()-1; + size_t lastpos = label.length() - 1; while (label[lastpos] >= 48 && label[lastpos] <= 57) { // if 'lastpos' becomes 0 then all characters are digits. In this case we use // the complete label again if (lastpos == 0) { - lastpos = label.length()-1; + lastpos = label.length() - 1; break; } lastpos--; } bool changed = false; - label = label.substr(0,lastpos+1); - if(label != obj->getNameInDocument() - && boost::starts_with(obj->getNameInDocument(),label)) - { + label = label.substr(0, lastpos + 1); + if (label != obj->getNameInDocument() + && boost::starts_with(obj->getNameInDocument(), label)) { // In case the label has the same base name as object's // internal name, use it as the label instead. - const char *objName = obj->getNameInDocument(); - const char *c = &objName[lastpos+1]; - for(;*c;++c) { - if(*c<48 || *c>57) + const char* objName = obj->getNameInDocument(); + const char* c = &objName[lastpos + 1]; + for (; *c; ++c) { + if (*c < 48 || *c > 57) { break; + } } - if(*c == 0 && std::find(objectLabels.begin(), objectLabels.end(), - obj->getNameInDocument())==objectLabels.end()) - { + if (*c == 0 + && std::find(objectLabels.begin(), + objectLabels.end(), + obj->getNameInDocument()) + == objectLabels.end()) { label = obj->getNameInDocument(); changed = true; } } - if(!changed) + if (!changed) { label = Base::Tools::getUniqueName(label, objectLabels, 3); + } } } - if(label.empty()) + if (label.empty()) { label = newLabel; + } obj->onBeforeChangeLabel(label); newLabel = label.c_str(); - if(!obj->getDocument()->testStatus(App::Document::Restoring)) { + if (!obj->getDocument()->testStatus(App::Document::Restoring)) { // Only update label reference if we are not restoring. When // importing (which also counts as restoring), it is possible the // new object changes its label. However, we cannot update label @@ -1397,10 +1477,10 @@ void PropertyString::setValue(const char* newLabel) // dependency order. It can only be done in afterRestore(). // // See PropertyLinkBase::restoreLabelReference() for more details. - propChanges = PropertyLinkBase::updateLabelReferences(obj,newLabel); + propChanges = PropertyLinkBase::updateLabelReferences(obj, newLabel); } - if(!propChanges.empty() && !GetApplication().getActiveTransaction()) { + if (!propChanges.empty() && !GetApplication().getActiveTransaction()) { commit = true; std::ostringstream str; str << "Change " << obj->getNameInDocument() << ".Label"; @@ -1412,14 +1492,16 @@ void PropertyString::setValue(const char* newLabel) _cValue = newLabel; hasSetValue(); - for(auto &change : propChanges) + for (auto& change : propChanges) { change.first->Paste(*change.second.get()); + } - if(commit) + if (commit) { GetApplication().closeActiveTransaction(); + } } -void PropertyString::setValue(const std::string &sString) +void PropertyString::setValue(const std::string& sString) { setValue(sString.c_str()); } @@ -1429,14 +1511,16 @@ const char* PropertyString::getValue() const return _cValue.c_str(); } -PyObject *PropertyString::getPyObject() +PyObject* PropertyString::getPyObject() { - PyObject *p = PyUnicode_DecodeUTF8(_cValue.c_str(),_cValue.size(),nullptr); - if (!p) throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()"); + PyObject* p = PyUnicode_DecodeUTF8(_cValue.c_str(), _cValue.size(), nullptr); + if (!p) { + throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()"); + } return p; } -void PropertyString::setPyObject(PyObject *value) +void PropertyString::setPyObject(PyObject* value) { std::string string; if (PyUnicode_Check(value)) { @@ -1452,90 +1536,103 @@ void PropertyString::setPyObject(PyObject *value) setValue(string); } -void PropertyString::Save (Base::Writer &writer) const +void PropertyString::Save(Base::Writer& writer) const { std::string val; auto obj = dynamic_cast(getContainer()); writer.Stream() << writer.ind() << "isAttachedToDocument() && - obj->isExporting() && &obj->Label==this) - { - if(obj->allowDuplicateLabel()) - writer.Stream() <<"restore=\"1\" "; - else if(_cValue==obj->getNameInDocument()) { - writer.Stream() <<"restore=\"0\" "; + if (obj && obj->isAttachedToDocument() && obj->isExporting() && &obj->Label == this) { + if (obj->allowDuplicateLabel()) { + writer.Stream() << "restore=\"1\" "; + } + else if (_cValue == obj->getNameInDocument()) { + writer.Stream() << "restore=\"0\" "; val = encodeAttribute(obj->getExportName()); exported = true; } } - if(!exported) + if (!exported) { val = encodeAttribute(_cValue); - writer.Stream() <<"value=\"" << val <<"\"/>" << std::endl; + } + writer.Stream() << "value=\"" << val << "\"/>" << std::endl; } -void PropertyString::Restore(Base::XMLReader &reader) +void PropertyString::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("String"); // get the value of my Attribute auto obj = dynamic_cast(getContainer()); - if(obj && &obj->Label==this) { - if(reader.hasAttribute("restore")) { + if (obj && &obj->Label == this) { + if (reader.hasAttribute("restore")) { int restore = reader.getAttributeAsInteger("restore"); - if(restore == 1) { + if (restore == 1) { aboutToSetValue(); _cValue = reader.getAttribute("value"); hasSetValue(); - }else + } + else { setValue(reader.getName(reader.getAttribute("value"))); - } else + } + } + else { setValue(reader.getAttribute("value")); - }else + } + } + else { setValue(reader.getAttribute("value")); + } } -Property *PropertyString::Copy() const +Property* PropertyString::Copy() const { - PropertyString *p= new PropertyString(); + PropertyString* p = new PropertyString(); p->_cValue = _cValue; return p; } -void PropertyString::Paste(const Property &from) +void PropertyString::Paste(const Property& from) { setValue(dynamic_cast(from)._cValue); } -unsigned int PropertyString::getMemSize () const +unsigned int PropertyString::getMemSize() const { return static_cast(_cValue.size()); } -void PropertyString::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyString::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(bool)) - setValue(boost::any_cast(value)?"True":"False"); - else if (value.type() == typeid(int)) + if (value.type() == typeid(bool)) { + setValue(boost::any_cast(value) ? "True" : "False"); + } + else if (value.type() == typeid(int)) { setValue(std::to_string(boost::any_cast(value))); - else if (value.type() == typeid(long)) + } + else if (value.type() == typeid(long)) { setValue(std::to_string(boost::any_cast(value))); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(std::to_string(App::any_cast(value))); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(std::to_string(App::any_cast(value))); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue(boost::any_cast(value).getUserString().toUtf8().constData()); - else if (value.type() == typeid(std::string)) - setValue(boost::any_cast(value)); + } + else if (value.type() == typeid(std::string)) { + setValue(boost::any_cast(value)); + } else { Base::PyGILStateLocker lock; setValue(pyObjectFromAny(value).as_string()); } } -const boost::any PropertyString::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyString::getPathValue(const ObjectIdentifier& path) const { verifyPath(path); return _cValue; @@ -1546,13 +1643,13 @@ const boost::any PropertyString::getPathValue(const ObjectIdentifier &path) cons // PropertyUUID //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyUUID , App::Property) +TYPESYSTEM_SOURCE(App::PropertyUUID, App::Property) PropertyUUID::PropertyUUID() = default; PropertyUUID::~PropertyUUID() = default; -void PropertyUUID::setValue(const Base::Uuid &id) +void PropertyUUID::setValue(const Base::Uuid& id) { aboutToSetValue(); _uuid = id; @@ -1568,7 +1665,7 @@ void PropertyUUID::setValue(const char* sString) } } -void PropertyUUID::setValue(const std::string &sString) +void PropertyUUID::setValue(const std::string& sString) { aboutToSetValue(); _uuid.setValue(sString); @@ -1585,13 +1682,13 @@ const Base::Uuid& PropertyUUID::getValue() const return _uuid; } -PyObject *PropertyUUID::getPyObject() +PyObject* PropertyUUID::getPyObject() { - PyObject *p = PyUnicode_FromString(_uuid.getValue().c_str()); + PyObject* p = PyUnicode_FromString(_uuid.getValue().c_str()); return p; } -void PropertyUUID::setPyObject(PyObject *value) +void PropertyUUID::setPyObject(PyObject* value) { std::string string; if (PyUnicode_Check(value)) { @@ -1614,12 +1711,12 @@ void PropertyUUID::setPyObject(PyObject *value) } } -void PropertyUUID::Save (Base::Writer &writer) const +void PropertyUUID::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyUUID::Restore(Base::XMLReader &reader) +void PropertyUUID::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Uuid"); @@ -1627,21 +1724,21 @@ void PropertyUUID::Restore(Base::XMLReader &reader) setValue(reader.getAttribute("value")); } -Property *PropertyUUID::Copy() const +Property* PropertyUUID::Copy() const { - PropertyUUID *p= new PropertyUUID(); + PropertyUUID* p = new PropertyUUID(); p->_uuid = _uuid; return p; } -void PropertyUUID::Paste(const Property &from) +void PropertyUUID::Paste(const Property& from) { aboutToSetValue(); _uuid = dynamic_cast(from)._uuid; hasSetValue(); } -unsigned int PropertyUUID::getMemSize () const +unsigned int PropertyUUID::getMemSize() const { return static_cast(sizeof(_uuid)); } @@ -1650,7 +1747,7 @@ unsigned int PropertyUUID::getMemSize () const // PropertyFont //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFont , App::PropertyString) +TYPESYSTEM_SOURCE(App::PropertyFont, App::PropertyString) PropertyFont::PropertyFont() = default; @@ -1660,7 +1757,7 @@ PropertyFont::~PropertyFont() = default; // PropertyStringList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyStringList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyStringList, App::PropertyLists) PropertyStringList::PropertyStringList() = default; @@ -1673,20 +1770,23 @@ void PropertyStringList::setValues(const std::list& lValue) { std::vector vals; vals.reserve(lValue.size()); - for(const auto &v : lValue) + for (const auto& v : lValue) { vals.push_back(v); + } setValues(vals); } -PyObject *PropertyStringList::getPyObject() +PyObject* PropertyStringList::getPyObject() { PyObject* list = PyList_New(getSize()); - for (int i = 0;iob_type->tp_name; throw Base::TypeError(error); @@ -1709,27 +1811,28 @@ std::string PropertyStringList::getPyValue(PyObject *item) const return ret; } -unsigned int PropertyStringList::getMemSize () const +unsigned int PropertyStringList::getMemSize() const { - size_t size=0; - for(int i = 0;i(size); } -void PropertyStringList::Save (Base::Writer &writer) const +void PropertyStringList::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(int i = 0;i" << endl; + writer.Stream() << writer.ind() << "" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyStringList::Restore(Base::XMLReader &reader) +void PropertyStringList::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("StringList"); @@ -1737,7 +1840,7 @@ void PropertyStringList::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::vector values(count); - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("String"); values[i] = reader.getAttribute("value"); } @@ -1748,14 +1851,14 @@ void PropertyStringList::Restore(Base::XMLReader &reader) setValues(values); } -Property *PropertyStringList::Copy() const +Property* PropertyStringList::Copy() const { - PropertyStringList *p= new PropertyStringList(); + PropertyStringList* p = new PropertyStringList(); p->_lValueList = _lValueList; return p; } -void PropertyStringList::Paste(const Property &from) +void PropertyStringList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } @@ -1765,7 +1868,7 @@ void PropertyStringList::Paste(const Property &from) // PropertyMap //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyMap , App::Property) +TYPESYSTEM_SOURCE(App::PropertyMap, App::Property) PropertyMap::PropertyMap() = default; @@ -1780,62 +1883,59 @@ int PropertyMap::getSize() const return static_cast(_lValueList.size()); } -void PropertyMap::setValue(const std::string& key,const std::string& value) +void PropertyMap::setValue(const std::string& key, const std::string& value) { aboutToSetValue(); _lValueList[key] = value; hasSetValue(); } -void PropertyMap::setValues(const std::map& map) +void PropertyMap::setValues(const std::map& map) { aboutToSetValue(); - _lValueList=map; + _lValueList = map; hasSetValue(); } - - -const std::string& PropertyMap::operator[] (const std::string& key) const +const std::string& PropertyMap::operator[](const std::string& key) const { static std::string empty; - std::map::const_iterator it = _lValueList.find(key); - if(it!=_lValueList.end()) + auto it = _lValueList.find(key); + if (it != _lValueList.end()) { return it->second; - else - return empty; + } + return empty; } - -PyObject *PropertyMap::getPyObject() +PyObject* PropertyMap::getPyObject() { PyObject* dict = PyDict_New(); - for (std::map::const_iterator it = _lValueList.begin();it!= _lValueList.end(); ++it) { + for (auto it = _lValueList.begin(); it != _lValueList.end(); ++it) { PyObject* item = PyUnicode_DecodeUTF8(it->second.c_str(), it->second.size(), nullptr); if (!item) { Py_DECREF(dict); throw Base::UnicodeError("UTF8 conversion failure at PropertyMap::getPyObject()"); } - PyDict_SetItemString(dict,it->first.c_str(),item); + PyDict_SetItemString(dict, it->first.c_str(), item); Py_DECREF(item); } return dict; } -void PropertyMap::setPyObject(PyObject *value) +void PropertyMap::setPyObject(PyObject* value) { if (PyDict_Check(value)) { - std::map values; + std::map values; // get key and item list PyObject* keyList = PyDict_Keys(value); PyObject* itemList = PyDict_Values(value); Py_ssize_t nSize = PyList_Size(keyList); - for (Py_ssize_t i=0; iob_type->tp_name; throw Base::TypeError(error); } @@ -1855,7 +1955,7 @@ void PropertyMap::setPyObject(PyObject *value) values[keyStr] = PyUnicode_AsUTF8(item); } else { - std::string error = std::string("type in list must be string or unicode, not "); + std::string error("type in list must be string or unicode, not "); error += item->ob_type->tp_name; throw Base::TypeError(error); } @@ -1864,44 +1964,44 @@ void PropertyMap::setPyObject(PyObject *value) setValues(values); } else { - std::string error = std::string("type must be a dict object"); + std::string error("type must be a dict object"); error += value->ob_type->tp_name; throw Base::TypeError(error); } } -unsigned int PropertyMap::getMemSize () const +unsigned int PropertyMap::getMemSize() const { - size_t size=0; - for (const auto & it : _lValueList) { + size_t size = 0; + for (const auto& it : _lValueList) { size += it.second.size(); size += it.first.size(); } return size; } -void PropertyMap::Save (Base::Writer &writer) const +void PropertyMap::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for (const auto & it : _lValueList) { - writer.Stream() << writer.ind() << "" << endl; + for (const auto& it : _lValueList) { + writer.Stream() << writer.ind() << "" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyMap::Restore(Base::XMLReader &reader) +void PropertyMap::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Map"); // get the value of my Attribute int count = reader.getAttributeAsInteger("count"); - std::map values; - for(int i = 0; i < count; i++) { + std::map values; + for (int i = 0; i < count; i++) { reader.readElement("Item"); values[reader.getAttribute("key")] = reader.getAttribute("value"); } @@ -1912,14 +2012,14 @@ void PropertyMap::Restore(Base::XMLReader &reader) setValues(values); } -Property *PropertyMap::Copy() const +Property* PropertyMap::Copy() const { - PropertyMap *p= new PropertyMap(); + PropertyMap* p = new PropertyMap(); p->_lValueList = _lValueList; return p; } -void PropertyMap::Paste(const Property &from) +void PropertyMap::Paste(const Property& from) { aboutToSetValue(); _lValueList = dynamic_cast(from)._lValueList; @@ -1927,14 +2027,12 @@ void PropertyMap::Paste(const Property &from) } - - //************************************************************************** //************************************************************************** // PropertyBool //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyBool , App::Property) +TYPESYSTEM_SOURCE(App::PropertyBool, App::Property) //************************************************************************** // Construction/Destruction @@ -1952,7 +2050,7 @@ PropertyBool::~PropertyBool() = default; void PropertyBool::setValue(bool lValue) { aboutToSetValue(); - _lValue=lValue; + _lValue = lValue; hasSetValue(); } @@ -1961,12 +2059,12 @@ bool PropertyBool::getValue() const return _lValue; } -PyObject *PropertyBool::getPyObject() +PyObject* PropertyBool::getPyObject() { return PyBool_FromLong(_lValue ? 1 : 0); } -void PropertyBool::setPyObject(PyObject *value) +void PropertyBool::setPyObject(PyObject* value) { if (PyBool_Check(value) || PyLong_Check(value)) { setValue(Base::asBoolean(value)); @@ -1978,17 +2076,19 @@ void PropertyBool::setPyObject(PyObject *value) } } -void PropertyBool::Save (Base::Writer &writer) const +void PropertyBool::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" ; - else - writer.Stream() << "false" <<"\"/>" ; + writer.Stream() << writer.ind() << ""; + } + else { + writer.Stream() << "false" << "\"/>"; + } writer.Stream() << std::endl; } -void PropertyBool::Restore(Base::XMLReader &reader) +void PropertyBool::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Bool"); @@ -1998,41 +2098,48 @@ void PropertyBool::Restore(Base::XMLReader &reader) } -Property *PropertyBool::Copy() const +Property* PropertyBool::Copy() const { - PropertyBool *p= new PropertyBool(); + PropertyBool* p = new PropertyBool(); p->_lValue = _lValue; return p; } -void PropertyBool::Paste(const Property &from) +void PropertyBool::Paste(const Property& from) { aboutToSetValue(); _lValue = dynamic_cast(from)._lValue; hasSetValue(); } -void PropertyBool::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyBool::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(bool)) + if (value.type() == typeid(bool)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(int)) + } + else if (value.type() == typeid(int)) { setValue(boost::any_cast(value) != 0); - else if (value.type() == typeid(long)) + } + else if (value.type() == typeid(long)) { setValue(boost::any_cast(value) != 0); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue(boost::any_cast(value).getValue() != 0); - else + } + else { throw bad_cast(); + } } -const boost::any PropertyBool::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyBool::getPathValue(const ObjectIdentifier& path) const { verifyPath(path); @@ -2044,7 +2151,7 @@ const boost::any PropertyBool::getPathValue(const ObjectIdentifier &path) const // PropertyBoolList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyBoolList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyBoolList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -2057,10 +2164,10 @@ PropertyBoolList::~PropertyBoolList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyBoolList::getPyObject() +PyObject* PropertyBoolList::getPyObject() { PyObject* tuple = PyTuple_New(getSize()); - for(int i = 0;i values(str); setValues(values); - }else + } + else { inherited::setPyObject(value); + } } -bool PropertyBoolList::getPyValue(PyObject *item) const { +bool PropertyBoolList::getPyValue(PyObject* item) const +{ if (PyBool_Check(item)) { return Base::asBoolean(item); - } else if (PyLong_Check(item)) { + } + else if (PyLong_Check(item)) { return (PyLong_AsLong(item) ? true : false); - } else { + } + else { std::string error = std::string("type in list must be bool or int, not "); error += item->ob_type->tp_name; throw Base::TypeError(error); } } -void PropertyBoolList::Save (Base::Writer &writer) const +void PropertyBoolList::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" ; + writer.Stream() << bitset << "\"/>"; writer.Stream() << std::endl; } -void PropertyBoolList::Restore(Base::XMLReader &reader) +void PropertyBoolList::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("BoolList"); @@ -2115,19 +2227,19 @@ void PropertyBoolList::Restore(Base::XMLReader &reader) setValues(bitset); } -Property *PropertyBoolList::Copy() const +Property* PropertyBoolList::Copy() const { - PropertyBoolList *p= new PropertyBoolList(); + PropertyBoolList* p = new PropertyBoolList(); p->_lValueList = _lValueList; return p; } -void PropertyBoolList::Paste(const Property &from) +void PropertyBoolList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyBoolList::getMemSize () const +unsigned int PropertyBoolList::getMemSize() const { return static_cast(_lValueList.size()); } @@ -2137,7 +2249,7 @@ unsigned int PropertyBoolList::getMemSize () const // PropertyColor //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyColor , App::Property) +TYPESYSTEM_SOURCE(App::PropertyColor, App::Property) //************************************************************************** // Construction/Destruction @@ -2149,10 +2261,10 @@ PropertyColor::~PropertyColor() = default; //************************************************************************** // Base class implementer -void PropertyColor::setValue(const Color &col) +void PropertyColor::setValue(const Color& col) { aboutToSetValue(); - _cCol=col; + _cCol = col; hasSetValue(); } @@ -2166,7 +2278,7 @@ void PropertyColor::setValue(uint32_t rgba) void PropertyColor::setValue(float r, float g, float b, float a) { aboutToSetValue(); - _cCol.set(r,g,b,a); + _cCol.set(r, g, b, a); hasSetValue(); } @@ -2175,7 +2287,7 @@ const Color& PropertyColor::getValue() const return _cCol; } -PyObject *PropertyColor::getPyObject() +PyObject* PropertyColor::getPyObject() { PyObject* rgba = PyTuple_New(4); PyObject* r = PyFloat_FromDouble(_cCol.r); @@ -2191,50 +2303,62 @@ PyObject *PropertyColor::getPyObject() return rgba; } -void PropertyColor::setPyObject(PyObject *value) +void PropertyColor::setPyObject(PyObject* value) { App::Color cCol; - if (PyTuple_Check(value) && (PyTuple_Size(value) == 3 || PyTuple_Size(value) == 4) ) { + if (PyTuple_Check(value) && (PyTuple_Size(value) == 3 || PyTuple_Size(value) == 4)) { PyObject* item; - item = PyTuple_GetItem(value,0); + item = PyTuple_GetItem(value, 0); if (PyFloat_Check(item)) { cCol.r = (float)PyFloat_AsDouble(item); - item = PyTuple_GetItem(value,1); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 1); + if (PyFloat_Check(item)) { cCol.g = (float)PyFloat_AsDouble(item); - else + } + else { throw Base::TypeError("Type in tuple must be consistent (float)"); - item = PyTuple_GetItem(value,2); - if (PyFloat_Check(item)) + } + item = PyTuple_GetItem(value, 2); + if (PyFloat_Check(item)) { cCol.b = (float)PyFloat_AsDouble(item); - else + } + else { throw Base::TypeError("Type in tuple must be consistent (float)"); + } if (PyTuple_Size(value) == 4) { - item = PyTuple_GetItem(value,3); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 3); + if (PyFloat_Check(item)) { cCol.a = (float)PyFloat_AsDouble(item); - else + } + else { throw Base::TypeError("Type in tuple must be consistent (float)"); + } } } else if (PyLong_Check(item)) { - cCol.r = PyLong_AsLong(item)/255.0; - item = PyTuple_GetItem(value,1); - if (PyLong_Check(item)) - cCol.g = PyLong_AsLong(item)/255.0; - else + cCol.r = PyLong_AsLong(item) / 255.0; + item = PyTuple_GetItem(value, 1); + if (PyLong_Check(item)) { + cCol.g = PyLong_AsLong(item) / 255.0; + } + else { throw Base::TypeError("Type in tuple must be consistent (integer)"); - item = PyTuple_GetItem(value,2); - if (PyLong_Check(item)) - cCol.b = PyLong_AsLong(item)/255.0; - else + } + item = PyTuple_GetItem(value, 2); + if (PyLong_Check(item)) { + cCol.b = PyLong_AsLong(item) / 255.0; + } + else { throw Base::TypeError("Type in tuple must be consistent (integer)"); + } if (PyTuple_Size(value) == 4) { - item = PyTuple_GetItem(value,3); - if (PyLong_Check(item)) - cCol.a = PyLong_AsLong(item)/255.0; - else + item = PyTuple_GetItem(value, 3); + if (PyLong_Check(item)) { + cCol.a = PyLong_AsLong(item) / 255.0; + } + else { throw Base::TypeError("Type in tuple must be consistent (integer)"); + } } } else { @@ -2245,21 +2369,22 @@ void PropertyColor::setPyObject(PyObject *value) cCol.setPackedValue(PyLong_AsUnsignedLong(value)); } else { - std::string error = std::string("type must be integer or tuple of float or tuple integer, not "); + std::string error = + std::string("type must be integer or tuple of float or tuple integer, not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } - setValue( cCol ); + setValue(cCol); } -void PropertyColor::Save (Base::Writer &writer) const +void PropertyColor::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" + << endl; } -void PropertyColor::Restore(Base::XMLReader &reader) +void PropertyColor::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("PropertyColor"); @@ -2268,14 +2393,14 @@ void PropertyColor::Restore(Base::XMLReader &reader) setValue(rgba); } -Property *PropertyColor::Copy() const +Property* PropertyColor::Copy() const { - PropertyColor *p= new PropertyColor(); + PropertyColor* p = new PropertyColor(); p->_cCol = _cCol; return p; } -void PropertyColor::Paste(const Property &from) +void PropertyColor::Paste(const Property& from) { aboutToSetValue(); _cCol = dynamic_cast(from)._cCol; @@ -2286,7 +2411,7 @@ void PropertyColor::Paste(const Property &from) // PropertyColorList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyColorList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyColorList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -2298,11 +2423,11 @@ PropertyColorList::~PropertyColorList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyColorList::getPyObject() +PyObject* PropertyColorList::getPyObject() { PyObject* list = PyList_New(getSize()); - for(int i = 0;i" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; } } -void PropertyColorList::Restore(Base::XMLReader &reader) +void PropertyColorList::Restore(Base::XMLReader& reader) { reader.readElement("ColorList"); if (reader.hasAttribute("file")) { - std::string file (reader.getAttribute("file")); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } } -void PropertyColorList::SaveDocFile (Base::Writer &writer) const +void PropertyColorList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); @@ -2357,33 +2484,33 @@ void PropertyColorList::SaveDocFile (Base::Writer &writer) const } } -void PropertyColorList::RestoreDocFile(Base::Reader &reader) +void PropertyColorList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); - uint32_t value; // must be 32 bit long - for (auto & it : values) { + uint32_t value; // must be 32 bit long + for (auto& it : values) { str >> value; it.setPackedValue(value); } setValues(values); } -Property *PropertyColorList::Copy() const +Property* PropertyColorList::Copy() const { - PropertyColorList *p= new PropertyColorList(); + PropertyColorList* p = new PropertyColorList(); p->_lValueList = _lValueList; return p; } -void PropertyColorList::Paste(const Property &from) +void PropertyColorList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyColorList::getMemSize () const +unsigned int PropertyColorList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(Color)); } @@ -3126,8 +3253,7 @@ void PropertyMaterialList::Save(Base::Writer& writer) const if (!writer.isForceXML()) { writer.Stream() << writer.ind() << "" - << std::endl; + << " version=\"3\"/>" << std::endl; } } @@ -3169,7 +3295,7 @@ void PropertyMaterialList::SaveDocFile(Base::Writer& writer) const } } -void PropertyMaterialList::writeString(Base::OutputStream& str, const std::string &value) const +void PropertyMaterialList::writeString(Base::OutputStream& str, const std::string& value) const { uint32_t uCt = (uint32_t)value.size(); str << uCt; @@ -3299,44 +3425,50 @@ unsigned int PropertyMaterialList::getMemSize() const // PropertyPersistentObject //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPersistentObject , App::PropertyString) +TYPESYSTEM_SOURCE(App::PropertyPersistentObject, App::PropertyString) -PyObject *PropertyPersistentObject::getPyObject(){ - if(_pObject) +PyObject* PropertyPersistentObject::getPyObject() +{ + if (_pObject) { return _pObject->getPyObject(); + } return inherited::getPyObject(); } -void PropertyPersistentObject::Save(Base::Writer &writer) const{ +void PropertyPersistentObject::Save(Base::Writer& writer) const +{ inherited::Save(writer); -#define ELEMENT_PERSISTENT_OBJ "PersistentObject" - writer.Stream() << writer.ind() << "<" ELEMENT_PERSISTENT_OBJ ">" << std::endl; - if(_pObject) { + writer.Stream() << writer.ind() << "" << std::endl; + if (_pObject) { writer.incInd(); _pObject->Save(writer); writer.decInd(); } - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyPersistentObject::Restore(Base::XMLReader &reader){ +void PropertyPersistentObject::Restore(Base::XMLReader& reader) +{ inherited::Restore(reader); - reader.readElement(ELEMENT_PERSISTENT_OBJ); - if(_pObject) + reader.readElement("PersistentObject"); + if (_pObject) { _pObject->Restore(reader); - reader.readEndElement(ELEMENT_PERSISTENT_OBJ); + } + reader.readEndElement("PersistentObject"); } -Property *PropertyPersistentObject::Copy() const{ - auto *p= new PropertyPersistentObject(); +Property* PropertyPersistentObject::Copy() const +{ + auto* p = new PropertyPersistentObject(); p->_cValue = _cValue; p->_pObject = _pObject; return p; } -void PropertyPersistentObject::Paste(const Property &from){ - const auto &prop = dynamic_cast(from); - if(_cValue!=prop._cValue || _pObject!=prop._pObject) { +void PropertyPersistentObject::Paste(const Property& from) +{ + const auto& prop = dynamic_cast(from); + if (_cValue != prop._cValue || _pObject != prop._pObject) { aboutToSetValue(); _cValue = prop._cValue; _pObject = prop._pObject; @@ -3344,29 +3476,38 @@ void PropertyPersistentObject::Paste(const Property &from){ } } -unsigned int PropertyPersistentObject::getMemSize () const{ +unsigned int PropertyPersistentObject::getMemSize() const +{ auto size = inherited::getMemSize(); - if(_pObject) + if (_pObject) { size += _pObject->getMemSize(); + } return size; } -void PropertyPersistentObject::setValue(const char *type) { - if(!type) type = ""; - if(type[0]) { +void PropertyPersistentObject::setValue(const char* type) +{ + if (!type) { + type = ""; + } + if (type[0]) { Base::Type::importModule(type); Base::Type t = Base::Type::fromName(type); - if(t.isBad()) + if (t.isBad()) { throw Base::TypeError("Invalid type"); - if(!t.isDerivedFrom(Persistence::getClassTypeId())) + } + if (!t.isDerivedFrom(Persistence::getClassTypeId())) { throw Base::TypeError("Type must be derived from Base::Persistence"); - if(_pObject && _pObject->getTypeId()==t) + } + if (_pObject && _pObject->getTypeId() == t) { return; + } } aboutToSetValue(); _pObject.reset(); _cValue = type; - if(type[0]) + if (type[0]) { _pObject.reset(static_cast(Base::Type::createInstanceByName(type))); + } hasSetValue(); } diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index 4bdf33b300..3fce6611bb 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -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 &Enums); + void setEnums(const std::vector& 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 getEnumVector() const; /// set enum values as vector of strings - void setEnumVector(const std::vector &); + void setEnumVector(const std::vector&); /// 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& values); + void addValue(long value) + { + _lValueSet.insert(value); + } + void setValues(const std::set& values); - const std::set &getValues() const{return _lValueSet;} + const std::set& 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(&other)->getValues(); } + private: std::set _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&); + void setValue() + {} + void setValue(const std::string& key, const std::string& value); + void setValues(const std::map&); /// 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 &getValues() const{return _lValueList;} + const std::map& 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 _lValueList; + std::map _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 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 using inherited = PropertyListsT; 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 > +class AppExport PropertyBoolList: public PropertyListsT> { TYPESYSTEM_HEADER_WITH_OVERRIDE(); - using inherited = PropertyListsT >; + using inherited = PropertyListsT>; 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 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::setValue(materials); } - void setValues(const std::vector& newValues = std::vector()) override; + void + setValues(const std::vector& newValues = std::vector()) 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 getObject() const { + std::shared_ptr getObject() const + { return _pObject; } @@ -1244,6 +1330,6 @@ protected: std::shared_ptr _pObject; }; -} // namespace App +} // namespace App -#endif // APP_PROPERTYSTANDARD_H +#endif // APP_PROPERTYSTANDARD_H diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index 867555456c..bd8a0610bc 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -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(value); + Base::QuantityPy* pcObject = static_cast(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(value); + Base::UnitPy* pcObject = static_cast(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::min(); } double PropertyQuantityConstraint::getMaximum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->UpperBound; + } return std::numeric_limits::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 } // ------------------------------------------------------ diff --git a/src/App/PropertyUnits.h b/src/App/PropertyUnits.h index c0854e47c1..0d4780eac5 100644 --- a/src/App/PropertyUnits.h +++ b/src/App/PropertyUnits.h @@ -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(&other)->getValue() && _Unit == static_cast(&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 diff --git a/src/App/private/DocumentP.h b/src/App/private/DocumentP.h index b0098f1715..64d3b6697d 100644 --- a/src/App/private/DocumentP.h +++ b/src/App/private/DocumentP.h @@ -154,8 +154,8 @@ struct DocumentP Path tmp); std::vector topologicalSort(const std::vector& objects) const; - static std::vector partialTopologicalSort( - const std::vector& objects); + static std::vector + partialTopologicalSort(const std::vector& objects); static void checkStringHasher(const Base::XMLReader& reader); };