Correct non-gui DXF C++ importer to not generate pending python exceptions (#20328)

* Add a test case for DXF import

* Test gui flag rather than look for import error to make gui decision

The new code is cleaner and faster and avoids any exception stuff

* Properly avoid trying to use Layer's View object in non-GUI

The code was trying to avoid this but had a Python None object rather than a null C++ pointer and so tried setting a property on None. This left an unhandled exception state which acted as a booby trap that caused the later failure of some unrelated code.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* De-lint, remove wong "unsupported" message
Hidden layers have been supported for a while but still generated an import note about this being unsupported.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Kevin Martin
2025-03-31 12:20:37 -04:00
committed by GitHub
parent 9153926cbf
commit 0986dadb2f
7 changed files with 2373 additions and 23 deletions

View File

@@ -462,7 +462,7 @@ void ImpExpDxfRead::ExpandInsert(const std::string& name,
double rotation,
const Base::Vector3d& scale)
{
if (Blocks.count(name) == 0) {
if (!Blocks.contains(name)) {
ImportError("Reference to undefined or external block '%s'\n", name);
return;
}
@@ -607,15 +607,14 @@ ImpExpDxfRead::Layer::Layer(const std::string& name,
std::string&& lineType,
PyObject* drawingLayer)
: CDxfRead::Layer(name, color, std::move(lineType))
, DraftLayerView(drawingLayer == nullptr ? nullptr
, DraftLayerView(drawingLayer == nullptr ? Py_None
: PyObject_GetAttrString(drawingLayer, "ViewObject"))
, GroupContents(
drawingLayer == nullptr
? nullptr
: (App::PropertyLinkListHidden*)(((App::FeaturePythonPyT<App::DocumentObjectPy>*)
drawingLayer)
->getPropertyContainerPtr())
->getDynamicPropertyByName("Group"))
, GroupContents(drawingLayer == nullptr
? nullptr
: dynamic_cast<App::PropertyLinkListHidden*>(
(((App::FeaturePythonPyT<App::DocumentObjectPy>*)drawingLayer)
->getPropertyContainerPtr())
->getDynamicPropertyByName("Group")))
{}
ImpExpDxfRead::Layer::~Layer()
{
@@ -631,7 +630,7 @@ void ImpExpDxfRead::Layer::FinishLayer() const
// App::FeaturePython, and its Proxy is a draftobjects.layer.Layer
GroupContents->setValue(Contents);
}
if (DraftLayerView != nullptr && Hidden) {
if (DraftLayerView != Py_None && Hidden) {
// Hide the Hidden layers if possible (if GUI exists)
// We do this now rather than when the layer is created so all objects
// within the layers also become hidden.
@@ -672,7 +671,7 @@ ImpExpDxfRead::MakeLayer(const std::string& name, ColorIndex_t color, std::strin
"Solid");
}
auto result = new Layer(name, color, std::move(lineType), layer);
if (result->DraftLayerView != nullptr) {
if (result->DraftLayerView != Py_None) {
PyObject_SetAttrString(result->DraftLayerView, "OverrideLineColorChildren", Py_False);
PyObject_SetAttrString(result->DraftLayerView,
"OverrideShapeAppearanceChildren",

View File

@@ -147,6 +147,7 @@ protected:
void operator=(const Layer&) = delete;
void operator=(Layer&&) = delete;
~Layer() override;
// The View object for the layer or Py_None (e.g. if no gui)
PyObject* const DraftLayerView;
std::vector<App::DocumentObject*> Contents;
void FinishLayer() const;
@@ -334,7 +335,7 @@ protected:
const std::string& name,
double rotation) override
{
InsertsList[Reader.m_entityAttributes].push_back(
InsertsList[Reader.m_entityAttributes].emplace_back(
Block::Insert(name, point, rotation, scale));
}

View File

@@ -2950,9 +2950,6 @@ bool CDxfRead::ReadLayer()
// TODO: Should have an import option to omit frozen layers.
UnsupportedFeature("Frozen layers");
}
if (layerColor < 0) {
UnsupportedFeature("Hidden layers");
}
Layers[layername] = MakeLayer(layername, layerColor, std::move(lineTypeName));
return true;
}