Compare commits

...

655 Commits

Author SHA1 Message Date
dependabot[bot] 99bc33af60 Bump actions/cache from 5.0.3 to 5.0.4
Bumps [actions/cache](https://github.com/actions/cache) from 5.0.3 to 5.0.4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/cdf6c1fa76f9f475f3d7449005a359c84ca0f306...668228422ae6a00e4ad889ee87cd7109ec5666a7)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 5.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-19 11:54:39 +00:00
Parag Debnath 8718bc28fe Part: add precise tooltips on Part/PartDesign General settings page (#27785)
* Part: add precise tooltips on Part/PartDesign General settings page

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Furgo <148809153+furgo16@users.noreply.github.com>

* added new tooltip

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Part/Gui/DlgSettingsGeneral.ui

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

---------

Co-authored-by: Parag Debnath <paragforwork@gmail.com>
Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>
Co-authored-by: Furgo <148809153+furgo16@users.noreply.github.com>
2026-03-19 04:57:30 +00:00
Chris Hennes 7886ebae10 Merge pull request #26716 from maxwxyz/spline-split
Part: Add method to split B-spline curve
2026-03-18 18:42:42 -05:00
sliptonic f22887868f Merge pull request #28431 from sliptonic/missinggrbl
CAM: Grbl post inadvertently dropped from cmake.  Fixing
2026-03-18 18:30:17 -05:00
Chris Hennes 2e7c16fccd Build: Update sign tool installation command in workflow
Cannot pin to a specific version since it is perpetually a "pre-release".
2026-03-19 00:02:41 +01:00
sliptonic b29db79928 Grbl post inadvertently dropped from cmake. Fixing 2026-03-18 16:11:51 -05:00
Chris Hennes 8a369481d6 Part: Add Python signature for B-spline curve split 2026-03-18 15:12:57 -05:00
wwmayer 603ec56151 Part: Add method to split B-spline curve
Add the method GeomBSplineCurve::split() to split a B-Spline curve into
two curves.
2026-03-18 15:12:57 -05:00
Kacper Donat 12cced51f1 Merge pull request #21978 from theo-vt/document_transaction
GSOC Multi file editing
2026-03-18 18:37:38 +01:00
Chris Hennes 439c50c5c4 Build: Pin Eigen to fix weekly build failure (#28421)
Pin version to >=3.3,<5 because of PCL incompatibility
2026-03-18 17:10:27 +00:00
Petter Reinholdtsen 87a3bcf9db Gui: Don't add redundant == or != to nullptr conditions
Follow C++ Core Guidelines ES.87: Don't add redundant == or != to conditions.
2026-03-18 11:15:45 -05:00
Benjamin Nauck 8910345149 Merge pull request #28033 from chennes/azureCodeSigning3
Packaging: Add Azure-based artifact signing on Win
2026-03-18 16:05:33 +01:00
PaddleStroke af4e54a6b7 Assembly: Fix datum typo in isBodySubObject (#28415) 2026-03-18 07:36:12 -05:00
wandererfan 90a0132533 [TD]fix selection order prevents area dimension 2026-03-17 14:18:03 -05:00
Chris Hennes fe425c3f57 Merge pull request #27747 from WandererFan/SmoothEdges
TechDraw: Draw smooth edges with thin line
2026-03-17 13:51:57 -05:00
dependabot[bot] 8098d72bb2 Bump step-security/harden-runner from 2.15.1 to 2.16.0
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.15.1 to 2.16.0.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/58077d3c7e43986b6b15fba718e8ea69e387dfcc...fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-17 12:50:09 -05:00
dependabot[bot] ebde1e3d9a Bump actions/dependency-review-action from 4.8.2 to 4.8.3
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.2 to 4.8.3.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](https://github.com/actions/dependency-review-action/compare/3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261...05fe4576374b728f0c523d6a13d64c25081e0803)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.8.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-17 12:47:55 -05:00
dependabot[bot] d9b4006aa1 Bump geekyeggo/delete-artifact from 5.1.0 to 6.0.0
Bumps [geekyeggo/delete-artifact](https://github.com/geekyeggo/delete-artifact) from 5.1.0 to 6.0.0.
- [Release notes](https://github.com/geekyeggo/delete-artifact/releases)
- [Changelog](https://github.com/GeekyEggo/delete-artifact/blob/main/CHANGELOG.md)
- [Commits](https://github.com/geekyeggo/delete-artifact/compare/f275313e70c08f6120db482d7a6b98377786765b...176a747ab7e287e3ff4787bf8a148716375ca118)

---
updated-dependencies:
- dependency-name: geekyeggo/delete-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-17 12:43:27 -05:00
Chris Hennes 0b78b5ade8 Merge pull request #28247 from hyarion/various-text-fixes
Sketcher: Fix minor text tool issues
2026-03-17 11:44:40 -05:00
Benjamin Nauck 4750f06058 Build: Add harfbuzz to pixi.toml
It is already in pixi.lock
2026-03-17 11:28:13 -05:00
Chris Hennes 0cb8f7e240 Sketcher: Add backwards-compat path for external geo
Before 0aed23c (PR #19582), external geometry projection used a different algorithm and produced slightly different geometry for some kinds of projections (B-splines in particular). This adds a backwards-compatibility path that allows old files to continue to use the old algorithm, while using the new and improved algorithm with new files.
2026-03-17 15:22:11 +01:00
Chris Hennes 49d7d77274 PD: Add migration to handle reversed TwoLengths prism
Commit a346c266 (PR #21794) was a major refactoring of the extrusion code, and one consequence of it was that the 'TwoLengths' extrusion was deprecated and replaced. The code that replaced it generated the same final geometry, but in the opposite direction, changing the face order and breaking the element names. This commit adds a backwards-compatibility branch to the file loading code that flips the direction of the inputs, so the final output matches the original.
2026-03-17 02:06:42 +01:00
Bas Ruigrok d443d5b065 Gui: Combine getFocalPoint() and getCenterPointOnFocalPlane() 2026-03-16 23:10:11 +01:00
tarman3 013a1d5f3a CAM: Job Stock - Exclude PartDesign elements 2026-03-16 22:23:48 +01:00
Alfredo Monclus 180c39709a PartDesign: thread texture (#22573)
* PD: Hole Thread texture

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

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

* refactor: vp-texture remove logging

* refactor: vp-hole cleanup unused declaration

* refactor: vp-hole remove logging

* refactor: vp-hole use convertTo

* refactor: vp-hole use freecad_cast

* refactor: make unwrapsurface private

* fix: logic error with model-thread handling

* fix: modelthreadchanged issues

threaddepth doesnt depend on modeled or not so remove it

* fix: model thread getting disabled when it shouldnt

* revert: use base-0 poly triangulation

previously had issues, but all is good now

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-16 21:52:36 +01:00
marioalexis 601bcd5e3d App: Fix separator path in safe mode 2026-03-16 21:03:28 +01:00
PaddleStroke dcb380e1ca Sketcher: Text position OVP fix 2026-03-16 19:15:09 +01:00
Alfredo Monclus cfe641fb7d Gui: improve quantitySpinbox / Sketcher OVP (#25978)
* Gui: fix quantity spinbox size not adapting to number of decimals

* Gui: fix quantity spinbox units getting cut (force max chars)

* Gui: editableDatumLabel remove hardcoded values

* fixes

* Gui: sketcher ovp auto adjust size

* Gui: ovp fix cursor jumping behind the unit

* Gui: Refactor changes to QuantitySpinBox

The QuantitySpinBox uses d-pointer (pimpl) to store its private data -
this commit ensures that all state is stored here and exposed via
getters and setters + qproperties.

* Gui: sketcher ovp fix cursor jumping after the unit

* Gui: allow quantitySpinBox to set max digits allowed

Useful for adjustable width in the Sketcher OVP

---------

Co-authored-by: Kacper Donat <kadet1090@gmail.com>
2026-03-16 18:41:00 +01:00
PaddleStroke d384c9d8cb Link : Fix transparent face regression 2026-03-16 18:32:36 +01:00
PaddleStroke 3620b68b21 Assembly: Command: Select joints of component (#27530)
* Assembly: Command: Select joints of component https://github.com/FreeCAD/FreeCAD/issues/23721

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

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

* Update src/Mod/Assembly/Gui/Commands.cpp

Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
2026-03-16 18:25:05 +01:00
tarman3 20e70f84e1 CAM: ToolController - Default RampFeed after migration (#27191) 2026-03-16 13:10:34 -04:00
Nishendra Singh e28b1ce1ad techdraw: added supplementary angle display 2026-03-16 18:07:32 +01:00
Alfredo Monclus c8efc26982 PartDesign: fix the range of the custom clearance of threads (#26296)
* PartDesign: fix the range of the custom clearance of threads

* PartDesign: hole ensure diameter is on the correct range
2026-03-16 18:02:31 +01:00
Loke Strøm 9abe7b4af1 Sketcher: Fix: Arc of Hyperbola (#27656)
* Sketcher: Fix: Arc of Hyperbola

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

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

* Added minor grater than major radius support

* Fixed merge errors

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

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

* Improved comments and added a confused points check for S1 and S2 distance.

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

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

* Added compile check for occ version and check before getting minor radius.

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

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

* Apply suggestions from code review

OCC version check

Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
2026-03-16 17:49:34 +01:00
Timothy Miller 27f077c62b Part: Fix AttacherEngine property not synced with AttacherType (#15716)
When Part2DObject (e.g., Sketch) is created, it calls setAttacher() to
set up AttachEnginePlane. This updated the internal AttacherType property
but left the user-visible AttacherEngine enum at its default "Engine 3D".

Now setAttacher() also updates AttacherEngine for non-base attachers,
keeping the visible property in sync with the actual engine type.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-16 17:42:36 +01:00
PaddleStroke eabd052c17 Core: Fix freecad when windows path has non ASCII characters (#28222)
* Core: Fix freecad when Windows username has non ASCII characters

* Update ApplicationDirectories.cpp

* Tests: Add tests of pathToString/stringToPath

Validates the fix for non-ASCII characters in filesystem paths (e.g.
Windows usernames with umlauts). Includes Windows-specific tests that
verify pathToString produces UTF-8 from wide-string paths and that
the naive fs::path::string() does not. On Linux these functions are
effectively a no-op, so the tests themselves are only really useful
on Windows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 17:37:43 +01:00
freecad-gh-actions-translation-bot 706b01f607 Update translations from Crowdin 2026-03-16 17:31:49 +01:00
dependabot[bot] 8a2f665430 Bump github/issue-metrics from 4.1.0 to 4.1.1
Bumps [github/issue-metrics](https://github.com/github/issue-metrics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](https://github.com/github/issue-metrics/compare/41a7961f701cc64490f32e143af8ef479b93e87d...6a35322ff89cee3e1a594d282c27eb34bffa9174)

---
updated-dependencies:
- dependency-name: github/issue-metrics
  dependency-version: 4.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-16 14:05:28 +01:00
sliptonic 9fe630e0c3 Merge pull request #23093 from Connor9220/UpdateCircularHoleBaseGUI
CAM: Circular Hole Improvements - GUI sorting enhancements, and migration fixes
2026-03-15 15:02:28 -05:00
Ladislav Michl 91f015b132 Gui: {get,set}Camera expects utf-8 encoding
Python interface to the setCamera() is using 's' format string, which
converts Unicode object to C string using 'utf-8' encoding. Reflect
that for QString conversion as well.
2026-03-15 20:38:42 +01:00
theo-vt ad630cbb9c Use new transaction methods in dlgmaterial 2026-03-14 12:35:31 -04:00
theo-vt 51ac15b375 Allow one clipping plane dock widget per document 2026-03-14 12:15:47 -04:00
theo-vt db1469f219 Add dialog for link insertion when selection buffer is empty 2026-03-14 12:15:47 -04:00
theo-vt 1665dec4e4 Adress review 2026-03-14 12:15:47 -04:00
theo-vt 99e414efab Return string instead of const char* in Selection::getSelectedElement 2026-03-14 12:15:47 -04:00
theo-vt 7cb3815fb1 Filter events per document at the SelectionObserver level 2026-03-14 12:15:47 -04:00
theo-vt 5c6bf5461d Remove most activate-deactivate 2026-03-14 12:15:47 -04:00
theo-vt 3076ce66be Scope the selection per document 2026-03-14 12:15:47 -04:00
theo-vt d59471b6bd Gui: Allow a selection gate per document 2026-03-14 12:15:47 -04:00
theo-vt 4ba5504e7a Remove dupplicate clone code causing crash 2026-03-14 12:15:46 -04:00
theo-vt 7db3f901fd Fix diapearing sketcher tools 2026-03-14 12:15:46 -04:00
theo-vt f4665aa7b5 Core: support multiple active transactions 2026-03-14 12:15:46 -04:00
sliptonic 6d8b98d471 block delete logic 2026-03-14 11:19:14 -04:00
tarman3 03f506c5a5 fix onDocumentRestored 2026-03-14 11:18:54 -04:00
Turan Furkan Topak d90c88f0fc make polar and circular arrays aware of the active working plane (#28324) 2026-03-14 13:18:00 +01:00
Bojan Pejic df8c6b5db9 BIM: fix zero level height warning dialog (#28065)
* BIM: fix zero level height warning dialog
2026-03-14 11:48:49 +00:00
Yash Suthar 5455306a4a Draft: fix angular mode extension lines creation (#27987)
* Draft: fix angular mode extension lines creation

Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>

* Draft: update the agularDimension extlines svg representation

Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>

---------

Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
2026-03-14 12:34:58 +01:00
Furgo d1476c819c BIM: refactor link processing, add BIM_Link wrapper command (#28104)
* BIM: refactor, introduce link properties override helper

* BIM: add Link support to Arch_Add, Arch_Remove

Fixes: https://github.com/FreeCAD/FreeCAD/issues/26255
Fixes: https://github.com/FreeCAD/FreeCAD/issues/28139

Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>

* BIM: add link command wrapper

* BIM: add link addition and removal tests

---------

Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>
2026-03-14 12:22:02 +01:00
Billy Huddleston 88a74cfa3a Fix Drag'n drop for QT6.10
Fix Merge conflicts
2026-03-13 18:09:12 -04:00
Billy Huddleston 5e818e961c CAM: Remove "Automatic TSP" mode and improve natural sorting
CAM: CircularHoleBase - Fix onDocumentRestored

Removed the expermental "Automatic TSP" sorting mode and ensured legacy
files are migrated to "Automatic". Start using C++ TSP sorting for
"Automatic" mode for better performance. Refactored natural sorting for
table columns, relocating the utility class for reuse and using a robust
sort key.

src/Mod/CAM/Path/Op/CircularHoleBase.py:
- Removed "Automatic TSP" from SortingMode options and logic
- Added migration logic for legacy "Automatic TSP" values
- Cleaned up redundant assignments

src/Mod/CAM/Path/Op/Gui/CircularHoleBase.py:
- Updated to use relocated NaturalSortTableWidgetItem for feature and
diameter columns
- Improved sorting behavior for mixed text/number columns

src/Mod/CAM/Path/Base/Gui/Util.py:
- Added NaturalSortTableWidgetItem using the existing natural_sort_key
for robust sorting
2026-03-13 15:57:13 -04:00
Billy Huddleston fdef6c35e7 GUI sorting enhancements, and migration fixes
This update enhances the GUI with new sorting modes and manual reordering, and
adds migration logic to ensure robust property

src/Mod/CAM/Gui/Resources/panels/PageBaseHoleGeometryEdit.ui:
- Add Sorting mode combo box with "Automatic", "Automatic TSP", and "Manual" options
- Add UI improvements for hole sorting, selection, and filtering

src/Mod/CAM/Path/Op/CircularHoleBase.py:
- Add migration logic to ensure SortingMode property exists and is up to date
- Use sort_locations_tsp when SortingMode is "Automatic TSP"

src/Mod/CAM/Path/Op/Gui/CircularHoleBase.py:
- Add RowMoveTableWidget for manual row reordering in the GUI
- Update TaskPanelHoleGeometryPage to support new sorting modes and improved UI behavior
2026-03-13 15:56:14 -04:00
Chris Hennes 4ac848aab0 Merge pull request #26031 from pjcreath/split-sketchobject
Split monolithic SketchObject.cpp
2026-03-13 14:37:49 -05:00
sliptonic e1fdc27e7c Merge pull request #28321 from davidgilkaufman/roadmap_clipper
[CAM] Clipper upgrade roadmap epic
2026-03-13 13:35:07 -05:00
sliptonic 0caccde398 Merge pull request #25667 from tarman3/boundary_threshold
CAM: DressupBoundary - RetractThreshold
2026-03-13 12:52:59 -05:00
sliptonic 244dffcfb7 Merge pull request #27514 from tarman3/holes_diameter
CAM: CircularHoleBase - Fix holeDiameter() for face
2026-03-13 12:45:43 -05:00
David Kaufman 5328e74e3d link FPA grant proposal 2026-03-13 13:27:54 -04:00
sliptonic 3c48b4a950 CAM: Machine-based postprocessing (#27507)
CAM: Add template dropdown below machine name in editor

Adds a template selection dropdown to the Machine Editor dialog,
positioned below the machine name field. Dropdown lists user and
built-in templates for new machines only. Adds MachineFactory
template discovery and ensures templates are copied to build directory.

src/Mod/CAM/CMakeLists.txt:
- Copy machine templates to build directory for runtime access

src/Mod/CAM/Machine/models/machine.py:
- Add MachineFactory.list_builtin_templates() for template discovery
- Use FreeCAD install path for built-in templates

src/Mod/CAM/Machine/ui/editor/machine_editor.py:
- Add template dropdown below name field for new machines
- Populate dropdown with user and built-in templates
- Update UI fields when template is selected

Major improvements to the GenericPlasma postprocessor with new dialog-based
mode selection and robust plasma cutting features.

New Features:
- Add pre_processing_dialog() for interactive mode selection
- Replace persistent mark_entry_only property with runtime dialog
- User-friendly choice between Normal Cutting and Mark Entry Points Only
- Enhanced torch control with pierce height movement
- Complete mark_entry_only implementation with proper marking sequence
- Improved error handling and state management

Technical Improvements:
- Add _reset_plasma_state() for clean per-operation tracking
- Fix Z direction detection with proper null checking
- Enhanced height extraction from StartDepth/FinalDepth/ClearanceHeight
- Better error handling with debug logging
- Graceful fallback when GUI not available

Bug Fixes:
- Fix torch control to move to pierce height before ignition
- Fix force_rapid_feeds to remove F parameters (revert from override)
- Fix state tracking initialization and null value handling
- Add proper state reset for each operationUses a dialog to set mark_only.

Co-authored-by: tarman3 <joice501790018@tutamail.com>
2026-03-13 13:18:45 -04:00
sliptonic a78c31be69 Merge pull request #28274 from Connor9220/FixToolbitSubClass
CAM: Fix saving of _shape_type for toolbits
2026-03-13 12:11:19 -05:00
sliptonic c2495411b7 Merge pull request #28173 from tarman3/linking_opti
CAM: Linking - Minor optimization for simple solid
2026-03-13 12:01:50 -05:00
sliptonic 1a8e2fb333 Merge pull request #28172 from tarman3/maneuver_toCommand
CAM: Maneuver - Move instruction_to_command() to class
2026-03-13 12:00:07 -05:00
sliptonic 73c3c78474 Merge pull request #28167 from tarman3/machinestate
CAM: MachineState - Allow process list of commands
2026-03-13 11:57:49 -05:00
sliptonic 509c881ea0 Merge pull request #28140 from tarman3/linking_tolerance
CAM: Linking - Tolerance in get_linking_moves()
2026-03-13 11:55:08 -05:00
David Kaufman d690dcb1d3 Clipper upgrade roadmap 2026-03-13 11:47:33 -04:00
dependabot[bot] 493829b376 Bump actions/download-artifact from 8.0.0 to 8.0.1
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-12 21:46:11 -05:00
pre-commit-ci[bot] 0819d776d7 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-03-12 20:25:01 +00:00
pjcreath 79aca8950f Sketch: [5/5] Fix up files after splitting SketchObject.cpp
Remove stale includes and make other adjustments for compilation.
2026-03-12 16:17:08 -04:00
pjcreath 8efe9964e7 Sketch: [4/5] Move code from SketchObject.cpp to SketchObjectExternal.cpp.
This is a purely mechanical reorganization with no functional changes.
Use "git blame -C --minimal" to trace line origins prior to this commit.
2026-03-12 16:17:08 -04:00
pjcreath eda87a7efe Sketch: [3/5] Move code from SketchObject.cpp to SketchObjectGeometry.cpp.
This is a purely mechanical reorganization with no functional changes.
Use "git blame -C --minimal" to trace line origins prior to this commit.
2026-03-12 16:17:08 -04:00
pjcreath e1815f10ff Sketch: [2/5] Move code from SketchObject.cpp to SketchObjectConstraints.cpp.
This is a purely mechanical reorganization with no functional changes.
Use "git blame -C --minimal" to trace line origins prior to this commit.
2026-03-12 16:17:08 -04:00
pjcreath 7d39a9d59a Sketch: [1/5] Move code from SketchObject.cpp to SketchObjectOperations.cpp.
This is a purely mechanical reorganization with no functional changes.
Use "git blame -C --minimal" to trace line origins prior to this commit.
2026-03-12 16:17:08 -04:00
wmayer baa47bd606 Sketch: Refactor SketchObject::getPoint
Add the helper class SketchGeometryType and the interface SketchGeometry with the needed sub-classes to
remove the cascaded if-else construct
2026-03-12 16:17:08 -04:00
wmayer 51b37da53e Sketch: Fix crash when moving sketch with hidden constraints
Clicking the eye icon on the constraints panel hides all constraints. This calls SketchObject::setVirtualSpace where the existing Constraint
objects will be replaced. However, the Constraint objects are also stored inside the member 'solvedSketch' but won't be replaced so that the
pointers there will become dangling.

If the user starts to drag the sketch the pointers are still dangling and cause a crash when calling 'solvedSketch.moveGeometries'.

The crash can be reproduced with:
1. Create a sketch
2. Add a single line
3. Set a length constraint
4. Make it a non-driving constraint
5. Hide it with the eye icon or by unticking the check box
6. Move the line

The same crash also occurs when calling the methods setLabelDistance() or setLabelPosition() from Python and then trying to move the sketch.

Solution:

To fix the problem add the lightweight method 'Sketch::updateConstraints' and call it inside SketchObject::setVirtualSpace to quickly update
the pointers after invalidating them.

This fixes issue 19566
2026-03-12 16:17:08 -04:00
André Lopes 8ce3c4a1cc Fix #24079: clarify TechDraw Scale tooltip (#28293) 2026-03-12 18:12:02 +00:00
Roy-043 037ce3bffd BIM: update tooltips in BIM Setup to match current prefs
Related to #25004

Updated the tooltips to point to correct pref pages.

Additionally:
* Minor text tweaks.
* Replaced "Gui::PrefColorButton" with "Gui::ColorButton".
2026-03-12 18:28:48 +01:00
Roy-043 b9306c6f63 BIM: fix BuildingPart color issues including v1.0 regressions (#28001)
* BIM: fix BuildingPart color issues including v1.0 regressions

Fixes #27136.

* [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>
2026-03-12 14:39:24 +00:00
tarman3 7b2b972efa CAM: MachineState - Allow process list of commands 2026-03-12 10:28:31 +02:00
filippor 6d66721582 fix CAM missing python file in cmake 2026-03-11 22:03:23 -04:00
Billy Huddleston 448235cd2b CAM: Fix saving of _shape_type for toolbits
Corrects logic so that the _shape_type is saved properly and not always
defaulted to the primary toolbit type. Ensures subclass/alias
information is preserved when saving toolbits.

src/Mod/CAM/Path/Tool/toolbit/models/base.py:
- Fix fallback logic for _shape_type to correctly save subclass/alias
when present
- Only default to primary type if _shape_type is missing or matches the
main class

src/Mod/CAM/Path/Tool/docobject/ui/docobject.py:
- Improve label formatting by handling underscores, hyphens, and extra
spaces

src/Mod/CAM/Path/Tool/toolbit/ui/typefilter.py:
- Simplify type filter mapping and display logic for toolbit subtypes
2026-03-11 21:58:32 -04:00
Bojan a729bb4bc1 Material: add transaction support to Std_SetMaterial task 2026-03-11 20:00:39 -05:00
Chris Hennes 03fc08d02e Revert "[Weekly Build] Update IfcOpenShell to 0.8.4"
This reverts commit 5e7bbe15e3.
2026-03-11 08:18:44 +01:00
WandererFan e44c1ce75a TechDraw: Allow 3d dimension references to use point objects (#28199)
* [TD]fix 3d point object reference in dimension

* [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>
2026-03-11 06:08:35 +01:00
marioalexis 4083c7c616 Fem: Add name to examples dock widget 2026-03-11 06:05:07 +01:00
PaddleStroke 76a84f63ab Sketcher: Dimension tool: don't update distance type based on position for horizontal/vert 2026-03-11 05:36:10 +01:00
WandererFan 065315d7a4 TechDraw: fix crash in area dim for face with nested voids (#28097) 2026-03-10 22:57:59 -05:00
Chris Hennes 6206ed2c51 Packaging: Add Azure-based artifact signing on Win
Sign all *.exe, *.dll, and *.pyd files in the bin directory of the
build, as well as the two Chocolatey stubs and the installer. Requires
the use of several environment variables and secrets, documented at
https://github.com/FreeCAD/DevelopersHandbook/blob/main/technical/codesigning.md#windows
2026-03-10 22:25:02 -05:00
PaddleStroke 451072f0d7 Sketcher : arc with symmetric + 2 coincidence fix (#28120) 2026-03-10 22:13:02 -05:00
Roy-043 0b232ac1ff Draft: Avoid import of whole Draft module (#25386) 2026-03-10 21:59:36 -05:00
Grzegorz Kwacz 737cab44f2 Gui/View: Move (get|set)Camera to methods (#27801) 2026-03-10 21:57:34 -05:00
Benjamin Nauck a06be5de68 Sketcher: Fix void bounding box fall-through in constraint visualization
Add missing break after hiding rectangle points for a void bounding box,
preventing fall-through to CornerMin()/CornerMax() which would produce
undefined values.
2026-03-10 19:11:48 +01:00
Benjamin Nauck 0ea238f90c Sketcher: Fix dangling command context on double-click text edit
Remove the openCommand() call in editDoubleClicked() since
EditTextDialog already manages its own command lifecycle. The redundant
outer command was never closed when the user cancelled the dialog.
2026-03-10 19:11:48 +01:00
Benjamin Nauck 5ae85148cc Merge pull request #22217 from PaddleStroke/sk_texttool
Sketcher: Text tool
2026-03-10 18:07:50 +01:00
tarman3 1182be91bc CAM: Maneuver - Move instruction_to_command() to class 2026-03-10 15:52:35 +02:00
Benjamin Nauck cd5876dc54 Sketcher: Escape text and font path in EditTextDialog
Escape user-provided text and font path strings before inserting them
into the Python command string, preventing breakage or injection from
strings containing quotes or backslashes.
2026-03-10 12:54:45 +01:00
Benjamin Nauck ca4660167e Sketcher: Add .ttc (TrueType Collection) to font file discovery 2026-03-10 12:54:45 +01:00
Benjamin Nauck a0c97a102e Part: Add HarfBuzz text shaping for proper kerning in makeTextWires
Replace the character-by-character positioning loop with HarfBuzz
text shaping. The old code used FT_Get_Kerning which only reads
legacy kern tables. HarfBuzz handles both GPOS kerning and legacy
kern tables, as well as ligatures and complex script shaping.
2026-03-10 12:54:45 +01:00
Roy-043 90c83636cb Draft: update GUI text in Draft_SelectPlane
After #27979, the Draft_SelectPlane code also accepts 1 or 2 vertices. This PR updates the task panel text accordingly.
2026-03-10 10:33:23 +01:00
tarman3 e561950ff8 CAM: Linking - Minor optimization for simple solid 2026-03-10 09:06:14 +02:00
PaddleStroke e7e5e39e7b Sketcher: Change default text to Text 2026-03-10 07:22:26 +01:00
paddle d842e4151c Sketcher: Text: Fixes 2026-03-10 07:22:25 +01:00
paddle 320bd61156 Sketcher: Text tool - review changes 2026-03-10 07:22:25 +01:00
PaddleStroke fed11359d9 Update SketcherToolDefaultWidget.h 2026-03-10 07:22:09 +01:00
paddle fdf0013dcb Sketcher: Text tool 2026-03-10 07:21:04 +01:00
tarman3 bf98221885 CAM: Linking - Tolerance in get_linking_moves() 2026-03-10 06:52:28 +02:00
Bojan d214306d1b PartDesign/Part: prevent chamfer crash on OCC kernel failure 2026-03-10 01:52:57 +01:00
PaddleStroke a0af0d2b85 Link: Fix mirror twice color issue (#28071) 2026-03-09 22:12:34 +01:00
Turan Furkan Topak ee27de857a Contribution Standards: Adding new rules, mostly around AI discussions (#24646) 2026-03-09 15:55:49 -05:00
sliptonic 4afbadec04 Merge pull request #26605 from tarman3/inspect_title
CAM: Inspect and Export - Window title
2026-03-09 15:25:18 -05:00
sliptonic cdd9d685fe CAM: Improvements to machine (#28011)
* CAM:  Improvements to machine

* CAM: SPDX

* lint and translation string problems

* fixing headers and missing toolhead tests

---------

Co-authored-by: tarman3 <joice501790018@tutamail.com>
2026-03-09 14:02:31 -04:00
Krish Sharma a34bad7da4 Add status bar hints for modifier keys in Std_Measure (#26568)
* Add status bar hints for modifier keys in Std_Measure

* Align status bar hints according to design guide

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

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

* Update src/Mod/Measure/Gui/TaskMeasure.cpp

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

* Update src/Mod/Measure/Gui/TaskMeasure.cpp

Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>

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

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

* Replace 'invert' with 'toggle' to improve readability

* Added missing namespace qualifier

* Fix MSVC list assignment errors with explicit std::list<InputHint>

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

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

* fix InputHint': undeclared identifier

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com>
2026-03-09 18:24:54 +01:00
PaddleStroke e20b42e484 Assembly: fix joint creation not working on draft links (#26085)
* Assembly: add support for draft links

* Update AssemblyObject.cpp

* Update ViewProviderAssembly.cpp

* Update GeoFeature.cpp

* Update JointObject.py

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

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

* [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>
2026-03-09 18:15:01 +01:00
PaddleStroke 79923c16f3 Gui: Fix shortcut warning (#28217) 2026-03-09 18:00:22 +01:00
Bojan 004927e16e TechDraw: clear selection after editing Annotation from 2D page Fixes FreeCAD#27983 2026-03-09 17:59:17 +01:00
Yorik van Havre e8d9f30c10 Merge pull request #28020 from Roy-043/BIM-remove-switch-to-beam-creation-based-on-dimensions
BIM: remove switch to profile beam creation based on dimensions
2026-03-09 16:52:18 +00:00
dependabot[bot] f06dfa5af8 Bump github/issue-metrics from 3.25.5 to 4.1.0
Bumps [github/issue-metrics](https://github.com/github/issue-metrics) from 3.25.5 to 4.1.0.
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](https://github.com/github/issue-metrics/compare/67526e7bd8100b870f10b1c120780a8375777b43...41a7961f701cc64490f32e143af8ef479b93e87d)

---
updated-dependencies:
- dependency-name: github/issue-metrics
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:22:17 +01:00
Jonas Voigt dc1e96c46a Gui: Add styling to spreadsheet color picker (#28191) 2026-03-09 13:11:44 +00:00
freecad-gh-actions-translation-bot 96afba8351 Update translations from Crowdin 2026-03-09 07:28:51 +01:00
Chris Hennes 72b9a91337 Materials: Correct missing or incorrect licenses and authors
During conversion of some materials from the originals, in some cases authorship
was lost, or licensing mistaken. In addition, during their creation some files
had incorrect licenses applied. Files previously licensed LGPL-2.1.-or-later had
that license restored. Other files were re-licensed by agreement of their
author.

Co-Authored-By: David Carter <dcarter@davidcarter.ca>
2026-03-09 06:02:07 +01:00
WandererFan c468a622e6 TechDraw: Trap attempt to write to held file (#25716) 2026-03-09 04:32:27 +00:00
marioalexis edde9fb18e Fem: Remove transparency from equation icons 2026-03-09 05:15:36 +01:00
Roy-043 5754c66a55 BIM: do not process shapes of BuildingParts for TD BIMViews
Fixes #17661.
Fixes #27396.

In ArchSectionPlane.py the shape of BuildingParts was also processed. This resulted in duplicate geometry as BuildingParts inherit their shape from their (also processed) content.

This PR requires some testing, it should not be backported to v1.1.
2026-03-08 22:11:20 -05:00
Roy-043 146ed0d704 Draft: allow more than 1 character for in-command shortcuts (#26950) 2026-03-08 22:08:57 -05:00
Chris Hennes e807d2d421 Part: Fix dangling pointer in getElementSource() 2026-03-08 22:50:47 +01:00
Parag Debnath 0e83500531 Core: Fix the visibility of bounding boxes (#28123)
Co-authored-by: Parag Debnath <paragforwork@gmail.com>
2026-03-08 22:48:04 +01:00
Chris Hennes 143c1737af Merge pull request #25200 from pieterhijma/doc-formatting
Doc: Improve the formatting of doxygen output
2026-03-08 15:32:15 -05:00
tarman3 f7939beee0 CAM: Linking - Tolerance in get_linking_moves() 2026-03-08 21:30:24 +02:00
marioalexis84 c6aeec9146 Fem: Add method to create custom arrays in pipeline (#26076)
Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
2026-03-08 19:25:48 +00:00
marioalexis 9e065cdb7f Fem: Add command to clear mesh groups 2026-03-08 13:58:12 -05:00
marioalexis b55dd47120 Spreadsheet: Include missing header <QTextDocument> 2026-03-08 13:42:34 -05:00
Gaurang-2005 11dd9d8870 Fix Collada exporter skipping App::Link geometry (#27974)
* Fix Collada exporter skipping App::Link geometry

Resolve App::Link objects recursively during export so referenced
geometry is included in the .dae output while preserving link placement.

* Arch: Fix Collada export for App::Link objects

The Collada exporter skipped geometry for App::Link instances because
it only handled objects directly present in the document.

This change resolves Link objects using getLinkedObject() and exports
their referenced geometry while applying the placement of the exporting
instance.

The original App::Part expansion behavior is preserved.

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

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

* Arch: fix placement handling for App::Link and primitives in Collada export

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

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

* final change

* [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>
2026-03-08 17:31:54 +00:00
marioalexis 88940fb375 Fem: Fix crash in pipeline 2026-03-08 11:24:52 -05:00
dependabot[bot] aa5feb3df0 CI: Pin actions/github script to 8.1.0 by hash 2026-03-08 11:15:35 -05:00
dependabot[bot] dee9d5a498 Bump step-security/harden-runner from 2.13.3 to 2.14.0
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.13.3 to 2.14.0.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/df199fb7be9f65074067a9eb93f12bb4c5547cf2...20cf305ff2072d973412fa9b1e3a4f227bda3c76)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-08 11:12:32 -05:00
marioalexis 8c18208c97 Fem: Add log verbosity preference to Elmer 2026-03-08 11:09:37 -05:00
Bojan Pejic d68b0c087e Draft: move working plane to vertex when pre-selected (#27979) 2026-03-08 11:53:13 +00:00
Chris 35b77bc069 bim: attempt to fix crash with issue #27984 bim text in td doc (#28135) 2026-03-08 12:30:51 +01:00
tarman3 0702616895 CAM: BoundaryDressup - RetractThreshold 2026-03-08 12:47:43 +02:00
theo-vt f36aeef878 Sketcher.planegcs: don't check for constraint update in solve routine 2026-03-07 17:41:35 -06:00
Syres916 5e7bbe15e3 [Weekly Build] Update IfcOpenShell to 0.8.4 2026-03-07 16:50:58 -06:00
Maik-0000FF 687c75e5bc Gui: Fix Linux SpaceMouse performance: event coalescing, camera batching, per-axis deadzone (#28110)
* Fix Linux SpaceMouse jerkiness: coalesce spnav events and batch camera updates

On Linux, pollSpacenav() posts every spnav motion event individually
(125-250Hz from spacenavd), each triggering a full scene redraw. Combined
with camera->orientation and camera->position each triggering separate
Coin3D notifications, this results in up to 500 redraws/sec.

Fix 1 - Event coalescing (GuiNativeEventLinux.cpp):
The drain loop now keeps only the latest motion state and posts once after
all pending events are consumed. SpaceMouse events are absolute deflection
(current puck position), not deltas, so the latest event always contains
the complete state.

Fix 2 - Batched camera updates (NavigationStyle.cpp):
Wrap camera property changes in enableNotify(false/true) + touch() so
Coin3D fires a single redraw instead of two per event.

Together this reduces redraws from ~500/sec to ~60/sec (display refresh),
eliminating the jerky navigation that Linux users experience with complex
models.

Fixes #25926

* Add per-axis deadzone filtering for Linux SpaceMouse

Each SpaceMouse axis has different sensitivity and noise characteristics.
A single global deadzone is too coarse — rotation axes may need different
thresholds than translation axes.

Read per-axis deadzone values from user.cfg (BaseApp/Spaceball/Motion)
using keys PanLRDeadzone, PanUDDeadzone, ZoomDeadzone, TiltDeadzone,
RollDeadzone, SpinDeadzone. Values default to 0 (no filtering).

Axis values below their individual threshold are zeroed before posting
the motion event, preventing unintended drift from sensor noise while
preserving intentional small movements.

This is the Linux equivalent of deadzone handling that NavLib provides
on Windows/macOS.

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

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

* Use std::array for axisDeadzoneKeys to avoid magic number

Replace C-style array with std::array and use .size() instead of
hardcoded loop bound, as suggested in code review.

* Cache deadzone values with ParameterGrp Observer instead of polling

Replace per-event GetParameterGroupByPath + GetInt calls with a static
DeadzoneCache that loads values once and updates them via
ParameterGrp::ObserverType when user.cfg changes. Also use
static constexpr for the keys array and std::abs for readability.

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

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

* Move DeadzoneCache from static local to member variable

Replace the static local DeadzoneCache in pollSpacenav() with a
std::unique_ptr<DeadzoneCache> member of GuiNativeEvent, initialized
in initSpaceball() after the spnav connection is established.
Forward-declare in the header to keep includes minimal.

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

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

---------

Co-authored-by: Maik-0000FF <Maik-0000FF@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-07 22:37:59 +01:00
PaddleStroke 36dd4b983c Sketcher: Dimension tool: Filter coincident points (#27630) 2026-03-07 15:34:56 -06:00
Chris cee71e1fb1 CMake: Add check for Qt/PySide version mismatch (#27156)
* CMake: fixes issue #27065 check for Qt/PySide version mismatches
* lint / format several PySide related CMake files
2026-03-07 15:12:57 -06:00
mosfet80 baed171ec5 PD: Remove unused variable from TaskRevolutionParameters.cpp (#26009) 2026-03-07 14:19:05 -06:00
PeterfoxUwU ecb188fe4c Base: Added Quantities for Optic/Chemical mechanics (#27944)
* Base: Added Quantities for Optic/Chemical mechanics

* [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>
2026-03-07 21:10:40 +01:00
Grzegorz Kwacz 1027be1efa Spreadsheet: Decrease default size (#27152)
* Spreadsheet: dynamic row and coulumn counts

* Spreadsheet: test distant cell

* Spreadsheet: fix removeColumns condition

* Spreadsheet: Fix zoom detachment

* Spreadsheet: Fix SheetModel::containInView

* Spreadsheet: Make sure the number of rows/cols decreases correctly after removal

* Spreadsheet: Code quality fixes

* Spreadsheet: Fix typo

* Spreadsheet: Move sheet->insert/remove outside Qt signals

* Update src/Mod/Spreadsheet/Gui/SheetTableView.cpp

Co-authored-by: Benjamin Nauck <benjamin@nauck.se>

* Update src/Mod/Spreadsheet/Gui/SheetModel.h

Co-authored-by: Benjamin Nauck <benjamin@nauck.se>

* Spreadsheet: Add comment about nesting beginInsertColumn

* Spreadsheet: Remove c-style Qt header

---------

Co-authored-by: Benjamin Nauck <benjamin@nauck.se>
2026-03-07 20:59:49 +01:00
Andrea d2b84db105 Sketcher: Cleanup commented-out code
Remove the TestSketcherGui file entirely, it contained only commented
lines. Delete commented out debugging output. Remove other commented-out
code that didn't have any explanation or justification for leaving it
in.
2026-03-07 13:55:52 -06:00
Benjamin Nauck c263d8f51c Merge pull request #18678 from chennes/applicationAddTranslatableExportType 2026-03-07 17:03:09 +01:00
Chris Hennes 0f0d2c849f Points: Add translation tags to export formats 2026-03-07 00:47:05 -06:00
Chris Hennes 025d4a9f5c Part: Add translation tags to export formats 2026-03-07 00:47:05 -06:00
Chris Hennes 8140957413 OpenSCAD: Add translation tags to export formats 2026-03-07 00:47:05 -06:00
Chris Hennes 6ad2206595 Mesh: Add translation tags to export formats 2026-03-07 00:47:05 -06:00
Chris Hennes dff7fc6ca8 Import: Add translation tags to export formats 2026-03-07 00:47:00 -06:00
Chris Hennes 1671ecb902 FEM: Add translation tags to export formats 2026-03-07 00:46:53 -06:00
Chris Hennes 8a17ca36a4 Draft: Add translation tags to export formats 2026-03-07 00:46:53 -06:00
Chris Hennes b8929f279f BIM: Add translation tags to export formats 2026-03-07 00:46:53 -06:00
Chris Hennes 07540ad3ba Gui: Add translation tags to export formats 2026-03-07 00:46:53 -06:00
Chris Hennes c387a4b5c9 App: Create addTranslatableExportType method
This method aims to solve the problem of untranslatable description
strings on file types. Some, but not all, file format description
strings contain translatable elements. For example, some languages
may translate "FEM mesh formats". Many format descriptions include
the words "file," "format," or "mesh" -- these could potentially be
replaced with localized versions.
2026-03-07 00:46:47 -06:00
Chris Hennes 21ef29bb82 Merge pull request #27969 from 3x380V/pd_cleanup
PartDesign: Minor cleanup
2026-03-07 00:27:26 -06:00
Chris Hennes 8cb06956d0 Merge pull request #27759 from dhruvjamwal/main
Fix #27741: Prevent camel case splitting on numbers in Property Editor.
2026-03-07 00:08:47 -06:00
Benjamin Nauck 17651fbfa4 Part: Fix signal handler compatibility with OCCT 8
OCCT 8.0.0 removed the NewInstance/Jump API from signal exception
classes in favor of Standard_ErrorHandler::Abort.
2026-03-06 23:58:26 -06:00
Yurii Sokolovskyi 87651cdd4c Autoconstraints redundancy error message fix
Report view now shows which sketch caused the 'Autoconstraints cause redundancy, Removing them' error
2026-03-06 23:26:26 -06:00
dependabot[bot] d34969f7d6 Bump actions/download-artifact from 7.0.0 to 8.0.0
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/37930b1c2abaa49bbe596cd826c3c89aef350131...70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-06 23:19:22 -06:00
Chris Hennes 60ebafd0b3 Gui: Tweak comment for clarity
Co-authored-by: Pieter Hijma <pieterhijma@users.noreply.github.com>
2026-03-06 22:36:12 -06:00
Chris Hennes 15dd009f13 Tests: Add test for PropertyItem setName() behavior 2026-03-06 22:34:42 -06:00
marioalexis dbb6cbe335 Fem: Add property to set pipeline and filters color if Field is None - fixes #21352 2026-03-06 22:25:42 -06:00
Ladislav Michl 2dcb495a67 TD: Fix warnings 2026-03-06 22:23:46 -06:00
Pieter Hijma a102c8a359 Gui: Prevent unhandled exception adding properties
This commit prevents unhandled exceptions to be thrown in the Add
Property dialog.  When the user provides a valid name, for example 'Abc'
and then an invalid name, for example 'Abc^', an exception is thrown
that is caught by Qt's notify which may lead to a crash.  This is caused
by the fact that the editor is still bound to the old property that has
been removed.  The main idea was to preserve values that were provided
by the user as long as possible, also when a property name changes.
This design goal tried to preserve the user provided value even if the
property name is not valid.  Although the underlying property item is
explicitly unbound in that situation, the editor is not.

The solution is to also explicitly unbind the editor if there is an
editor that can have bindings.  Unbinding an editor does not
automatically hide the f(x) symbol in the editor (leading to errors on
unbound editors), so this commit also adds a bit of logic to hide
the f(x) symbol when an editor is unbound.
2026-03-06 22:12:49 -06:00
Kristian Rekstad 8fda540e1a Idf: improve dox 2026-03-06 20:50:45 -06:00
PaddleStroke bbd1266398 PartDesign: Fix wireframe not working on external link to body 2026-03-06 20:34:17 -06:00
Petter Reinholdtsen 087522528b Base: Corrected delete() call in XMLTools.
The memory is allocated using new() with alignment requirements, and
should be deleted using the same alignment requirement.  See
issue #27781 for the valgrind error.
2026-03-06 19:18:01 -06:00
marioalexis 18cf24e1d9 Fem: Show all solvers in tool bar - fixes #27703 2026-03-06 17:17:25 -06:00
Connor9220 f0a70d5468 Merge pull request #23747 from tarman3/selectside
CAM: Path.Op.Area - Fix offer side
2026-03-06 17:50:15 -05:00
tarman3 26357db694 CAM: Inspect and Export gcode window title 2026-03-06 21:46:58 +02:00
PaddleStroke 83d14b785e Sketcher: Fix crash on external deletion (#27717)
* Sketcher: Fix crash on external deletion

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

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

* Update SketchObject.pyi

* Update SketchObjectPyImp.cpp

* Update ViewProviderSketch.cpp

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

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

* Update SketchObjectPyImp.cpp

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

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

* Sketcher: Fix last external not being removed from ref 27719

* Update SketchObject.cpp

* Update SketchObject.cpp

* Update SketchObject.h

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

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

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

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

* rename fixMissingAxisInExternalGeo

* Update SketchObject.cpp

* Update SketchObjectPyImp.cpp

* [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>
2026-03-06 19:19:13 +00:00
PaddleStroke bc0d94d7a7 RTGroup 2: App: add PropertyListsT::removeIf() (#26173)
* App: add PropertyListsT::removeIf()

For convenient list value filtering.
Co-authored-by: Zheng Lei <realthunder.dev@gmail.com>

* Update Property.h

* Update Property.h
2026-03-06 19:15:33 +00:00
Connor9220 840122a358 Merge pull request #26976 from tarman3/points_coincide_list
CAM: Path.Geom.pointsCoincide - allow list and tuple
2026-03-06 12:36:09 -05:00
FilippoR a18f77f3b8 fix CAMTests.TestPathOpUtil.TestPathOpUtil.test46 & test47 (#28038)
* fix CAMTests.TestPathOpUtil.TestPathOpUtil.test46

* fix CAMTests.TestPathOpUtil.TestPathOpUtil.test47

* disable CAMTests.TestTestPost.TestTestPost.test00190
2026-03-06 12:31:05 -05:00
Connor9220 eb522b52dc Merge pull request #26507 from tarman3/save_gcode
CAM: Exporting G-code - Buttons text
2026-03-06 12:13:22 -05:00
tarman3 04e0518051 CAM: LeadInOut - Fix positive overtravel for open profile (#25482)
* CAM: LeadInOut - Replace G01 by G1

* CAM: LeadInOut - Fix positive overtravel for open profile
2026-03-06 12:08:10 -05:00
Connor9220 dac4062d54 Merge pull request #27960 from petterreinholdtsen/cam-fanuc-new-improved
CAM: Improved Fanuc support (header, python warnings).
2026-03-06 11:56:22 -05:00
PaddleStroke 949c5421cf Sketcher: refactor removeAxesAlignment (#27451) 2026-03-06 17:29:52 +01:00
PaddleStroke 912fd47b5f Merge pull request #27531 from PaddleStroke/asm_gotolink
Assembly: Command: Got to linked assembly
2026-03-06 15:50:59 +01:00
kkocdko b098f3ad44 Linux: use exec command in AppRun 2026-03-06 15:45:51 +01:00
PaddleStroke f65dda922f Assembly: Fix JCS position if assembly is transformed (#28089)
* Assembly: Fix JCS position if assembly is transformed

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

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

* redrawJointPlacement & showPreviewJCS Refactor to avoid duplicate code

* Assembly: JointObject: Simplify setJCSPosition

Co-authored-by: Benjamin Nauck <benjamin@nauck.se>

* Update JointObject.py

* Update src/Mod/Assembly/JointObject.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Nauck <benjamin@nauck.se>
2026-03-06 09:41:15 +00:00
Petter Reinholdtsen 4c6eed1e63 CAM: Improved Fanuc support (header, python warnings).
Adjusted G code output to include FreeCAD body and job information.
The first comment in the G code is shown on the machine controller,
and should contain useful information for operators to to identify
jobs.  Fetch the body and job label using findParentJob and insert it
into the G code.  For some reason the body and job information is not
available when called from TestFanucPost.py, so handle case where it
is undefined as earlier.  This new use of findParentJob exposes error
in mock code used in code tests.  This is fixed in a different pull
request to make this patch easily backportable to the 1.1 branch.

Fixed issues with Fanuc post processor discovered by lint.  Made sure
global variables used are declared.  This fixes issue updating the
postamble and preamble introduced in
ef794c31bd

Added docstrings, adjusted import statements and wrapped long line to
keep linter happy.

Reformatted code with black for consistent formatting.

Also reverted obsolete setText() workaround from commit
9c78ced00c now
that https://github.com/FreeCAD/FreeCAD/pull/26008 is merged.
2026-03-06 09:09:11 +01:00
Benjamin Nauck 6238fe1081 Merge pull request #26172 from PaddleStroke/patch-985354 2026-03-06 07:10:59 +01:00
sliptonic b20a6acc26 CAM: Consolidates tapping into Drilling as a new strategy. (#27506) 2026-03-05 21:46:32 +01:00
Devanshi Bhatt c6b99363d6 #25004: change the tooltip contents for correct line width location (#28057)
* #25004: change the tooltip contents for correct line width location

* #25004 : Update the tooltip contents for correct line width location
2026-03-05 19:50:22 +00:00
Benjamin Nauck 26435d03fd Merge pull request #27845 from marioalexis84/fem-pipelinepy_time_info 2026-03-05 17:32:45 +01:00
marioalexis 3c56c164ee Fem: Fix start page example 2026-03-05 09:30:04 -06:00
Zheng Lei 6ea74652c9 App: fix PropertyLinkBase::getLinkedObjects() 2026-03-05 08:31:53 +01:00
Parag Debnath 2db12d8a66 added conflict free shortcuts (#28036)
Co-authored-by: Parag Debnath <paragforwork@gmail.com>
2026-03-04 20:57:30 +01:00
Benjamin Nauck 637463ac35 Merge pull request #27746 from furgo16/bim-add-options-task-boxes
BIM: add quick-access options task boxes to all relevant objects
2026-03-03 23:57:35 +01:00
Ladislav Michl e516eae53b Part: Remove deprecated cutFaces 2026-03-03 23:55:29 +01:00
paul e12d8fd01e [ArchWall] Multi-Material width return to Width Property (#27972)
* [ArchWall] Multi-Material width return to Width Property

Fix #27804
- BIM: Wall with MultiMaterial assigned reports wrong Width

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

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

* [ArchWall] Multi-Material width return to Width Property (rev.)

Fix #27804

- BIM: Wall with MultiMaterial assigned reports wrong Width

(rev.
Better algorithm - https://github.com/FreeCAD/FreeCAD/issues/27804#issuecomment-3986056788)

* [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>
2026-03-03 04:53:33 +00:00
Chris Hennes e1644a7310 Merge pull request #27879 from kadet1090/fix-checked-state
Part: Make 3D View properly checkable
2026-03-02 19:22:01 -06:00
marioalexis 3ae8d45506 Fem: Read material info from .frd file 2026-03-02 23:17:45 +01:00
Furgo 2777999d03 BIM: Fix placement jump when uncloning objects (#27597)
* BIM: Fix placement jump when uncloning objects

The Unclone command incorrectly multiplied the parent's placement by the
clone's placement. Since Arch clones store absolute placement (not
relative to the parent), this resulted in a double transform.

This caused baseless walls to jump to a new position upon uncloning.
Standard base-backed walls often masked this bug because their local
placement is usually Identity (0,0,0), but they would also fail if moved
independently of their base.

This fix assigns the clone's current placement directly to the new
object, preserving its position.

Fixes https://github.com/FreeCAD/FreeCAD/issues/26929

* BIM: do placement assignment and recompute only once
2026-03-02 21:58:45 +01:00
Roy-043 64a4cee116 BIM: remove switch to profile beam creation based on dimensions
Fixes #28013.

When creating a structure from a profile the code could ignore `self.bmode` (beam-mode) and create a beam even if the user selected the column option in the task panel.

Rounding errors due to the conversion of numerical values read from the input boxes triggered the bug (89mm -> 3.5" -> 88.89999999999999mm).

But beyond that, it is IMO not correct to disregard user input. If the column option is specified, a column should be created irrespective of the dimensions.
2026-03-02 21:17:56 +01:00
jffmichi fe25d8d0f7 CAM: Fix new CAM simulator on macOS 2026-03-02 11:32:02 -06:00
Florian Foinant-Willig be1ec84709 Sketcher: extend Perpendicular constraint to point point line 2026-03-02 11:30:55 -06:00
Roy-043 ffab288f4e Draft: fix clone diffuse color regression
Fixes #27958.

Delay formatting of clone object to ensure shape availability.
2026-03-02 17:13:13 +00:00
Kacper Donat 2fb271ff28 Gui: Clear cached shape after change to Deviation 2026-03-02 11:12:36 -06:00
marioalexis 617db3a2d4 Fem: Remove deprecated Calculix implementation 2026-03-02 11:09:34 -06:00
nishi 2d6e49cb7f Measurement: label drag when infront of model (#27832)
Co-authored-by: Nishendra Singh <snishendra@student.ethz.ch>
2026-03-02 11:08:54 -06:00
chris jones @ipatch 7d454121de core: fix issue #26478 select all instances even in group with mirror'd objects + unit tests 2026-03-02 11:05:45 -06:00
Grzegorz Kwacz ba404c03ef Spreadsheet: Don't show overlay 2026-03-02 11:04:47 -06:00
sliptonic 8faaa60a0a Merge pull request #27860 from petterreinholdtsen/cam-fanuc-post-crash-fix
CAM: Implemented Fanuc thread tapping and fixed crash in post processor.
2026-03-02 10:59:12 -06:00
chris jones @ipatch 7e7045577f fixes #27968 material: sunset usage of reinterpret_cast 2026-03-02 10:53:08 -06:00
Roy-043 93e537f3b3 BIM: BIM_DrawingView: always create Cut lines view
Fixes #27803.

As suggested by @semhustej: always create the "Cut lines" view, even of there are no solids (yet) that intersect the section plane.
2026-03-02 15:03:28 +00:00
Roy-043 da584c2c84 BIM: fix window hinge direction if edge has no delta Z
Fixes #24903.

If the global Z-coordinates of the endpoints of the hinge edge are equal, compare the local Z-, Y- or X-coordinates instead.
2026-03-02 15:02:22 +00:00
Roy-043 d6479d055d BIM: change TD BIMView linecaps to square 2026-03-02 15:00:54 +00:00
Roy-043 1f848b4d78 BIM: remove superfluous transaction handling when editing IFC props
As pointed out here:
https://github.com/FreeCAD/FreeCAD/pull/26758#issuecomment-3830289031
2026-03-02 14:59:47 +00:00
freecad-gh-actions-translation-bot b78b0a7d60 Update translations from Crowdin 2026-03-02 08:17:01 +01:00
Furgo d321a330ee squash with structure 2026-03-02 07:01:48 +01:00
Furgo 6a4697c74d BIM: _Equipment uses generic options task box on edit 2026-03-02 07:01:48 +01:00
Furgo f329584eb5 BIM: _Structure uses generic options task box on edit 2026-03-02 07:01:48 +01:00
Furgo 6a76d22d76 BIM: _Space uses generic options task box on edit 2026-03-02 07:01:48 +01:00
Furgo 6c85e4a6a2 BIM: Truss uses generic options task box on edit 2026-03-02 07:01:48 +01:00
Furgo d9dc07c890 BIM: _CurtainWall uses generic options task box on edit 2026-03-02 07:01:48 +01:00
Furgo 5199c47c2d BIM: _Panel uses generic options task box on edit 2026-03-02 07:01:48 +01:00
Furgo aade9e1eed BIM: Component provides a reusable options task box 2026-03-02 07:01:39 +01:00
sliptonic 07cc653e66 Merge pull request #27990 from jffmichi/cam_remove_dogbone
CAM: Remove remaining reference to deprecated Dogbone dressup
2026-03-01 21:43:14 -06:00
jffmichi 3a05cb2756 CAM: Remove remaining reference to deprecated Dogbone dressup 2026-03-02 00:19:40 +01:00
Parag Debnath 230b64f2f5 Gui: Add shortcut for save a copy (#27966)
* added shortcut for save copy

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

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

* Ctrl+Alt+Shift+S to save a copy

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

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

---------

Co-authored-by: Parag Debnath <paragforwork@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-01 19:42:54 +01:00
Ladislav Michl 1e982cae1f PD: Remove unused remapSupportShape 2026-02-28 23:20:31 +01:00
Ladislav Michl 1ed0e153dc PD: Remove unused parameter from getTopoShapeVerifiedFace 2026-02-28 23:20:17 +01:00
Petter Reinholdtsen 263bfe9948 CAM: Updated Fanuc test and support methods to match working post script.
The thread tapping is corrected and the test code is adjusted to match.
2026-02-28 22:11:15 +01:00
Chris Hennes 61418544a5 Base: Fix typo unexpection->unexpected 2026-02-28 19:57:41 +01:00
Petter Reinholdtsen df1a1ab981 CAM: Implemented Fanuc thread tapping and fixed crash in post processor.
The current post processor fail completely for any operation because the
ShapeName attribute no longer exist.  Changed code to look for attributes
present in FreeCAD 1.1 and master branch.  Rewrote thread tapping code
to work with new tapping support. Switched thread tapping to use feed in
distance per minute (G94) instead of earlier distance per revolution to
avoid switching between mm/min and mm/rev for different operations.

Fixes #27814
2026-02-28 19:38:19 +01:00
Wiljam Holmes 6dfe193428 Sketch: Rename "Attachment Editor" to "Edit Attachment" in context menu 2026-02-28 11:12:01 -06:00
sliptonic ec4dcde60c Merge pull request #27585 from tarman3/holes_auto
CAM: Drillable - Auto-select optimizations
2026-02-28 09:26:33 -06:00
sliptonic df3809e66b Original dogbone dressup has been deprecated for more than 4 years.
Dogbone II is stable.
Removing the deprecated code and tests
2026-02-28 08:47:38 -06:00
FilippoR 8653d94287 App: Add #include <climit> and switch to std::numeric_limits (#27742)
* add missing include to fix compilation on Fedora 44
* change short limit notation
2026-02-28 08:02:23 -06:00
Benjamin Nauck 93f76a8991 Merge pull request #27854 from 3x380V/signal
Part: Use signal handlers based on OCC's implementation
2026-02-28 13:58:19 +01:00
Syres916 34d03ebee6 [Mesh] Stop repeated /home/username/freecad-daily-source/src/Mod/Mesh/App/WildMagic4/Wm4MathMCR.h:30:50: warning: backslash-newline at end of file 2026-02-28 13:45:12 +01:00
wmayer 512cf349f9 Part: Use Part::SignalException in FCBRepAlgoAPI_BooleanOperation::Build
This avoids a hard crash as reported in issue 19403 and still shows the stack trace
2026-02-28 10:11:03 +01:00
wmayer 2eb4dc7c73 Part: Use signal handlers based on OCC's implementation 2026-02-28 10:11:03 +01:00
wmayer be5e657a61 Core: Refactor code to install new and SIGSEGV handlers 2026-02-28 10:11:00 +01:00
PaddleStroke 821596140d Assembly: Show Solver Task only when in Assembly workbench (#27502) 2026-02-28 08:17:43 +01:00
Chris Hennes 0c66d18c21 Wide character support for env vars on windows (#27626)
* Base: Move wstring conversion into Base::Tools

* App: Switch Windows calls from getenv to GetEnvironmentVariableW

* Apply suggestion from @kadet1090

---------

Co-authored-by: Kacper Donat <kadet1090@gmail.com>
2026-02-28 04:02:30 +00:00
Krish Sharma 9ac1b960a6 App: Improve clarity of out-of-scope link error message (#26776) 2026-02-27 21:53:57 -06:00
theo-vt 68b3d8d6e4 App.DocumentObserver: set toPython in all constructors 2026-02-27 21:30:00 -06:00
Adam Spontarelli 88787b11d1 Changed Insert Component parts list to be collapsed by default (#27658)
* Changed Insert Component parts list to be collapsed by default

* only collapse large assemblies and only expand first child.

---------

Co-authored-by: Adam Spontarelli <adam@vector-space.org>
2026-02-27 18:43:28 -06:00
wmayer 8caa218950 Sketcher: Handle exception in DrawSketchHandlerOffset::drawOffsetPreview
Do not let exception slip through Qt event handlers as this is known to cause a crash on macOS.

This fixes issue 19587
2026-02-28 01:33:35 +01:00
wmayer 61d17a6122 Part: Fix crash in Revolution::execute()
If a datum line is used as base shape then it causes a segmentation
fault because the shape is infinite that the CAD kernel fails with.

Solution:
Explicitly check beforehand if the shape is infinite or null.

This fixes issue 21429
2026-02-28 00:38:21 +01:00
wmayer d588e89d1d Gui: Do not allow to activate disabled workbench
Change Command::_assureWorkbench to check if the passed workbench is
disabled or not. If yes then do nothing.

This fixes issue 21477.

Hint: The method Application::activateWorkbench() is still able to
activate a disabled workbench
2026-02-27 23:45:37 +01:00
Chris Hennes 92ebf00cc4 Gui: Add attempted lock file name when IPC fails 2026-02-27 23:37:33 +01:00
Chris Hennes b37da5b3cc App: Check for empty path component name before appending 2026-02-27 23:37:03 +01:00
Chris Hennes 3d60531390 TD: Migrate version check to ProgramVersion class
Eliminates a use of deprecated `sscanf`
2026-02-27 23:30:37 +01:00
Chris Hennes ac576bc05e Part: Migrate version check to ProgramVersion class
Also add v1.2 to the recognized program version enumeration.
2026-02-27 23:30:11 +01:00
Chris Hennes 07e94dfaae Part: Eliminate use of sscanf
Replace with safer modern C++ `std::from_chars` (plus some additional
validation for expected inputs). Includes unit tests for new function.
2026-02-27 23:29:31 +01:00
Chris Hennes b4325de672 Core: Allow implicit construction of QString from ASCII 2026-02-27 23:21:17 +01:00
tarman3 b9b8d4023f CAM: Exporting G-code - Buttons text 2026-02-27 22:56:40 +02:00
tarman3 eb0d7ba6a5 CAM: CircularHoleBase.holeDiameter() - Remove useless obj 2026-02-27 20:43:56 +02:00
tarman3 eaf76e4d0a CAM: CircularHoleBase.holeDiameter() - Fix face 2026-02-27 20:41:07 +02:00
sliptonic b8f98e2842 Merge pull request #27040 from Dimitris75/CAM-Waterline-OCL-Adaptive-Add-Optimize-Linear-Paths
CAM: Waterline OCL Adaptive - Adding Optimize Linear Paths - Removing BoundBox ComboBox
2026-02-27 11:57:53 -06:00
sliptonic 2b98e80313 Merge pull request #27091 from Connor9220/ToolbitSubClass
CAM: Refactor shape type handling for aliases and subtypes
2026-02-27 11:53:47 -06:00
Chris Hennes 659780c31b Tests: Add QtTests run to CI 2026-02-27 11:30:55 -06:00
Dhruv Singh Jamwal 7be33f496e Gui: Prevent camel case splitting on numbers/symbols in Property Editor 2026-02-27 11:30:21 -06:00
sliptonic 51cff10dcc Merge pull request #24849 from tarman3/leadinout_arcz
CAM: LeadInOut - ArcZ following profile
2026-02-27 11:28:06 -06:00
sliptonic c9517011d2 Merge pull request #27504 from tarman3/holes_face_multiple_edges
CAM: CircularHoleBase - Fix holePosition() for face with several arcs
2026-02-27 11:25:20 -06:00
sliptonic 7deca678ca Merge pull request #27686 from tarman3/base_addgeometry_apply
CAM: Base Task Panel - Fix Apply after adding geometry
2026-02-27 11:14:21 -06:00
sliptonic 8a011392bc Merge pull request #27178 from davidgilkaufman/fix_big_arcs
[CAM] separate tolerance variable used for arc fitting from tolerance used for section height offsets
2026-02-27 10:43:50 -06:00
Chris Hennes 0872d45827 Merge pull request #27099 from timpieces/expressionparser-improvements
ExpressionParser: Return unique_ptr from public interface (#27098)
2026-02-27 09:51:08 -06:00
dependabot[bot] e292f96feb Bump actions/upload-artifact from 6.0.0 to 7.0.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-27 09:48:11 -06:00
FEA-eng 46dd3badbd Replace "Change Image" option name for clarity (#27913) 2026-02-27 13:46:21 +01:00
Benjamin Nauck 8694ccf754 Merge pull request #27862 from marioalexis84/fem-material_nonlinear
Fem: MaterialMechanicalNonlinear grouped under MaterialSolid
2026-02-26 21:32:02 +01:00
sliptonic 4878248572 Merge pull request #27859 from Doriangaensslen/d_dev
CAM: Move ThreadMilling and Tapping from experimental to standard
2026-02-26 14:08:31 -06:00
Furgo 2ee49e0647 BIM: _Wall options task box gains expressions and units support 2026-02-26 20:20:40 +01:00
Parag Debnath ca575acf1e Renamed '3d View' to 'Pick Position'. 2026-02-26 20:11:34 +01:00
marioalexis 046be9efc5 Fem: Update examples 2026-02-26 15:07:57 -03:00
marioalexis a1acc9cf38 Fem: Improve nonlinear properties 2026-02-26 15:07:57 -03:00
Roy-043 bfb0e203da Revert " Draft: fix ghost preview of Arch_SectionPlane and Draft_WorkingPlane…"
This reverts commit 37600b85a0.
2026-02-26 17:17:44 +01:00
Benjamin Nauck f319a57252 Merge pull request #27835 from 3x380V/fem 2026-02-26 17:09:50 +01:00
wmayer e1b9cbf48a FEM: Fix build warnings 2026-02-26 13:44:40 +01:00
wmayer d60deb6fb6 Fem: Optimize netgen mesh creation
When pressing the Apply button the fem mesh feature is computed but still
marked as touched. When pressing the OK button it will be recomputed even
if nothing has changed. To avoid the superfluous recompute purge the
touched flag when the Apply button is pressed.
2026-02-26 13:34:58 +01:00
tarman3 7cb5c2663d CAM: CircularHoleBase.holePosition() - Remove useless obj 2026-02-26 13:43:39 +02:00
tarman3 5e0695d150 CAM: CircularHoleBase.holePosition() - Fix for face with several arcs 2026-02-26 13:43:39 +02:00
Louis Gombert 0df693e204 Remove extra header define checks (#27851) 2026-02-25 22:46:40 -06:00
dependabot[bot] b6c8e68eda Bump step-security/harden-runner from 2.14.2 to 2.15.0
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.14.2 to 2.15.0.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/5ef0c079ce82195b2a36a210272d6b661572d83e...a90bcbc6539c36a85cdfeb73f7e2f433735f215b)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-25 22:43:52 -06:00
sliptonic a17bb6bf10 Merge pull request #27013 from tarman3/CmdMoveMill
CAM: Path.Geom.CmdMoveMill
2026-02-25 18:31:26 -06:00
Kacper Donat e62d68a49e Gui: Improve visuals of checked toolbar buttons 2026-02-25 21:05:05 +01:00
Kacper Donat 1a8840bff9 Part: Make 3D View properly checkable
This commit fixes the 3D View button in "Location" sections in Part GUI
to stay pressed when it is active.
2026-02-25 21:05:05 +01:00
tarman3 4a773d2f6a CAM: Refactor CmdMoveMill 2026-02-25 20:49:22 +02:00
tarman3 9972df7c1d CAM: Path.Geom.pointsCoincide - allow list and tuple 2026-02-25 20:40:19 +02:00
tarman3 97cf569756 CAM: PathScripts/PathUtils.py - Get CmdMove from Geom 2026-02-25 20:38:49 +02:00
tarman3 6620e149a5 CAM: Path.Geom.CmdMoveMill 2026-02-25 20:38:41 +02:00
sliptonic f2063c055f Cam constants (#27861)
* CAM: Create a more accessible CONSTANTS file

* Changes to make the tests less noisy

* Update src/Mod/CAM/CONSTANTS.py

Co-authored-by: tarman3 <joice501790018@tutamail.com>

* missing cmake change

* maintainer feedback

---------

Co-authored-by: tarman3 <joice501790018@tutamail.com>
2026-02-25 19:11:33 +01:00
Chris Hennes ad50c6eb64 Merge pull request #27428 from kadet1090/add-style-parameter-tuples
Gui: Add Tuple type to StyleParameters
2026-02-25 08:28:50 -06:00
tarman3 657a34b48a CAM: Drillable - allowPartial for faces 2026-02-25 08:07:07 +02:00
Dorian Gaensslen d5397516b5 move thread milling out of experimental too 2026-02-24 21:38:31 +01:00
Dorian Gaensslen 4895bea741 Forum Thread 49591, move from Experimental to standard 2026-02-24 21:11:44 +01:00
tarman3 9abcdad176 CAM: Drillable - Auto-select faces with number edges more than 3 2026-02-24 21:22:04 +02:00
tarman3 e643328599 CAM: Drillable - Optimizations for Auto-select 2026-02-24 21:20:54 +02:00
marioalexis 9c9bf18478 Fem: Set pipeline time info for new CalculiX 2026-02-24 16:15:57 -03:00
marioalexis c1ca8a79c9 Fem: Add method to set pipeline time info data 2026-02-24 16:00:51 -03:00
theo-vt 34ae16cd01 Sketcher: fix evaluation of driven diameter constraint 2026-02-24 19:54:53 +01:00
Ladislav Michl 6d9201c828 PD: Avoid QString to std::string back and forth conversion
Fixes Qt5 build.
2026-02-24 11:30:24 -06:00
sliptonic ab2f655245 Merge pull request #26131 from tarman3/axismap
CAM: Axismap Dressup - Invert rotary axis
2026-02-24 09:34:17 -06:00
Roy-043 650b15dd76 Draft: fix anno style assignment regression
Fixes #27822.

Break statement had wrong indentation.
2026-02-24 13:03:25 +01:00
Syres916 ab5ef99344 [MeshPart] Fix string encoding document, object and subobject names 2026-02-24 00:28:35 -06:00
tarman3 0a4f6ec7c4 CAM: Drillable - Remove raisedFeature() 2026-02-24 06:20:11 +02:00
tarman3 2e7261eec3 CAM: Drillable - Fix linter errors 2026-02-24 06:20:11 +02:00
ᴩʜᴏɴᴇᴅʀᴏɪᴅ e89d849bb7 [ Sketcher ]: Fix Windows Include (#27829) 2026-02-23 21:35:35 -06:00
PaddleStroke 3c860396d8 TechDraw: Annotation tool rework (#24624) 2026-02-24 00:59:15 +00:00
Parag Debnath acb14726b6 Part: add missing tooltips to Location task panel (fixes #27736) 2026-02-23 21:41:16 +01:00
Louis Gombert 0b44a3f6c8 Sketcher: Optimize eliminateNonZerosOverPivotInUpperTriangularMatrix for sparse matrices
Matrix processing function eliminateNonZerosOverPivotInUpperTriangularMatrix tried to eliminate ALL non zero values in the upper triangle, even values under a small epsilon. This makes the routine take much more time than it should be. Not considering small values significantly speeds it up, ultimately increasing sketch constraint solving performance.
2026-02-23 18:30:54 +01:00
tarman3 26a1e452c0 CAM: Profile - Fix 2 equal length edges 2026-02-23 11:30:01 -06:00
PaddleStroke 4deb889057 Assembly: Fix mirrored links not working. (#26090) 2026-02-23 11:29:27 -06:00
xtemp09 59370eeb23 [GUI] Prevent double click event on visibility icon (#26043) 2026-02-23 11:26:15 -06:00
theo-vt 92894ea3a8 Sketcher: Evaluate driven constraints rather than solving them (#26632) 2026-02-23 11:14:22 -06:00
Loke Strøm f153960396 Measurement: Added disc/circular faces measurements radius, diameter and area. (#27415)
* Added disc measurements radius, diameter and area.

* [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>
2026-02-23 18:04:01 +01:00
Paul Ebbers e591fe0901 GUI: Add wrap-around to search in parameters (#24772) 2026-02-23 11:02:55 -06:00
sliptonic 88e7c60414 Merge pull request #27788 from petterreinholdtsen/cam-fanuc-fix-drilling
CAM: Adjusted fanuc post processor to always use required drill parameters.
2026-02-23 10:54:41 -06:00
Yash Suthar 1c0ac9a269 Measure: fix measurements are saved if exit tool by opening a sketch
Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
2026-02-23 10:47:21 -06:00
PaddleStroke 194ec0820c PartDesign: UpToFace to plane in LCS (#27637)
* PartDesign: UpToFace to plane in LCS

* Update TaskSketchBasedParameters.cpp
2026-02-23 10:46:05 -06:00
tarman3 ab1b3246d4 CAM: AxisMap Dressup - Add 'Invert' to Task panel 2026-02-23 18:42:48 +02:00
tarman3 27b74f3ba3 CAM: AxisMap Dressup - Deflection 2026-02-23 18:42:47 +02:00
tarman3 1396309093 CAM: AxisMap Dressup - Invert axis 2026-02-23 18:42:42 +02:00
Kacper Donat cd19a3cee5 Merge pull request #27127 from alfrix/fix_tapered
PD: hole fix tapered threads not cutting properly
2026-02-23 17:42:24 +01:00
Benjamin Nauck 7923614124 Merge pull request #27367 from 3x380V/app
App: Random fixes 3
2026-02-23 14:09:23 +01:00
captain0xff f238a5f4e5 CAM: fix the transform tool 2026-02-23 11:07:37 +01:00
wmayer 26c2d7a77c App: Fix linter warnings 2026-02-23 10:12:38 +01:00
wmayer 05ef4153f5 App: Add overloaded method Application::closeDocument 2026-02-23 10:12:38 +01:00
wmayer 7a392c4d99 App: Add overloaded method Document::removeObject 2026-02-23 10:12:38 +01:00
wmayer 0eb01c636c App: Fix PropertyFileIncluded::SaveDocFile
Before trying to access the filename check whether it isn't set.
In this case print a warning and return.
2026-02-23 10:12:38 +01:00
wmayer af5c40d8e8 App: Fix some linter warnings 2026-02-23 10:12:38 +01:00
wmayer e4b6e5ab43 App: Add convenience methods to DocumentT and DocumentObjectT 2026-02-23 10:12:38 +01:00
wmayer 322da60cb2 Fix macro Q_DISABLE_COPY_MOVE 2026-02-23 10:12:38 +01:00
Furgo 99d142af38 BIM: rename obsolete Mesh property to HiRes (#27783)
* BIM: rename obsolete Mesh property to HiRes

* BIM: remove unused createMeshView function

* BIM: remove all remaining references of Mesh
2026-02-23 08:09:40 +01:00
freecad-gh-actions-translation-bot 23df715e24 Update translations from Crowdin 2026-02-22 22:04:19 -06:00
marioalexis 159059fc7d Fem: Fix import vtk Python module 2026-02-22 21:51:32 -06:00
marioalexis d4c28786df Fem: Add displace mesh option to CalculiX 2026-02-22 16:29:45 -06:00
ᴩʜᴏɴᴇᴅʀᴏɪᴅ ca9e1ecdf3 All: Header Guards ➞ Pragma Once (#27154) 2026-02-22 16:28:20 -06:00
Max Wilfinger 3a241c5515 Merge pull request #27775 from marioalexis84/fem-elmer_text_output
Fem: Load Elmer text output
2026-02-22 21:30:32 +01:00
tarman3 144f1843fa CAM: Axismap Dressup - Refactoring 2026-02-22 21:36:06 +02:00
tarman3 92a23ca21b CAM: Axismap Dressup - Remove _linear2angular() 2026-02-22 21:36:06 +02:00
tarman3 a57ea57dba CAM: AxisMap Dressup - Remove _stripArcs() 2026-02-22 21:36:06 +02:00
tarman3 0fce2611ad CAM: Base Task Panel - Fix Apply after adding geometry 2026-02-22 16:38:20 +02:00
Morten Vajhøj cc626f88b1 Measurement: Moved buttons to top (#27774)
* Moved button position

* Remove command

Remove setting button position in TaskMeasure constructor.
2026-02-22 12:01:16 +01:00
Petter Reinholdtsen 954a1239f3 Adjusted fanuc post processor to always use required drill parameters.
At least for G73, the Z, Q and R parameters seem to be required.
Assuming drill related parameters are required for all drill
operations to err on the safe side.

Fixes #27413
2026-02-22 09:56:33 +01:00
marioalexis 1e51d10de8 Fem: Enable keep results on rerun option for new CalculiX 2026-02-21 18:40:13 -03:00
marioalexis e116b5ae34 Fem: Load Elmer solver text output 2026-02-21 18:40:06 -03:00
Max Wilfinger 7001255e90 Merge pull request #27749 from marioalexis84/fem-elmer_examples_run
Fem: Run Elmer examples - fixes #27547
2026-02-21 22:04:22 +01:00
Furgo b36991b239 BIM: initial implementation of Sliding Door preset (#27375)
* BIM: initial implementation of sliding door preset

* BIM: fix sliding door context menus

* BIM: limit travel distance

* BIM: increase preset indexes for icons

* BIM: update edit task panel to adapt to sliding doors

* BIM: make rotation/translation data exclusive or

* BIM: remove code duplication for Sliding and -Sliding doors

* BIM: refine travel distance clamping to expose handle

* BIM: make sliding direction independent of geometry direction

* BIM: remove non-visible 2D symbol for now

* BIM: make door leaf wire comment more precise

* BIM: use local coordinates when calculating the start/end points for the sliding track
2026-02-21 19:10:46 +00:00
Max Wilfinger d3496b0458 Merge pull request #27616 from WandererFan/nearestFractionFillTemplateFields
TechDraw: Fix fillTemplateFields returns unusual fractional scale
2026-02-21 16:01:46 +01:00
Max Wilfinger 23f046075a Merge pull request #27577 from pieterhijma/fix-fem-analysis-toggle 2026-02-21 13:54:04 +01:00
Chris Hennes 359e1033ec Addon Manager: Update to 2026-02-19 2026-02-21 13:49:47 +01:00
tarman3 c9518817c6 CAM: Path.Op.Area - Offer side 2026-02-21 08:45:24 +02:00
dependabot[bot] 2fda119f74 Bump korthout/backport-action from 3.4.1 to 4.1.0
Bumps [korthout/backport-action](https://github.com/korthout/backport-action) from 3.4.1 to 4.1.0.
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](https://github.com/korthout/backport-action/compare/d07416681cab29bf2661702f925f020aaa962997...01619ebc9a6e3f6820274221b9956b3e7365000a)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-20 20:20:14 -06:00
chris jones @ipatch 1d6b2a4cca core: git: alphabetize entries in .gitignore and add entry for .clangd 2026-02-21 01:05:06 +01:00
Billy Huddleston 69b1b19024 CAM: Refactor shape type handling for aliases and subtypes
This PR intruduces a way to dynamicly alias toolbits and adds subtype
for toolbits. Prior to this change, aliases were hardcoded in multiple
locations, making it difficult to maintain and extend. Now, aliases
and the newly subtypes are defined in a single JSON file, which is
loaded at runtime. This allows for easier management and addition of new
aliases or subtypes without modifying the codebase.

Updated the shape system to use a dict format for aliases and subtypes,
improved label formatting, and fixed normalization logic for toolbit
types. Enhanced dropdown display and editor logic to properly handle
subtypes and aliases, including special cases for consecutive capitals.

Users can add shape_aliases.json to the toolbit Shape dirctory allowing
theme to add/remove entries.  Adding a "!" in front of a alias or a
subtime removes it from the list.

This PR also introduces the ability for  the user to choose tools from
a libary or all tools when adding tools via the Job panel.

src/Mod/CAM/Path/Tool/docobject/ui/docobject.py:
- Added keep_case and preserve_consecutive_caps options to
_get_label_text for improved label formatting

src/Mod/CAM/Path/Tool/shape/__init__.py:
- Refactored alias/subtype loading to support new dict format
- Applied aliases and subtypes to shape classes

src/Mod/CAM/Path/Tool/shape/models/base.py:
- Added subtypes attribute to ToolBitShape
- Updated class lookup to support subtypes

src/Mod/CAM/Path/Tool/toolbit/models/base.py:
- Improved normalization logic for aliases and subtypes in
ToolBit.from_dict

src/Mod/CAM/Path/Tool/toolbit/ui/editor.py:
- Updated editor logic to use subtypes and aliases for dropdowns
- Improved read-only and editable state handling

src/Mod/CAM/Path/Tool/toolbit/ui/typefilter.py:
- Used _get_label_text for dropdown filter display with improved
formatting

src/Mod/CAM/Tools/Shape/shape_aliases.json:
- Converted to new dict format with separate aliases and subtypes
2026-02-20 18:48:46 -05:00
sliptonic e3857b11a1 Merge pull request #26818 from tarman3/engrave_fix_taskpanel
CAM: Engrave - Fix regression in Task panel after #22304
2026-02-20 12:02:57 -06:00
sliptonic 6a4b6af094 Merge pull request #27389 from tarman3/path_length
CAM: Fix calculation arc move length
2026-02-20 12:00:47 -06:00
sliptonic 088b384216 Merge pull request #27704 from tarman3/leadinout_g00
CAM: LeadInOut - Replace G00 and G01 by G0 and G1
2026-02-20 11:57:10 -06:00
sliptonic 3f83c820d5 Merge pull request #24958 from tarman3/startPoint
CAM: Profile - Start point in the middle of longthest edge
2026-02-20 11:05:53 -06:00
marioalexis 49652e3c60 Fem: Update and clean up examples and test 2026-02-20 13:01:07 -03:00
marioalexis f8e5a92b98 Fem: Add base class for solver and mesher tools 2026-02-20 10:43:49 -03:00
marioalexis 6f8e9f1a9e Fem: Add Tool property to solvers and meshers 2026-02-20 10:43:49 -03:00
chris jones @ipatch b026958f80 part: fixes #27592 add tooltips for part primitives 2026-02-20 10:14:16 +01:00
marcuspollio d90b6ebd0d Gui: Add line selection to TextEditor 2026-02-19 22:24:40 -06:00
dependabot[bot] 0327534ffe Bump actions/upload-artifact from 5.0.0 to 6.0.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 16:20:29 -06:00
dependabot[bot] b4e690d9cb Bump actions/download-artifact from 6.0.0 to 7.0.0
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/018cc2cf5baa6db3ef3c5f8a56943fffe632ef53...37930b1c2abaa49bbe596cd826c3c89aef350131)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 16:20:17 -06:00
wandererfan ba24ab8a49 [TD]fix unhelpful warning message 2026-02-19 15:30:48 -05:00
wandererfan b0e11e286b [TD]use thin line for smooth edges 2026-02-19 15:30:48 -05:00
Pieter Hijma 94c722d285 Fem: Improve visibility toggling Result and Solver 2026-02-19 16:28:00 +01:00
Roy-043 ddb54cce65 BIM: workaround for WP switch crash (issue #26539) (#27373) 2026-02-19 09:26:35 -06:00
Pieter Hijma 0339458869 Core: Disable toggling visibility text document 2026-02-19 16:22:55 +01:00
Furgo 85e0038515 BIM: Set default value of 'MoveWithHost' property to True (#27685) 2026-02-19 14:39:44 +01:00
Yash Suthar f67088a970 Measure: Fix crash while dragging label of unsaved measurment
Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
2026-02-19 07:36:43 +01:00
Nathan Schulte 99016e37ed Gui: Add startup log when missing SVG support (#27694) 2026-02-18 18:00:14 -06:00
PaddleStroke be6af47f29 Sketcher: Offset: add checkbox tooltips (#26114) 2026-02-18 21:02:54 +00:00
tarman3 c29868cd48 CAM: LeadInOut - Replace G00(1,2,3) by G0(1,2,3) 2026-02-18 20:43:44 +02:00
dependabot[bot] 45f65f643d Bump actions/stale from 10.1.0 to 10.2.0
Bumps [actions/stale](https://github.com/actions/stale) from 10.1.0 to 10.2.0.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/5f858e3efba33a5ca4407a664cc011ad407f2008...b5d41d4e1d5dceea10e7104786b73624c18a190f)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: 10.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-18 13:41:16 +01:00
paul aa4a71b55b [ArchWall] Fix Regression: sortSketchWidth only in addon (#27676)
* [ArchWall] Fix Regression: sortSketchWidth only in addon

Regression was introduced when get_width() method uses ArchSketchObject.sortSketchWidth() function in below lines.

https://github.com/FreeCAD/FreeCAD/blob/468269b9a6ea58cd8b0f9d8579b711c530db83b2/src/Mod/BIM/ArchWall.py#L1668-L1673
        if not lwidths:
            if obj.OverrideWidth:
                if obj.Base and obj.Base.isDerivedFrom("Sketcher::SketchObject"):
                    lwidths = ArchSketchObject.sortSketchWidth(
                        obj.Base, obj.OverrideWidth, obj.ArchSketchEdges
                    )

ArchSketchObject.sortSketchWidth() function is not in the FC core ArchSketchObject.py module and this results in error.  This function would only exist when the external add-on is present and loaded.

Previously, a try/exception test was used; now hasattr() is used in this fix to test the presence of the required function before it is used.

* [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>
2026-02-18 11:49:33 +01:00
Yash Suthar 2d3b0a2ded Measure: ix angle measurement for face and edge selection
Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
2026-02-18 09:21:17 +01:00
Louis Gombert 3bad5dabde Add missing NOLINTEND clang-tidy comment 2026-02-17 15:26:14 -06:00
PaddleStroke bd07c8a214 Sketcher: OVP Fix tab not working when mouse move (#27638)
* Sketcher: OVP Fix tab not working when mouse move

* [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>
2026-02-17 22:02:36 +01:00
Benjamin Nauck 99f4776fda Merge pull request #27381 from furgo16/bim-window-task-panel
BIM: add window options task box
2026-02-17 18:52:33 +01:00
Furgo c788a88d6a BIM: simplify value assignment for quantity spinboxes
Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>
2026-02-17 17:19:55 +01:00
Furgo 6f0b1fca3d BIM: use the correct widget for percentages 2026-02-17 17:19:55 +01:00
Furgo 9fad0ed223 BIM: add window options task box 2026-02-17 17:19:55 +01:00
dependabot[bot] fca58d99ed Bump actions/cache from 4.3.0 to 5.0.3
Bumps [actions/cache](https://github.com/actions/cache) from 4.3.0 to 5.0.3.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/0057852bfaa89a56745cba8c7296529d2fc39830...cdf6c1fa76f9f475f3d7449005a359c84ca0f306)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 5.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-17 09:08:42 -06:00
bdieterm 468269b9a6 TemplatePyMod: fix DocumentObject for newer FreeCAD versions (#27662)
* TemplatePyMod: fix DocumentObject for newer FreeCAD versions

original bug report:
https://forum.freecad.org/viewtopic.php?p=873546

* TemplatePyMod: fix FeaturePython example for newer FreeCAD versions
2026-02-17 10:07:58 +01:00
Louis Gombert 289411f51c Move costly boost includes out of core headers
Use pimpl or move definitions to .cpp files in order to avoid including huge Boost headers in core FreeCAD headers. Due to boost inclusions in a few core headers, boost graph utilities, multi index and predicates headers were included in in a large portion of translation units, without them being actually required. This helps reduce build time of the project.
2026-02-16 21:58:36 -06:00
Chris Hennes f83aaf0e59 Merge pull request #25538 from marioalexis84/fem-clean_dlg_settings
Fem: Remove unnecessary code
2026-02-16 11:14:31 -06:00
xtemp09 f1d79d9ab4 [GUI] Make precision of QuantitySpinBox accessible from Python 2026-02-16 11:13:52 -06:00
marbocub bc3c0dc19a Sketcher: Add symmetric constraint option (an element + a symmetry line) (#25525) 2026-02-16 11:05:56 -06:00
Steven James 8567dce28a FeaturePython objects include the Python class's __repr__ it their __repr__ (#24462) 2026-02-16 10:57:14 -06:00
Chris Hennes 72a024aaeb Merge pull request #27587 from WandererFan/BrokenViewRemoveFCBRepAlgoAPI_Cut2
TechDraw: FCBRepAlgoAPI_Cut returns null shape for BrokenView break
2026-02-16 10:51:06 -06:00
xtemp09 e0cd49e670 [Spreadsheet] Syncronize scrollbars in ZoomableView
Closes #27165.
2026-02-16 10:38:56 -06:00
Chris 17d5bca2ec part: fixes #27365 mirror place copy at correct location (#27370) 2026-02-16 10:32:08 -06:00
WandererFan 82ba9ec9d8 fix spelling mistake
Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
2026-02-16 09:24:47 -05:00
Furgo d05db60465 BIM: prevent child objects from moving during Arch Wall debasing (#27290)
* BIM: regression test for child object stability during wall debasing

Introduces test_debase_wall_stationary_children to verify that objects
attached to a wall (via Additions or Hosts) retain their global position
when the wall's base is removed and its placement is recalculated.

* BIM: Fix wall debasing to maintain stationary child element positions

Corrects the placement propagation that occurred when Arch.debaseWall()
recalculated the Wall's Placement, causing connected children (Windows,
Additions) to shift their global coordinates.

The fix pins children by capturing their current global placements before
the wall's placement is updated, and immediately restoring those placements
after the wall's transformation is complete.

Fixes: https://github.com/FreeCAD/FreeCAD/issues/27267

* Avoid confusing comment about wall placement in TestArchWall.py

---------

Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>
2026-02-16 14:14:34 +00:00
PaddleStroke bb5afb911a Sketcher: Fix loss of expression on trim (#27505) 2026-02-15 20:41:13 -06:00
freecad-gh-actions-translation-bot ec9ead0db9 Update translations from Crowdin 2026-02-15 19:41:17 -06:00
PaddleStroke 94a4017432 Assembly: Bom: fix non-grouping regression 2026-02-15 19:03:06 -06:00
Louis Gombert 5f89fd4e98 Replace deprecated QImage::mirrored by QImage::flipped
QImage::mirrored was deprecated and will be deleted by Qt6.13
2026-02-15 18:59:37 -06:00
Grzegorz Kwacz 7b4770c3f2 Remove Navigation from context menu 2026-02-15 18:57:54 -06:00
Chris Hennes f991407900 PD: Return inversion status by reference (#27435)
* PD: Return inversion status by reference

* Update FeatureExtrude.cpp

Co-authored-by: PaddleStroke <pierrelouis.boyer@gmail.com>

---------

Co-authored-by: PaddleStroke <pierrelouis.boyer@gmail.com>
2026-02-16 01:01:37 +01:00
PaddleStroke 47855a018b Assembly: Fix nested assembly stuck isolate bug 2026-02-15 17:50:13 -06:00
wandererfan f60f3d7cc5 [TD]use nearestFraction to get scale 2026-02-15 18:33:09 -05:00
wandererfan bef9d03312 [TD]expose nearestFraction to python 2026-02-15 18:32:06 -05:00
Roy-043 37600b85a0 Draft: fix ghost preview of Arch_SectionPlane and Draft_WorkingPlaneProxy (#27605) 2026-02-15 17:06:44 -06:00
bdieterm ce38741a52 Core: improve Python docstring for Document.addObject 2026-02-15 17:04:19 -06:00
Roy-043 62700a5f12 TemplatePyMod: fix regression due to locked=True mod
Fix regression caused by:
https://github.com/FreeCAD/FreeCAD/commit/a7331cbb43876b14e5e84d1fde1b673e8c381bb7
2026-02-15 12:48:53 -06:00
Furgo 562cac277c BIM: fix coordinate normalization and area calculation for generic ArchComponents (#27322)
* BIM: extend ArchComponent test suite

Adds several unit tests to TestArchComponent.py to validate the
coordinate system logic and CSG behavior of generic Arch Components.

Included tests cover:
- Double-transformation/displacement bugs when using moved base objects.
- Correct alignment of CSG additions/subtractions in world space.
- Consistency of Vertical and Horizontal area calculations for
  rotated components.
- Automatic geometry spreading (arraying) via the Axis property.
- Cleanup behavior ensuring the shape is cleared when the Base
  link is removed.

* BIM: fix double displacement bug and area calculation in ArchComponent

Rewrites ArchComponent.Component.execute to resolve placement
conflicts between the Document Object and its internal TopoShape.

Changes:
- Reset base_shape.Placement to Identity immediately after copying
  from the source. This strips inherited placements from the Base
  object, ensuring the geometry is local before processing.
- Pass the object's placement to processSubShapes. This allows
  additions and subtractions to be correctly localized to the
  component's local origin.
- Replaces direct Shape assignment with self.applyShape(). This fixes
  area calculations by ensuring the AreaCalculator receives the
  correct placement context, and enables automatic geometry
  spreading via the Axis property.

Fixes: https://github.com/FreeCAD/FreeCAD/issues/24580

* BIM: Refine base validation in ArchComponent to prevent stale shapes

Updates the validation logic in ArchComponent.execute() to correctly
handle the removal of a base object.

Changes:
- The check on self.ensureBase(obj) now explicitly looks for
  False. Because ensureBase returns None when no base is present,
  the previous logic would return early and leave the old shape
  behind.
- This change allows the method to fall through to the shape-clearing
  logic, ensuring that unlinking a base object correctly removes its
  geometry from the 3D view.
- Added a TODO note to ensureBase() regarding its undocumented
  triple-state return (True, False, None) for future cleanup.
2026-02-15 17:35:26 +01:00
Kacper Donat fae6cda1d7 Merge pull request #26938 from chennes/macroPathToDefault
Gui: Don't record macro path if default
2026-02-14 20:24:31 +01:00
Chris Hennes 45598fa319 Merge pull request #27552 from hyarion/fix-schema-issues
Base: Fix schema issues
2026-02-14 12:17:51 -06:00
Loke Strøm cbdb615141 Measurement: Fix: Implicit C-string to QString conversions causing build failure (#27580)
* Measurement: Fix: missing tr() wrapping causing build failure

* Swapped tr() with QLatin1String()

* [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>
2026-02-14 09:49:34 +01:00
Chris Hennes 3fecf957cb Points: Switch to modern libE57 types 2026-02-13 23:33:24 +01:00
Chris Hennes 0cacc9bd34 Merge pull request #27363 from 3x380V/import
Import fixes
2026-02-13 15:43:45 -06:00
theo-vt 9cbef0c5ce Sketcher.scale: scale constraint with the right index (#27188) 2026-02-13 15:34:46 -06:00
chris jones @ipatch 4938a6f75b material: fixes #25817 prevent unecessary save over dialogue 2026-02-13 15:32:46 -06:00
PaddleStroke 885b8cf1de Sketcher : SketchObject::getHigherElements fix (#27560) 2026-02-13 15:32:26 -06:00
Pieter Hijma 1bfaa81d77 FEM: Reenable toggling visibility
This reenables visibility toggling for Analysis and Solver objects.
2026-02-13 22:16:03 +01:00
Pieter Hijma 7586620d41 Revert [Core] Remove various DisplayModes from FEM
This reverts commit 5915575f19.
2026-02-13 21:54:02 +01:00
Loke Strøm 5d81f8ac16 Sketcher: Fix: Arc of ellipse when first and second X coordinates are the same (#27327) 2026-02-13 11:57:27 -06:00
Syres916 ba030237b7 [Gui] Ensure Read Only Booleans in PropertyEditor are shown using Disabled Text Color (#27429)
* Ensure read only Booleans are shown using Disabled Text color
* Make the disabled text color a more significant contrast to enabled
* Ensure correct contrasting color for Axis letters versus background color for both Light and Dark themes
2026-02-13 11:56:20 -06:00
Frank David Martínez M f1366e8a75 Base: Remove assertion on isForceXML() (#27491)
This fixes a difference between Main code and LS3 Code ported during TNP big merge. The Issue generates a crash if FreeCAD is compiled in Debug Mode: #27489.
2026-02-13 11:51:52 -06:00
Chris e595cc49f2 FEM: Update netgenplugin src files to fix builds with netgen >= 6.2.2601 (#27508) 2026-02-13 11:50:04 -06:00
chris jones @ipatch 9289e27230 gui: preferences fixes #27379 2026-02-13 11:48:48 -06:00
Roy-043 a8757f7947 Draft: fix depency of patharray normal on view direction
Change normal calculation to use get_shape_normal
2026-02-13 11:47:44 -06:00
Chris Hennes 9e042ff480 PD: Improve error handling for RevolMethod::ToFirst 2026-02-13 17:48:13 +01:00
wandererfan 6d73f9173c [TD]use BRepAlgoAPI_Cut instead of FCBRepAlgoAPI_Cut 2026-02-13 10:29:46 -05:00
wandererfan 36ddfdc7b9 [TD]fix crash on failed cut
- wrong result and warning on first time through.  Fixes itself after
  next execute().
- https://github.com/FreeCAD/FreeCAD/issues/27414
2026-02-13 10:29:46 -05:00
Paweł Biegun 1752fd59f9 Measurement: Add on the fly measurement unit change (#27462)
Enables the user to change the unit of the measurement temporarily to convert to a different unit. This is useful when the user sometimes needs to get a dimension of the model in a different unit than the one it was designed in.
2026-02-12 14:35:54 +00:00
Benjamin Nauck d94269f85f Base: Add sweep round-trip tests for all unit schemas
Sweep tests parse a string and translate it back, verifying identical
output. Values cover every threshold band at 10x increments plus a
scientific-notation value in each default band. Tests all 10 schemas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 14:26:46 +01:00
Benjamin Nauck bb977afe55 Base: Fix floating point issue in schema threshold comparison
When a parsed value lands exactly at a threshold boundary (e.g. "1 S/m"
= 1e-9 at threshold 1e-9), floating point rounding could cause the
wrong unit to be selected. Shrink thresholds by a relative epsilon so
boundary values fall through to the next (more natural) unit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 14:26:45 +01:00
Benjamin Nauck 3f17f2f01f Base: Fix schema translation data
Corrects 12 bugs across Internal and MKS schemas where factors were
wrong, units were assigned to the wrong threshold positions, or
thresholds didn't align with natural unit boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 14:26:45 +01:00
Roy-043 7912f84136 BIM+Draft: fix Placement task panel issue for Arch_SectionPlane and Draft_WorkingPlaneProxy (#27101)
* BIM+Draft: fix Placement Task Panel issue for Arch_SectionPlane and Draft_WorkingPlaneProxy

* BIM+Draft: fix Placement Task Panel issue for Arch_SectionPlane and Draft_WorkingPlaneProxy
2026-02-12 12:39:46 +00:00
Roy-043 db5fff6ccc BIM: fix BuildingPart issues with Arch_Reference 2026-02-12 11:35:55 +00:00
PaddleStroke 6abb2b447f Assembly: Isolate grounded objects on selection (#24952)
* Assembly: Isolate grounded objects on selection

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

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

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

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

* Update ViewProviderAssembly.cpp

* Update ViewProviderAssembly.cpp

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
2026-02-12 09:43:46 +01:00
marioalexis ba174bdad5 Fem: Remove unnecessary code from Z88 preference page 2026-02-12 09:38:33 +01:00
marioalexis ea27d96374 Fem: Remove unnecessary code from import/export INP preference page 2026-02-12 09:38:33 +01:00
marioalexis 1fcbe6095c Fem: Remove unnecessary code from CalculiX preference page 2026-02-12 09:38:33 +01:00
JIJINBEI 379179ce2b README: Update compiling section to recommend pixi (#27501) 2026-02-11 21:36:18 +00:00
Chris Hennes 076c5916b5 Sketcher: Remove unneeded parameters from seekConstraintPosition 2026-02-11 19:49:31 +01:00
Yash Suthar 3d14203fa4 Draft: fix Draft_Label MaxChars property (#27478)
* Draft: fix Draft_Label MaxChars property

Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>

* Minor tweak: moved/replaced call to self.onChanged

---------

Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>
2026-02-11 17:58:42 +00:00
Chris Hennes ec18d4e250 Tests/Sketcher: Eliminate unused variables 2026-02-11 17:03:18 +01:00
Chris Hennes ecbe21ca03 Sketcher: Annotate unused parameter 2026-02-10 19:10:36 +01:00
Roy-043 54c0c2f83c Draft: fix ghost preview of Draft_Labels
Draft_Labels have a unique Placement implementation. A ghost preview therefore cannot be generated in the standard manner. This was missed in #18795 (my bad).
2026-02-10 11:43:22 -06:00
Chris 47aa61bd94 CI: allow libpack builds to be triggered via githubs workflow_dispatch (#26742) 2026-02-10 11:42:23 -06:00
Yash Suthar 2cd45b07f7 Sketcher: Fix snap while drag and fix drag for arc
Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
2026-02-10 10:20:11 -06:00
Roy-043 0eaf14373f BIM: fix case of some titles (#27474) 2026-02-10 15:41:05 +00:00
dependabot[bot] ff377e031f Bump jwlawson/actions-setup-cmake from 2.0.2 to 2.1.1
Bumps [jwlawson/actions-setup-cmake](https://github.com/jwlawson/actions-setup-cmake) from 2.0.2 to 2.1.1.
- [Release notes](https://github.com/jwlawson/actions-setup-cmake/releases)
- [Commits](https://github.com/jwlawson/actions-setup-cmake/compare/802fa1a2c4e212495c05bf94dba2704a92a472be...3a6cbe35ba64df7ca70c51365c4aff65db9a9037)

---
updated-dependencies:
- dependency-name: jwlawson/actions-setup-cmake
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-10 09:12:33 -06:00
PaddleStroke 3d0df45cd4 Assembly: BOM: take mirrored state of links in account. (#26113) 2026-02-10 09:10:03 -06:00
wmayer be3acac53a Import: Fix import/export of STEP file
For the import/export use the transparency value of the material property.
Since v1.0 the alpha channel of the diffuse color is used for this but
when changing the transparency in the user interface this alpha channel
won't be adjusted and thus leads to unexpected results.

This fixes issue 18569
2026-02-10 11:03:27 +01:00
wmayer 1412cad2ec Import: Use ImportGui module for IGES import & export
Fixes issue 10701
2026-02-10 11:03:27 +01:00
Caio Venâncio do Rosário bf51a00dfd Draft: Fix switchUi method bug (#27422)
* Draft: Fix switchUi method bug

* [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>
2026-02-10 10:33:35 +01:00
Christoph Niethammer 1046c3682a Fix typos (#26576)
* Fix typos in code documentation

Signed-off-by: Christoph Niethammer <christoph.niethammer@gmail.com>

* Update tool tip for links 'copyOnChange' property

The tool tip for the copyOnChange property was missing the "tracking"
option and had some typos. For details see the wiki documentation at
https://wiki.freecad.org/Std_LinkMake and commit
d1b6bb78d1.

Signed-off-by: Christoph Niethammer <christoph.niethammer@gmail.com>

---------

Signed-off-by: Christoph Niethammer <christoph.niethammer@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
2026-02-09 19:15:50 -06:00
sliptonic 4497ce0146 Merge pull request #22204 from jffmichi/camsim
CAM: integrate new simulator as MDI widget into main window
2026-02-09 11:40:06 -06:00
tarman3 353459f1fe CAM: Profile - fix _getCutAreaCrossSection() 2026-02-09 11:12:11 -06:00
drwho495 72b1076788 Remove hasher check and migrate CAM files 2026-02-09 11:00:23 -06:00
Chris Hennes 6a1da227cd Merge pull request #27346 from TomPcz/sketcher-label-offset
Sketcher: Fix dimension label alignment and inactive strikethrough
2026-02-09 10:58:39 -06:00
Billy Huddleston 6e34b79da4 CAM: Update SVG annotation IDs for tool shapes
Renamed several SVG text element IDs in tool shape files that did not
match the expected naming conventions used. This ensures that the tool
parameters are correctly recognized and utilized by the Tool library
editor.

src/Mod/CAM/Tools/Shape/bullnose.svg:
- Changed text element id from "torus_radius" to "corner_radius"

src/Mod/CAM/Tools/Shape/radius.svg:
- Changed text element id from "cutting_edge_height-7" to
"cutting_radius"
- Changed text element id from "diameter-9" to "tip_diameter"

src/Mod/CAM/Tools/Shape/svg_source/bullnose.svg:
- Changed text element id from "torus_radius" to "corner_radius"

src/Mod/CAM/Tools/Shape/svg_source/radius.svg:
- Changed text element id from "cutting_edge_height-7" to
"cutting_radius"
- Changed text element id from "diameter-9" to "tip_diameter"
2026-02-09 10:55:53 -06:00
Neale Swinnerton e38c831970 feat(Gui): set client name to FreeCAD when connecting to spacenav
This enables per-application configuration in spacenavd for FreeCAD.
2026-02-09 10:55:23 -06:00
sliptonic 3f84746a5c Merge pull request #27247 from Daniel-Khodabakhsh/fix-0-step-down
CAM: Fix case when CAM operation `Start depth` equal to `Final depth` and `Step down` is zero
2026-02-09 10:06:04 -06:00
dependabot[bot] 94b147fcad Bump step-security/harden-runner from 2.14.1 to 2.14.2
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.14.1 to 2.14.2.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/e3f713f2d8f53843e71c69a996d56f51aa9adfb9...5ef0c079ce82195b2a36a210272d6b661572d83e)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-09 10:01:10 -06:00
chris jones @ipatch c4317f88f8 sketcher: fixes #27281 fix access out of bounds crash with "remove axes alignment" 2026-02-09 09:52:02 -06:00
dependabot[bot] c8c764e215 Bump prefix-dev/setup-pixi from 0.9.3 to 0.9.4
Bumps [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) from 0.9.3 to 0.9.4.
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](https://github.com/prefix-dev/setup-pixi/compare/82d477f15f3a381dbcc8adc1206ce643fe110fb7...a0af7a228712d6121d37aba47adf55c1332c9c2e)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-09 08:53:31 -06:00
freecad-gh-actions-translation-bot e5d0e5316d Update translations from Crowdin 2026-02-09 05:39:43 +01:00
Kacper Donat 1cc53d911a Gui: Add element-wise tuple arithmetic to StyleParameters
Add arithmetic operators (+, -, *, /, unary -) to Value, enabling
element-wise operations on tuples and scalar broadcast with numerics.
Tuple addition/subtraction uses union semantics: named elements match
by name, unnamed elements match positionally, and unmatched elements
pass through. BinaryOp and UnaryOp now delegate to these Value operators.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:33:00 +01:00
Kacper Donat 7bf2050865 Gui: Add dot syntax for tuple member access in StyleParameters
Add MemberAccess AST node and postfix `.member` parsing to support
extracting individual elements from tuple-valued parameters, e.g.
`@ButtonBorderThickness.left` or `@Grays.0`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:33:00 +01:00
Kacper Donat b7b3187e1d Gui: Split Value types out of ParameterManager into Value.h/.cpp
Move Numeric, Tuple, Value, valueTypeName, ArgumentParser, and ParamDef
into their own Value.h/.cpp files. ParameterManager.h now includes
Value.h and keeps only parameter sources and the manager itself.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:33:00 +01:00
Kacper Donat 9e0538abc8 Gui: Add ArgumentParser for named/positional function arguments
Adds ArgumentParser class that resolves mixed positional and named
arguments against a declared function signature (Python-style).
Includes Tuple::get<T>(name) for type-checked access with
user-friendly error messages. Refactors lighten/darken/blend to use it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:33:00 +01:00
Kacper Donat a64a43b9ca Gui: Refactor function arguments to use TupleLiteral
Replace the separate argument parsing in parseFunctionCall() with a
call to parseTuple(), unifying the two comma-separated-expression
parsing paths. FunctionCall now stores a TupleLiteral instead of
a vector of expressions, and evaluates it into a Tuple value that
functions access via at()/find().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:33:00 +01:00
Kacper Donat 7c813a6f5a Gui: Add tests for StyleParameters tuple support
Test cases cover unnamed, named, and mixed tuples, single named
elements, nested tuples, expressions and mixed types in elements,
toString roundtrip, Value::holds/get accessors, Tuple::at/find/size,
error handling, and backward compatibility of grouped expressions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:33:00 +01:00
Kacper Donat 884baf2cb8 Gui: Add tuple parsing to StyleParameters parser
Add TupleLiteral AST node and parser support for tuple syntax using
parentheses with comma-separated elements: (val1, val2) for unnamed
tuples, (name: val1, val2) for named elements.

Disambiguation with grouped expressions in parseFactor():
- `(identifier:` lookahead → tuple
- expression followed by `,` → tuple
- expression followed by `)` → grouped expression (backward compatible)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:33:00 +01:00
Daniel Khodabakhsh 8d3c786656 Fix case when CAM operation start = stop and step down is zero. 2026-02-08 15:30:19 -08:00
Kacper Donat 0f4ad868f7 Gui: Add Tuple type to StyleParameters
Add a tuple value type to the StyleParameters system, allowing related
values to be grouped into a single parameter with optional named fields.

Tuple is stored inline in the Value variant. The circular dependency
(Value contains Tuple, Tuple elements contain Value) is broken by
storing element values as shared_ptr<const Value> inside Tuple::Element.

Generic holds<T>() and get<T>() template methods are added to Value
for uniform type-checked access to all variant alternatives.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:29:03 +01:00
Captain 3237a21580 PartDesign: add interactive gizmos for box, cylinder and sphere operations (#23700) 2026-02-08 14:36:04 -06:00
Joe a79a22185d Materials: Add Copper Alloys to Material-Metals (#25832)
* Add Copper Alloys to Material-Metals

Added a set of Copper Alloys presented in Application Data Sheet
'cda144-8-mechanical-low-temperature.pdf, Nov1974'
Permission and Credit to the 'Copper Distributor's Association (CDA)'
These cards follow values for 295°K

Colours approximate values found by general search of images and
descriptions found on the internet and use FreeCAD's appearances.

* Add Copper Alloy general/generic information

This additional information appears as general info not affected by
anneal or cold drawn or aging factors.
Information found from pages C10200, C12200, C15000, C22000, C23000,
C44300, C46400, C51000, C61400, C64700, C65500, C70600, C71500, C95500

Also followed suggestions of adding tagging and description mentioned
in pull request.

* Add Copper Alloy source URL

Added the URL for the source Application Data Sheet
'cda144-8-mechanical-low-temperature.pdf, Nov1974'
This pdf is hosted by the 'Copper Distributor's Association (CDA)'

Here is the source URL for this pull request in case it's needed:
https://github.com/FreeCAD/FreeCAD/pull/25832

* Add Copper Alloy UltimateStrain for 102,122a,122b at 295°K

102=2.8%, 122a=39.7%, 122b=1.46%

* Add Copper Alloy UltimateStrain for remaining cards 150...955 at 295°K

105=4.13%, 220=41.5%, 230=40.4%, 443=82%, 464=31.8%, 510=3.6%, 614=27%
647=9.9%, 655=10.4%, 706=28.4%, 715=39.9%, 955=10.6%.

Removed spaces between IACS = nn%, so that it all stays on same line.

Added C95500 compressive MPa.
Added C64700 Si and IACS ranges.

Also looked at 'KindOfMaterial' for Steel and made similar edits based
on Table 2 info shown in brackets () to try keep a bit of consistency.

* Fix Ultimate Strain Description and Units

Ultimate Strain is the maximum stretch you can do to a material before it
gives up. This is associated with Ultimate Tensile Strength, which is the
maximum stress you can apply before the material starts to fail, elongate
and eventually fracture.

Units are of the type ΔL/L, such as, stretched 0.10in per 1.0in (10%), or
stretched 0.15mm per 1.0mm (15%). To avoid confusion, use 0.1 or 0.15 and
avoid using 10 as for 10% or 15 as with 15%, and just call it a fraction.

* Add Copper Alloy Elongation, Reduction of Area, Yield Strain, Toughness

Impact Charpy and Notch Tensile Strength are both considered as Toughness
There is currently no use for these in FreeCAD, but maybe a future use as
these are part of the Table 2 and better to add them now vs forget adding
them later. The Charpy test is a fast cost-effective standardized method,
and there are other more sophisticated impact tests that can be "better".
There are other tests than the notch tensile strength test, but it's also
a simple, fast, cost-effective method to create fracture toughness data.

While adding 'Elongation' and 'Reduction of Area' both these are referred
to as percentages (preferred over fraction), it seemed best to change the
'Ultimate Strain' to percentages too for consistency even though this has
was referred to as fraction or percentage when searching for definitions.

Added Yield Strain, probably not important now because the elastic region
is pretty small, but with smart metals that can do up to 5% bends then it
seems something worth adding it for that category of future metal alloys.

* Add Copper Alloy Isotropic, Linear, Toughness Temperature Arrays

* Add Copper Alloy Elastic & Toughness arrays and reduce model wordiness

Reduced wordiness of array models by cutting-out Metal and Temperature
as these are somewhat redundant words.

Added remaining ElasticProperties and PlasticTriaxialProperties.

* Add Copper Alloy Linear Elastic Temperature Arrays

Moved Elongation and ReductionOfArea after YieldStrain/Strength and added
FractureStrength so these are grouped together on the cards since they're
all related (Note: Material viewer resorts these alphabetically).

Linear Elastic arrays are set in the order of strain/strength for Tensile
then strain/strength for Yield, and then Elongation/FractureStrength, and
then ReductionOfArea.

Reviewed pdf again and corrected a few errors missed/made earlier.
2026-02-08 12:04:28 -06:00
William Skellenger 5f952812c3 Fix tooltips on mirror checkboxes in sketcher (#27131) 2026-02-08 10:03:37 +00:00
Chris Hennes 0f23770ad7 Merge pull request #27064 from ScholliYT/addObjectNameTo3mfExport
Mesh: Add object name attribute to 3MF export
2026-02-08 03:22:56 -06:00
Kacper Donat 9dbf5ae94b Part: Refactor TopoShape::splitWires (#23096)
This refactors TopoShape::splitWires method to be easier to follow and
use variable names that better describe the intent.
2026-02-07 23:24:47 -06:00
mosfet80 fa97300ec6 Remove unused files
removed unnecessary doxygen files
2026-02-07 23:14:25 -06:00
ᴩʜᴏɴᴇᴅʀᴏɪᴅ 8af563804c SPDX [ 49 ][ Src / Mod / PartDesign ] (#26715) 2026-02-07 22:53:31 -06:00
PhoneDroid 0d4d884a59 [ Doc ]: Rework 3rd party library overview 2026-02-07 22:51:05 -06:00
William Skellenger f2a392c8f1 make the filename tooltip show the actual filename 2026-02-07 22:40:15 -06:00
wandererfan 0745d40f86 [TD]fix fail on single edge cutting profile 2026-02-07 21:47:00 -06:00
Roy-043 105543bf17 BIM: fix regression caused by Link Hosts handling (#27406) 2026-02-07 21:43:30 -06:00
Chris Hennes 5b27deb4f0 Gui: Migrate old macro dir if needed 2026-02-07 20:36:43 -06:00
Chris Hennes f008c80030 Gui: Don't record macro path if default 2026-02-07 20:35:32 -06:00
TomPcz b441a3b6c1 Assembly: Fix help text height in CreateBom 2026-02-07 18:38:37 +01:00
sliptonic f36c9a8580 Merge pull request #27114 from petterreinholdtsen/cam-toolbit-m10-m8-taps
CAM: Added M8x1.25 (aka M8 coarse) thread tapping bit.
2026-02-07 09:06:12 -06:00
jffmichi 184c977677 CAM: show new cam simulator in main window 2026-02-07 11:03:23 +01:00
timpieces adf15a401d ExpressionParser: Add more tests for expression parsing (#27098)
- I'm not familiar with absolutely all usages of expressions - this is
  intended more as a starting point to make it easy to add more
- The test captures *current* behaviour, please don't assume that
  everything it tests is *correct* behaviour
2026-02-07 11:23:13 +08:00
timpieces 1de8cd5e36 ExpressionParser: Make cosmetic test changes before adding more tests (#27098)
Fix some weird quirks before adding new tests:
- The whole file has clang format off, this feels unnecessary, localize
  it to where it's important
- Put the code inside a nested test namespace within the production
  namespace, this is generally good practice rather than putting it in
  the global namespace, and it means we don't have to explicitly namespace
  methods that are directly under test
- Rename variables to camelCase, which afaict is closer to 'normal' in
  freecad cpp
- Remove the usage of arrays. Maintaining manual array sizes is
  annoying. Just use initializer lists here as they are all constants.
- I have *not* renamed the snake_case methods, as I feel that it
  destroys too much of the git history for too little benefit
2026-02-07 11:23:13 +08:00
timpieces daceb8afe4 ExpressionParser: Return unique_ptr from simplified (#27098)
- Removes many/most of the copy().release() from the last commit
- Still some .release() in the simplify functions now
- It doesn't work to rename simplify and turn it into a protected
  method, because it's called recursively within the tree
2026-02-07 11:23:13 +08:00
timpieces 8dad760db4 ExpressionParser: Return unique_ptr from copy (#27098)
- We need copy().release() on many of these calls because nodes in the
  tree call 'copy' explicitly. It's not really different to the code
  that's there now, but it's not pretty either. Some of these will go
  away in the upcoming commit
2026-02-07 11:23:13 +08:00
timpieces 1455321ace ExpressionParser: Return unique_ptr from eval (#27098)
- Most of the usages of 'release' are temporary here, but a few will
  likely need to stay. In these cases, the existing behaviour is
  retained. To fix all usages, smart pointers would need to be used all
  throughout the tree
- The freecad_cast looks awkward now. I haven't added a new version that
  works with smart pointers because it's not clear what the right
  ownership semantics would be. Make the caller be explicit for now.
2026-02-07 11:23:13 +08:00
timpieces 47d02c0618 ExpressionParser: Return unique_ptr from parse (#27098)
- Start at ScanResult, as starting higher makes it easy to have memory
  issues.
- There are multiple memory leaks (at least in tests, but possibly in
  production code too) from using raw pointers in the public interface
  here. Fix these before adding more tests.
- Starts at ScanResult
- The bison changes were applied manually, as I don't think that it's
  pixified and running my local version showed many changes.
- I've chosen not to pimplify Expression, but only because it would be
  such a significant change for not so much value.
2026-02-07 11:23:09 +08:00
jffmichi 61de0ffa8f CAM: use QOpenGLWidget for new simulator 2026-02-07 00:38:07 +01:00
tarman3 53bb61da00 CAM: Fix calculation arc move time 2026-02-06 22:25:39 +02:00
tarman3 dd3c12758f CAM: Fix calculation arc move length 2026-02-06 21:46:57 +02:00
Petter Reinholdtsen dfdabbfc87 CAM: Reintroduce matching pre-/postamble and help text for dynapath_4060_post.py
This change was introduced in 80a35a8765 (#24617) and
reverted without explanation in 21a597a85e (#27202).
I assume it was reverted by mistake.

Note that for dynapath_4060_post.py, the original help text did not match the postamble,
illustrating the need to ensure the actual value matches the help text.
2026-02-06 19:44:40 +01:00
Kristian Rekstad 2db8942fa9 Web: improve docs by explaining purpose and use
Also remove python example in AppWeb.cpp because it is duplicated by
web.dox
2026-02-06 11:49:51 -06:00
dependabot[bot] 71e4b4f564 Bump actions/setup-python from 6.1.0 to 6.2.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/83679a892e2d95755f2dac6acb0bfd1e9ac5d548...a309ff8b426b58ec0e2a45f0f869d46889d02405)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-06 11:43:33 -06:00
dependabot[bot] 6a349de3e3 Bump step-security/harden-runner from 2.13.3 to 2.14.1
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.13.3 to 2.14.1.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/df199fb7be9f65074067a9eb93f12bb4c5547cf2...e3f713f2d8f53843e71c69a996d56f51aa9adfb9)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.14.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-06 11:43:23 -06:00
dependabot[bot] cc665f1070 Bump peter-evans/create-pull-request from 7.0.11 to 8.1.0
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.11 to 8.1.0.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/22a9089034f40e5a961c8808d113e2c98fb63676...c0f553fe549906ede9cf27b5156039d195d2ece0)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-version: 8.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-06 11:43:12 -06:00
Petter Reinholdtsen 626c510177 CAM: Added M8x1.25 (aka M8 coarse) thread tapping bit.
This provide a metric thread tap example alongside the
imperial 3/8"-16 tap example.
2026-02-06 06:29:12 +01:00
Krish Sharma 24f0c8e2c3 Update src/Gui/PreferencePages/DlgSettingsSelection.ui
Co-authored-by: Furgo <148809153+furgo16@users.noreply.github.com>
2026-02-05 21:46:40 +01:00
Krrish777 4768f20d89 Update tooltip for auto-switch to 3D view preference to match Std_TreeSyncView behavior 2026-02-05 21:46:40 +01:00
Krrish777 13909dbb00 Remove duplicate/old tooltips 2026-02-05 21:46:40 +01:00
Krrish777 ed2471e835 Gui: Add informative tooltips to Tree Selection Behavior 2026-02-05 21:46:40 +01:00
Krrish777 afd998541d Gui: Add tooltips to Selection preference page 2026-02-05 21:46:40 +01:00
Benjamin Nauck 74e1d71c65 Merge pull request #27355 from 3x380V/app
App: Random fixes 2
2026-02-05 20:22:43 +01:00
dependabot[bot] 1d11f05560 Bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-05 08:48:07 -06:00
paul 45a8650b7d [BimWall] Fix Regression check ArchSketchLock (#27324)
* [BimWall] Fix Regression check ArchSketchLock

Github Discussion / Fix Regression:
Fix #24595
(https://github.com/FreeCAD/FreeCAD/pull/24595#issuecomment-3763092751)
(and incorporate comments in previous PR, to be abandoned, https://github.com/FreeCAD/FreeCAD/pull/26985)

Regression and Fix:
-  When external SketchArch Add-on is installed, and ArchSketchLock is False (not pressed), the BimWall.Arch_Wall() tool with BaseLine select 'Sketch' return error
-  This PR fix the said regression

* [BimWall] Fix Regression check ArchSketchLock (rev. 1)
(Update following comment at - https://github.com/FreeCAD/FreeCAD/pull/27324#pullrequestreview-3750099100)

Github Discussion / Fix Regression:

- Fix https://github.com/FreeCAD/FreeCAD/pull/24595#issuecomment-3763092751
- (and incorporate comments in previous PR, to be abandoned, https://github.com/FreeCAD/FreeCAD/pull/26985

Regression and Fix:

- When external SketchArch Add-on is installed, and ArchSketchLock is False (not pressed), the BimWall.Arch_Wall() tool with BaseLine select 'Sketch' return error
-  This PR fix the said regression

* [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>
2026-02-05 12:36:16 +01:00
wmayer cda2b8cbdb Use Application::getExecutableName() instead of Config()["ExeName"] 2026-02-05 10:59:52 +01:00
wmayer 4f116d8de3 App: Move Python functions from Application to ApplicationPy
This reduces build time when adding new Python functions because
only one file must be compiled.
2026-02-05 10:59:52 +01:00
wmayer c97f6e5b3f App: Improve Document::writeObjects
Do not directly pass getNameInDocument() to the ostream as this will
set the badbit in case it returns nullptr. As a result no further
output is written to the stream and leads to loss of data.

Instead the returned C string is stored in a local variable and in case
it's nullptr an empty string is passed to the ostream.

At the end of the function writeObjects() it's checked whether the
failbit or badbit is set. If yes an error message is printed and the
failbit or badbit are cleared.

This is supposed to fix the issue 18044.

In case this fix is not sufficient it can be also check for every
object inside writeObjectData()
2026-02-05 10:59:50 +01:00
wmayer 2c3d9e2bb7 Base: Add C++ iostate methods to Writer class 2026-02-05 10:58:12 +01:00
wmayer 2c2cdbfe7f App: Refactor Document::writeObjects 2026-02-05 10:47:49 +01:00
wmayer 6c9ad95a70 App: Improve handling with freeze status
* Do not raise an exception when saving a document and an object has
  'freeze' status because this breaks the project file and may lead
  to loss of data.
* Make 'freeze' state persistent
* When toggling 'freeze' status only work directly on the selection.
  Do not use in-list or out-list of an object because this makes it
  quite inflexible and leads to unpredictable behaviour.

This fixes issue with saving frozen files described in 18806.
2026-02-05 10:04:46 +01:00
Tomáš Pikálek 41e3cdb9a5 Sketcher: Reimplement strikethrough of inactive constraint labels 2026-02-04 21:04:06 +01:00
Chris Hennes 27587b9cd2 Packaging: Fix typo in end-of-line format 2026-02-04 20:46:02 +01:00
Tomáš Pikálek 77e5645af0 Sketcher: Vertical centering of constraint labels 2026-02-04 19:44:21 +01:00
Jacob Oursland 9440749423 CI: pin swig on release builds. 2026-02-04 18:51:14 +01:00
Chris Hennes 6f60022a35 Package: Make Windows uninstaller preferences language clearer 2026-02-04 06:37:22 +01:00
PaddleStroke 8a6872e69d Merge pull request #25848 from PaddleStroke/sk_scale_distances
Sketcher: Distance constraints: scale label distance on creation.
2026-02-03 16:34:53 -06:00
Chris Hennes ed6c0c8111 Merge pull request #25990 from Lgt2x/find-netgen-fix
CMake: require Netgen when BUILD_FEM_NETGEN is ON, don't fail silently
2026-02-03 23:10:38 +01:00
xtemp09 0b5a0a6abb [GUI] Handle Enter and Escape in the search box in Preferences. 2026-02-03 21:57:29 +01:00
Pieter Hijma 6d3f786b38 Doc: Improve layout doxygen output 2026-02-03 21:07:13 +01:00
Pieter Hijma 1eb6968265 Doc: Comment out doxygen javascript
This commit comments out javascript for doxygen that does not work
anymore or is unneeded in newer versions.  The code is left in for later
attempts to revitalize this functionality, most notable the search
function.
2026-02-03 21:07:13 +01:00
Chris Hennes 6ada8e2cef Merge pull request #25199 from pieterhijma/doc-element-mapping
Doc: Improve the documentation of element mapping
2026-02-03 21:06:53 +01:00
Chris Hennes f3b4aa6b8c Merge pull request #25198 from pieterhijma/doc-expressions
Doc: Improve the documentation of expressions
2026-02-03 21:06:13 +01:00
Chris Hennes eb42b77285 Merge pull request #25143 from furgo16/issue_24571
App: cherry-pick - Implement Save() & Restore() for int/float constraint properties
2026-02-03 21:04:50 +01:00
Roy-043 8657d0a377 BIM: fix BuildingPart area calculation for indirect children (#24848)
* BIM: fix BuildingPart area calculation for indirect children

Fixes #24667.
2026-02-03 13:23:59 -06:00
Steven James c07d248bc3 Make Subclasses of Part::Feature objects repr as their derived Type (#24429) 2026-02-03 11:03:29 -06:00
Roy-043 dafed93c63 BIM: support relative path for hybrid IFC file (#24190) 2026-02-03 10:16:10 -06:00
Ladislav Michl e7bcb2c15e Gui: cleanup includes in *PyImp.cpp
Sort includes and implicitely add missing ones. While there
consistently explain where generated files some from.
2026-02-03 16:56:45 +01:00
Roy-043 f9ab227459 Draft: title in default task panel in title case
See #27314.
2026-02-03 12:09:08 +01:00
Roy-043 e6808b6f2e BIM: titles in default task panel in title case
This task panel appears when no command is active. There are 2 versions. One appears if there is a selection, the other if there is none.
2026-02-03 11:05:29 +01:00
captain0xff 79632dd3c6 App: handle symlinks in Application::processFiles & DocInfo::getDocPath 2026-02-02 19:50:36 +01:00
Chris Hennes a4a1ef7294 App: Get Addon name from Metadata 2026-02-02 19:50:16 +01:00
Yash Suthar 8f2a3a4d7d Draft : Added knots support for snapping (#26571)
* Draft : Added knots support for snapping

Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>

* Use Special snap for knots and rename snapToBSpline to snapToBSplineKnots

---------

Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>
2026-02-02 17:11:20 +00:00
Dan Henderson 21a597a85e CAM: Post Processor Dyna_4060_Post - various bug fixes and updates (#27202)
* various bug fixes and updates

* [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>
2026-02-02 18:07:31 +01:00
Daniel-Khodabakhsh 1c90c1ec44 CAM: Fix case when CAM operation Safe height, Start depth, and Final depth are the same value. (#27258)
Co-authored-by: Daniel Khodabakhsh <d@niel.khodabakh.sh>
2026-02-02 18:03:59 +01:00
Roy-043 30ea676367 BIM: add processSubShapes to ArchSpace.py
Fixes #24579.
2026-02-02 18:03:08 +01:00
Roy-043 ed104dd2c1 BIM: remove LibraryWebSearch option from BIM_Library as it required the Web WB (#27048)
* BIM: remove LibraryWebSearch option from BIM_Library as it required the Web WB

Removed the 'checkWebSearch' checkbox and updated tooltip text formatting.

* BIM: remove LibraryWebSearch option from BIM_Library as it required the Web WB

* Restore tooltip
2026-02-02 17:59:40 +01:00
PaddleStroke a3486b4dd2 Assembly: Insert flexible assembly grounds the correct part (#27206)
* Assembly: Insert flexible assembly grounds the correct part

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

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

* Assembly: Migrate ObjectToGround to PropertyLinkGlobal to support assembly links

* Update JointObject.py

* Assembly: ViewProviderAssembly fix assembly link deletion issue

* Assembly: ViewProviderAssembly: make sure no duplicates in canDelete

* Assembly CommandInsertLink fix typo

* [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>
2026-02-02 17:43:45 +01:00
PaddleStroke 212e4f07af Assembly: Fix isolate not working on sub assembly components 2026-02-02 17:41:41 +01:00
Kacper Donat 92dbaad9db Merge pull request #27243 from 3x380V/app
App: Random fixes 1
2026-02-02 17:40:40 +01:00
David Kaufman 388c66b41e move max-arc-radius test from AlmostALine to CheckForArc 2026-02-02 10:46:00 -05:00
Furgo 125ff0dcea BIM: add task panel box for wall options (#26758)
* BIM: add Wall options task box to ArchWall's edit task panel

* BIM: update Align property live on the task box

* BIM: make wall options cancellable

* BIM: make the Component task box actions reversible, in particular debasing a wall

* BIM: implement baseless walls creation (#24595)

* BIM: Implement smart base removal for Walls

Previously, removing the Base object from an Arch Wall would cause the
wall to reset its position to the document origin and could lead to
unintended geometric changes for complex walls.

This commit introduces a "smart debasing" mechanism integrated into the
Component Task Panel's "Remove" button:

- For walls based on a single straight line, the operation now preserves
  the wall's global position and parametric `Length`, making it an
  independent object.
- For walls with complex bases (multi-segment, curved), a warning dialog
  is now presented to the user, explaining the consequences (shape
  alteration and position reset) before allowing the operation to
  proceed.

This is supported by new API functions `Arch.is_debasable()` and
`Arch.debaseWall()`, which contain the core logic for the feature.

Fixes: https://github.com/FreeCAD/FreeCAD/issues/24453

* BIM: Move wall debasing logic into ArchWall proxy

The logic for handling the removal of a wall's base object was previously
implemented directly within the generic `ComponentTaskPanel` in
`ArchComponent.py`. This created a tight coupling, forcing the generic
component UI to have specific knowledge about the `ArchWall` type.

This commit refactors the implementation to follow a more object-oriented
and polymorphic design:

1.  A new overridable method, `handleComponentRemoval(subobject)`, has been
    added to the base `ArchComponent` proxy class. Its default implementation
    maintains the standard removal behavior.

2.  The `_Wall` proxy class in `ArchWall.py` now overrides this method. All
    wall-specific debasing logic, including the eligibility check and the
    user-facing warning dialog, now resides entirely within this override.

3.  The `ComponentTaskPanel.removeElement` method has been simplified. It is
    now a generic dispatcher that calls `handleComponentRemoval` on the
    proxy of the object being edited, with no specific knowledge of object types.

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

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

* BIM: Add interactive creation of baseless walls

Introduce a new workflow for creating Arch Walls without a dependency on
a baseline object (e.g., a Draft Line).

- The `Arch_Wall` command is enhanced with a "No baseline" mode, controlled
  by a new "Walls baseline" preference, allowing users to create
  placement-driven walls directly in the 3D view.
- The existing `debaseWall` function has been refactored for correctness
  and consistency with the new baseless wall geometry.

Co-authored-by: Yorik van Havre <yorik@uncreated.net>

* BIM: Refactor structure of the Arch Wall command

Refactor the `Arch_Wall` GUI command (`BimWall.py`) for improved
readability, maintainability, and architectural clarity.

- A `WallBaselineMode` Enum is introduced to replace the original
  integer values, making the code self-documenting.
- The monolithic `create_wall` method is broken down into smaller,
  single-responsibility helper functions for each creation mode.
- The `addDefault` method has been removed, with its logic
  integrated into the new structure.

* BIM: Add Draft Stretch support for baseless walls

This commit makes the new baseless Arch Walls graphically editable using
the `Draft_Stretch` tool.

- An API for stretching (`calc_endpoints` and `set_from_endpoints`)
  has been added to the `ArchWall` proxy.
- The `Draft_Stretch` tool is now aware of baseless walls and calls this
  new proxy API to perform the stretch operation, enabling users to
  stretch them.

Co-authored-by: Yorik van Havre <yorik@uncreated.net>

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

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

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

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

* BIM: address CodeQL warnings

* BIM: Fix wall alignment for GUI creation of baseless walls

Fixes an issue whereby creating a baseless wall from the GUI would
ignore the selected `Align` property, always resulting in a
center-aligned wall.

- The underlying geometry generation for baseless walls now correctly
  honors the `Align` property passed by the GUI and API.
- To ensure predictable behavior, the implementation uses the same
  geometric convention as walls built from a base object, making the
  `Align` property work uniformly for all wall types.
- This also corrects the behavior of the `Arch.makeWall` function for
  baseless walls.
- Update unit tests to test wall alignment.

* BIM: Refactor wall geometry generation for improved clarity and maintainability

Improves the internal logic for wall geometry creation, addressing CodeQL warnings and enhancing overall maintainability without changing external behavior.

- The `build_base_from_scratch` method is refactored to unify the separate logic paths for single- and multi-layer walls, reducing code duplication.
- A local helper function is introduced to create face geometry, for better modularity and readability.
- In the `_Wall.execute` method, the control flow that relied on implicit type checking is replaced with an explicit strategy pattern for fusing solids, making the logic more robust.
- Variable names are made more descriptive.
- A NumPy-style docstring is added to better document the function.

* Draft: fix stretching of rotated baseless walls

* BIM: add unit test for stretching baseless walls

* BIM: add regression tests for working-plane-relative coordinates and reuse of base sketches

* BIM: Fix baseless wall creation to respect the working plane

Corrects an issue where baseless walls were created using global
coordinates instead of being relative to the active Draft working plane.

The calculated local placement of the wall is now correctly transformed
into the global coordinate system by multiplying it with the working
plane's placement.

* BIM: Ensure unique baselines for subsequent wall creation

Fixes a bug where creating multiple walls with baselines would
incorrectly reuse the same underlying Sketch or Draft Line object.

The object retrieval logic after the `doCommand` call now correctly uses
`ActiveObject` to get a reliable reference to the new object instead of
relying on a hardcoded name.

* BIM: Make the wall's base object label translatable

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

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

* BIM: use singular for consistency with other labels

Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>

* Fix typo

* BIM: address reviewer's comments about improving object reference passing between Python and FreeCAD contexts, and functions

* BIM: remove defensive programming: the callback is only executed as a result of a user's GUI action

* BIM: use the params API to define WallBaseline parameter

* BIM: add Arch Wall tests for joining wall logic

* BIM: add joining logic

* BIM: re-add ArchSketch support

* BIM: re-add multimaterial support on wall creation

* BIM: address CodeQL warning, remove module duplication

* BIM: fix check for SketchArch module when creating sketch-based walls

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Yorik van Havre <yorik@uncreated.net>
Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>

* CI: upgrade Ubuntu native build to 24.04

* CI: reenable Ubuntu native build

* CI: abandon PySide6 pip approach, try KDE Neon repos

* BIM: fix mistake in casting return value

* BIM: add wall label to better identify transaction in the Undo stack

* BIM: remove superfluous statement

* BIM: add explanatory comment about additional transaction  pending flag

* BIM: Refactor Wall transaction logic to use explicit argument passing

This replaces the `Proxy.InTransaction` flag mechanism with a cleaner
transaction architecture based on explicit argument passing.

The motivation for managing the transaction mechanism is that
previously, removing a Wall's base object via the Task Panel triggered
`debaseWall`, which opened and committed its own transaction
immediately. This nested commit finalized the document state
prematurely, rendering the Task Panel's "Cancel" button ineffective.

The Task Panel now owns the transaction lifecycle for the editing
session. It propagates a `manage_transaction=False` flag down to the
logic layer, preventing nested transactions from committing prematurely.

Key changes:
- Arch.py: `debaseWall` now accepts `manage_transaction` (default True).
  Setting it to False allows the Task Panel to disable the nested
  transaction and include the debasing operation into its own
  transaction context instead.
- ArchComponent.py:
  - `ComponentTaskPanel` now manages the transaction lifecycle (Open in
    init, Commit in accept, Abort in reject).
  - `ComponentTaskPanel.removeElement` now passes
    `manage_transaction=False` when calling the object's
    `handleComponentRemoval` proxy method.
  - Updated `Component.handleComponentRemoval` signature to accept the
    `manage_transaction` argument.
- ArchWall.py:
  - Updated `_Wall.handleComponentRemoval` to pass the
    `manage_transaction` flag to `debaseWall`.
  - Cleaned up `WallTaskPanel` by removing the deprecated
    `InTransaction` logic and redundant overrides.

* BIM: provide immediate visual feedback on additions and subtractions

* BIM: remove low-level API transaction management

* BIM: Refactor transaction management in ComponentTaskPanel

The C++ GUI layer implicitly manages the transaction lifecycle when
entering and exiting edit mode.

Explicitly opening a transaction in init and committing in accept() is
redundant, as the backend establishes the transaction name and performs
the final commit during the resetEdit() cleanup phase.

The reject() method retains an explicit abortTransaction() call to
signal a rollback, which prevents the backend from committing session
changes by default.

Docstrings are added to clarify this implicit interaction between the
Python UI and the C++ document management logic.

* Wall Options in title case

* QtGui.QApplication.translate -> translate

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Yorik van Havre <yorik@uncreated.net>
Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>
2026-02-02 15:39:20 +00:00
Roy-043 ca923d089f BIM: some improvements for ArchProfile.py (#27118) 2026-02-02 16:04:13 +01:00
Roy-043 7ad0b16d02 BIM: add test for horizontal area of tilted cylinders (#27108)
* BIM: add test for horizontal area of tilted cylinders

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

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

* Fix typos and use makeComponent instead of makeStructure

* Change makeComponent back to makeStructure

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-02 16:03:50 +01:00
Furgo 36c0eaf44b BIM: Prevent incorrect assembly icon for baseless parametric walls (#27277)
The icon logic in _ViewProviderWall.getIcon previously switched to the
assembly icon for any wall without a Base that contained Additions. This
caused an unexpected icon change when a wall was debased, as it still
retains a parametric body defined by its Length property.

Update the logic to only show the assembly icon if the wall has no Base,
has Additions, and its Length is zero. This ensures that baseless walls
driven by their own dimensions maintain the standard wall icon.
2026-02-02 15:56:08 +01:00
freecad-gh-actions-translation-bot 0b7da82433 Update translations from Crowdin 2026-02-02 11:49:57 +01:00
PaddleStroke 3d7cc53317 Measure: fix new measure marked as recompute (#27235) 2026-02-01 14:45:04 +01:00
nishi 1818911c5f Measure: corrected angle measurements bug (#27254) 2026-02-01 14:43:10 +01:00
xtemp09 ce3fdd6e4b Add an icon to "Clear Recent Files List" action 2026-02-01 12:31:09 +01:00
Billy Huddleston c98d077d91 Revert "CAM: Add threshold for treating large-radius arcs as linear in simulator"
This reverts commit 0b35385f4a9416c58bda2353e912bf2539d21c6d.
2026-02-01 09:02:17 +01:00
Kacper Donat bf83b9bfde Base: Add TimeTracker (#26305)
* Base: Add TimeTracker

This adds TimeTracker utility that can be used to orchestrate code
with time measurements in an easy way and detect performance issues.

* Update src/Base/TimeInfo.h

Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>

---------

Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
2026-01-31 20:00:40 +01:00
Furgo 2a103cf08e Gui: Unify Python exception reporting in command handlers
Replace custom exception formatting with PyException::reportException()
for consistent output that includes previously missing exception types.
2026-01-31 19:59:42 +01:00
Pieter Hijma 1d51b8e5e5 Doc: Improve the Expression Framework topic 2026-01-31 19:52:33 +01:00
Pieter Hijma befd4a23ee Doc: Improve App::PropertyExpressionEngine docs 2026-01-31 19:52:33 +01:00
Pieter Hijma ee538f707f Doc: Move doc comments in PropertyExpressionEngine
Several doc comments in App/PropertyExpressionEngine.cpp are moved to
header files.
2026-01-31 19:52:33 +01:00
Pieter Hijma f113e775a1 Doc: Improve the App::Expression documentation 2026-01-31 19:52:33 +01:00
Pieter Hijma 063f03c764 Doc: Move doc comments in App::Expression
Several doc comments in App/Expression.cpp are moved to header files.
2026-01-31 19:52:33 +01:00
Chris Hennes bbd0ba7626 Merge pull request #25197 from pieterhijma/doc-link
Doc: Improve the documentation of Link
2026-01-31 19:52:19 +01:00
mosfet80 af4a989dc1 Build: Fix CMake deprecation warning in FastSignals (#26819) 2026-01-31 15:59:49 +01:00
PaddleStroke 964e7387e3 Assembly: Explode temporarily (#25456) 2026-01-31 15:57:22 +01:00
Grzegorz Kwacz cd8fd9ace5 Spreadsheet: Update row/column context menu 2026-01-31 15:36:55 +01:00
PaddleStroke fb4721bcb2 Assembly: Remove solver msg when file is closed (#27210) 2026-01-31 15:19:36 +01:00
Louis Gombert 2dcc351532 TechDraw: fix Qt5 compatibility
emplace_back was added in Qt6, replace by append which does the same thing.
2026-01-31 12:51:11 +01:00
Arusekk c497a583ca BIM: Fix ArchBuildingPart not moving child object base (#27237)
When a child (e.g. a Wall) of an ArchBuildingPart (e.g. of a Level)
had both 'Move With Host' and 'Move Base' enabled, it failed to move
the base (e.g. Line) of the child, and only displaced the child
itself (effectively ignoring the 'Move Base' setting).

Example project structure:

Level
|
+- Wall ('Move With Host' = true, 'Move Base' = true)
   |
   +- (base of Wall) Line
2026-01-31 11:50:51 +01:00
Chris Hennes 0a585dc3bb Base: Add tests for escapeXml 2026-01-31 09:09:27 +01:00
Tom Stein 49c80ebe5c Mesh: Add object name attribute to 3MF export
Export mesh object names as 'name' attribute in 3MF files according to
the 3MF specification. This allows downstream tools to identify objects
by their original FreeCAD names.

Changes:
- Moved Exporter::xmlEscape() to Base XMLTools::escapeXml() for shared XML entity escaping
- Update Writer3MF::AddMesh() to accept and output object names with default "" where no attribute will be added
- Updated all codepaths leading to 3mf exports to include the object name
2026-01-31 09:09:27 +01:00
kkocdko 44fd6754d8 Pixi: Fix qt6-wayland dep
add qt6-wayland into `./package/rattler-build/recipe.yaml` in `run` section, and run `pixi lock`
2026-01-31 09:05:03 +01:00
Ladislav Michl 0831f7e392 App: Avoid C string compare
Since we are linking to boost anyway, use boost function for case
insensitive string compare. While there, make affected methods accept
std::string arguments, which simplifies code a bit.
2026-01-30 10:58:09 +01:00
wmayer 1886bcda00 App: Fix crash in Transaction::addObjectChange
It can happen that TransactionFactory::createTransaction() fails to create a transaction object because an unsuitable type is passed
(like BadType) and returns a null pointer.

The calling instances (Transaction::addObjectChange, Transaction::addObjectDel, Transaction::addObjectNew, Transaction::addOrRemoveProperty)
do not check for a null pointer and thus cause a segmentation fault by dereferencing it.

To fix the issue change the above methods to explicitly handle a null pointer.

This fixes issue 21095.

Note: In this case it's caused by the class ViewProviderFace which on purpose isn't added to the type system so that its type will be BadType.
2026-01-30 10:58:09 +01:00
wmayer 60b0221402 App: Optimize PropertyMaterialList::getDiffuseColors()/getTransparencies() 2026-01-30 10:58:09 +01:00
wmayer 8062fadbd4 App: Replace C macros with lambda expression 2026-01-30 10:58:09 +01:00
wmayer 93ee3a3475 App: Remove assert() from PropertyXLink::Restore
If the property is added to a view provider then in debug mode this will
cause a crash while in release mode this will cause undefined behaviour
because of a static_cast.

To fix crashes remove the assert() and replace the static_cast with
freecad_cast.
2026-01-30 10:58:09 +01:00
wmayer dace71205f App: In ProjectFile::loadDocument() check for parse errors
In case a parse error occurred then return with false and do not set the DOMDocument
2026-01-30 10:56:05 +01:00
wmayer 56e687d9cc App: Refactor PropertyExpressionEngine::afterRestore()
Put the reading of each expression of an object into a try/catch block. This is to avoid that all expressions of an object may be lost.

This mitigates the issue 19866
2026-01-30 10:56:05 +01:00
wmayer 3fba587044 App: In ExpressionParser::parse add the failing expression text to the error message 2026-01-30 10:56:05 +01:00
wmayer 2799aa2700 App: Simplify and fix code for ifcopenshell version check 2026-01-30 10:56:05 +01:00
Leandro Heck 2c25b65b92 Fix warning of widgets with the same name. 2026-01-29 20:20:46 +01:00
Chase Naples b182ebdfd6 Docs: update Link copyOnChange tooltip (#26603) 2026-01-29 17:46:32 +00:00
Yash Suthar b47bb64398 Core: redirect to toolbar creation if user tries to add function when there is nothing in Tree
Signed-off-by: Yash Suthar <yashsuthar983@gmail.com>
2026-01-29 16:09:48 +01:00
Roy-043 0f2bdf280f Draft: fix autogroup behavior if active group is a layer (#27102) 2026-01-29 15:38:55 +01:00
PaddleStroke 00c3422c1f Sketcher: Tooltip when hovering expression driven constraint (#25954) 2026-01-29 15:04:40 +01:00
timpieces ad6c6bc8fd Gui: Default load/save img to working directory (#26182)
- FileOptionsDialog is only used in the 'save screenshot / save image'
  codepath, and currently it doesn't set a directory to it defaults to
  process CWD, which is surely not what the user wants.
- The load image codepath uses a custom QFileDialog instead of the
  helper code in FileDialog, there doesn't seem to be a great reason for
  this, although the helper doesn't have support for mime types it seems.
- I haven't changed the dialogs to 'set/store' the working directory. I'm
  not sure this is desired as this isn't a 'normal' save/load operation.
- It would be ideal to remove the FileOptionsDialog in future. The
  extended functionality could be turned into a separate dialog which
  opens before or after the file chooser. This would allow native dialogs
  to be used and would unify the code paths for file selection.
- Further, it would be nice to just merge at least the load image into
  the existing import/open option, and to put 'save image' next to
  'export', but those changes may be much more time consuming.

For now I've kept it simple. Let's see what others think.
2026-01-29 14:08:48 +01:00
Krrish777 32ee950210 Improve UX for Rename Property Group with tooltip 2026-01-29 14:07:28 +01:00
phaseloop 32e47bdda6 increase max line size to 120 in pylintrc 2026-01-29 14:04:36 +01:00
Roy-043 c2504d2639 BIM: fix typos in #27213 (#27225) 2026-01-29 13:04:19 +00:00
Roy-043 4f7b473a4a TechDraw update some GUI texts (Title Case mod) (#26849)
* Menu text "Align Horizontal/Vertical Chain Dimensions" to match "Align Oblique Chain Dimensions"

* Menu text "Centerline Between 2 Faces" is not correct.

* Update button text "Replace References With Current Selection" to title case

* Change task panel title from 'Add offset vertex' to 'Offset Vertex'

* Correct text casing for 'Pick points' button

* Correct text casing for 'Pick points' and 'Edit points'

* Fix capitalization of task panel section title

* Correct text case for 'Escape Picking' button

* Update texts for centerline buttons to match menu texts
2026-01-29 14:01:56 +01:00
sliptonic 63dba7bb64 Merge pull request #26951 from chennes/libe57formatTo330
LibE57format to v3.3.0
2026-01-29 06:33:59 -06:00
Chris Hennes a00db89f57 Merge pull request #25196 from pieterhijma/doc-application
Doc: Improve the documentation of Application
2026-01-29 13:31:09 +01:00
Chris Hennes c74ac37488 Merge pull request #25195 from pieterhijma/doc-document
Doc: Improve the documentation of Document
2026-01-29 13:29:43 +01:00
sliptonic 836c0c0d2e Merge pull request #25534 from chennes/msvcBlanketWarningDisabling
Build: Remove blanket disabling of deprecation warnings
2026-01-29 06:27:19 -06:00
PaddleStroke a0847c22c7 Sketcher: fix logic flaw in ConstraintLineByAngle 2026-01-29 13:15:42 +01:00
Chris Hennes 96e4071e2d Merge pull request #27134 from WandererFan/CosCircleLineStyle2
TechDraw: Fix circle centerline default line style
2026-01-29 13:14:39 +01:00
Chris Hennes 63e0c0ff49 Merge pull request #27094 from WandererFan/ProjGroupDragGoesToOrigin4
TechDraw: Projection Group jumps to origin
2026-01-29 12:52:59 +01:00
Kacper Donat 4dda92e599 Part: Fix regressions in MultiCommon boolean operation
This commit addresses two regressions in the MultiCommon feature:

1. Computation Logic: Fixed an issue where the common operation was
   calculated as the intersection of the first shape with the union of
   the rest (the default behavior of makeElementBoolean). It now
   correctly computes the intersection of all shapes sequentially.

2. Compound Handling: Added logic to expand a single compound input
   into its constituent shapes. Previously, a compound was treated
   as a single entity, leading to incorrect intersection results.

To maintain backward compatibility, a hidden 'Behavior' property is
introduced. This ensures that documents created in FreeCAD 1.0, which
rely on the previous behavior, continue to render as originally
intended while new objects use the corrected logic.
2026-01-29 12:40:20 +01:00
Vassily Checkin d3d6459484 Sketcher: fix intermittent crash on sketch exit 2026-01-29 11:42:04 +01:00
Timothy Miller 9eed3a8d77 Part: Fix mirror() regression with non-identity Placement (#26963)
* Part: Fix mirror() regression with non-identity Placement

The makeElementMirror() function incorrectly extracted and pre-multiplied
the shape's Location with the mirror transform. Since BRepBuilderAPI_Transform
already handles shapes with Location correctly, this resulted in the placement
being applied twice, producing incorrect results for shapes with non-identity
Placement.

Fixes #20834

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Part: Add regression test for mirror() with Placement

Adds testTopoShapeMirrorWithPlacement to verify that mirror() produces
identical results regardless of whether the shape is positioned via
direct coordinates or via Placement.

This test would have caught the bug fixed in the previous commit where
shapes with non-identity Placement produced incorrect mirror results.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix regression test for mirror with Placement

The test was incorrectly trying to create equivalent boxes using
different methods that don't actually produce the same geometry.
Part.makeBox with a direction vector is not equivalent to setting
a Placement with rotation.

Fixed to use the correct approach that demonstrates the actual bug:
- Method 1: Box with geometry at (0,30,0), identity Placement
- Method 2: Box with geometry at origin, moved via Placement

Both should produce identical mirror results, which they now do
with the makeElementMirror() fix.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Timothy Miller <theosib@zeromark.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:05:35 +01:00
Jacob Oursland 5f0d6b4aef Pixi: pin xcb-util-cursor==0.1.5 to address cursor bug. 2026-01-29 10:07:35 +01:00
Furgo d77e77f9f4 App: Replace getAttributeAs{Integer,Float} with templated getAttribute
Template was introduced in https://github.com/FreeCAD/FreeCAD/pull/19907
2026-01-29 08:44:25 +01:00
wwmayer 2c221883c1 Test: Add test case for issue 24571 2026-01-29 08:44:25 +01:00
wwmayer 2de933793d App: Implement Save() & Restore() for int/float constraint properties
Implement the methods Save() and Restore() for PropertyIntegerConstraint and PropertyFloatConstraint. Handle also the case of a user-defined ranges.

This fixes https://github.com/FreeCAD/FreeCAD/issues/24571.

Hint: For PropertyQuantityConstraint this is not doable because it doesn't support user-defined ranges
2026-01-29 08:44:25 +01:00
graelo b0a9c6ea4b Fix quicklook appex build (#27144) 2026-01-29 08:23:04 +01:00
Roy-043 104089179c BIM: fix title case of GUI texts (#27213) 2026-01-28 21:08:27 +01:00
Alfredo Monclus 928e5e0fbb PD: preview substractive feature check for removed volume 2026-01-28 11:03:30 -03:00
Alfredo Monclus 603fc4b341 PD: hole speficify the tolerance in the boolean op
this fixes issues in which the helix is the only thing being cut and the revolve is ignored
2026-01-28 11:03:30 -03:00
Alfredo Monclus 70b9305f2e PD: hole use a compound instead of a fuse for threads 2026-01-28 11:03:30 -03:00
David Kaufman 8e04386c67 use CArea::get_accuracy instead of Point::arc_tolerance 2026-01-26 16:27:19 -05:00
David Kaufman cdce2f0ffd [CAM] separate tolerance variable used for arc fitting from tolerance used for section height offsets 2026-01-26 10:35:23 -05:00
wandererfan b8f09bd758 [TD]clang warnings 2026-01-24 08:40:51 -05:00
wandererfan 29066c1a53 [TD]fix circle centerlines line style 2026-01-24 08:40:46 -05:00
tarman3 6a66c233f1 CAM: Profile - Start point in the middle of edges 2026-01-24 00:38:52 +02:00
wandererfan ea58456534 [TD]avoid crash on missing ViewProviderPage 2026-01-22 19:29:08 -05:00
wandererfan bef6aafa73 [TD]handle AutoDistribute property toggle 2026-01-22 16:14:39 -05:00
wandererfan 3fca5d99ee [TD]fix secondary view drag goes to origin 2026-01-22 16:14:07 -05:00
wandererfan fd014445fb [TD]make QGIProjGroup methods public
- also adds a convenience method to return all the views in the group
2026-01-22 16:13:11 -05:00
wandererfan 5d4495785b [TD]more reliable test for DrawProjGroupItem 2026-01-22 16:11:14 -05:00
Dimitris75 1800ef0f10 CAM Waterline OCL Adaptive
Add - Optimize Linear Paths
Remove - Unecessary BoundBox selection
2026-01-20 04:35:32 +02:00
Chris Hennes 3a553dc4f9 3rdParty/libE57Format: Update subtree to v3.3.0
Merge commit '30858e0f2b6cc88cde5635f1383bc70e40458c78' into libe57formatTo330
2026-01-15 20:30:58 -06:00
Chris Hennes 30858e0f2b Squashed 'src/3rdParty/libE57Format/' changes from d51a32d6ab7..d885ae35147
d885ae35147 {doc} Update CHANGELOG for 3.3.0
9e7c0a25e4c {cmake} Update version to 3.3.0
8b668f19380 {doc} Update CHANGELOG
dcdda358b0f {doc} Add MicMac to README
5fb956155c7 Replace codecvt_utf8_utf16(deprecatred in C++17) with WIN32 API if C++>=17
a99cbb9ac82 {ci} Update actions/checkout to v5
23a37530095 {ci} Fix CI warnings
04a913cc35e {ci, doc} Fix clang -documentation warnings (#327)
7e3079b9a35 {ci} Make Windows CI working again (#325)
bab1d8b2350 {doc} Update CHANGELOG

git-subtree-dir: src/3rdParty/libE57Format
git-subtree-split: d885ae35147dabd0ad9f6a85e46538b27b1b701c
2026-01-15 20:30:58 -06:00
Pieter Hijma 0537bd6c36 Doc: Add a topic for element mapping 2026-01-12 10:36:11 +01:00
Pieter Hijma 171a14f542 Doc: Improve documentation element mapping 2026-01-12 10:36:09 +01:00
Pieter Hijma 88c2e9122e Doc: Improve the Expression Framework topic 2026-01-12 10:11:54 +01:00
Pieter Hijma 817c8e9dd3 Doc: Improve App::PropertyExpressionEngine docs 2026-01-12 10:11:54 +01:00
Pieter Hijma 8f110b59e7 Doc: Move doc comments in PropertyExpressionEngine
Several doc comments in App/PropertyExpressionEngine.cpp are moved to
header files.
2026-01-12 10:11:54 +01:00
Pieter Hijma 6afb6f7071 Doc: Improve the App::Expression documentation 2026-01-12 10:11:54 +01:00
Pieter Hijma 250b3790dd Doc: Move doc comments in App::Expression
Several doc comments in App/Expression.cpp are moved to header files.
2026-01-12 10:11:53 +01:00
Pieter Hijma fac384d677 Doc: Add a topic for App::link 2026-01-12 10:01:45 +01:00
Pieter Hijma 401400cbcd Doc: Apply cog to Link.h and Link.cpp
Cog is reapplied to create improved documentation for LinkParams.  See
LinkParams.py
2026-01-12 10:01:45 +01:00
Pieter Hijma 16592cae48 Doc: Improve the App::Link documentation 2026-01-12 10:01:43 +01:00
Pieter Hijma 393434026a Doc: Add a topic for App::Application 2026-01-12 09:38:45 +01:00
Pieter Hijma d4a115df06 [Doc] Improve the App::Application documentation 2026-01-12 09:38:42 +01:00
Pieter Hijma df85b59de9 Doc: Improve the topic for App::Document 2026-01-12 09:19:05 +01:00
Pieter Hijma bd3a7c1368 Doc: Improve App::Document documentation 2026-01-12 09:19:03 +01:00
Pieter Hijma c093fd484c Doc: Add a topic for App::DocumentObject 2026-01-12 08:39:53 +01:00
Pieter Hijma 788fe423e8 Doc: Improve App::DocumentObject documentation
It also improves documentation from other files for relevant dependent
functions.
2026-01-12 08:39:48 +01:00
Pieter Hijma d0b1191b2d Doc: Move App::DocumentObject documentation
App::DocumentObject had docstrings both in the cpp file and in the
header file.  All documentation has been moved to the header file. In
cases where documentation existed in both the header and cpp file, the
documentation has been reconciled.
2026-01-12 08:27:51 +01:00
tarman3 bc81a16eb4 CAM: Engrave - Fix regression in Task panel after #22304 2026-01-10 10:04:39 +02:00
Louis Gombert 193a789354 CMake: only find Netgen when using internal smesh 2026-01-09 18:42:25 +01:00
Louis Gombert 96f8b3a43b CMake: require Netgen when BUILD_FEM_NETGEN is ON, don't fail silently 2026-01-09 18:42:25 +01:00
tarman3 22f40741ee CAM: LeadInOut - ArcZ following profile 2026-01-06 14:59:25 +02:00
Chris Hennes e01063b3c4 Build: Remove blanket disabling of deprecation warnings
Also document other disabled warnings.
2025-11-21 17:02:11 -06:00
3668 changed files with 389430 additions and 160600 deletions
+2 -2
View File
@@ -58,7 +58,7 @@ jobs:
logdir: /tmp/log/
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -108,7 +108,7 @@ jobs:
done
- name: Upload logs
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ github.job }}-Logs
path: |
@@ -68,6 +68,12 @@ runs:
testCommand: ${{ inputs.builddir }}/tests/Gui_tests_run --gtest_output=json:${{ inputs.reportdir }}gui_gtest_results.json
testLogFile: ${{ inputs.reportdir }}gui_gtest_test_log.txt
testName: Gui
- name: C++ Qt tests
id: qttests
uses: ./.github/workflows/actions/runCPPTests/runQtTests
with:
builddir: ${{ inputs.builddir }}
testLogFile: ${{ inputs.reportdir }}qt_ctest_log.txt
- name: C++ Material tests
id: material
uses: ./.github/workflows/actions/runCPPTests/runSingleTest
@@ -0,0 +1,55 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# SPDX-FileNotice: Part of the FreeCAD project.
name: runQtTests
description: "Run all QtTest-based C++ tests (those labelled 'Qt' in CTest), generate log and report"
inputs:
builddir:
description: "Build directory containing CTestTestfile.cmake"
required: true
testLogFile:
description: "Path for the command-line output of the tests"
required: true
outputs:
reportText:
description: "Report text"
value: ${{ steps.report.outputs.reportText }}
runs:
using: "composite"
steps:
- name: Run Qt tests via CTest
shell: bash -l {0}
env:
BUILD_DIR: ${{ inputs.builddir }}
TEST_LOG_FILE: ${{ inputs.testLogFile }}
run: |
set -o pipefail
ctest --test-dir "$BUILD_DIR" -L Qt --output-on-failure | tee -a "$TEST_LOG_FILE"
- name: Parse test results
if: always()
id: report
shell: bash -l {0}
env:
TEST_LOG_FILE: ${{ inputs.testLogFile }}
run: |
result=$(grep -E "(Test #|tests passed|tests failed|Total Test time)" "$TEST_LOG_FILE" || true)
if grep -qE "[1-9][0-9]* tests failed" "$TEST_LOG_FILE"
then
reportText="<details><summary>:fire: QtTest C++ tests failed</summary>\n"
else
reportText="<details><summary>:heavy_check_mark: QtTest C++ tests succeeded</summary>\n"
fi
reportText+="\n"
reportText+="Results\n"
reportText+="\n"
reportText+='```\n'
reportText+="$result\n"
reportText+='```\n'
reportText+="</details>\n"
reportText+="\n"
echo "reportText<<EOD" >> $GITHUB_OUTPUT
echo -e "$reportText" >> $GITHUB_OUTPUT
echo "EOD" >> $GITHUB_OUTPUT
echo -e "$reportText"
@@ -0,0 +1,62 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# SPDX-FileNotice: Part of the FreeCAD project.
name: runSingleQtTest
description: "Run a single QtTest-based C++ test executable, generate log and report"
inputs:
testCommand:
description: "Test executable path"
required: true
testLogFile:
description: "Path for the command-line output of the tests"
required: true
testName:
description: "A descriptive name for the test suite"
required: true
outputs:
reportText:
description: "Report text"
value: ${{ steps.report.outputs.reportText }}
runs:
using: "composite"
steps:
- name: Run QtTest tests
shell: bash -l {0}
env:
QT_QPA_PLATFORM: offscreen
TEST_COMMAND: ${{ inputs.testCommand }}
TEST_LOG_FILE: ${{ inputs.testLogFile }}
run: |
set -o pipefail
$TEST_COMMAND | tee -a "$TEST_LOG_FILE"
- name: Parse test results
if: always()
id: report
shell: bash -l {0}
env:
TEST_LOG_FILE: ${{ inputs.testLogFile }}
TEST_NAME: ${{ inputs.testName }}
run: |
# This bonkers sed regex is to try to find the start and end of the QtTest output block, which is not really
# designed to be machine-readable. Why did they have to choose asterisks?!?!
result=$(sed -n '/^\*\*\*\*\*\*\*\*\* Start/,/^\*\*\*\*\*\*\*\*\* Finished/p' "$TEST_LOG_FILE" || true)
if grep -qE "^FAIL!" "$TEST_LOG_FILE"
then
reportText="<details><summary>:fire: QtTest C++ test suite '${TEST_NAME}' failed</summary>\n"
else
reportText="<details><summary>:heavy_check_mark: QtTest C++ test suite '${TEST_NAME}' succeeded</summary>\n"
fi
reportText+="\n"
reportText+="Results\n"
reportText+="\n"
reportText+='```\n'
reportText+="$result\n"
reportText+='```\n'
reportText+="</details>\n"
reportText+="\n"
echo "reportText<<EOD" >> $GITHUB_OUTPUT
echo -e "$reportText" >> $GITHUB_OUTPUT
echo "EOD" >> $GITHUB_OUTPUT
echo -e "$reportText"
@@ -21,13 +21,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: '🧹 Tag & close stale unconfirmed bugs'
id: stale_issues
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: 90
@@ -53,7 +53,7 @@ jobs:
- name: '🧹 Close stale requested feedback issues'
id: awaiting_issues
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: 20
@@ -80,7 +80,7 @@ jobs:
- name: '🧹 Tag & close inactive issues'
id: inactive_issues
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: 190
@@ -110,7 +110,7 @@ jobs:
- name: '🧹 Tag & close inactive PRs'
id: inactive_pr
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: -1
+2 -2
View File
@@ -28,12 +28,12 @@ jobs:
)
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ secrets.GH_TOKEN_FOR_CI_RUNNERS }}
- name: Create backport pull requests
uses: korthout/backport-action@d07416681cab29bf2661702f925f020aaa962997 # v3.4.1
uses: korthout/backport-action@01619ebc9a6e3f6820274221b9956b3e7365000a # v4.1.0
with:
# Inputs documented here: https://github.com/korthout/backport-action?tab=readme-ov-file#inputs
github_token: ${{ secrets.GH_TOKEN_FOR_CI_RUNNERS }}
+88 -20
View File
@@ -10,6 +10,10 @@ permissions:
contents: write
actions: write
concurrency:
group: build-release-${{ github.event_name }}
cancel-in-progress: true
jobs:
upload_src:
runs-on: ubuntu-latest
@@ -17,19 +21,19 @@ jobs:
build_tag: ${{ steps.get_tag.outputs.build_tag }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: Checkout Source
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Checkout source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.sha }}
fetch-depth: 2
fetch-tags: true
submodules: 'recursive'
- name: get tag and create release if weekly
- name: Get tag and create release if weekly
id: get_tag
shell: bash -l {0}
env:
@@ -39,14 +43,17 @@ jobs:
export BUILD_TAG="${{ github.event.release.tag_name }}"
else
export BUILD_TAG=weekly-$(date "+%Y.%m.%d")
gh release create ${BUILD_TAG} --title "Development Build ${BUILD_TAG}" -F .github/workflows/weekly-build-notes.md --prerelease || true
gh release create ${BUILD_TAG} --title "Development Build ${BUILD_TAG}" \
-F .github/workflows/weekly-build-notes.md \
--prerelease || \
gh release view ${BUILD_TAG} > /dev/null # fail if it doesn't exist
fi
echo "BUILD_TAG=${BUILD_TAG}" >> "$GITHUB_ENV"
echo "build_tag=${BUILD_TAG}" >> "$GITHUB_OUTPUT"
- name: Trigger notes updater workflow (only for weekly)
if: startsWith(steps.get_tag.outputs.build_tag, 'weekly-')
uses: actions/github-script@v7
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
WEEKLY_TAG: ${{ steps.get_tag.outputs.build_tag }}
with:
@@ -95,8 +102,9 @@ jobs:
include:
- { target: linux-64, os: ubuntu-22.04 }
- { target: linux-arm64, os: ubuntu-22.04-arm }
- { target: osx-64, os: macos-15-intel }
- { target: osx-arm64, os: macos-latest }
- { target: osx-64, os: macos-15-intel, deploy_target: "10.13" }
- { target: osx-arm64, os: macos-latest, deploy_target: "11.0" }
- { target: osx-arm64, os: macos-latest, deploy_target: "15.0" }
- { target: win-64, os: windows-latest }
fail-fast: false
@@ -104,7 +112,7 @@ jobs:
environment: weekly-build
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -117,7 +125,7 @@ jobs:
remove-android: 'true' # (frees ~9 GB)
remove-cached-tools: 'true' # (frees ~8.3 GB)
- name: Set Platform Environment Variables
- name: Set platform environment variables
shell: bash -l {0}
env:
OPERATING_SYSTEM: ${{ runner.os }}
@@ -127,21 +135,21 @@ jobs:
echo 'RATTLER_CACHE_DIR=D:\rattler' >> "$GITHUB_ENV"
fi
- name: Checkout Source
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Checkout source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.sha }}
fetch-depth: 2
fetch-tags: true
submodules: 'recursive'
- uses: prefix-dev/setup-pixi@82d477f15f3a381dbcc8adc1206ce643fe110fb7 # v0.9.3
- uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
with:
pixi-version: v0.59.0
cache: false
- name: Install the Apple certificate and provisioning profile
id: get_cert
id: macos_get_cert
if: runner.os == 'macOS'
env:
APP_SPECIFIC_PASSWORD: ${{ secrets.APP_SPECIFIC_PASSWORD }}
@@ -149,7 +157,6 @@ jobs:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
DEVELOPER_TEAM_ID: ${{ secrets.DEVELOPER_TEAM_ID }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
run: |
if [ -z "$BUILD_CERTIFICATE_BASE64" ]; then
@@ -185,20 +192,81 @@ jobs:
xcrun notarytool store-credentials "FreeCAD" --keychain "$KEYCHAIN_PATH" --apple-id "${APPLE_ID}" --password "${APP_SPECIFIC_PASSWORD}" --team-id "${DEVELOPER_TEAM_ID}"
- name: Build and Release Packages
- name: Setup .NET 10 SDK
if: runner.os == 'Windows'
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
with:
dotnet-version: '10.0.103'
- name: Install sign tool
if: runner.os == 'Windows'
run: |
# NOTE: The sign tool is ONLY available as a prerelease package, they never issue real releases.
dotnet tool install --global --prerelease sign
echo "$env:USERPROFILE\.dotnet\tools" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
dotnet --info
sign --version
- name: Build packages
shell: bash
env:
GH_TOKEN: ${{ github.token }}
TARGET_PLATFORM: ${{ matrix.target }}
BUILD_TAG: ${{ needs.upload_src.outputs.build_tag }}
run: |
set -euo pipefail
if [[ "${{ runner.os }}" == "macOS" ]]; then
export MACOS_DEPLOYMENT_TARGET="${{ matrix.deploy_target }}"
fi
python3 package/scripts/write_version_info.py ../freecad_version.txt
cd package/rattler-build
pixi install
- name: Azure login for Windows build code signing
id: azure_login
if: runner.os == 'Windows'
continue-on-error: true
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0
with:
creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'
- name: Release packages with optional code-signing on Windows and macOS
shell: bash
env:
GH_TOKEN: ${{ github.token }}
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
SIGN_RELEASE: ${{ steps.get_cert.outputs.has_cert }}
TARGET_PLATFORM: ${{ matrix.target }}
MAKE_INSTALLER: "true"
UPLOAD_RELEASE: "true"
BUILD_TAG: ${{ needs.upload_src.outputs.build_tag }}
run: |
python3 package/scripts/write_version_info.py ../freecad_version.txt
set -euo pipefail
export MACOS_SIGN_RELEASE=0
export WINDOWS_SIGN_RELEASE=0
case "${RUNNER_OS}" in
Windows)
export WINDOWS_SIGN_RELEASE="${{ steps.azure_login.outcome }}"
export WINDOWS_AZURE_ENDPOINT="${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT }}"
export WINDOWS_AZURE_CERTIFICATE_PROFILE="${{ vars.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }}"
export WINDOWS_AZURE_SIGNING_ACCOUNT="${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT }}"
# For good measure, normalize the azure_login result to 1 or 0
if [[ "${WINDOWS_SIGN_RELEASE:-}" == "success" ]]; then
export WINDOWS_SIGN_RELEASE=1
else
export WINDOWS_SIGN_RELEASE=0
fi
;;
macOS)
export MACOS_SIGN_RELEASE="${{ steps.macos_get_cert.outputs.has_cert }}"
export MACOS_SIGNING_KEY_ID="${{ secrets.SIGNING_KEY_ID }}"
export MACOS_DEPLOYMENT_TARGET="${{ matrix.deploy_target }}"
;;
esac
cd package/rattler-build
pixi install
pixi run -e package create_bundle
## Needed if running on a self-hosted runner:
+2 -2
View File
@@ -64,12 +64,12 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2
submodules: recursive
+3 -3
View File
@@ -68,7 +68,7 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -84,7 +84,7 @@ jobs:
remove-docker-images: 'true' # (frees ~3.2 GB)
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2
submodules: recursive
@@ -156,7 +156,7 @@ jobs:
sarif_file: sarif-results/cpp.sarif
- name: Upload loc as a Build Artifact
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v7.0.0
with:
name: sarif-results
path: sarif-results
+3 -3
View File
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: 'Checkout Repository'
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: 'Dependency Review'
uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4
uses: actions/dependency-review-action@05fe4576374b728f0c523d6a13d64c25081e0803 # v4
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
copr_url = https://copr.fedorainfracloud.org
" > ~/.config/copr
- name: checkout sources
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 500
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
token: ${{ secrets.GH_TOKEN_FOR_CROWDIN_SYNC }}
@@ -25,7 +25,7 @@ jobs:
arch: "linux_gcc_64"
- name: Setup Python & dependencies
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: "3.13"
- name: Install Python packages
@@ -57,7 +57,7 @@ jobs:
git push origin update-crowdin-translations --force
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
branch: update-crowdin-translations
title: "Update translations from Crowdin"
+2 -2
View File
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -35,7 +35,7 @@ jobs:
echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV"
- name: Run issue-metrics tool
uses: github/issue-metrics@67526e7bd8100b870f10b1c120780a8375777b43 # v3.25.5
uses: github/issue-metrics@6a35322ff89cee3e1a594d282c27eb34bffa9174 # v4.1.1
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SEARCH_QUERY: 'repo:FreeCAD/FreeCAD is:issue created:${{ env.last_month }}'
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
ref: releases/FreeCAD-1-1
@@ -25,7 +25,7 @@ jobs:
arch: "linux_gcc_64"
- name: Setup Python & dependencies
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: "3.13"
- name: Install Python packages
+3 -3
View File
@@ -36,12 +36,12 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: "Checkout code"
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
@@ -68,7 +68,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: SARIF file
path: results.sarif
+7 -7
View File
@@ -75,7 +75,7 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -91,7 +91,7 @@ jobs:
fi
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Add GCC Problem Matcher
if: runner.os == 'Linux'
@@ -116,7 +116,7 @@ jobs:
mkdir -p ${{ env.reportdir }}
echo "reportFile=${{ env.reportfilename }}" >> $GITHUB_OUTPUT
- uses: prefix-dev/setup-pixi@82d477f15f3a381dbcc8adc1206ce643fe110fb7 # v0.9.3
- uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
with:
pixi-version: v0.59.0
cache: false
@@ -124,7 +124,7 @@ jobs:
- name: Restore Compiler Cache
id: cache-restore
if: always()
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ${{ env.CCACHE_DIR }}
key: FC-${{ env.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
@@ -209,14 +209,14 @@ jobs:
- name: Save Compiler Cache
id: cache-save
if: always()
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ${{ env.CCACHE_DIR }}
key: FC-${{ env.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
- name: Upload logs
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ inputs.artifactBasename }}-${{ matrix.os }}-Logs
path: |
@@ -225,7 +225,7 @@ jobs:
- name: Upload report
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.reportfilename }}
path: |
+7 -7
View File
@@ -77,12 +77,12 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: Checking out source code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
@@ -116,7 +116,7 @@ jobs:
- name: Restore Compiler Cache
id: cache-restore
if: always()
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ${{ env.CCACHE_DIR }}
key: FC-${{ steps.genCacheKey.outputs.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
@@ -131,7 +131,7 @@ jobs:
ccache -p
- name: Install cmake
uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2.0.2
uses: jwlawson/actions-setup-cmake@3a6cbe35ba64df7ca70c51365c4aff65db9a9037 # v2.1.1
with:
cmake-version: '3.31.6'
@@ -216,14 +216,14 @@ jobs:
- name: Save Compiler Cache
id: cache-save
if: always()
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ${{ env.CCACHE_DIR }}
key: FC-${{ steps.genCacheKey.outputs.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
- name: Upload logs
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ inputs.artifactBasename }}-Logs
path: |
@@ -232,7 +232,7 @@ jobs:
- name: Upload report
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.reportfilename }}
path: |
+20 -8
View File
@@ -24,15 +24,27 @@
name: Build Windows
on:
workflow_dispatch:
inputs:
artifactBasename:
description: "Base name for artifact"
required: false
type: string
default: "FreeCAD"
allowedToFail:
description: "whether a failed build is allowed"
required: false
type: boolean
default: false
workflow_call:
inputs:
artifactBasename:
type: string
required: true
type: string
allowedToFail:
required: false
default: false
type: boolean
required: false
outputs:
reportFile:
value: ${{ jobs.Build.outputs.reportFile }}
@@ -66,12 +78,12 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: Checking out source code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
@@ -99,7 +111,7 @@ jobs:
- name: Restore compiler cache
id: cache-restore
if: always()
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ${{ env.CCACHE_DIR }}
key: FC-${{ env.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
@@ -114,7 +126,7 @@ jobs:
. $env:ccachebindir\ccache -p
- name: Install cmake
uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2.0.2
uses: jwlawson/actions-setup-cmake@3a6cbe35ba64df7ca70c51365c4aff65db9a9037 # v2.1.1
with:
cmake-version: '3.31.6'
@@ -157,14 +169,14 @@ jobs:
- name: Save Compiler Cache
id: cache-save
if: always()
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ${{ env.CCACHE_DIR }}
key: FC-${{ env.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
- name: Upload logs
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ inputs.artifactBasename }}-Logs
path: |
+4 -4
View File
@@ -198,12 +198,12 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
- name: Check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
@@ -355,7 +355,7 @@ jobs:
- name: Upload logs and fixes
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ inputs.artifactBasename }}-Logs
path: |
@@ -364,7 +364,7 @@ jobs:
- name: Upload report
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.reportfilename }}
path: |
+4 -4
View File
@@ -81,7 +81,7 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -94,7 +94,7 @@ jobs:
touch ${{ env.logdir }}changedFiles.lst ${{ env.logdir }}changedCppFiles.lst ${{ env.logdir }}changedPythonFiles.lst
echo "reportFile=${{ env.reportfilename }}" >> $GITHUB_OUTPUT
- name: Check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- name: Determine base and head SHA in case of PR
@@ -180,14 +180,14 @@ jobs:
echo "" >> $GITHUB_OUTPUT
- name: Upload logs
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ inputs.artifactBasename }}-Logs
path: |
${{ env.logdir }}
- name: Upload report
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.reportfilename }}
path: |
+3 -3
View File
@@ -54,7 +54,7 @@ jobs:
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit
@@ -62,7 +62,7 @@ jobs:
run: |
mkdir -p ${{ env.artifactsDownloadDir }}
- name: Download artifacts
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: ${{ env.artifactsDownloadDir }}
- name: Save input data to file
@@ -119,7 +119,7 @@ jobs:
cat report.md >> $GITHUB_STEP_SUMMARY
- name: Delete used artifacts
continue-on-error: true
uses: geekyeggo/delete-artifact@f275313e70c08f6120db482d7a6b98377786765b # v5.1.0
uses: geekyeggo/delete-artifact@176a747ab7e287e3ff4787bf8a148716375ca118 # v6.0.0
with:
name: |
${{ env.usedArtifacts }}
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Inject compare link into weekly release notes
uses: actions/github-script@v7
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
# Pass manual inputs via env for convenience
CURRENT_TAG: ${{ github.event.inputs.current_tag }}
+29 -28
View File
@@ -1,59 +1,60 @@
# file types to ignore
.*
!/.packit.yaml
!*.gitattributes
!*.gitignore
!/.clang-format
!/.clang-tidy
!/.git-blame-ignore-revs
!/.gitattributes
!/.github/
!/.gitignore
!/.gitmodules
!/.packit.yaml
!/.pre-commit-config.yaml
!/.pylintrc
!/.github/
!/contrib/.vscode/
!*.gitattributes
!*.gitignore
*.clangd
*.DS_Store
*.pyc
*.obj
*.lib
*.pch
*.vcproj
*.kdev4
*.exp
*.dep
*.exp
*.kdev4
*.lib
*.manifest
*.o
*.obj
*.orig
*.output
*.pch
*.pyc
*.vcproj
# Ignore .db files created by Qt Designer when editing .ui files
*.db
qrc_*.cpp
BuildLog.htm
cmake_install.cmake
*~
CMakeFiles/
*qrc.depends
ui_*.h
moc_*.cpp
Makefile
*~
BuildLog.htm
CMakeCache.txt
CMakeFiles/
CMakeLists.txt.user
Makefile
cmake_install.cmake
config.h
install_manifest.txt
/bin/
moc_*.cpp
qrc_*.cpp
ui_*.h
/.vscode/
/ALL_BUILD.dir/
/doc/
/lib/
/Mod/
/ZERO_CHECK.dir/
/build/
/bin/
/build-*/
/build/
/cmake-build*/
/src/Tools/offlinedoc/localwiki/
/src/Tools/offlinedoc/*.txt
/conda/environment.yml
/.vscode/
/doc/
/lib/
/src/Tools/offlinedoc/*.txt
/src/Tools/offlinedoc/localwiki/
OpenSCAD_rc.py
tags
/CMakeUserPresets.json
@@ -63,10 +64,10 @@ compile_commands.json
*.sublime-workspace
# crowdin file
files_to_translate.txt
src/Tools/freecad.zip
tsupdate_stderr.log
tsupdate_stdout.log
files_to_translate.txt
# pixi environments
.pixi
*.egg-info
.pixi
+1
View File
@@ -46,6 +46,7 @@ exclude: |
src/App/ExpressionParser.tab.h|
src/App/ExpressionParser.y|
src/App/lex.ExpressionParser.c|
src/Doc/ThirdPartyLibraries.html.cmake|
src/Gui/3Dconnexion/navlib|
src/Gui/QSint|
src/Gui/Quarter|
+1 -1
View File
@@ -398,7 +398,7 @@ indent-after-paren=4
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
max-line-length=120
# Maximum number of lines in a module.
max-module-lines=1000
+5 -2
View File
@@ -95,8 +95,11 @@ if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER OR FREECAD_LIB
endif(BUILD_GUI)
SetupSalomeSMESH()
if (BUILD_FEM_NETGEN)
find_package(NETGEN)
endif(BUILD_FEM_NETGEN)
set(NETGEN_DEFINITIONS -DNO_PARALLEL_THREADS -DOCCGEOMETRY)
if (NOT FREECAD_USE_EXTERNAL_SMESH)
find_package(NETGEN REQUIRED)
endif()
endif()
# not needed at the moment
#find_package(OpenCV REQUIRED)
SetupSwig()
+3 -1
View File
@@ -62,7 +62,9 @@ The FreeCAD Contribution Process is expressed here with the following specific g
1. the PR description MUST contain proper attribution as the first line, for example: "This is work of XYZ cherry-picked from <link>";
2. all commits MUST have proper authorship, i.e. be authored by the original author and committed by the author of the PR;
3. if changes to cherry-picked commits are necessary they SHOULD be done as follow-up commits. If it is not possible to do so, then the modified commits MUST contain a `Co-Authored-By` trailer in their commit message.
14. A “Valid PR” is one which satisfies the above requirements.
14. Contributions must meet existing quality standards. Raw AI output is not accepted under any circumstances. AI may be used only as an assistive tool; in all cases, the resulting content must be reviewed, validated, and justifiable by the contributor. The contributor should be able to explain design and code decisions, answer reviewers questions, and ensure that AI use does not waste reviewers time during review. That being said, the use of AI is not recommended under any circumstances or in any manner.
15. The contributor provides reasonable assurance that the contribution does not infringe third-party copyrights or license terms.
16. A “Valid PR” is one which satisfies the above requirements.
## 6. Process
+2 -8
View File
@@ -56,14 +56,8 @@ Other options are described on the [wiki Download page](https://wiki.freecad.org
Compiling
---------
FreeCAD requires several dependencies to correctly compile for development and
production builds. The following pages contain updated build instructions for
their respective platforms:
- [Linux](https://wiki.freecad.org/Compile_on_Linux)
- [Windows](https://wiki.freecad.org/Compile_on_Windows)
- [macOS](https://wiki.freecad.org/Compile_on_MacOS)
- [MinGW](https://wiki.freecad.org/Compile_on_MinGW)
See the [Developers Handbook Getting Started](https://freecad.github.io/DevelopersHandbook/gettingstarted/)
for build instructions.
Reporting Issues
+6 -5
View File
@@ -13,19 +13,15 @@
# See also: http://git.salome-platform.org/gitweb/?p=NETGENPLUGIN_SRC.git;a=summary
find_package(Netgen CONFIG)
find_package(Netgen CONFIG QUIET)
IF (Netgen_FOUND)
set(NGLIB_INCLUDE_DIR ${NETGEN_INCLUDE_DIRS})
set(NGLIB_LIBRARIES nglib)
set(NETGEN_DEFINITIONS -DNO_PARALLEL_THREADS -DOCCGEOMETRY)
# for external smesh only the following two variables are needed:
set(NETGEN_FOUND True)
set(NETGEN_INCLUDE_DIRS ${NETGEN_INCLUDE_DIRS})
ELSE ()
SET(NETGEN_DEFINITIONS -DNO_PARALLEL_THREADS -DOCCGEOMETRY)
IF (WIN32)
FIND_PATH(NGLIB_INCLUDE_DIR NAMES nglib.h PATHS ${NETGEN_INCLUDEDIR})
SET(NETGEN_LIBS nglib mesh occ interface)
@@ -147,3 +143,8 @@ IF (Netgen_FOUND)
MESSAGE(STATUS "Found NETGEN version ${NETGEN_VERSION_MAJOR}.${NETGEN_VERSION_MINOR}, calculated: ${NETGEN_VERSION_C}")
LIST(APPEND NETGEN_DEFINITIONS -DNETGEN_VERSION=${NETGEN_VERSION_C})
ENDIF ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NETGEN
REQUIRED_VARS NGLIB_INCLUDE_DIR NGLIB_LIBRARIES NETGEN_INCLUDE_DIRS
VERSION_VAR NETGEN_VERSION)
+41 -9
View File
@@ -1,7 +1,11 @@
# The Qt for Python project officially recommends using pip to install PySide, so we expect to find PySide in the
# site-packages directory. The library will be called "PySide6.abi3.*", and there will be an "include" directory inside
# the site-packages/PySide6. Over time some distros may provide custom versions, so we also support using a more normal
# cMake find_package() call
# The Qt for Python project officially recommends using pip to install PySide,
# so we expect to find PySide in the site-packages directory.
# The library will be called "PySide6.abi3.*", and there will
# be an "include" directory inside the site-packages/PySide6.
# Over time some distros may provide custom versions, so we also support
# using a more normal cMake find_package() call
include(FindPackageHandleStandardArgs)
find_package(PySide6 CONFIG QUIET)
@@ -9,12 +13,40 @@ if(NOT PySide6_FOUND)
find_pip_package(PySide6)
endif()
if(NOT PySide6_INCLUDE_DIRS AND TARGET PySide6::pyside6)
get_property(PySide6_INCLUDE_DIRS TARGET PySide6::pyside6 PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif()
if(PySide6_FOUND)
# verify PySide6 version matches Qt6 version (major.minor)
if(PySide6_VERSION AND Qt6_VERSION)
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)" _qt6_major_minor "${Qt6_VERSION}")
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)" _pyside6_major_minor "${PySide6_VERSION}")
# Also provide the old-style variables so we don't have to update everything yet
if (PySide6_FOUND)
message(STATUS "Qt version: ${Qt6_VERSION}")
message(STATUS "PySide version: ${PySide6_VERSION}")
if(NOT _qt6_major_minor STREQUAL _pyside6_major_minor)
message(FATAL_ERROR
" --------------------------------------------------------
Qt/PySide version mismatch!
cmake found Qt: ${Qt6_VERSION}
cmake found PySide: ${PySide6_VERSION}
major.minor versions of Qt and PySide must match to avoid errors.
Ensure CMAKE_PREFIX_PATH points to matching Qt and PySide6 installations.
--------------------------------------------------------"
)
endif()
message(STATUS "PySide/Qt version check passed (${_pyside6_major_minor})")
endif()
if(NOT PySide6_INCLUDE_DIRS AND TARGET PySide6::pyside6)
get_property(PySide6_INCLUDE_DIRS TARGET PySide6::pyside6 PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif()
find_package_handle_standard_args(PySide6
REQUIRED_VARS PySide6_INCLUDE_DIRS
VERSION_VAR PySide6_VERSION
)
# Also provide the old-style variables so we don't have to update everything yet
set(PYSIDE_INCLUDE_DIR ${PySide6_INCLUDE_DIRS})
set(PYSIDE_LIBRARY ${PySide6_LIBRARIES})
set(PYSIDE_FOUND TRUE)
+6 -6
View File
@@ -3,11 +3,11 @@
# PYSIDE_RCC_EXECUTABLE - Location of PYSIDE6RCC executable
# PYSIDE_TOOLS_FOUND - PYSIDE6 utilities found.
if (TARGET Qt6::uic)
if(TARGET Qt6::uic)
get_target_property(PYSIDE6_UIC_EXECUTABLE Qt6::uic LOCATION)
set(UICOPTIONS "--generator=python")
endif()
if (TARGET Qt6::rcc)
if(TARGET Qt6::rcc)
get_target_property(PYSIDE6_RCC_EXECUTABLE Qt6::rcc LOCATION)
set(RCCOPTIONS "--generator=python" "--compress-algo=zlib" "--compress=1")
endif()
@@ -18,15 +18,15 @@ set(PySideTools_VERSION 6)
if(PYSIDE_RCC_EXECUTABLE AND PYSIDE_UIC_EXECUTABLE)
set(PYSIDE_TOOLS_FOUND TRUE)
if (NOT PYSIDE6Tools_FIND_QUIETLY)
if(NOT PYSIDE6Tools_FIND_QUIETLY)
message(STATUS "Found PYSIDE6 tools: ${PYSIDE_UIC_EXECUTABLE}, ${PYSIDE_RCC_EXECUTABLE}")
endif ()
endif()
else()
if(PYSIDE6Tools_FIND_REQUIRED)
message(FATAL_ERROR "PYSIDE6 tools could not be found, but are required.")
else()
if (NOT PYSIDE6Tools_FIND_QUIETLY)
if(NOT PYSIDE6Tools_FIND_QUIETLY)
message(STATUS "PYSIDE6 tools: not found.")
endif ()
endif()
endif()
endif()
+2 -2
View File
@@ -10,14 +10,14 @@ if(NOT Shiboken6_FOUND)
endif()
if(NOT Shiboken6_INCLUDE_DIR)
find_pip_package(Shiboken6)
if (Shiboken6_FOUND)
if(Shiboken6_FOUND)
set(SHIBOKEN_LIBRARY ${Shiboken6_LIBRARIES})
set(SHIBOKEN_MAJOR_VERSION 6)
set(SHIBOKEN_FOUND ON)
endif()
# The include directory we actually want is part of shiboken6-generator
find_pip_package(shiboken6_generator)
if (shiboken6_generator_FOUND)
if(shiboken6_generator_FOUND)
set(SHIBOKEN_INCLUDE_DIR ${shiboken6_generator_INCLUDE_DIRS})
endif()
endif()
+16
View File
@@ -7,6 +7,22 @@ macro(SetupFreetype)
message("===============================================================\n"
"FreeType2 not found. Part module will lack of makeWireString().\n"
"===============================================================\n")
else()
# find_package(harfbuzz CONFIG) fails on windows
# lets do it the complicated way instead.
find_path(HARFBUZZ_INCLUDE_DIR hb.h PATH_SUFFIXES harfbuzz)
find_library(HARFBUZZ_LIBRARY NAMES harfbuzz)
if(HARFBUZZ_INCLUDE_DIR AND HARFBUZZ_LIBRARY)
if(NOT TARGET harfbuzz::harfbuzz)
add_library(harfbuzz::harfbuzz UNKNOWN IMPORTED)
set_target_properties(harfbuzz::harfbuzz PROPERTIES
IMPORTED_LOCATION "${HARFBUZZ_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${HARFBUZZ_INCLUDE_DIR}"
)
endif()
else()
message(FATAL_ERROR "HarfBuzz not found")
endif()
endif(NOT FREETYPE_FOUND)
endif(FREECAD_USE_FREETYPE)
@@ -7,7 +7,7 @@ macro(SetupShibokenAndPyside)
if(DEFINED MACPORTS_PREFIX)
find_package(Shiboken REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
find_package(PySide REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
endif(DEFINED MACPORTS_PREFIX)
endif()
if(FREECAD_QT_MAJOR_VERSION EQUAL 5)
set(SHIBOKEN_MAJOR_VERSION 2)
@@ -21,16 +21,16 @@ macro(SetupShibokenAndPyside)
# Shiboken2Config.cmake may explicitly set CMAKE_BUILD_TYPE to Release which causes
# CMake to fail to create Makefiles for a debug build.
# So as a workaround we save and restore the value after checking for Shiboken2.
set (SAVE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
set(SAVE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
find_package(Shiboken${SHIBOKEN_MAJOR_VERSION} QUIET)
set (CMAKE_BUILD_TYPE ${SAVE_BUILD_TYPE})
if (Shiboken${SHIBOKEN_MAJOR_VERSION}_FOUND)
set(CMAKE_BUILD_TYPE ${SAVE_BUILD_TYPE})
if(Shiboken${SHIBOKEN_MAJOR_VERSION}_FOUND)
# Shiboken config file was found but it may use the wrong Python version
# Try to get the matching config suffix and repeat finding the package
set(SHIBOKEN_PATTERN .cpython-${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})
file(GLOB SHIBOKEN_CONFIG "${Shiboken${SHIBOKEN_MAJOR_VERSION}_DIR}/Shiboken${SHIBOKEN_MAJOR_VERSION}Config${SHIBOKEN_PATTERN}*.cmake")
if (SHIBOKEN_CONFIG)
if(SHIBOKEN_CONFIG)
get_filename_component(SHIBOKEN_CONFIG_SUFFIX ${SHIBOKEN_CONFIG} NAME)
string(SUBSTRING ${SHIBOKEN_CONFIG_SUFFIX} 15 -1 SHIBOKEN_CONFIG_SUFFIX)
string(REPLACE ".cmake" "" PYTHON_CONFIG_SUFFIX ${SHIBOKEN_CONFIG_SUFFIX})
@@ -47,11 +47,11 @@ macro(SetupShibokenAndPyside)
# to dance to be compatible with the old (<5.12) and the new versions (>=5.12)
if(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken${SHIBOKEN_MAJOR_VERSION}::libshiboken)
get_property(SHIBOKEN_INCLUDE_DIR TARGET Shiboken${SHIBOKEN_MAJOR_VERSION}::libshiboken PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken${SHIBOKEN_MAJOR_VERSION}::libshiboken)
endif()
if(NOT SHIBOKEN_INCLUDE_DIR)
find_pip_package(Shiboken${SHIBOKEN_MAJOR_VERSION})
if (Shiboken${SHIBOKEN_MAJOR_VERSION}_FOUND)
if(Shiboken${SHIBOKEN_MAJOR_VERSION}_FOUND)
set(SHIBOKEN_INCLUDE_DIR ${Shiboken${SHIBOKEN_MAJOR_VERSION}_INCLUDE_DIRS})
set(SHIBOKEN_LIBRARY ${Shiboken${SHIBOKEN_MAJOR_VERSION}_LIBRARIES})
endif()
@@ -63,11 +63,11 @@ macro(SetupShibokenAndPyside)
# Our internal FindPySide6.cmake file already provides these for PySide6
if(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide${PYSIDE_MAJOR_VERSION}::pyside${PYSIDE_MAJOR_VERSION})
get_property(PYSIDE_INCLUDE_DIR TARGET PySide${PYSIDE_MAJOR_VERSION}::pyside${PYSIDE_MAJOR_VERSION} PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide${PYSIDE_MAJOR_VERSION}::pyside${PYSIDE_MAJOR_VERSION})
endif()
if(NOT PYSIDE_INCLUDE_DIR)
find_pip_package(PySide${PYSIDE_MAJOR_VERSION})
if (PySide${PYSIDE_MAJOR_VERSION}_FOUND)
if(PySide${PYSIDE_MAJOR_VERSION}_FOUND)
set(PYSIDE_INCLUDE_DIR ${PySide${PYSIDE_MAJOR_VERSION}_INCLUDE_DIRS})
set(PYSIDE_LIBRARY ${PySide${PYSIDE_MAJOR_VERSION}_LIBRARIES})
endif()
@@ -175,22 +175,22 @@ macro(SetupShibokenAndPyside)
message(STATUS "PySide ${PySide_VERSION} Python module found at ${PRINT_OUTPUT}.\n")
endif()
endmacro(SetupShibokenAndPyside)
endmacro()
MACRO(PYSIDE_WRAP_RC outfiles)
if (NOT PYSIDE_RCC_EXECUTABLE)
macro(PYSIDE_WRAP_RC outfiles)
if(NOT PYSIDE_RCC_EXECUTABLE)
message(FATAL_ERROR "Qt rcc is required for generating ${ARGN}")
endif()
FOREACH(it ${ARGN})
GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
SET(outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}_rc.py")
foreach(it ${ARGN})
get_filename_component(outfile ${it} NAME_WE)
get_filename_component(infile ${it} ABSOLUTE)
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}_rc.py")
#ADD_CUSTOM_TARGET(${it} ALL
# DEPENDS ${outfile}
#)
if(WIN32 OR APPLE)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
add_custom_command(OUTPUT ${outfile}
COMMAND ${PYSIDE_RCC_EXECUTABLE} ${RCCOPTIONS} ${infile} -o ${outfile}
MAIN_DEPENDENCY ${infile}
)
@@ -198,7 +198,7 @@ MACRO(PYSIDE_WRAP_RC outfiles)
# Especially on Open Build Service we don't want changing date like
# pyside-rcc generates in comments at beginning, which is why
# we follow the tool command with in-place sed.
ADD_CUSTOM_COMMAND(OUTPUT "${outfile}"
add_custom_command(OUTPUT "${outfile}"
COMMAND "${PYSIDE_RCC_EXECUTABLE}" ${RCCOPTIONS} "${infile}" ${PY_ATTRIBUTE} -o "${outfile}"
# The line below sometimes catches unwanted lines too - but there is no date in the file
# anymore with Qt5 RCC, so commenting it out for now...
@@ -207,5 +207,5 @@ MACRO(PYSIDE_WRAP_RC outfiles)
)
endif()
list(APPEND ${outfiles} ${outfile})
ENDFOREACH(it)
ENDMACRO (PYSIDE_WRAP_RC)
endforeach()
endmacro()
Binary file not shown.
+4 -3
View File
@@ -64,7 +64,8 @@ ${LangFileString} SecUnPreferencesDescription 'Deletes FreeCAD$\'s configuration
$AppSuff\$\r$\n\
${APP_DIR_USERDATA}$\")$\r$\n\
for you or for all users (if you are admin).'
${LangFileString} DialogUnPreferences 'You chose to delete the FreeCADs user configuration.$\r$\n\
This will also delete all installed FreeCAD addons.$\r$\n\
Do you agree with this?'
${LangFileString} DialogUnPreferences 'You chose to delete the FreeCAD user configuration.$\r$\n\
This will also delete all installed FreeCAD addons, and will affect the$\r$\n\
preferences for all versions of FreeCAD.$\r$\n\
Are you sure you want to proceed?'
${LangFileString} SecUnProgramFilesDescription "Uninstall FreeCAD and all of its components."
-2
View File
@@ -57,8 +57,6 @@
test: xvfb-run /usr/bin/FreeCAD -t TestPartGui
/TestPartDesignGui :
test: xvfb-run /usr/bin/FreeCAD -t TestPartDesignGui
/TestSketcherGui :
test: xvfb-run /usr/bin/FreeCAD -t TestSketcherGui
/TestTechDrawGui :
test: xvfb-run /usr/bin/FreeCAD -t TestTechDrawGui
/Workbench :
+29 -1
View File
@@ -8,7 +8,9 @@ if [[ ${HOST} =~ .*darwin.* ]]; then
# add hacks for osx here!
echo "adding hacks for osx"
# install space-mouse
# Install 3DConnexion (SpaceMouse) driver
# Note: For local builds, comment out the following lines if you encounter issues
# installing the driver or don't need SpaceMouse support
/usr/bin/curl -o /tmp/3dFW.dmg -L 'https://download.3dconnexion.com/drivers/mac/10-7-0_B564CC6A-6E81-42b0-82EC-418EA823B81A/3DxWareMac_v10-7-0_r3411.dmg'
hdiutil attach -readonly /tmp/3dFW.dmg
sudo installer -package /Volumes/3Dconnexion\ Software/Install\ 3Dconnexion\ software.pkg -target /
@@ -17,6 +19,31 @@ if [[ ${HOST} =~ .*darwin.* ]]; then
CMAKE_PLATFORM_FLAGS+=(-D3DCONNEXIONCLIENT_FRAMEWORK:FILEPATH="/Library/Frameworks/3DconnexionClient.framework")
CXXFLAGS="${CXXFLAGS} -D_LIBCPP_DISABLE_AVAILABILITY"
# Use MACOS_DEPLOYMENT_TARGET from environment, default to 11.0 for backwards compat.
# Note that CI sets this per target: 10.13 (Intel), 11.0 (ARM legacy), 15.0 (ARM modern)
# - macOS 10.13+ Intel: legacy QuickLook generator (.qlgenerator)
# - macOS 11-14 ARM: legacy QuickLook generator (.qlgenerator)
# - macOS 15+ ARM: modern QuickLook App Extensions (.appex)
DEPLOY_TARGET="${MACOS_DEPLOYMENT_TARGET:-11.0}"
CMAKE_PLATFORM_FLAGS+=(-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOY_TARGET})
# Patch Qt6's FindWrapOpenGL.cmake to not link AGL on macOS 10.15+
# AGL framework was removed in macOS 10.15 Catalina and Qt6's cmake
# unconditionally tries to link it on Apple platforms, causing build failures.
# Only apply this patch for deployment targets >= 10.15.
# See: https://github.com/conda-forge/qt-main-feedstock/issues/240
DEPLOY_MAJOR=$(echo "$DEPLOY_TARGET" | cut -d. -f1)
DEPLOY_MINOR=$(echo "$DEPLOY_TARGET" | cut -d. -f2)
if [[ "$DEPLOY_MAJOR" -gt 10 ]] || [[ "$DEPLOY_MAJOR" -eq 10 && "$DEPLOY_MINOR" -ge 15 ]]; then
FIND_WRAP_OPENGL="$PREFIX/lib/cmake/Qt6/FindWrapOpenGL.cmake"
if [[ -f "$FIND_WRAP_OPENGL" ]]; then
echo "Patching Qt6 FindWrapOpenGL.cmake to remove AGL linkage (not available on macOS 10.15+)..."
sed -i.bak \
-e '/find_library(WrapOpenGL_AGL/,/target_link_libraries.*__opengl_agl_fw_path/d' \
"$FIND_WRAP_OPENGL"
fi
fi
fi
unset CMAKE_GENERATOR
@@ -24,6 +51,7 @@ unset CMAKE_GENERATOR_PLATFORM
cmake \
${CMAKE_ARGS} \
${CMAKE_PLATFORM_FLAGS[@]} \
--preset ${CMAKE_PRESET} \
-D CMAKE_IGNORE_PREFIX_PATH="/opt/homebrew;/usr/local/homebrew" \
-D CMAKE_INCLUDE_PATH:FILEPATH="$PREFIX/include" \
+1 -1
View File
@@ -31,4 +31,4 @@ else
MAIN="$HERE/usr/bin/freecad"
fi
"${MAIN}" "$@"
exec "${MAIN}" "$@"
+33 -6
View File
@@ -48,7 +48,11 @@ mkdir -p FreeCAD.app/Contents/MacOS
cp build/FreeCAD FreeCAD.app/Contents/MacOS/FreeCAD
python_version=$(${conda_env}/bin/python -c 'import platform; print("py" + platform.python_version_tuple()[0] + platform.python_version_tuple()[1])')
version_name="FreeCAD_${BUILD_TAG}-macOS-$(uname -m)-${python_version}"
# Add deployment target suffix to artifact name (e.g., "-macOS11" or "-macOS15")
deploy_target="${MACOS_DEPLOYMENT_TARGET:-11.0}"
deploy_suffix="-macOS${deploy_target%%.*}"
version_name="FreeCAD_${BUILD_TAG}-macOS-$(uname -m)${deploy_suffix}-${python_version}"
application_menu_name="FreeCAD_${BUILD_TAG}"
echo -e "\################"
@@ -62,14 +66,37 @@ sed -i "s/APPLICATION_MENU_NAME/${application_menu_name}/" ${conda_env}/../Info.
pixi list -e default > FreeCAD.app/Contents/packages.txt
sed -i '1s/.*/\nLIST OF PACKAGES:/' FreeCAD.app/Contents/packages.txt
# copy the plugin into its final location
cp -a ${conda_env}/Library ${conda_env}/..
rm -rf ${conda_env}/Library
# move plugins into their final location (Library only exists for macOS < 15.0 builds)
if [ -d "${conda_env}/Library" ]; then
mv ${conda_env}/Library ${conda_env}/..
fi
if [[ "${SIGN_RELEASE}" == "true" ]]; then
# move App Extensions (PlugIns) to the correct location for macOS registration
if [ -d "${conda_env}/PlugIns" ]; then
mv ${conda_env}/PlugIns ${conda_env}/..
fi
if [[ "${MACOS_SIGN_RELEASE}" == "true" ]]; then
# create the signed dmg
../../scripts/macos_sign_and_notarize.zsh -p "FreeCAD" -k ${SIGNING_KEY_ID} -o "${version_name}.dmg"
../../scripts/macos_sign_and_notarize.zsh -p "FreeCAD" -k ${MACOS_SIGNING_KEY_ID} -o "${version_name}.dmg"
else
# Ad-hoc sign for local builds (required for QuickLook extensions to register)
if [ -d "FreeCAD.app/Contents/PlugIns" ]; then
echo "Ad-hoc signing App Extensions with entitlements..."
codesign --force --sign - \
--entitlements ../../../src/MacAppBundle/QuickLook/modern/ThumbnailExtension.entitlements \
FreeCAD.app/Contents/PlugIns/FreeCADThumbnailExtension.appex
codesign --force --sign - \
--entitlements ../../../src/MacAppBundle/QuickLook/modern/PreviewExtension.entitlements \
FreeCAD.app/Contents/PlugIns/FreeCADPreviewExtension.appex
fi
echo "Ad-hoc signing app bundle..."
codesign --force --sign - FreeCAD.app/Contents/packages.txt
if [ -f "FreeCAD.app/Contents/Library/QuickLook/QuicklookFCStd.qlgenerator/Contents/MacOS/QuicklookFCStd" ]; then
codesign --force --sign - FreeCAD.app/Contents/Library/QuickLook/QuicklookFCStd.qlgenerator/Contents/MacOS/QuicklookFCStd
fi
codesign --force --sign - FreeCAD.app
# create the dmg
dmgbuild -s dmg_settings.py "FreeCAD" "${version_name}.dmg"
fi
@@ -1,7 +1,12 @@
cmake_minimum_required(VERSION 3.20)
project(freecad-launcher LANGUAGES CXX)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum OS X deployment version" FORCE)
# Use MACOS_DEPLOYMENT_TARGET from environment if set, otherwise keep original default
if(DEFINED ENV{MACOS_DEPLOYMENT_TARGET})
set(CMAKE_OSX_DEPLOYMENT_TARGET "$ENV{MACOS_DEPLOYMENT_TARGET}" CACHE STRING "Minimum OS X deployment version" FORCE)
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum OS X deployment version" FORCE)
endif()
set(CMAKE_CXX_STANDARD 17)
add_executable(FreeCAD FreeCAD.cpp)
File diff suppressed because it is too large Load Diff
+2
View File
@@ -28,10 +28,12 @@ create_bundle = 'bash -c "cd $(bash scripts/get_os.bash) && bash create_bundle.s
## Linux (x86-64)
[feature.package.target.linux-64.dependencies]
coreutils = "*"
xcb-util-cursor = "==0.1.5" ## hack to address https://github.com/FreeCAD/FreeCAD/issues/26726
## Linux (aarch64)
[feature.package.target.linux-aarch64.dependencies]
coreutils = "*"
xcb-util-cursor = "==0.1.5" ## hack to address https://github.com/FreeCAD/FreeCAD/issues/26726
## macOS (Intel)
[feature.package.target.osx-64.dependencies]
+6 -2
View File
@@ -22,7 +22,7 @@ requirements:
- noqt5
- python>=3.11,<3.12
- qt6-main>=6.8,<6.9
- swig
- swig>=4.3,<4.4
- if: linux and x86_64
then:
@@ -52,6 +52,7 @@ requirements:
- pixman-cos7-x86_64
- sed
- sysroot_linux-64
- xcb-util-cursor==0.1.5 ## hack to address https://github.com/FreeCAD/FreeCAD/issues/26726
- xorg-x11-server-common-cos7-x86_64
- xorg-x11-server-xvfb-cos7-x86_64
- xorg-xproto
@@ -84,6 +85,7 @@ requirements:
- pixman-cos7-aarch64
- sed
- sysroot_linux-aarch64
- xcb-util-cursor==0.1.5 ## hack to address https://github.com/FreeCAD/FreeCAD/issues/26726
- xorg-x11-server-common-cos7-aarch64
- xorg-x11-server-xvfb-cos7-aarch64
- xorg-xproto
@@ -98,7 +100,7 @@ requirements:
host:
- coin3d
- eigen
- eigen >=3.3,<5
- fmt
- freetype
- hdf5
@@ -176,3 +178,5 @@ requirements:
- if: linux
then:
- libspnav
- qt6-wayland
- xcb-util-cursor==0.1.5 ## hack to address https://github.com/FreeCAD/FreeCAD/issues/26726
@@ -44,6 +44,9 @@ find ${copy_dir} -name \*arm\*.exe -delete # arm binaries that fail to extract u
mv ${copy_dir}/bin/Lib/ssl.py .ssl-orig.py
cp ssl-patch.py ${copy_dir}/bin/Lib/ssl.py
# Turn off the echo before we start actually calling "echo"
set +x
echo '[Paths]' >> ${copy_dir}/bin/qt6.conf
echo 'Prefix = ../lib/qt6' >> ${copy_dir}/bin/qt6.conf
@@ -67,6 +70,64 @@ sed -i '1s/.*/\nLIST OF PACKAGES:/' ${copy_dir}/packages.txt
mv ${copy_dir} ${version_name}
# Sign the EXE, DLL, and PYD files (if we can access the Azure account for signing):
set -euo pipefail
SIGN_DIR="${version_name}"
if [[ "${WINDOWS_SIGN_RELEASE:-0}" == "1" ]]; then
TENANT="$(az account show --query tenantId -o tsv)"
export AZURE_IDENTITY_DISABLE_WORKLOAD_IDENTITY=true
export AZURE_IDENTITY_DISABLE_MANAGED_IDENTITY=true
unset AZURE_IDENTITY_LOGGING_ENABLED
if az account get-access-token \
--tenant "$TENANT" \
--scope "https://codesigning.azure.net/.default" \
>/dev/null 2>&1;
then
echo "Azure Artifact Signing access confirmed. Beginning signing process..."
shopt -s nullglob
FILES=(
"$SIGN_DIR"/*.exe
"$SIGN_DIR"/bin/*.exe
"$SIGN_DIR"/bin/*.dll
"$SIGN_DIR"/bin/*.pyd
)
count=0
total=${#FILES[@]}
echo "Signing $total files"
for f in "${FILES[@]}"; do
((count+=1))
echo "Signing [$count/$total]: $f"
sign code artifact-signing \
--artifact-signing-endpoint "${WINDOWS_AZURE_ENDPOINT}" \
--artifact-signing-certificate-profile "${WINDOWS_AZURE_CERTIFICATE_PROFILE}" \
--artifact-signing-account "${WINDOWS_AZURE_SIGNING_ACCOUNT}" \
--timestamp-url https://timestamp.acs.microsoft.com \
--timestamp-digest sha256 \
"$f" >/dev/null 2>&1
# Output was redirected to /dev/null because Azure authentication is absurdly noisy, with constant misleading
# "failure" messages about Managed Identity authentication failing. We don't use, or want to use, that
# authentication, and the fact that it fails is not a problem as long as the real authentication succeeds.
done
# Manually check the important one!
signtool verify -pa "$SIGN_DIR/bin/FreeCAD.exe"
echo "Signing completed."
else
echo "Signing requested, but no Azure Artifact Signing available -- skipping signing."
fi
else
echo "Not logged into Azure -- skipping signing."
fi
7z a -t7z -mx9 -mmt=${NUMBER_OF_PROCESSORS} ${version_name}.7z ${version_name} -bb
# create hash
sha256sum ${version_name}.7z > ${version_name}.7z-SHA256.txt
@@ -88,6 +149,28 @@ if [ "${MAKE_INSTALLER}" == "true" ]; then
-X'SetCompressor /FINAL lzma' \
../../WindowsInstaller/FreeCAD-installer.nsi
mv ../../WindowsInstaller/${version_name}-installer.exe .
echo "Created installer ${version_name}-installer.exe"
# See if we can sign the installer exe as well:
if [[ "${WINDOWS_SIGN_RELEASE:-0}" == "1" ]] && \
az account get-access-token \
--tenant "$TENANT" \
--scope "https://codesigning.azure.net/.default" \
>/dev/null 2>&1;
then
echo "Signing the installer..."
sign code artifact-signing \
--artifact-signing-endpoint "${WINDOWS_AZURE_ENDPOINT}" \
--artifact-signing-certificate-profile "${WINDOWS_AZURE_CERTIFICATE_PROFILE}" \
--artifact-signing-account "${WINDOWS_AZURE_SIGNING_ACCOUNT}" \
--timestamp-url https://timestamp.acs.microsoft.com \
--timestamp-digest sha256 \
${version_name}-installer.exe >/dev/null 2>&1 \
|| { echo "Signing the installer failed!"; exit 1; }
else
echo "No code signing available, leaving the installer unsigned"
fi
sha256sum ${version_name}-installer.exe > ${version_name}-installer.exe-SHA256.txt
else
echo "Error: Failed to get NsProcess plugin. Aborting installer creation..."
@@ -96,8 +179,10 @@ if [ "${MAKE_INSTALLER}" == "true" ]; then
fi
if [ "${UPLOAD_RELEASE}" == "true" ]; then
echo "Uploading the release..."
gh release upload --clobber ${BUILD_TAG} "${version_name}.7z" "${version_name}.7z-SHA256.txt"
if [ "${MAKE_INSTALLER}" == "true" ]; then
gh release upload --clobber ${BUILD_TAG} "${version_name}-installer.exe" "${version_name}-installer.exe-SHA256.txt"
fi
echo "Done uploading"
fi
+5 -1
View File
@@ -123,7 +123,11 @@ done
# Two additional files that must be signed that aren't caught by the above searches:
run_codesign "${CONTAINING_FOLDER}/${APP_NAME}/Contents/packages.txt"
run_codesign "${CONTAINING_FOLDER}/${APP_NAME}/Contents/Library/QuickLook/QuicklookFCStd.qlgenerator/Contents/MacOS/QuicklookFCStd"
# Sign legacy QuickLook generator if present (not built for macOS 15.0+)
if [ -f "${CONTAINING_FOLDER}/${APP_NAME}/Contents/Library/QuickLook/QuicklookFCStd.qlgenerator/Contents/MacOS/QuicklookFCStd" ]; then
run_codesign "${CONTAINING_FOLDER}/${APP_NAME}/Contents/Library/QuickLook/QuicklookFCStd.qlgenerator/Contents/MacOS/QuicklookFCStd"
fi
# Sign new Swift QuickLook extensions (macOS 15.0+) with their specific entitlements
# These must be signed before the app itself to avoid overriding the extension signatures
+7363 -6786
View File
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -19,11 +19,12 @@ debugpy = "*"
defusedxml = "*"
docutils = "*"
doxygen = "*"
eigen = "*"
eigen = ">=3.3,<5"
fmt = "*"
freetype = "*"
git = "*"
graphviz = "*"
harfbuzz = "*"
hdf5 = "*"
ifcopenshell = "*"
lark = "*"
@@ -92,9 +93,10 @@ mesa-libgl-cos7-x86_64 = "*"
mesa-libgl-devel-cos7-x86_64 = "*"
mold = "*"
pixman-cos7-x86_64 = "*"
qt6-wayland = "*"
qt6-wayland = ">=6.8,<6.9"
sed = "*"
sysroot_linux-64 = "*"
xcb-util-cursor = "==0.1.5" ## hack to address https://github.com/FreeCAD/FreeCAD/issues/26726
xorg-x11-server-common-cos7-x86_64 = "*"
xorg-x11-server-xvfb-cos7-x86_64 = "*"
xorg-xproto = "*"
@@ -131,9 +133,10 @@ mesa-libgl-devel-cos7-aarch64 = "*"
mesa-libglapi-cos7-aarch64 = "*"
mold = "*"
pixman-cos7-aarch64 = "*"
qt6-wayland = "*"
qt6-wayland = ">=6.8,<6.9"
sed = "*"
sysroot_linux-aarch64 = "*"
xcb-util-cursor = "==0.1.5" ## hack to address https://github.com/FreeCAD/FreeCAD/issues/26726
xorg-x11-server-common-cos7-aarch64 = "*"
xorg-x11-server-xvfb-cos7-aarch64 = "*"
xorg-xproto = "*"
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(FastSignals)
+5 -4
View File
@@ -92,12 +92,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
- name: Checkout Test Data
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
repository: 'asmaloney/libE57Format-test-data'
path: libE57Format-test-data
@@ -105,7 +105,7 @@ jobs:
- name: Install Dependencies (macOS)
if: matrix.platform == 'macos'
run: |
brew install ccache ninja xerces-c
brew install ccache xerces-c
- name: Install Dependencies (Linux)
if: matrix.platform == 'linux'
@@ -118,13 +118,14 @@ jobs:
if: matrix.platform == 'windows'
uses: conda-incubator/setup-miniconda@v3
with:
channels: conda-forge
channels: conda-forge,defaults
- name: Install More Dependencies (Windows)
if: matrix.platform == 'windows'
shell: bash -el {0}
run: |
conda install conda-forge::xerces-c
echo "CMAKE_PREFIX_PATH=${CONDA_PREFIX}/Library" >> "$GITHUB_ENV"
choco upgrade ccache ninja
ccache --version | head -n 1
echo "ninja $(ninja --version)"
+12 -2
View File
@@ -2,7 +2,7 @@
All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 3.3.0 - (in progress)
## [3.3.0](https://github.com/asmaloney/libE57Format/releases/tag/v3.3.0) - 2025-10-24
### Added
@@ -14,10 +14,20 @@ All notable changes to this project will be documented in this file. The format
### Fixed
- {cmake} Added missing include for GNUInstallDirs ([#315](https://github.com/asmaloney/libE57Format/pull/315)) (Thanks Adrian!)
- Fix clang 17 warnings about `@throw` documentation. ([#327](https://github.com/asmaloney/libE57Format/pull/327))
- Fix MSVC C++17 deprecation of `codecvt_utf8_utf16`; replaced with `MultiByteToWideChar` if compiling with C++ &gt;= 17. ([#326](https://github.com/asmaloney/libE57Format/pull/326)) (Thanks Christophe!)
- {ci} Fix some CI warnings and update actions. ([#328](https://github.com/asmaloney/libE57Format/pull/328))
- {ci} Fix GitHub CI for Windows. ([#325](https://github.com/asmaloney/libE57Format/pull/325)) (Thanks Christophe!)
- {cmake} Add missing include for GNUInstallDirs ([#315](https://github.com/asmaloney/libE57Format/pull/315)) (Thanks Adrian!)
If you built without testing on, the cmake files were not installed to the correct location.
- {standard conformance} Don't try to fill in intensity limits when using the simple API. They are for the limits that the sensor can produce, not the limits of the data (8.4.19).
## [3.2.0](https://github.com/asmaloney/libE57Format/releases/tag/v3.2.0) - 2024-06-27
### Added
+6 -6
View File
@@ -36,12 +36,12 @@ set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/"
message( STATUS "Using CMake ${CMAKE_VERSION}" )
project( E57Format
DESCRIPTION
"E57Format is a library to read and write E57 files"
LANGUAGES
CXX
VERSION
3.2.0
DESCRIPTION
"E57Format is a library to read and write E57 files"
LANGUAGES
CXX
VERSION
3.3.0
)
string( TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPERCASE )
+1
View File
@@ -106,6 +106,7 @@ This _Simple API_ has evolved since this original port to fix some problems and
These projects use hard forks of libE57Format:
- [FreeCAD](https://github.com/FreeCAD/FreeCAD)
- [MicMac](https://github.com/micmacIGN/micmac)
- [PDAL](https://github.com/PDAL/PDAL)
There are also many commercial products using libE57Format. If any of them would like to sponsor the project and be listed here, please <a href="mailto:asmaloney@gmail.com?subject=libE57Format Sponsorship">contact Andy</a>.
+2 -2
View File
@@ -634,8 +634,8 @@ namespace e57
@param [in] data3D Completed header which indicates the fields we are using
@throw ::ErrorValueOutOfBounds
@throw ::ErrorInvalidNodeType
@throw ::ErrorValueOutOfBounds (n/c)
@throw ::ErrorInvalidNodeType (n/c)
*/
explicit Data3DPointsData_t( e57::Data3D &data3D );
+19 -19
View File
@@ -126,10 +126,10 @@ is an error to attempt to attach the BlobNode to a different ImageFile.
must be true).
@pre byteCount >= 0
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorInternal All objects in undocumented state
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorInternal All objects in undocumented state (n/c)
@see Node, BlobNode::read, BlobNode::write
*/
@@ -200,7 +200,7 @@ bool BlobNode::isAttached() const
@return The declared size of the blob when it was created.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see BlobNode::read, BlobNode::write
@@ -233,11 +233,11 @@ zero or more times.
@pre 0 <= count
@pre (@a start + @a count) < byteCount()
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorSeekFailed
@throw ::ErrorReadFailed
@throw ::ErrorBadChecksum
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorSeekFailed (n/c)
@throw ::ErrorReadFailed (n/c)
@throw ::ErrorBadChecksum (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see BlobNode::byteCount, BlobNode::write
@@ -276,14 +276,14 @@ destImageFile().isWritable()).
@pre 0 <= count
@pre (@a start + @a count) < byteCount()
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorNodeUnattached
@throw ::ErrorSeekFailed
@throw ::ErrorReadFailed
@throw ::ErrorWriteFailed
@throw ::ErrorBadChecksum
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorNodeUnattached (n/c)
@throw ::ErrorSeekFailed (n/c)
@throw ::ErrorReadFailed (n/c)
@throw ::ErrorWriteFailed (n/c)
@throw ::ErrorBadChecksum (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see BlobNode::byteCount, BlobNode::read
@@ -340,7 +340,7 @@ The handle @a n must be for an underlying BlobNode, otherwise an exception is th
that need to avoid the exception, use Node::type() to determine the actual type of the @a n before
downcasting. This function must be explicitly called (c++ compiler cannot insert it automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), BlobNode::operator Node()
*/
+27 -3
View File
@@ -32,8 +32,13 @@
#if defined( _WIN32 )
#if defined( _MSC_VER )
#include <codecvt>
#include <codecvt> // codecvt_utf8_utf16 is deprecated in C++17, removed in C++226
#include <io.h>
#define NOMINMAX // prevents <windows.h> to #define min and max. Sigh ...
// clang-format off: <windows.h> MUST be included before <stringapiset.h>
#include <windows.h>
#include <stringapiset.h> // Use WIN32 API to replace codecvt_utf8_utf16
// clang-format on
#elif defined( __GNUC__ )
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
@@ -233,12 +238,31 @@ CheckedFile::CheckedFile( const char *input, uint64_t size, ReadChecksumPolicy p
int CheckedFile::open64( const ustring &fileName, int flags, int mode )
{
#if defined( _MSC_VER )
// Ref: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/sopen-s-wsopen-s
// Handle UTF-8 file names - Windows requires conversion to UTF-16
// Handle UTF-8 file names - Windows requires conversion to UTF-16
#if ( ( defined( _MSVC_LANG ) && _MSVC_LANG >= 201703L ) || __cplusplus >= 201703L )
// Ref:
// https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar
std::wstring widePath;
int sizeUtf16 = ::MultiByteToWideChar( CP_UTF8, 0, fileName.c_str(), -1, NULL, 0 );
if ( sizeUtf16 > 0 )
{
widePath.resize( sizeUtf16 + 1 );
sizeUtf16 =
::MultiByteToWideChar( CP_UTF8, 0, fileName.c_str(), -1, &widePath[0], sizeUtf16 );
}
if ( sizeUtf16 <= 0 )
{
throw E57_EXCEPTION2( ErrorOpenFailed,
"Error in converting file name to UTF16. fileName=" + fileName );
}
#else
// Until C++17
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring widePath = converter.from_bytes( fileName );
#endif
// Ref: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/sopen-s-wsopen-s
int handle;
errno_t err = _wsopen_s( &handle, widePath.c_str(), flags, _SH_DENYNO, mode );
if ( err != 0 )
+29 -29
View File
@@ -197,12 +197,12 @@ prototype.isRoot())
@post prototype.isAttached()
@post codecs.isAttached()
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorBadPrototype
@throw ::ErrorBadCodecs
@throw ::ErrorAlreadyHasParent
@throw ::ErrorDifferentDestImageFile
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorBadPrototype (n/c)
@throw ::ErrorBadCodecs (n/c)
@throw ::ErrorAlreadyHasParent (n/c)
@throw ::ErrorDifferentDestImageFile (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see SourceDestBuffer, Node, CompressedVectorNode::reader, CompressedVectorNode::writer
@@ -275,7 +275,7 @@ any writes completed.
@return Current number of records in CompressedVectorNode.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorNode::reader, CompressedVectorNode::writer
@@ -293,7 +293,7 @@ int64_t CompressedVectorNode::childCount() const
@return A smart Node handle referencing the root of the prototype tree.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorNode::CompressedVectorNode, SourceDestBuffer, CompressedVectorNode::reader,
@@ -313,7 +313,7 @@ CompressedVectorNode.
@return A smart VectorNode handle referencing the root of the codecs tree.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorNode::CompressedVectorNode, SourceDestBuffer, CompressedVectorNode::reader,
@@ -372,7 +372,7 @@ designs that need to avoid the exception, use Node::type() to determine the actu
before downcasting. This function must be explicitly called (c++ compiler cannot insert it
automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), CompressedVectorNode::operator, Node()
*/
@@ -422,17 +422,17 @@ CompressedVectorNode cannot be set twice).
@return A smart CompressedVectorWriter handle referencing the underlying iterator object.
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorSetTwice
@throw ::ErrorTooManyWriters
@throw ::ErrorTooManyReaders
@throw ::ErrorNodeUnattached
@throw ::ErrorPathUndefined
@throw ::ErrorBufferSizeMismatch
@throw ::ErrorBufferDuplicatePathName
@throw ::ErrorNoBufferForElement
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorSetTwice (n/c)
@throw ::ErrorTooManyWriters (n/c)
@throw ::ErrorTooManyReaders (n/c)
@throw ::ErrorNodeUnattached (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorBufferSizeMismatch (n/c)
@throw ::ErrorBufferDuplicatePathName (n/c)
@throw ::ErrorNoBufferForElement (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorWriter, SourceDestBuffer, CompressedVectorNode::CompressedVectorNode,
@@ -461,14 +461,14 @@ prototype. It is not an error to create a CompressedVectorReader for an empty Co
@return A smart CompressedVectorReader handle referencing the underlying iterator object.
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorTooManyWriters
@throw ::ErrorNodeUnattached
@throw ::ErrorPathUndefined
@throw ::ErrorBufferSizeMismatch
@throw ::ErrorBufferDuplicatePathName
@throw ::ErrorBadCVHeader
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorTooManyWriters (n/c)
@throw ::ErrorNodeUnattached (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorBufferSizeMismatch (n/c)
@throw ::ErrorBufferDuplicatePathName (n/c)
@throw ::ErrorBadCVHeader (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorReader, SourceDestBuffer, CompressedVectorNode::CompressedVectorNode,
+27 -37
View File
@@ -162,29 +162,19 @@ destroyed.
@return The number of records read.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorReaderNotOpen
@throw ::ErrorConversionRequired This CompressedVectorReader
in undocumented state
@throw ::ErrorValueNotRepresentable This CompressedVectorReader
in undocumented state
@throw ::ErrorScaledValueNotRepresentable This CompressedVectorReader
in undocumented state
@throw ::ErrorReal64TooLarge This CompressedVectorReader
in undocumented state
@throw ::ErrorExpectingNumeric This CompressedVectorReader
in undocumented state
@throw ::ErrorExpectingUString This CompressedVectorReader
in undocumented state
@throw ::ErrorBadCVPacket This CompressedVectorReader, associated
ImageFile in undocumented state
@throw ::ErrorSeekFailed This CompressedVectorReader, associated
ImageFile in undocumented state
@throw ::ErrorReadFailed This CompressedVectorReader, associated
ImageFile in undocumented state
@throw ::ErrorBadChecksum This CompressedVectorReader, associated
ImageFile in undocumented state
@throw ::ErrorInternal All objects in undocumented state
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorReaderNotOpen (n/c)
@throw ::ErrorConversionRequired This CompressedVectorReader in undocumented state
@throw ::ErrorValueNotRepresentable This CompressedVectorReader in undocumented state
@throw ::ErrorScaledValueNotRepresentable This CompressedVectorReader in undocumented state
@throw ::ErrorReal64TooLarge This CompressedVectorReader in undocumented state
@throw ::ErrorExpectingNumeric This CompressedVectorReader in undocumented state
@throw ::ErrorExpectingUString This CompressedVectorReader in undocumented state
@throw ::ErrorBadCVPacket This CompressedVectorReader, associated ImageFile in undocumented state
@throw ::ErrorSeekFailed This CompressedVectorReader, associated ImageFile in undocumented state
@throw ::ErrorReadFailed This CompressedVectorReader, associated ImageFile in undocumented state
@throw ::ErrorBadChecksum This CompressedVectorReader, associated ImageFile in undocumented state
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorReader::read(std::vector<SourceDestBuffer>&),
CompressedVectorNode::reader, SourceDestBuffer,
@@ -230,11 +220,11 @@ detect that a memory buffer been destroyed.
@return The number of records read.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorReaderNotOpen
@throw ::ErrorPathUndefined
@throw ::ErrorBufferSizeMismatch
@throw ::ErrorBufferDuplicatePathName
@throw ::ErrorImageFileNotOpen nc
@throw ::ErrorReaderNotOpen (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorBufferSizeMismatch (n/c)
@throw ::ErrorBufferDuplicatePathName (n/c)
@throw ::ErrorConversionRequired This CompressedVectorReader in undocumented state
@throw ::ErrorValueNotRepresentable This CompressedVectorReader in undocumented state
@throw ::ErrorScaledValueNotRepresentable This CompressedVectorReader in undocumented state
@@ -269,13 +259,13 @@ childCount() (i.e. to one record past end of CompressedVectorNode).
@pre The associated ImageFile must be open.
@pre This CompressedVectorReader must be open (i.e isOpen())
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorReaderNotOpen
@throw ::ErrorBadCVPacket
@throw ::ErrorSeekFailed
@throw ::ErrorReadFailed
@throw ::ErrorBadChecksum
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorReaderNotOpen (n/c)
@throw ::ErrorBadCVPacket (n/c)
@throw ::ErrorSeekFailed (n/c)
@throw ::ErrorReadFailed (n/c)
@throw ::ErrorBadChecksum (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorNode::reader
@@ -308,7 +298,7 @@ void CompressedVectorReader::close()
@pre The associated ImageFile must be open.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorReader::close, CompressedVectorNode::reader
@@ -328,7 +318,7 @@ It is not an error if this CompressedVectorReader is closed.
@return A smart CompressedVectorNode handle referencing the underlying object being read from.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorReader::close, CompressedVectorNode::reader
+17 -17
View File
@@ -152,13 +152,13 @@ all writes to the CompressedVectorNode will be lost (it will have zero children)
@pre The associated ImageFile must be open.
@pre This CompressedVectorWriter must be open (i.e isOpen())
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorWriterNotOpen
@throw ::ErrorPathUndefined
@throw ::ErrorNoBufferForElement
@throw ::ErrorBufferSizeMismatch
@throw ::ErrorBufferDuplicatePathName
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorWriterNotOpen (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorNoBufferForElement (n/c)
@throw ::ErrorBufferSizeMismatch (n/c)
@throw ::ErrorBufferDuplicatePathName (n/c)
@throw ::ErrorConversionRequired This CompressedVectorWriter in undocumented state, associated
CompressedVectorNode modified but consistent, associated ImageFile modified but consistent.
@throw ::ErrorValueOutOfBounds This CompressedVectorWriter in undocumented state, associated
@@ -218,13 +218,13 @@ is invoked, all writes to the CompressedVectorNode will be lost (it will have ze
@pre The associated ImageFile must be open.
@pre This CompressedVectorWriter must be open (i.e isOpen())
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorWriterNotOpen
@throw ::ErrorPathUndefined
@throw ::ErrorNoBufferForElement
@throw ::ErrorBufferSizeMismatch
@throw ::ErrorBufferDuplicatePathName
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorWriterNotOpen (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorNoBufferForElement (n/c)
@throw ::ErrorBufferSizeMismatch (n/c)
@throw ::ErrorBufferDuplicatePathName (n/c)
@throw ::ErrorConversionRequired This CompressedVectorWriter in undocumented state, associated
ImageFile modified but consistent.
@throw ::ErrorValueOutOfBounds This CompressedVectorWriter in undocumented state, associated
@@ -269,7 +269,7 @@ writes to the CompressedVectorNode will be lost (it will have zero children).
@pre The associated ImageFile must be open.
@post This CompressedVectorWriter is closed (i.e !isOpen())
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorSeekFailed This CompressedVectorWriter, associated ImageFile in undocumented state
@throw ::ErrorReadFailed This CompressedVectorWriter, associated ImageFile in undocumented state
@throw ::ErrorWriteFailed This CompressedVectorWriter, associated ImageFile in undocumented state
@@ -288,7 +288,7 @@ void CompressedVectorWriter::close()
@pre The associated ImageFile must be open.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorWriter::close, CompressedVectorNode::writer
@@ -305,7 +305,7 @@ bool CompressedVectorWriter::isOpen()
@return A smart CompressedVectorNode handle referencing the underlying object being written to.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorNode::writer
+9 -9
View File
@@ -141,10 +141,10 @@ if 0 is within bounds, or a @a value = @a minimum if 0 is not within bounds.
be true).
@pre minimum <= value <= maximum
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorValueOutOfBounds
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorValueOutOfBounds (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see FloatPrecision, FloatNode::value, Node, CompressedVectorNode, CompressedVectorNode::prototype
@@ -222,7 +222,7 @@ is ::PrecisionDouble, the double precision value is returned as a double.
@return The IEEE floating point value stored, represented as a double.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see FloatNode::minimum, FloatNode::maximum
@@ -241,7 +241,7 @@ double FloatNode::value() const
@return The declared precision of the floating point number, either ::PrecisionSingle or
::PrecisionDouble.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see FloatPrecision
@@ -263,7 +263,7 @@ precision is ::PrecisionDouble, the double precision minimum is returned as a do
@return The declared minimum that the value may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see FloatNode::maximum, FloatNode::value
@@ -285,7 +285,7 @@ precision is ::PrecisionDouble, the double precision maximum is returned as a do
@return The declared maximum that the value may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see FloatNode::minimum, FloatNode::value
@@ -340,7 +340,7 @@ The handle @a n must be for an underlying FloatNode, otherwise an exception is t
that need to avoid the exception, use Node::type() to determine the actual type of the @a n before
downcasting. This function must be explicitly called (c++ compiler cannot insert it automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), FloatNode::operator Node()
*/
+38 -38
View File
@@ -265,19 +265,19 @@ read-only). There is no API support for appending data onto an existing E57 data
@post Resulting ImageFile is in @c open state if constructor succeeds (no exception thrown).
@throw ::ErrorBadAPIArgument
@throw ::ErrorOpenFailed
@throw ::ErrorSeekFailed
@throw ::ErrorReadFailed
@throw ::ErrorWriteFailed
@throw ::ErrorBadChecksum
@throw ::ErrorBadFileSignature
@throw ::ErrorUnknownFileVersion
@throw ::ErrorBadFileLength
@throw ::ErrorXMLParserInit
@throw ::ErrorXMLParser
@throw ::ErrorBadXMLFormat
@throw ::ErrorBadConfiguration
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorOpenFailed (n/c)
@throw ::ErrorSeekFailed (n/c)
@throw ::ErrorReadFailed (n/c)
@throw ::ErrorWriteFailed (n/c)
@throw ::ErrorBadChecksum (n/c)
@throw ::ErrorBadFileSignature (n/c)
@throw ::ErrorUnknownFileVersion (n/c)
@throw ::ErrorBadFileLength (n/c)
@throw ::ErrorXMLParserInit (n/c)
@throw ::ErrorXMLParser (n/c)
@throw ::ErrorBadXMLFormat (n/c)
@throw ::ErrorBadConfiguration (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see IntegerNode, ScaledIntegerNode, FloatNode, StringNode, BlobNode, StructureNode, VectorNode,
@@ -307,7 +307,7 @@ is empty in a newly created write mode ImageFile.
@return A smart StructureNode handle referencing the underlying object.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see StructureNode.
@@ -339,11 +339,11 @@ It is not an error if ImageFile is already closed.
@post ImageFile is in @c closed state.
@throw ::ErrorSeekFailed
@throw ::ErrorReadFailed
@throw ::ErrorWriteFailed
@throw ::ErrorCloseFailed
@throw ::ErrorBadChecksum
@throw ::ErrorSeekFailed (n/c)
@throw ::ErrorReadFailed (n/c)
@throw ::ErrorWriteFailed (n/c)
@throw ::ErrorCloseFailed (n/c)
@throw ::ErrorBadChecksum (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::cancel, ImageFile::isOpen
@@ -432,7 +432,7 @@ CompressedVectorWriter objects are created by the CompressedVectorNode::writer f
@return The current number of open CompressedVectorWriter objects writing to ImageFile.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorNode::writer, CompressedVectorWriter
@@ -454,7 +454,7 @@ CompressedVectorReader objects are created by the CompressedVectorNode::reader f
@return The current number of open CompressedVectorReader objects reading from ImageFile.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see CompressedVectorNode::reader, CompressedVectorReader
@@ -496,11 +496,11 @@ See the class discussion at bottom of ImageFile page for more details about name
@pre prefix != ""
@pre uri != ""
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorDuplicateNamespacePrefix
@throw ::ErrorDuplicateNamespaceURI
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorDuplicateNamespacePrefix (n/c)
@throw ::ErrorDuplicateNamespaceURI (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::extensionsCount, ImageFile::extensionsLookupPrefix, ImageFile::extensionsLookupUri
@@ -524,8 +524,8 @@ an error if @a prefix contains an illegal character combination for E57 namespac
@return true if prefix is declared in the ImageFile.
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::extensionsLookupUri
@@ -554,8 +554,8 @@ namespace prefixes. It is not an error if @a prefix is well-formed, but not defi
@return true if prefix is declared in the ImageFile.
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@@ -584,8 +584,8 @@ function just returns false).
@return true if URI is declared in the ImageFile.
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::extensionsLookupPrefix
@@ -606,7 +606,7 @@ The default E57 namespace does not count as an extension.
@return The number of E57 extensions defined in the ImageFile.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::extensionsPrefix, ImageFile::extensionsUri
@@ -632,8 +632,8 @@ counted as an extension.
@return The E57 extension prefix at the given index.
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::extensionsCount, ImageFile::extensionsUri
@@ -659,8 +659,8 @@ as an extension.
@return The E57 extension URI at the given index.
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::extensionsCount, ImageFile::extensionsPrefix
@@ -704,7 +704,7 @@ prefixed form, the prefix does not have to be declared in the ImageFile.
@post No visible state is modified.
@throw ::ErrorBadPathName
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::isElementNameExtended
+8 -8
View File
@@ -134,10 +134,10 @@ ignored). If the IntegerNode is to be used in a prototype, it is recommended to
be true).
@pre minimum <= value <= maximum
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorValueOutOfBounds
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorValueOutOfBounds (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see IntegerNode::value, Node, CompressedVectorNode, CompressedVectorNode::prototype
@@ -211,7 +211,7 @@ bool IntegerNode::isAttached() const
@return integer value stored.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see IntegerNode::minimum, IntegerNode::maximum
@@ -229,7 +229,7 @@ int64_t IntegerNode::value() const
@return The declared minimum that the value may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see IntegerNode::value
@@ -247,7 +247,7 @@ int64_t IntegerNode::minimum() const
@return The declared maximum that the value may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see IntegerNode::value
@@ -303,7 +303,7 @@ The handle @a n must be for an underlying IntegerNode, otherwise an exception is
that need to avoid the exception, use Node::type() to determine the actual type of the @a n before
downcasting. This function must be explicitly called (c++ compiler cannot insert it automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), IntegerNode::operator Node()
*/
+5 -5
View File
@@ -372,7 +372,7 @@ relationship (see Node::isAttached and CompressedVectorNode::CompressedVectorNod
@return true if this node is a root node.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see Node::parent, Node::isAttached, CompressedVectorNode::CompressedVectorNode
@@ -407,7 +407,7 @@ infinite recursion.
@return A smart Node handle referencing the parent node or this node if is a root node.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see Node::isRoot, Node::isAttached, CompressedVectorNode::CompressedVectorNode, Node::elementName
@@ -441,7 +441,7 @@ root node has the empty string ("") as its elementName.
@return The absolute path name of the node.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see Node::elementName, Node::parent, Node::isRoot
@@ -473,7 +473,7 @@ by the position of the child.
@return The element name of the node, or "" if a root node.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see Node::pathName, Node::parent, Node::isRoot
@@ -524,7 +524,7 @@ eventually attached to the ImageFile.
@return @c true if node is child of (or in codecs or prototype of a child CompressedVectorNode of)
the root node of an ImageFile.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see Node::destImageFile, ImageFile::root
+17 -17
View File
@@ -139,10 +139,10 @@ be true).
@pre minimum <= rawValue <= maximum
@pre scale != 0
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorValueOutOfBounds
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorValueOutOfBounds (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::rawValue, Node, CompressedVectorNode, CompressedVectorNode::prototype
@@ -201,10 +201,10 @@ be true).
@pre scaledMinimum <= scaledValue <= scaledMaximum
@pre scale != 0
@throw ::ErrorBadAPIArgument
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorValueOutOfBounds
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorValueOutOfBounds (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::scaledValue, Node, CompressedVectorNode, CompressedVectorNode::prototype
@@ -280,7 +280,7 @@ bool ScaledIntegerNode::isAttached() const
@return The raw unscaled integer value stored.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::scaledValue, ScaledIntegerNode::minimum, ScaledIntegerNode::maximum
@@ -298,7 +298,7 @@ int64_t ScaledIntegerNode::rawValue() const
@return The scaled value (rawValue*scale + offset) calculated from the rawValue stored.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::rawValue
@@ -316,7 +316,7 @@ double ScaledIntegerNode::scaledValue() const
@return The declared minimum that the rawValue may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::maximum, ScaledIntegerNode::rawValue
@@ -334,7 +334,7 @@ int64_t ScaledIntegerNode::minimum() const
@return The declared minimum that the rawValue may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::scaledMaximum, ScaledIntegerNode::scaledValue
@@ -352,7 +352,7 @@ double ScaledIntegerNode::scaledMinimum() const
@return The declared maximum that the rawValue may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::minimum, ScaledIntegerNode::rawValue
@@ -370,7 +370,7 @@ int64_t ScaledIntegerNode::maximum() const
@return The declared maximum that the rawValue may take.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::scaledMinimum, ScaledIntegerNode::scaledValue
@@ -388,7 +388,7 @@ double ScaledIntegerNode::scaledMaximum() const // Added by SC
@return The scaling factor used to compute scaledValue from rawValue.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::scaledValue
@@ -406,7 +406,7 @@ double ScaledIntegerNode::scale() const
@return The offset used to compute scaledValue from rawValue.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ScaledIntegerNode::scaledValue
@@ -463,7 +463,7 @@ designs that need to avoid the exception, use Node::type() to determine the actu
before downcasting. This function must be explicitly called (c++ compiler cannot insert it
automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), ScaledIntegerNode::operator, Node()
*/
+9 -9
View File
@@ -149,10 +149,10 @@ transfer with a CompressedVectorNode.
@pre The @a destImageFile must be open (i.e. destImageFile.isOpen() must be true).
@pre The stride must be >= sizeof(*b)
@throw ::ErrorBadAPIArgument
@throw ::ErrorBadPathName
@throw ::ErrorBadBuffer
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorBadBuffer (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::reader, ImageFile::writer,
@@ -287,10 +287,10 @@ destroyed).
@pre b.size() must be > 0.
@pre The @a destImageFile must be open (i.e. destImageFile.isOpen() must be true).
@throw ::ErrorBadAPIArgument
@throw ::ErrorBadPathName
@throw ::ErrorBadBuffer
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadAPIArgument (n/c)
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorBadBuffer (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see SourceDestBuffer::doConversion for discussion on representations compatible with string
@@ -397,7 +397,7 @@ CompressedVectorReader or CompressedVectorWriter is created).
@return true if conversions will be performed to match the memory type of buffer.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
*/
bool SourceDestBuffer::doConversion() const
+4 -4
View File
@@ -103,8 +103,8 @@ If the StringNode is to be used in a CompressedVectorNode prototype, it is recom
@pre The @a destImageFile must have been opened in write mode (i.e. destImageFile.isWritable() must
be true).
@throw ::ErrorImageFileNotOpen
@throw ::ErrorFileReadOnly
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see StringNode::value, Node, CompressedVectorNode, CompressedVectorNode::prototype
@@ -177,7 +177,7 @@ bool StringNode::isAttached() const
@return The Unicode character string value stored.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
*/
ustring StringNode::value() const
@@ -232,7 +232,7 @@ The handle @a n must be for an underlying StringNode, otherwise an exception is
that need to avoid the exception, use Node::type() to determine the actual type of the @a n before
downcasting. This function must be explicitly called (c++ compiler cannot insert it automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), StringNode::operator Node()
*/
+18 -18
View File
@@ -127,7 +127,7 @@ to attach the StructureNode to a different ImageFile.
@pre The @a destImageFile must have been opened in write mode (i.e. destImageFile.isWritable() must
be true).
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see Node
@@ -199,7 +199,7 @@ bool StructureNode::isAttached() const
@return Number of child nodes contained by this StructureNode.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see StructureNode::get(int64_t) const,
@@ -225,8 +225,8 @@ is not attached to an ImageFile, the @a pathName origin root will not the root n
@return true if pathName is currently defined.
@throw ::ErrorBadPathName
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ImageFile::root, VectorNode::isDefined
@@ -251,8 +251,8 @@ the StructureNode. The order of children may change if more children are added t
@return A smart Node handle referencing the child node.
@throw ::ErrorChildIndexOutOfBounds
@throw ::ErrorImageFileNotOpen
@throw ::ErrorChildIndexOutOfBounds (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see StructureNode::childCount,
@@ -278,9 +278,9 @@ an ImageFile.
@return A smart Node handle referencing the child node.
@throw ::ErrorBadPathName
@throw ::ErrorPathUndefined
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see StructureNode::get(int64_t) const
@@ -321,14 +321,14 @@ destImageFile().isWritable()).
destImageFile() == n.destImageFile()).
@post The @a pathName will be defined (i.e. isDefined(pathName)).
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadPathName
@throw ::ErrorPathUndefined
@throw ::ErrorSetTwice
@throw ::ErrorAlreadyHasParent
@throw ::ErrorDifferentDestImageFile
@throw ::ErrorHomogeneousViolation
@throw ::ErrorFileReadOnly
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorSetTwice (n/c)
@throw ::ErrorAlreadyHasParent (n/c)
@throw ::ErrorDifferentDestImageFile (n/c)
@throw ::ErrorHomogeneousViolation (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see VectorNode::append
@@ -386,7 +386,7 @@ designs that need to avoid the exception, use Node::type() to determine the actu
before downcasting. This function must be explicitly called (c++ compiler cannot insert it
automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), StructureNode::operator Node()
*/
+16 -16
View File
@@ -146,7 +146,7 @@ unconstrained.
@pre The @a destImageFile must have been opened in write mode (i.e. destImageFile.isWritable() must
be true).
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see Node, VectorNode::allowHeteroChildren, ::ErrorHomogeneousViolation
@@ -223,7 +223,7 @@ changed.
@return True if child elements can be different types.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see ::ErrorHomogeneousViolation
@@ -241,7 +241,7 @@ bool VectorNode::allowHeteroChildren() const
@return Number of child elements in this VectorNode.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see VectorNode::get(int64_t), VectorNode::append, StructureNode::childCount
@@ -268,8 +268,8 @@ The element names of child elements of VectorNodes are numbers, encoded as strin
@return true if pathName is currently defined.
@throw ::ErrorBadPathName
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see StructureNode::isDefined
@@ -290,8 +290,8 @@ bool VectorNode::isDefined( const ustring &pathName ) const
@return A smart Node handle referencing the child node.
@throw ::ErrorChildIndexOutOfBounds
@throw ::ErrorImageFileNotOpen
@throw ::ErrorChildIndexOutOfBounds (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see VectorNode::childCount, VectorNode::append, StructureNode::get(int64_t) const
@@ -319,9 +319,9 @@ The element names of child elements of VectorNodes are numbers, encoded as strin
@return A smart Node handle referencing the child node.
@throw ::ErrorBadPathName
@throw ::ErrorPathUndefined
@throw ::ErrorImageFileNotOpen
@throw ::ErrorBadPathName (n/c)
@throw ::ErrorPathUndefined (n/c)
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see VectorNode::childCount, VectorNode::append, StructureNode::get(int64_t) const
@@ -352,11 +352,11 @@ The VectorNode must not be a descendent of a homogeneous VectorNode with more th
destImageFile().isWritable()).
@post the childCount is incremented.
@throw ::ErrorImageFileNotOpen
@throw ::ErrorHomogeneousViolation
@throw ::ErrorFileReadOnly
@throw ::ErrorAlreadyHasParent
@throw ::ErrorDifferentDestImageFile
@throw ::ErrorImageFileNotOpen (n/c)
@throw ::ErrorHomogeneousViolation (n/c)
@throw ::ErrorFileReadOnly (n/c)
@throw ::ErrorAlreadyHasParent (n/c)
@throw ::ErrorDifferentDestImageFile (n/c)
@throw ::ErrorInternal All objects in undocumented state
@see VectorNode::childCount, VectorNode::get(int64_t), StructureNode::set
@@ -413,7 +413,7 @@ The handle @a n must be for an underlying VectorNode, otherwise an exception is
that need to avoid the exception, use Node::type() to determine the actual type of the @a n before
downcasting. This function must be explicitly called (c++ compiler cannot insert it automatically).
@throw ::ErrorBadNodeDowncast
@throw ::ErrorBadNodeDowncast (n/c)
@see Node::type(), VectorNode::operator Node()
*/
@@ -126,7 +126,11 @@ namespace netgen {
#endif
//extern void OCCSetLocalMeshSize(OCCGeometry & geom, Mesh & mesh);
DLL_HEADER extern MeshingParameters mparam;
DLL_HEADER extern volatile multithreadt multithread;
#if NETGEN_VERSION >= NETGEN_VERSION_STRING(6,2,2601)
using ngcore::multithread;
#else
DLL_HEADER extern volatile multithreadt multithread;
#endif
DLL_HEADER extern bool merge_solids;
}
@@ -112,7 +112,11 @@ namespace netgen {
DLL_HEADER extern int OCCGenerateMesh (OCCGeometry&, Mesh*&, int, int, char*);
#endif
DLL_HEADER extern MeshingParameters mparam;
DLL_HEADER extern volatile multithreadt multithread;
#if NETGEN_VERSION >= NETGEN_VERSION_STRING(6,2,2601)
using ngcore::multithread;
#else
DLL_HEADER extern volatile multithreadt multithread;
#endif
}
using namespace nglib;
using namespace std;
+1 -5
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_ANNOTATION_H
#define APP_ANNOTATION_H
#pragma once
#include "DocumentObject.h"
#include "PropertyGeo.h"
@@ -74,6 +73,3 @@ public:
};
} // namespace App
#endif // APP_ANNOTATION_H
+262 -261
View File
@@ -34,14 +34,18 @@
# define WINVER 0x502 // needed for SetDllDirectory
# include <Windows.h>
# endif
# include <boost/algorithm/string.hpp>
# include <boost/program_options.hpp>
# include <boost/date_time/posix_time/posix_time.hpp>
# include <boost/scope_exit.hpp>
# include <chrono>
# include <optional>
# include <random>
# include <memory>
# include <utility>
# include <set>
# include <string>
# include <list>
# include <algorithm>
# include <iostream>
@@ -92,6 +96,7 @@
#include <Base/ProgressIndicatorPy.h>
#include <Base/RotationPy.h>
#include <Base/UniqueNameManager.h>
#include <Base/SystemHandler.h>
#include <Base/Tools.h>
#include <Base/Translate.h>
#include <Base/Type.h>
@@ -104,6 +109,7 @@
#include "Application.h"
#include "ApplicationDirectories.h"
#include "ApplicationDirectoriesPy.h"
#include "ApplicationPy.h"
#include "CleanupProcess.h"
#include "ComplexGeoData.h"
#include "Services.h"
@@ -159,18 +165,38 @@
#include "SafeMode.h"
#ifdef _MSC_VER // New handler for Microsoft Visual C++ compiler
# pragma warning( disable : 4535 )
# if !defined(_DEBUG) && defined(HAVE_SEH)
# define FC_SE_TRANSLATOR
# endif
# include <new.h>
# include <eh.h> // VC exception handling
#else // Ansi C/C++ new handler
# include <new>
#ifdef FC_OS_WIN32
#include <windows.h>
#endif
std::optional<std::string> getenvUTF8(const char* name) {
#ifdef FC_OS_WIN32
int wideLength = MultiByteToWideChar(CP_UTF8, 0, name, -1, nullptr, 0);
std::wstring wideName(wideLength ? wideLength - 1 : 0, L'\0');
if (wideLength) {
MultiByteToWideChar(CP_UTF8, 0, name, -1, wideName.data(), wideLength);
}
DWORD needed = GetEnvironmentVariableW(wideName.c_str(), nullptr, 0);
if (needed == 0) {
return std::nullopt;
}
std::wstring wideValue(needed, L'\0');
DWORD written = GetEnvironmentVariableW(wideName.c_str(), wideValue.data(), needed);
if (written == 0) {
return std::nullopt;
}
wideValue.resize(written);
return Base::Tools::wstringToString(wideValue);
#else
if (const char* v = std::getenv(name)) {
return std::string(v);
}
return std::nullopt;
#endif
}
FC_LOG_LEVEL_INIT("App", true, true)
using namespace App;
@@ -275,7 +301,7 @@ void Application::setupPythonTypes()
Base::PyGILStateLocker lock;
PyObject* modules = PyImport_GetModuleDict();
ApplicationMethods = Application::Methods;
ApplicationMethods = ApplicationPy::Methods;
PyObject* pAppModule = PyImport_ImportModule ("FreeCAD");
if (!pAppModule) {
PyErr_Clear();
@@ -425,14 +451,6 @@ void Application::setupPythonException(PyObject* module)
//**************************************************************************
// Interface
/// get called by the document when the name is changing
void Application::renameDocument(const char *OldName, const char *NewName)
{
(void)OldName;
(void)NewName;
throw Base::RuntimeError("Renaming document internal name is no longer allowed!");
}
Document* Application::newDocument(const char * proposedName, const char * proposedLabel, DocumentInitFlags CreateFlags)
{
bool isUsingDefaultName = Base::Tools::isNullOrEmpty(proposedName);
@@ -518,6 +536,11 @@ Document* Application::newDocument(const char * proposedName, const char * propo
return doc;
}
bool Application::closeDocument(const Document* doc)
{
return closeDocument(doc->getName());
}
bool Application::closeDocument(const char* name)
{
const auto pos = DocMap.find( name );
@@ -564,6 +587,15 @@ Document* Application::getDocument(const char *Name) const
return pos->second;
}
Document* Application::getDocumentOrActive(const char *Name) const
{
if (!Base::Tools::isNullOrEmpty(Name)) {
return getDocument(Name);
}
else {
return getActiveDocument();
}
}
const char * Application::getDocumentName(const Document* doc) const
{
@@ -932,7 +964,7 @@ Document* Application::openDocumentPrivate(const char * FileName,
if (!File.exists()) {
std::stringstream str;
str << "File '" << FileName << "' does not exist!";
throw Base::FileSystemError(str.str().c_str());
throw Base::FileSystemError(str.str());
}
// Before creating a new document we check whether the document is already open
@@ -963,7 +995,7 @@ Document* Application::openDocumentPrivate(const char * FileName,
// add it to _pendingDocsReopen to delay reloading.
for(auto obj2 : doc->getObjects())
objNames.emplace_back(obj2->getNameInDocument());
_pendingDocMap[doc->FileName.getValue()] = std::move(objNames);
_pendingDocMap[doc->FileName.getValue()] = objNames;
break;
}
}
@@ -1308,11 +1340,11 @@ Base::Reference<ParameterGrp> Application::GetParameterGroupByPath(const char*
return It->second->GetGroup(cName.c_str());
}
void Application::addImportType(const char* Type, const char* ModuleName)
void Application::addImportType(const char* filter, const char* moduleName)
{
FileTypeItem item;
item.filter = Type;
item.module = ModuleName;
item.filter = filter;
item.module = moduleName;
// Extract each filetype from 'Type' literal
std::string::size_type pos = item.filter.find("*.");
@@ -1325,8 +1357,8 @@ void Application::addImportType(const char* Type, const char* ModuleName)
}
// Due to branding stuff replace "FreeCAD" with the branded application name
if (strncmp(Type, "FreeCAD", 7) == 0) {
std::string AppName = Config()["ExeName"];
if (strncmp(filter, "FreeCAD", 7) == 0) {
std::string AppName = getExecutableName();
AppName += item.filter.substr(7);
item.filter = std::move(AppName);
// put to the front of the array
@@ -1337,28 +1369,25 @@ void Application::addImportType(const char* Type, const char* ModuleName)
}
}
void Application::changeImportModule(const char* Type, const char* OldModuleName, const char* NewModuleName)
void Application::changeImportModule(const char* filter, const char* oldModuleName, const char* newModuleName)
{
for (auto& it : _mImportTypes) {
if (it.filter == Type && it.module == OldModuleName) {
it.module = NewModuleName;
if (it.filter == filter && it.module == oldModuleName) {
it.module = newModuleName;
break;
}
}
}
std::vector<std::string> Application::getImportModules(const char* Type) const
std::vector<std::string> Application::getImportModules(const std::string& extension) const
{
std::vector<std::string> modules;
for (const auto & it : _mImportTypes) {
const std::vector<std::string>& types = it.types;
for (const auto & jt : types) {
#ifdef __GNUC__
if (strcasecmp(Type,jt.c_str()) == 0)
#else
if (_stricmp(Type,jt.c_str()) == 0)
#endif
if (boost::iequals(extension, jt)) {
modules.push_back(it.module);
}
}
}
@@ -1377,16 +1406,13 @@ std::vector<std::string> Application::getImportModules() const
return modules;
}
std::vector<std::string> Application::getImportTypes(const char* Module) const
std::vector<std::string> Application::getImportTypes(const std::string& Module) const
{
std::vector<std::string> types;
for (const auto & it : _mImportTypes) {
#ifdef __GNUC__
if (strcasecmp(Module,it.module.c_str()) == 0)
#else
if (_stricmp(Module,it.module.c_str()) == 0)
#endif
if (boost::iequals(Module, it.module)) {
types.insert(types.end(), it.types.begin(), it.types.end());
}
}
return types;
@@ -1405,18 +1431,15 @@ std::vector<std::string> Application::getImportTypes() const
return types;
}
std::map<std::string, std::string> Application::getImportFilters(const char* Type) const
std::map<std::string, std::string> Application::getImportFilters(const std::string& extension) const
{
std::map<std::string, std::string> moduleFilter;
for (const auto & it : _mImportTypes) {
const std::vector<std::string>& types = it.types;
for (const auto & jt : types) {
#ifdef __GNUC__
if (strcasecmp(Type,jt.c_str()) == 0)
#else
if (_stricmp(Type,jt.c_str()) == 0)
#endif
if (boost::iequals(extension, jt)) {
moduleFilter[it.filter] = it.module;
}
}
}
@@ -1433,11 +1456,11 @@ std::map<std::string, std::string> Application::getImportFilters() const
return filter;
}
void Application::addExportType(const char* Type, const char* ModuleName)
void Application::addExportType(const char* filter, const char* moduleName)
{
FileTypeItem item;
item.filter = Type;
item.module = ModuleName;
item.filter = filter;
item.module = moduleName;
// Extract each filetype from 'Type' literal
std::string::size_type pos = item.filter.find("*.");
@@ -1450,8 +1473,8 @@ void Application::addExportType(const char* Type, const char* ModuleName)
}
// Due to branding stuff replace "FreeCAD" with the branded application name
if (strncmp(Type, "FreeCAD", 7) == 0) {
std::string AppName = Config()["ExeName"];
if (strncmp(filter, "FreeCAD", 7) == 0) {
std::string AppName = getExecutableName();
AppName += item.filter.substr(7);
item.filter = std::move(AppName);
// put to the front of the array
@@ -1462,28 +1485,112 @@ void Application::addExportType(const char* Type, const char* ModuleName)
}
}
void Application::changeExportModule(const char* Type, const char* OldModuleName, const char* NewModuleName)
namespace {
// To enable changing languages while the program is running, cache the translatable export type
// entries so that their addition can be "replayed" when the language changes (after removing
// the originals).
struct TranslatableTypeCacheEntry {
std::string description;
const std::vector<std::string> extensions;
std::string moduleName;
};
class TranslatableTypeCache {
public:
TranslatableTypeCache() = default;
void addCacheEntry(TranslatableTypeCacheEntry entry) {
_cache.push_back(std::move(entry));
}
std::vector<TranslatableTypeCacheEntry> getCache() const {
return _cache;
}
void clear()
{
_cache.clear();
}
private:
std::vector<TranslatableTypeCacheEntry> _cache;
};
TranslatableTypeCache translatableExportTypeCache;
// Given a description string and a list of extensions, construct a type string that Qt's file
// dialogs will recognize
void appendTypeString(std::string &description, const std::vector<std::string> &extensions) {
description = fmt::format("{} (*.{})", description, fmt::join(extensions, " *."));
}
}
void Application::addTranslatableExportType(const std::string &description,
const std::vector<std::string> &extensions,
const std::string &moduleName)
{
assert(!extensions.empty()); // Programming error, there must be extensions
// Branding: replace "FreeCAD" in a file type description with the branded application name
auto replaceFreeCAD =
[](std::string& s)
{
constexpr std::string_view freecad = "FreeCAD";
if (auto pos = s.find(freecad); pos != std::string::npos) {
s.replace(pos, freecad.size(), getExecutableName());
return true; // Contained the app name
}
return false; // Did NOT contain the app name
};
translatableExportTypeCache.addCacheEntry({description, extensions, moduleName});
auto translatedDescription = QCoreApplication::translate("FileFormat", description.c_str()).toStdString();
bool containsAppName = replaceFreeCAD(translatedDescription); // Run *AFTER* translation
appendTypeString(translatedDescription, extensions);
FileTypeItem item;
item.filter = translatedDescription;
item.module = moduleName;
item.types = extensions;
item.translatable = true;
if (containsAppName) {
// put to the front of the array
_mExportTypes.insert(_mExportTypes.begin(),std::move(item));
}
else {
_mExportTypes.push_back(std::move(item));
}
}
void Application::retranslateExportTypes()
{
auto cache = translatableExportTypeCache.getCache();
translatableExportTypeCache.clear();
std::erase_if(_mExportTypes, [](const FileTypeItem& item) {
return item.translatable;
});
for (const auto &cacheEntry : translatableExportTypeCache.getCache()) {
addTranslatableExportType(cacheEntry.description, cacheEntry.extensions, cacheEntry.moduleName);
}
}
void Application::changeExportModule(const char* filter, const char* oldModuleName, const char* newModuleName)
{
for (auto& it : _mExportTypes) {
if (it.filter == Type && it.module == OldModuleName) {
it.module = NewModuleName;
if (it.filter == filter && it.module == oldModuleName) {
it.module = newModuleName;
break;
}
}
}
std::vector<std::string> Application::getExportModules(const char* Type) const
std::vector<std::string> Application::getExportModules(const std::string& extension) const
{
std::vector<std::string> modules;
for (const auto & it : _mExportTypes) {
const std::vector<std::string>& types = it.types;
for (const auto & jt : types) {
#ifdef __GNUC__
if (strcasecmp(Type,jt.c_str()) == 0)
#else
if (_stricmp(Type,jt.c_str()) == 0)
#endif
if (boost::iequals(extension, jt)) {
modules.push_back(it.module);
}
}
}
@@ -1502,16 +1609,13 @@ std::vector<std::string> Application::getExportModules() const
return modules;
}
std::vector<std::string> Application::getExportTypes(const char* Module) const
std::vector<std::string> Application::getExportTypes(const std::string& Module) const
{
std::vector<std::string> types;
for (const auto & it : _mExportTypes) {
#ifdef __GNUC__
if (strcasecmp(Module,it.module.c_str()) == 0)
#else
if (_stricmp(Module,it.module.c_str()) == 0)
#endif
if (boost::iequals(Module, it.module)) {
types.insert(types.end(), it.types.begin(), it.types.end());
}
}
return types;
@@ -1530,18 +1634,15 @@ std::vector<std::string> Application::getExportTypes() const
return types;
}
std::map<std::string, std::string> Application::getExportFilters(const char* Type) const
std::map<std::string, std::string> Application::getExportFilters(const std::string& extension) const
{
std::map<std::string, std::string> moduleFilter;
for (const auto & it : _mExportTypes) {
const std::vector<std::string>& types = it.types;
for (const auto & jt : types) {
#ifdef __GNUC__
if (strcasecmp(Type,jt.c_str()) == 0)
#else
if (_stricmp(Type,jt.c_str()) == 0)
#endif
if (boost::iequals(extension, jt)) {
moduleFilter[it.filter] = it.module;
}
}
}
@@ -1758,175 +1859,59 @@ void Application::destructObserver()
}
}
/** freecadNewHandler()
* prints an error message and throws an exception
*/
#ifdef _MSC_VER // New handler for Microsoft Visual C++ compiler
int __cdecl freecadNewHandler(size_t size )
namespace
{
// throw an exception
throw Base::MemoryException();
return 0;
}
#else // Ansi C/C++ new handler
static void freecadNewHandler ()
void initExceptions()
{
// throw an exception
throw Base::MemoryException();
// register exception producer types
// NOLINTBEGIN
new Base::ExceptionProducer<Base::AbortException>;
new Base::ExceptionProducer<Base::XMLBaseException>;
new Base::ExceptionProducer<Base::XMLParseException>;
new Base::ExceptionProducer<Base::XMLAttributeError>;
new Base::ExceptionProducer<Base::FileException>;
new Base::ExceptionProducer<Base::FileSystemError>;
new Base::ExceptionProducer<Base::BadFormatError>;
new Base::ExceptionProducer<Base::MemoryException>;
new Base::ExceptionProducer<Base::AccessViolation>;
new Base::ExceptionProducer<Base::AbnormalProgramTermination>;
new Base::ExceptionProducer<Base::UnknownProgramOption>;
new Base::ExceptionProducer<Base::ProgramInformation>;
new Base::ExceptionProducer<Base::TypeError>;
new Base::ExceptionProducer<Base::ValueError>;
new Base::ExceptionProducer<Base::IndexError>;
new Base::ExceptionProducer<Base::NameError>;
new Base::ExceptionProducer<Base::ImportError>;
new Base::ExceptionProducer<Base::AttributeError>;
new Base::ExceptionProducer<Base::RuntimeError>;
new Base::ExceptionProducer<Base::BadGraphError>;
new Base::ExceptionProducer<Base::NotImplementedError>;
new Base::ExceptionProducer<Base::ZeroDivisionError>;
new Base::ExceptionProducer<Base::ReferenceError>;
new Base::ExceptionProducer<Base::ExpressionError>;
new Base::ExceptionProducer<Base::ParserError>;
new Base::ExceptionProducer<Base::UnicodeError>;
new Base::ExceptionProducer<Base::OverflowError>;
new Base::ExceptionProducer<Base::UnderflowError>;
new Base::ExceptionProducer<Base::UnitsMismatchError>;
new Base::ExceptionProducer<Base::CADKernelError>;
new Base::ExceptionProducer<Base::RestoreError>;
new Base::ExceptionProducer<Base::PropertyError>;
// NOLINTEND
}
#endif
#if defined(FC_OS_LINUX)
#include <execinfo.h>
#include <dlfcn.h>
#include <cxxabi.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>
#if HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H
// This function produces a stack backtrace with demangled function & method names.
void printBacktrace(size_t skip=0)
{
#if defined HAVE_BACKTRACE_SYMBOLS
void *callstack[128];
size_t nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
size_t nFrames = backtrace(callstack, nMaxFrames);
char **symbols = backtrace_symbols(callstack, nFrames);
for (size_t i = skip; i < nFrames; i++) {
char *demangled = nullptr;
int status = -1;
Dl_info info;
if (dladdr(callstack[i], &info) && info.dli_sname && info.dli_fname) {
if (info.dli_sname[0] == '_') {
demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
}
}
std::stringstream str;
if (status == 0) {
void* offset = (void*)((char*)callstack[i] - (char*)info.dli_saddr);
str << "#" << (i-skip) << " " << callstack[i] << " in " << demangled << " from " << info.dli_fname << "+" << offset << '\n';
free(demangled);
}
else {
str << "#" << (i-skip) << " " << symbols[i] << '\n';
}
// cannot directly print to cerr when using --write-log
std::cerr << str.str();
}
free(symbols);
#else //HAVE_BACKTRACE_SYMBOLS
(void)skip;
std::cerr << "Cannot print the stacktrace because the C runtime library doesn't provide backtrace or backtrace_symbols\n";
#endif
}
#endif
void segmentation_fault_handler(int sig)
{
#if defined(FC_OS_LINUX)
(void)sig;
std::cerr << "Program received signal SIGSEGV, Segmentation fault.\n";
printBacktrace(2);
#if defined(FC_DEBUG)
abort();
#else
_exit(1);
#endif
#else
switch (sig) {
case SIGSEGV:
std::cerr << "Illegal storage access..." << '\n';
#if !defined(_DEBUG)
throw Base::AccessViolation("Illegal storage access! Please save your work under a new file name and restart the application!");
#endif
break;
case SIGABRT:
std::cerr << "Abnormal program termination..." << '\n';
#if !defined(_DEBUG)
throw Base::AbnormalProgramTermination("Break signal occurred");
#endif
break;
default:
std::cerr << "Unknown error occurred..." << '\n';
break;
}
#endif // FC_OS_LINUX
}
void unhandled_exception_handler()
{
std::cerr << "Terminating..." << '\n';
}
void unexpection_error_handler()
{
std::cerr << "Unexpected error occurred..." << '\n';
// try to throw an exception and give the user chance to save their work
#if !defined(_DEBUG)
throw Base::AbnormalProgramTermination("Unexpected error occurred! Please save your work under a new file name and restart the application!");
#else
terminate();
#endif
}
#if defined(FC_SE_TRANSLATOR) // Microsoft compiler
void my_se_translator_filter(unsigned int code, EXCEPTION_POINTERS* pExp)
{
Q_UNUSED(pExp)
switch (code)
{
case EXCEPTION_ACCESS_VIOLATION:
throw Base::AccessViolation();
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
Base::Console().error("SEH exception (%u): Division by zero\n", code);
return;
}
std::stringstream str;
str << "SEH exception of type: " << code;
// general C++ SEH exception for things we don't need to handle separately....
throw Base::RuntimeError(str.str());
}
#endif
void Application::init(int argc, char ** argv)
{
try {
// install our own new handler
#ifdef _MSC_VER // Microsoft compiler
_set_new_handler ( freecadNewHandler ); // Setup new handler
_set_new_mode( 1 ); // Re-route malloc failures to new handler !
#else // Ansi compiler
std::set_new_handler (freecadNewHandler); // ANSI new handler
#endif
// if an unexpected crash occurs we can install a handler function to
// write some additional information
#if defined (_MSC_VER) // Microsoft compiler
std::signal(SIGSEGV,segmentation_fault_handler);
std::signal(SIGABRT,segmentation_fault_handler);
std::set_terminate(unhandled_exception_handler);
::set_unexpected(unexpection_error_handler);
#elif defined(FC_OS_LINUX)
std::signal(SIGSEGV,segmentation_fault_handler);
#endif
#if defined(FC_SE_TRANSLATOR)
_set_se_translator(my_se_translator_filter);
#endif
Base::SystemHandler::installNewHandler();
Base::SystemHandler::installSegfaultHandler();
initTypes();
initConfig(argc,argv);
initApplication();
initExceptions();
}
catch (...) {
// force the log to flush
@@ -2166,6 +2151,7 @@ void Application::initTypes()
(DocumentObject::getClassTypeId());
// register exception producer types
// NOLINTBEGIN
new Base::ExceptionProducer<Base::AbortException>;
new Base::ExceptionProducer<Base::XMLBaseException>;
new Base::ExceptionProducer<Base::XMLParseException>;
@@ -2198,6 +2184,7 @@ void Application::initTypes()
new Base::ExceptionProducer<Base::CADKernelError>;
new Base::ExceptionProducer<Base::RestoreError>;
new Base::ExceptionProducer<Base::PropertyError>;
// NOLINTEND
Base::registerServiceImplementation<CenterOfMassProvider>(new NullCenterOfMass);
}
@@ -2514,7 +2501,9 @@ void processProgramOptions(const boost::program_options::variables_map& vm, std:
void Application::initConfig(int argc, char ** argv)
{
// find the home path....
mConfig["AppHomePath"] = ApplicationDirectories::findHomePath(argv[0]).string();
mConfig["AppHomePath"] = Base::FileInfo::pathToString(
ApplicationDirectories::findHomePath(argv[0])
);
// Version of the application extracted from SubWCRef into src/Build/Version.h
// We only set these keys if not yet defined. Therefore it suffices to search
@@ -2600,7 +2589,7 @@ void Application::initConfig(int argc, char ** argv)
auto moduleName = "FreeCAD";
PyImport_AddModule(moduleName);
ApplicationMethods = Application::Methods;
ApplicationMethods = ApplicationPy::Methods;
PyObject *pyModule = init_freecad_module();
PyDict_SetItemString(sysModules, moduleName, pyModule);
Py_DECREF(pyModule);
@@ -2761,9 +2750,9 @@ void Application::initConfig(int argc, char ** argv)
void Application::SaveEnv(const char* s)
{
const char *c = getenv(s);
if (c)
mConfig[s] = c;
if (auto c = getenvUTF8(s)) {
mConfig[s] = c.value();
}
}
void Application::initApplication()
@@ -2828,7 +2817,18 @@ std::list<std::string> Application::processFiles(const std::list<std::string>& f
std::list<std::string> processed;
Base::Console().log("Init: Processing command line files\n");
for (const auto & it : files) {
Base::FileInfo file(it);
// Can we safely remove the isSymlink check and directly query the canonical
// path for every string? The reason for avoiding it currently is that
// getCannonicalPath will log an error if the file doesn't exist
if (file.isSymlink()) {
if (auto cannonicalPath = file.getCannonicalPath()) {
file = Base::FileInfo(*cannonicalPath);
} else {
Base::Console().error("Failed to process symlink file: %s\n", file.filePath());
}
}
Base::Console().log("Init: Processing file: %s\n",file.filePath().c_str());
@@ -2855,8 +2855,7 @@ std::list<std::string> Application::processFiles(const std::list<std::string>& f
}
}
else {
std::string ext = file.extension();
std::vector<std::string> mods = GetApplication().getImportModules(ext.c_str());
std::vector<std::string> mods = GetApplication().getImportModules(file.extension());
if (!mods.empty()) {
std::string escapedstr = Base::Tools::escapedUnicodeFromUtf8(file.filePath().c_str());
escapedstr = Base::Tools::escapeEncodeFilename(escapedstr);
@@ -2889,7 +2888,6 @@ std::list<std::string> Application::processFiles(const std::list<std::string>& f
void Application::processCmdLineFiles()
{
// process files passed to command line
const std::list<std::string> files = getCmdLineFiles();
const std::list<std::string> processed = processFiles(files);
@@ -2914,9 +2912,8 @@ void Application::processCmdLineFiles()
output = Base::Tools::escapeEncodeFilename(output);
const Base::FileInfo fi(output);
const std::string ext = fi.extension();
try {
const std::vector<std::string> mods = GetApplication().getExportModules(ext.c_str());
const std::vector<std::string> mods = GetApplication().getExportModules(fi.extension());
if (!mods.empty()) {
Base::Interpreter().loadModule(mods.front().c_str());
Base::Interpreter().runStringArg("import %s",mods.front().c_str());
@@ -3432,9 +3429,9 @@ std::string Application::FindHomePath(const char* sCall)
}
// should be an absolute path now
std::string::size_type pos = absPath.find_last_of("/");
std::string::size_type pos = absPath.find_last_of('/');
homePath.assign(absPath,0,pos);
pos = homePath.find_last_of("/");
pos = homePath.find_last_of('/');
homePath.assign(homePath,0,pos+1);
return homePath;
@@ -3584,14 +3581,18 @@ void Application::addModuleInfo(QTextStream& str, const QString& modPath, bool&
firstMod = false;
str << "Installed mods: \n";
}
str << " * " << (mod.isDir() ? QDir(modPath).dirName() : mod.fileName());
QString addonName = mod.isDir() ? QDir(modPath).dirName() : mod.fileName();
QString versionString;
try {
auto metadataFile =
std::filesystem::path(mod.absoluteFilePath().toStdString()) / "package.xml";
if (std::filesystem::exists(metadataFile)) {
App::Metadata metadata(metadataFile);
if (!metadata.name().empty()) {
addonName = QString::fromStdString(metadata.name());
}
if (metadata.version() != App::Meta::Version()) {
str << QLatin1String(" ") + QString::fromStdString(metadata.version().str());
versionString = QString::fromStdString(" " + metadata.version().str());
}
}
}
@@ -3600,6 +3601,7 @@ void Application::addModuleInfo(QTextStream& str, const QString& modPath, bool&
QChar::fromLatin1(' '));
str << " (Malformed metadata: " << what << ")";
}
str << " * " << addonName << versionString;
QFileInfo disablingFile(mod.absoluteFilePath(), QStringLiteral("ADDON_DISABLED"));
if (disablingFile.exists()) {
str << " (Disabled)";
@@ -3622,7 +3624,7 @@ void Application::getVerboseCommonInfo(QTextStream& str, const std::map<std::str
const QString deskSess =
QProcessEnvironment::systemEnvironment().value(QStringLiteral("DESKTOP_SESSION"),
QString());
const QString major = getValueOrEmpty(mConfig, "BuildVersionMajor");
const QString minor = getValueOrEmpty(mConfig, "BuildVersionMinor");
const QString point = getValueOrEmpty(mConfig, "BuildVersionPoint");
@@ -3711,24 +3713,23 @@ void Application::getVerboseCommonInfo(QTextStream& str, const std::map<std::str
#endif
str << "xerces-c " << fcXercescVersion << ", ";
const char* cmd = "import ifcopenshell\n"
"version = ifcopenshell.version";
PyObject * ifcopenshellVer = nullptr;
try {
ifcopenshellVer = Base::Interpreter().getValue(cmd, "version");
}
catch (const Base::Exception& e) {
Base::Console().log("%s (safe to ignore, unless using the BIM workbench and IFC).\n", e.what());
}
if (ifcopenshellVer) {
const char* ifcopenshellVerAsStr = PyUnicode_AsUTF8(ifcopenshellVer);
if (ifcopenshellVerAsStr) {
str << "IfcOpenShell " << ifcopenshellVerAsStr << ", ";
Base::PyGILStateLocker lock;
Py::Module module(PyImport_ImportModule("ifcopenshell"), true);
if (!module.isNull() && module.hasAttr("version")) {
Py::String version(module.getAttr("version"));
auto ver_str = static_cast<std::string>(version);
str << "IfcOpenShell " << ver_str.c_str() << ", ";
}
Py_DECREF(ifcopenshellVer);
else {
Base::Console().log("Module 'ifcopenshell' not found (safe to ignore, unless using "
"the BIM workbench and IFC).\n");
}
}
catch (const Py::Exception&) {
Base::PyGILStateLocker lock;
Base::PyException e;
Base::Console().log("%s\n", e.what());
}
#if defined(HAVE_OCC_VERSION)
+758 -367
View File
File diff suppressed because it is too large Load Diff
+13 -6
View File
@@ -80,12 +80,16 @@ const fs::path& ApplicationDirectories::getTempPath() const {
return this->_temp;
}
fs::path ApplicationDirectories::getTempFileName(const std::string & filename) const {
fs::path ApplicationDirectories::getTempFileName(const std::string & filename) const
{
auto tempPath = Base::FileInfo::pathToString(getTempPath());
if (filename.empty()) {
return Base::FileInfo::getTempFileName(nullptr, tempPath.c_str());
return Base::FileInfo::stringToPath(Base::FileInfo::getTempFileName(nullptr, tempPath.c_str())
);
}
return Base::FileInfo::getTempFileName(filename.c_str(), tempPath.c_str());
return Base::FileInfo::stringToPath(
Base::FileInfo::getTempFileName(filename.c_str(), tempPath.c_str())
);
}
const fs::path& ApplicationDirectories::getUserCachePath() const
@@ -138,7 +142,10 @@ fs::path ApplicationDirectories::findPath(const fs::path& stdHome, const fs::pat
// If a custom user home path is given, then don't modify it
if (customHome.empty()) {
for (const auto& it : subdirs) {
appData = appData / it;
if (!it.empty()) {
// Refuse to add an empty directory path component
appData = appData / it;
}
}
}
@@ -179,7 +186,7 @@ void ApplicationDirectories::configurePaths(std::map<std::string,std::string>& m
bool keepDeprecatedPaths = mConfig.contains("KeepDeprecatedPaths");
// std paths
_home = fs::path(mConfig.at("AppHomePath"));
_home = Base::FileInfo::stringToPath(mConfig.at("AppHomePath"));
mConfig["BinPath"] = mConfig.at("AppHomePath") + "bin" + PATHSEP;
mConfig["DocPath"] = mConfig.at("AppHomePath") + "doc" + PATHSEP;
@@ -295,7 +302,7 @@ void ApplicationDirectories::configureResourceDirectory(const std::map<std::stri
_resource = Base::FileInfo::stringToPath(mConfig.at("AppHomePath")) / path;
}
#else
_resource = fs::path(mConfig.at("AppHomePath"));
_resource = Base::FileInfo::stringToPath(mConfig.at("AppHomePath"));
#endif
}
+1 -4
View File
@@ -20,8 +20,7 @@
* *
**************************************************************************************************/
#ifndef SRC_APP_APPLICATIONDIRECTORIES_H_
#define SRC_APP_APPLICATIONDIRECTORIES_H_
#pragma once
#include "FCConfig.h"
#include "FCGlobal.h"
@@ -257,5 +256,3 @@ namespace App {
};
} // App
#endif //SRC_APP_APPLICATIONDIRECTORIES_H_
+272 -197
View File
File diff suppressed because it is too large Load Diff
+92
View File
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#pragma once
#include <Base/PyObjectBase.h>
namespace App
{
/** The ApplicationPy class
* This is the Python wrapper class of Application.
* @author Jürgen Riegel, Werner Mayer
*/
class AppExport ApplicationPy
{
public:
// clang-format off
// static python wrapper of the exported functions
static PyObject* sGetParam (PyObject *self, PyObject *args);
static PyObject* sSaveParameter (PyObject *self, PyObject *args);
static PyObject* sGetVersion (PyObject *self, PyObject *args);
static PyObject* sGetConfig (PyObject *self, PyObject *args);
static PyObject* sSetConfig (PyObject *self, PyObject *args);
static PyObject* sDumpConfig (PyObject *self, PyObject *args);
static PyObject* sAddImportType (PyObject *self, PyObject *args);
static PyObject* sChangeImportModule (PyObject *self, PyObject *args);
static PyObject* sGetImportType (PyObject *self, PyObject *args);
static PyObject* sAddExportType (PyObject *self, PyObject *args);
static PyObject* sAddTranslatableExportType (PyObject *self, PyObject *args);
static PyObject* sChangeExportModule (PyObject *self, PyObject *args);
static PyObject* sGetExportType (PyObject *self, PyObject *args);
static PyObject* sGetResourcePath (PyObject *self, PyObject *args);
static PyObject* sGetLibraryPath (PyObject *self, PyObject *args);
static PyObject* sGetTempPath (PyObject *self, PyObject *args);
static PyObject* sGetUserCachePath (PyObject *self, PyObject *args);
static PyObject* sGetUserConfigPath (PyObject *self, PyObject *args);
static PyObject* sGetUserAppDataPath (PyObject *self, PyObject *args);
static PyObject* sGetUserMacroPath (PyObject *self, PyObject *args);
static PyObject* sGetHelpPath (PyObject *self, PyObject *args);
static PyObject* sGetHomePath (PyObject *self, PyObject *args);
static PyObject* sLoadFile (PyObject *self,PyObject *args);
static PyObject* sOpenDocument (PyObject *self,PyObject *args, PyObject *kwd);
static PyObject* sSaveDocument (PyObject *self,PyObject *args);
static PyObject* sNewDocument (PyObject *self,PyObject *args, PyObject *kwd);
static PyObject* sCloseDocument (PyObject *self,PyObject *args);
static PyObject* sActiveDocument (PyObject *self,PyObject *args);
static PyObject* sSetActiveDocument (PyObject *self,PyObject *args);
static PyObject* sGetDocument (PyObject *self,PyObject *args);
static PyObject* sListDocuments (PyObject *self,PyObject *args);
static PyObject* sAddDocObserver (PyObject *self,PyObject *args);
static PyObject* sRemoveDocObserver (PyObject *self,PyObject *args);
static PyObject *sIsRestoring (PyObject *self,PyObject *args);
static PyObject *sSetLogLevel (PyObject *self,PyObject *args);
static PyObject *sGetLogLevel (PyObject *self,PyObject *args);
static PyObject *sCheckLinkDepth (PyObject *self,PyObject *args);
static PyObject *sGetLinksTo (PyObject *self,PyObject *args);
static PyObject *sGetDependentObjects (PyObject *self,PyObject *args);
static PyObject *sSetActiveTransaction (PyObject *self,PyObject *args);
static PyObject *sGetActiveTransaction (PyObject *self,PyObject *args);
static PyObject *sCloseActiveTransaction (PyObject *self,PyObject *args);
static PyObject *sCheckAbort (PyObject *self,PyObject *args);
static PyMethodDef Methods[];
// clang-format on
};
}
+167 -167
View File
@@ -35,204 +35,217 @@ FC_LOG_LEVEL_INIT("App", true, true)
using namespace App;
static int _TransactionLock;
static int _TransactionClosed;
AutoTransaction::AutoTransaction(const char* name, bool tmpName)
AutoTransaction::AutoTransaction(int tid)
: tid(tid)
{
auto& app = GetApplication();
if (name && app._activeTransactionGuard >= 0) {
if (!app.getActiveTransaction() || (!tmpName && app._activeTransactionTmpName)) {
FC_LOG("auto transaction '" << name << "', " << tmpName);
tid = app.setActiveTransaction(name);
app._activeTransactionTmpName = tmpName;
}
}
// We use negative transaction guard to disable auto transaction from here
// and any stack below. This is to support user setting active transaction
// before having any existing AutoTransaction on stack, or 'persist'
// transaction that can out live AutoTransaction.
if (app._activeTransactionGuard < 0) {
--app._activeTransactionGuard;
}
else if (tid || app._activeTransactionGuard > 0) {
++app._activeTransactionGuard;
}
else if (app.getActiveTransaction()) {
FC_LOG("auto transaction disabled because of '" << app._activeTransactionName << "'");
--app._activeTransactionGuard;
}
else {
++app._activeTransactionGuard;
}
FC_TRACE("construct auto Transaction " << app._activeTransactionGuard);
}
AutoTransaction::AutoTransaction(Document* doc, const std::string& name)
: AutoTransaction(doc->openTransaction(name))
{
}
AutoTransaction::~AutoTransaction()
{
auto& app = GetApplication();
FC_TRACE("before destruct auto Transaction " << app._activeTransactionGuard);
if (app._activeTransactionGuard < 0) {
++app._activeTransactionGuard;
}
else if (!app._activeTransactionGuard) {
#ifdef FC_DEBUG
FC_ERR("Transaction guard error");
#endif
}
else if (--app._activeTransactionGuard == 0) {
try {
// We don't call close() here, because close() only closes
// transaction that we opened during construction time. However,
// when _activeTransactionGuard reaches zero here, we are supposed
// to close any transaction opened.
app.closeActiveTransaction();
}
catch (Base::Exception& e) {
e.reportException();
}
catch (...) {
}
}
FC_TRACE("destruct auto Transaction " << app._activeTransactionGuard);
close(TransactionCloseMode::Commit);
}
void AutoTransaction::close(bool abort)
void AutoTransaction::close(TransactionCloseMode mode)
{
if (tid || abort) {
GetApplication().closeActiveTransaction(abort, abort ? 0 : tid);
if (tid != NullTransaction) {
GetApplication().closeActiveTransaction(mode, tid);
tid = 0;
}
}
void AutoTransaction::setEnable(bool enable)
int Application::setActiveTransaction(TransactionName name)
{
auto& app = GetApplication();
if (!app._activeTransactionGuard) {
return;
if (name.name.empty()) {
name.name = "Command";
}
if ((enable && app._activeTransactionGuard > 0)
|| (!enable && app._activeTransactionGuard < 0)) {
return;
}
app._activeTransactionGuard = -app._activeTransactionGuard;
FC_TRACE("toggle auto Transaction " << app._activeTransactionGuard);
if (!enable && app._activeTransactionTmpName) {
bool close = true;
for (auto& v : app.DocMap) {
if (v.second->hasPendingTransaction()) {
close = false;
break;
}
}
if (close) {
app.closeActiveTransaction();
}
if (_pActiveDoc != nullptr) {
return _pActiveDoc->setActiveTransaction(name);
}
return openGlobalTransaction(name);
}
int Application::setActiveTransaction(const char* name, bool persist)
std::string Application::getActiveTransaction(int* id) const
{
if (id != nullptr) {
*id = _globalTransactionID;
}
return _globalTransactionID != 0 ? getTransactionName(_globalTransactionID) : "";
}
int Application::openGlobalTransaction(TransactionName name)
{
if (name.name.empty()) {
name.name = "Command";
}
if (!name || !name[0]) {
name = "Command";
}
this->signalBeforeOpenTransaction(name);
if (_activeTransactionGuard > 0 && getActiveTransaction()) {
if (_activeTransactionTmpName) {
FC_LOG("transaction rename to '" << name << "'");
for (auto& v : DocMap) {
v.second->renameTransaction(name, _activeTransactionID);
FC_WARN("Setting a global transaction with name='" << name.name);
if (_globalTransactionID != 0 && transactionTmpName(_globalTransactionID)) {
setTransactionName(_globalTransactionID, name);
} else {
FC_LOG("set global transaction '" << name.name << "'");
if (_globalTransactionID != 0 && !commitTransaction(_globalTransactionID)) {
FC_WARN("could not close current global transaction");
return _globalTransactionID;
}
_globalTransactionID = Transaction::getNewID();
setTransactionDescription(
_globalTransactionID,
TransactionDescription {
.initiator = nullptr,
.name = name
}
}
else {
if (persist) {
AutoTransaction::setEnable(false);
}
return 0;
}
);
}
else if (_TransactionLock) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Transaction locked, ignore new transaction '" << name << "'");
}
return 0;
return _globalTransactionID;
}
int Application::getGlobalTransaction() const
{
return _globalTransactionID;
}
bool Application::transactionIsActive(int tid) const
{
return transactionDescription(tid) != std::nullopt;
}
std::string Application::getTransactionName(int tid) const
{
auto desc = transactionDescription(tid);
return desc ? desc->name.name : "";
}
bool Application::transactionTmpName(int tid) const
{
auto desc = transactionDescription(tid);
return desc ? desc->name.temporary : false;
}
Document* Application::transactionInitiator(int tid) const
{
auto desc = transactionDescription(tid);
return desc ? desc->initiator : nullptr;
}
std::optional<TransactionDescription> Application::transactionDescription(int tid) const
{
if (tid == NullTransaction) {
return std::nullopt;
}
else {
FC_LOG("set active transaction '" << name << "'");
_activeTransactionID = 0;
auto found = _activeTransactionDescriptions.find(tid);
if (found != _activeTransactionDescriptions.end()) {
return std::optional<TransactionDescription>(found->second);
}
return std::nullopt;
}
void Application::setTransactionDescription(int tid, const TransactionDescription& desc)
{
if (tid == NullTransaction) {
return;
}
auto found = _activeTransactionDescriptions.find(tid);
bool wasPresent = (found != _activeTransactionDescriptions.end());
if (wasPresent && found->second.name.temporary) {
for (auto& v : DocMap) {
v.second->_commitTransaction();
v.second->renameTransaction(desc.name.name, tid);
}
_activeTransactionID = Transaction::getNewID();
}
_activeTransactionTmpName = false;
_activeTransactionName = name;
if (persist) {
AutoTransaction::setEnable(false);
if (!wasPresent || found->second.name.temporary) {
_activeTransactionDescriptions[tid] = desc;
FC_LOG("transaction rename to '" << desc.name.name << "'");
}
return _activeTransactionID;
}
void Application::setTransactionName(int tid, const TransactionName& name)
{
if (tid == NullTransaction || !transactionIsActive(tid)) {
return;
}
auto found = _activeTransactionDescriptions.find(tid);
if (found == _activeTransactionDescriptions.end() || found->second.name.temporary) {
_activeTransactionDescriptions[tid].name = name;
FC_LOG("transaction rename to '" << name.name << "'");
for (auto& v : DocMap) {
v.second->renameTransaction(name.name, tid);
}
}
}
const char* Application::getActiveTransaction(int* id) const
bool Application::closeActiveTransaction(TransactionCloseMode mode, int id)
{
int tid = 0;
if (Transaction::getLastID() == _activeTransactionID) {
tid = _activeTransactionID;
}
if (id) {
*id = tid;
}
return tid ? _activeTransactionName.c_str() : nullptr;
}
void Application::closeActiveTransaction(bool abort, int id)
{
if (!id) {
id = _activeTransactionID;
}
if (!id) {
return;
}
if (_activeTransactionGuard > 0 && !abort) {
FC_LOG("ignore close transaction");
return;
}
if (_TransactionLock) {
if (_TransactionClosed >= 0) {
_TransactionLock = abort ? -1 : 1;
bool abort = (mode == TransactionCloseMode::Abort);
if (id == NullTransaction) {
if (_pActiveDoc != nullptr && _pActiveDoc->getBookedTransactionID() != NullTransaction) {
id = _pActiveDoc->getBookedTransactionID();
} else {
id = _globalTransactionID;
}
FC_LOG("pending " << (abort ? "abort" : "close") << " transaction");
return;
}
if (id == NullTransaction || id == currentlyClosingID) {
return false;
}
currentlyClosingID = id;
FC_LOG("close transaction '" << _activeTransactionName << "' " << abort);
_activeTransactionID = 0;
TransactionSignaller signaller(abort, false);
for (auto& v : DocMap) {
if (v.second->getTransactionID(true) != id) {
std::vector<Document*> docsToPoke;
for (auto& docNameAndDoc : DocMap) {
if (docNameAndDoc.second->getBookedTransactionID() != id) {
continue;
}
if(docNameAndDoc.second->isTransactionLocked() || docNameAndDoc.second->transacting()) {
FC_LOG("pending " << (abort ? "abort" : "close") << " transaction");
currentlyClosingID = 0;
return false;
}
if(docNameAndDoc.second->transacting()) {
FC_LOG("pending " << (abort ? "abort" : "close") << " transaction");
currentlyClosingID = 0;
return false;
}
docsToPoke.push_back(docNameAndDoc.second);
}
FC_LOG("close transaction '" << _activeTransactionDescriptions[id].name.name << "' " << abort);
_activeTransactionDescriptions.erase(id);
if (id == _globalTransactionID) {
_globalTransactionID = 0;
}
TransactionSignaller signaller(abort, false);
for (auto& doc : docsToPoke) {
if (abort) {
v.second->_abortTransaction();
doc->_abortTransaction();
}
else {
v.second->_commitTransaction();
doc->_commitTransaction();
}
}
currentlyClosingID = 0;
return true;
}
bool Application::commitTransaction(int tid)
{
return closeActiveTransaction(TransactionCloseMode::Commit, tid);
}
bool Application::abortTransaction(int tid)
{
return closeActiveTransaction(TransactionCloseMode::Abort, tid);
}
////////////////////////////////////////////////////////////////////////
TransactionLocker::TransactionLocker(bool lock)
TransactionLocker::TransactionLocker(Document* doc, bool lock)
: active(lock)
, doc(doc)
{
if (lock) {
++_TransactionLock;
doc->lockTransaction();
}
}
@@ -267,22 +280,9 @@ void TransactionLocker::activate(bool enable)
active = enable;
if (active) {
++_TransactionLock;
doc->lockTransaction();
return;
}
if (--_TransactionLock != 0) {
return;
}
if (_TransactionClosed) {
bool abort = (_TransactionClosed < 0);
_TransactionClosed = 0;
GetApplication().closeActiveTransaction(abort);
}
}
bool TransactionLocker::isLocked()
{
return _TransactionLock > 0;
doc->unlockTransaction();
}
+24 -53
View File
@@ -22,16 +22,19 @@
* *
****************************************************************************/
#ifndef APP_AUTOTRANSACTION_H
#define APP_AUTOTRANSACTION_H
#pragma once
#include <cstddef>
#include <FCGlobal.h>
#include <string>
#include "TransactionDefs.h"
namespace App
{
class Application;
class Document;
/**
* @brief A helper class to manage transactions (i.e. undo/redo).
@@ -46,59 +49,31 @@ public:
void* operator new(std::size_t) = delete;
public:
/**
* @brief Construct an auto transaction.
*
* @param[in] name: optional new transaction name on construction
* @param[in] tmpName: if true and a new transaction is setup, the name given is
* considered as temporary, and subsequent construction of this class (or
* calling Application::setActiveTransaction()) can override the transaction
* name.
*
* The constructor increments an internal counter
* (Application::_activeTransactionGuard). The counter prevents any new
* active transactions being setup. It also prevents to close
* (i.e. commits) the current active transaction until it reaches zero. It
* does not have any effect on aborting transactions though.
/** Constructor
*
* @param tid the ID of the transaction to manage
*
* No action is done in the constructor
*/
AutoTransaction(const char* name = nullptr, bool tmpName = false);
/**
* @brief Destruct an auto transaction.
*
* This destructor decrease an internal counter
* (Application::_activeTransactionGuard), and will commit any current
* active transaction when the counter reaches zero.
explicit AutoTransaction(int tid);
AutoTransaction(Document* doc, const std::string& name);
/** Destructor
*
* This destructor attempts to commit the transaction it manages
*/
~AutoTransaction();
/**
* @brief Close or abort the transaction.
*
* This function can be used to explicitly close (i.e. commit) the
* transaction, if the current transaction ID matches the one created inside
* the constructor. For aborting, it will abort any current transaction.
*
* @param[in] abort: if true, abort the transaction; otherwise, commit it.
* This function can be used to explicitly close (i.e. commit / abort) the
* transaction,
*/
void close(bool abort = false);
/**
* @brief Enable/Disable any AutoTransaction instance on the current stack.
*
* Once disabled, any empty temporary named transaction is closed. If there
* are non-empty or non-temporary named active transaction, it will not be
* auto closed.
*
* This function may be used in, for example, Gui::Document::setEdit() to
* allow a transaction live past any command scope.
*
* @param[in] enable: if true, enable the AutoTransaction; otherwise, disable it.
*/
static void setEnable(bool enable);
void close(TransactionCloseMode mode = TransactionCloseMode::Commit);
private:
int tid = 0;
int tid { 0 };
};
@@ -117,7 +92,7 @@ public:
*
* @param[in] lock: whether to activate the lock
*/
TransactionLocker(bool lock = true);
TransactionLocker(Document* doc, bool lock = true);
/**
* @brief Destruct a transaction locker.
@@ -143,10 +118,7 @@ public:
{
return active;
}
/// Check if transaction is being locked.
static bool isLocked();
friend class Application;
public:
@@ -155,8 +127,7 @@ public:
private:
bool active;
Document* doc;
};
} // namespace App
#endif // APP_AUTOTRANSACTION_H
} // namespace App
+1 -4
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_BRANDING_H
#define APP_BRANDING_H
#pragma once
#include <string>
#include <QDomDocument>
@@ -54,5 +53,3 @@ private:
};
} // namespace App
#endif // APP_BRANDING_H
+2 -5
View File
@@ -21,8 +21,7 @@
* *
**************************************************************************/
#ifndef APP_CLEANUPPROCESS_H
#define APP_CLEANUPPROCESS_H
#pragma once
#include <functional>
#include <FCGlobal.h>
@@ -52,6 +51,4 @@ public:
static void callCleanup();
};
} // namespace App
#endif // APP_CLEANUPPROCESS_H
} // namespace App
+2 -5
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_COLORMODEL_H
#define APP_COLORMODEL_H
#pragma once
#include "Material.h"
#include <Base/Bitmask.h>
@@ -702,6 +701,4 @@ inline const ColorModel& ColorGradient::getColorModel() const
return currentModelPack.totalModel;
}
} // namespace App
#endif // APP_COLORMODEL_H
} // namespace App
+1
View File
@@ -41,6 +41,7 @@
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/algorithm/string/predicate.hpp>
using namespace Data;
+385 -157
View File
@@ -25,8 +25,7 @@
***************************************************************************/
#ifndef APP_COMPLEX_GEO_DATA_H
#define APP_COMPLEX_GEO_DATA_H
#pragma once
#include <algorithm>
#include <optional>
@@ -57,18 +56,21 @@ namespace Data
{
// struct MappedChildElements;
/// Option for App::GeoFeature::searchElementCache()
enum class SearchOption
{
/// Whether to compare shape geometry
CheckGeometry = 1,
SingleResult = 2,
CheckGeometry = 1, ///< Whether to compare shape geometry
SingleResult = 2, ///< Stop at first found result
};
typedef Base::Flags<SearchOption> SearchOptions;
/** Segments
* Sub-element type of the ComplexGeoData type
* It is used to split an object in further sub-parts.
/**
* @brief A class for segments.
*
* A segment is a sub-element type of the ComplexGeoData type. It is used to
* split an object in further sub-parts.
*/
class AppExport Segment: public Base::BaseClass
{
@@ -76,200 +78,356 @@ class AppExport Segment: public Base::BaseClass
public:
~Segment() override = default;
/// Get the name of the segment.
virtual std::string getName() const = 0;
};
enum ElementMapResetPolicy
{
AllowNoMap,
ForceEmptyMap
};
/** ComplexGeoData Object
/**
* @brief A class for complex geometric data.
* @ingroup ElementMapping
*/
class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled
{
TYPESYSTEM_HEADER_WITH_OVERRIDE(); // NOLINT
public:
/**
* @brief A line as a facet boundary in a 3D mesh.
*
* The line is represented by two point indices.
*/
struct Line
{
uint32_t I1;
uint32_t I2;
};
/**
* @brief A triangular facet in a 3D mesh.
*
* The facet is represented by three point indices.
*/
struct Facet
{
uint32_t I1;
uint32_t I2;
uint32_t I3;
};
/**
* @brief A domain in a 3D mesh.
*
* A domain consists of a list of points and a list of facets where the
* indices of a facet index into the points list.
*/
struct Domain
{
std::vector<Base::Vector3d> points;
std::vector<Facet> facets;
};
/// Constructor
ComplexGeoData();
/// Destructor
~ComplexGeoData() override = default;
/** @name Sub-element management */
//@{
/** Sub type list
* List of different sub-element types
* its NOT a list of the sub-elements itself
/**
* @name Sub-element management
* @{
*/
/**
* @brief Get a list of sub-element types.
*
* This list does not contain the sub-elements themselves.
*/
virtual std::vector<const char*> getElementTypes() const = 0;
/**
* @brief Get the number of sub-elements of a given type.
*
* @param[in] Type The type of sub-element.
* @return The number of sub-elements of the given type.
*/
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.
/**
* @brief Get the type and index from a combined name.
*
* An example is "Edge12", which would return the type "Edge" and the
* index 12.
*
* @param[in] Name The combined name of the sub-element.
* @returns A pair of a generic element type and index.
*
* @note The determined element type isn't necessarily supported by this
* geometry.
*/
static std::pair<std::string, unsigned long> getTypeAndIndex(const char* Name);
/// get the sub-element by type and number
/// Get the sub-element by type and number.
virtual Segment* getSubElement(const char* Type, unsigned long) const = 0;
/// get sub-element by combined name
/// Get sub-element by combined name
virtual Segment* getSubElementByName(const char* Name) const;
/** Get lines from segment */
virtual void getLinesFromSubElement(const Segment*,
/**
* @brief Get the lines from a segment.
*
* @param[in] segment The segment to get the lines from.
*
* @param[in,out] Points The list of points used by the lines.
* @param[in,out] lines The list of lines retrieved from the segment.
*/
virtual void getLinesFromSubElement(const Segment* segment,
std::vector<Base::Vector3d>& Points,
std::vector<Line>& lines) const;
/** Get faces from segment */
virtual void getFacesFromSubElement(const Segment*,
/**
* @brief Get the faces from a segment.
*
* @param[in] segment The segment to get the faces from.
* @param[in,out] Points The list of points used by the faces.
* @param[in,out] PointNormals The list of point normals used by the faces.
* @param[in,out] faces The list of faces retrieved from the segment.
*/
virtual void getFacesFromSubElement(const Segment* segment,
std::vector<Base::Vector3d>& Points,
std::vector<Base::Vector3d>& PointNormals,
std::vector<Facet>& faces) const;
//@}
/// @}
/** @name Placement control */
//@{
/** Applies an additional transformation to the current transformation. */
/**
* @name Placement control
*
* @{
*/
/// Apply an additional transformation to the current transformation.
void applyTransform(const Base::Matrix4D& rclTrf);
/** Applies an additional translation to the current transformation. */
/// Apply an additional translation to the current transformation.
void applyTranslation(const Base::Vector3d&);
/** Applies an additional rotation to the current transformation. */
/// Applies an additional rotation to the current transformation.
void applyRotation(const Base::Rotation&);
/** Override the current transformation with a placement
* using the setTransform() method.
/**
* @brief Override the current transformation with a placement.
*
* Override the current transformation with a placement using the
* setTransform() method.
*
* @param[in] rclPlacement The new placement to set.
*/
void setPlacement(const Base::Placement& rclPlacement);
/** Return the current transformation as placement using
* getTransform().
/**
* @brief Get the current transformation as placement.
*
* @return The current transformation as placement using getTransform().
*/
Base::Placement getPlacement() const;
/** Override the current transformation with the new one.
* This method has to be handled by the child classes.
* the actual placement and matrix is not part of this class.
/**
* @brief Override the current transformation.
*
* Override the current transformation with the new one. This method has
* to be handled by the child classes. the actual placement and matrix is
* not part of this class.
*
* @param[in] rclTrf The new transformation matrix to set.
*/
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.
/**
* @brief Get the current transformation matrix.
*
* This method has to be handled by the child classes. The actual
* placement and matrix is not part of this class.
*/
virtual Base::Matrix4D getTransform() const = 0;
//@}
/// @}
/** @name Modification */
//@{
/// Applies a transformation on the real geometric data type
/**
*@name Modification
*
* @{
*/
/**
* @brief Applies a transformation on the real geometric data type.
*
* @param[in] rclMat The transformation matrix to apply.
*/
virtual void transformGeometry(const Base::Matrix4D& rclMat) = 0;
//@}
/// @}
/** @name Getting basic geometric entities */
//@{
/// Get the standard accuracy to be used with getPoints, getLines or getFaces
/**
* @name Getting basic geometric entities
*
* @{
*/
/**
* @brief Get the standard accuracy for meshing.
*
* Get the standard accuracy to be used with getPoints(), getLines() or
* getFaces().
*
* @return The standard accuracy.
*/
virtual double getAccuracy() const;
/// Get the bound box
virtual Base::BoundBox3d getBoundBox() const = 0;
/** Get point from line object intersection */
/**
* @brief Get point from line object intersection.
*
* @param[in] base The base point of the line.
* @param[in] dir The direction of the line.
*
* @return The intersection point.
*/
virtual Base::Vector3d getPointFromLineIntersection(const Base::Vector3f& base,
const Base::Vector3f& dir) const;
/** Get points from object with given accuracy */
/**
* @brief Get points from object with given accuracy.
*
* @param[in,out] Points The list of points retrieved from the object.
* @param[in,out] Normals The list of normals associated with faces
* retrieved from the object. If there are no faces, then this list will
* be empty.
* @param[in] Accuracy The accuracy to use when retrieving the points.
* @param[in] flags Additional flags for point retrieval.
*/
virtual void getPoints(std::vector<Base::Vector3d>& Points,
std::vector<Base::Vector3d>& Normals,
double Accuracy,
uint16_t flags = 0) const;
/** Get lines from object with given accuracy */
/**
* @brief Get lines from object with given accuracy
*
* @param[in,out] Points The list of points retrieved from the object.
* @param[in,out] lines The list of lines retrieved from the object.
* @param[in] Accuracy The accuracy to use when retrieving the lines.
* @param[in] flags Additional flags for line retrieval.
*/
virtual void getLines(std::vector<Base::Vector3d>& Points,
std::vector<Line>& lines,
double Accuracy,
uint16_t flags = 0) const;
/** Get faces from object with given accuracy */
/**
* @brief Get faces from object with given accuracy.
*
* @param[in,out] Points The list of points retrieved from the object.
* @param[in,out] faces The list of faces retrieved from the object.
* @param[in] Accuracy The accuracy to use when retrieving the faces.
* @param[in] flags Additional flags for face retrieval.
*/
virtual void getFaces(std::vector<Base::Vector3d>& Points,
std::vector<Facet>& faces,
double Accuracy,
uint16_t flags = 0) const;
/** Get the center of gravity
* If this method is implemented then true is returned and the center of gravity.
* The default implementation only returns false.
/**
* @brief Get the center of gravity.
*
* @param[out] center The center of gravity.
*
* @return True if this method is implemented. The default implementation returns false.
*/
virtual bool getCenterOfGravity(Base::Vector3d& center) const;
virtual std::optional<Base::Vector3d> centerOfGravity() const;
//@}
/**
* @brief Get the center of gravity.
*
* @return The center of gravity if available.
*/
virtual std::optional<Base::Vector3d> centerOfGravity() const;
/// @}
/// Get the element map prefix.
static const std::string& elementMapPrefix();
/** @name Element name mapping */
//@{
/** Get element indexed name
/**
* @name Element name mapping
*
* @param name: the input name
* @param sid: optional output of and App::StringID involved forming this mapped name
* @{
*/
/**
* @brief Get the element's indexed name.
*
* @param[in] name The mapped name.
*
* @param[out] sid Optional output of and App::StringID involved forming
* this mapped name.
*
* @return Returns an indexed name.
*/
IndexedName getIndexedName(const MappedName& name, ElementIDRefs* sid = nullptr) const;
/** Get element mapped name
/**
* @brief Get the element's mapped name.
*
* @param name: the input name
* @param allowUnmapped: If the queried element is not mapped, then return
* an empty name if \c allowUnmapped is false, or
* else, return the indexed name.
* @param sid: optional output of and App::StringID involved forming this mapped name
* @return Returns the mapped name.
* @param[in] element The indexed name name of the element.
* @param[in] allowUnmapped If the queried element is not mapped, then
* return an empty name if @p allowUnmapped is false, or else, return the
* indexed name.
* @param sid Optional output of and App::StringID involved forming this
* mapped name.
*
* @return The mapped name.
*/
MappedName getMappedName(const IndexedName& element,
bool allowUnmapped = false,
ElementIDRefs* sid = nullptr) const;
/** Return a pair of indexed name and mapped name
*
* @param name: the input name.
* @param sid: optional output of any App::StringID involved in forming
* this mapped name
* @param copy: if true, copy the name string, or else use it as constant
* string, and caller must make sure the memory is not freed.
*
* @return Returns the MappedElement which contains both the indexed and
* mapped name.
/**
* @brief Get a pair of an indexed and mapped name.
*
* This function guesses whether the input name is an indexed name or
* mapped, and perform a lookup and return the names found. If the input
* mapped one, performs a lookup, and returns the names found. If the input
* name contains only alphabets and underscore followed by optional digits,
* it will be treated as indexed name. Or else, it will be treated as
* it will be treated as indexed name. Otherwise, it will be treated as a
* mapped name.
*
* @param[in] name The input name.
* @param[out] sid Optional output of any App::StringID involved in forming
* this mapped name.
* @param[in] copy If true, copy the name string, or else use it as
* constant string, and caller must make sure the memory is not freed.
*
* @return The MappedElement that contains both the indexed and mapped
* name.
*/
MappedElement
getElementName(const char* name, ElementIDRefs* sid = nullptr, bool copy = false) const;
/** Add a sub-element name mapping.
*
* @param element: the original \c Type + \c Index element name
* @param name: the mapped sub-element name. May or may not start with
* elementMapPrefix().
* @param sid: in case you use a hasher to hash the element name, pass in
* the string id reference using this parameter. You can have more than one
* string id associated with the same name.
* @param overwrite: if true, it will overwrite existing names
*
* @return Returns the stored mapped element name.
/**
* @brief Add a sub-element name mapping.
*
* An element can have multiple mapped names. However, a name can only be
* mapped to one element
*
* Note: the original proc was in the context of ComplexGeoData, which provided `Tag` access,
* now you must pass in `long masterTag` explicitly.
* @param[in] element The original @c Type + @c Index element name.
* @param[in] name The mapped sub-element name. It may or may not start
* with elementMapPrefix().
* @param[in] masterTag The master tag of the element.
* @param[in] sid In case you use a hasher to hash the element name, pass
* in the string id reference using this parameter. You can have more than
* one string id associated with the same name.
* @param[in] overwrite If true, it will overwrite existing names.
*
* @return The stored mapped element name.
*
* @note The original function was in the context of ComplexGeoData, which
* provided `Tag` access, now you must pass in `long masterTag` explicitly.
*/
MappedName setElementName(const IndexedName& element,
const MappedName& name,
@@ -280,30 +438,42 @@ public:
return _elementMap->setElementName(element, name, masterTag, sid, overwrite);
}
/// Check if there is an element map.
bool hasElementMap() const
{
return _elementMap != nullptr;
}
/** Get mapped element names
/**
* @brief Get mapped element names.
*
* @param element: original element name with \c Type + \c Index
* @param needUnmapped: if true, return the original element name if no
* mapping is found
* @param[in] element The original element name with @c Type + @c Index.
* @param[in] needUnmapped If true, return the original element name if no
* mapping is found.
*
* @return a list of mapped names of the give element along with their
* associated string ID references
* @return A list of mapped names of the give element along with their
* associated string ID references.
*/
std::vector<std::pair<MappedName, ElementIDRefs>>
getElementMappedNames(const IndexedName& element, bool needUnmapped = false) const;
/// Hash the child element map postfixes to shorten element name from hierarchical maps
/**
* @brief Hash the child element map postfixes.
*
* The hashing is done to shorten element names from hierarchical maps.
*/
void hashChildMaps();
/// Check if there is child element map
/// Check if there is child element map.
bool hasChildElementMap() const;
/// Append the Tag (if and only if it is non zero) into the element map
/**
* @brief Append the Tag (if and only if it is non zero) into the element map.
*
* @param[in] tag The master tag to append.
* @param[in] hasher The string hasher to use.
* @param[in] postfix An optional postfix to append after the tag.
*/
virtual void
reTagElementMap(long tag, App::StringHasherRef hasher, const char* postfix = nullptr)
{
@@ -312,7 +482,17 @@ public:
(void)postfix;
}
// NOTE: getElementHistory is now in ElementMap
/**
* @brief Get the history of an element name.
*
* @param[in] name The mapped element name to query.
* @param[out] original Optional output parameter to store the original
* element name.
* @param[out] history Optional output parameter to store the history of
* element names.
*
* @note This function is now in ElementMap.
*/
long getElementHistory(const MappedName& name,
MappedName* original = nullptr,
std::vector<MappedName>* history = nullptr) const
@@ -323,49 +503,68 @@ public:
return 0;
};
/// Set the mapped child elements.
void setMappedChildElements(const std::vector<Data::ElementMap::MappedChildElements>& children);
/// Get the mapped child elements.
std::vector<Data::ElementMap::MappedChildElements> getMappedChildElements() const;
/// Get the element type from a mapped name.
char elementType(const Data::MappedName&) const;
/// Get the element type from an indexed name.
char elementType(const Data::IndexedName&) const;
/// Get the element type from a raw name.
char elementType(const char* name) const;
/** Reset/swap the element map
/**
* @brief Reset/swap the element map.
*
* @param elementMap: optional new element map
* @param[in] elementMap: optional new element map.
*
* @return Returns the existing element map.
* @return The existing element map.
*/
virtual ElementMapPtr resetElementMap(ElementMapPtr elementMap = ElementMapPtr());
/// Get the entire element map
/// Get the entire element map.
std::vector<MappedElement> getElementMap() const;
/// Set the entire element map
/// Set the entire element map.
void setElementMap(const std::vector<MappedElement>& elements);
/// Get the current element map size
/// Get the current element map size.
size_t getElementMapSize(bool flush = true) const;
/// Return the higher level element names of the given element
/**
* @brief Get the higher level element names of the given element.
*
* @param name: the input element name.
* @param silent: if true, suppress throwing exceptions.
*/
virtual std::vector<IndexedName> getHigherElements(const char* name, bool silent = false) const;
/// Return the current element map version
/// Get the current element map version.
virtual std::string getElementMapVersion() const;
/// Return true to signal element map version change
/// Check the element map version.
virtual bool checkElementMapVersion(const char* ver) const;
/// Check if the given sub-name only contains an element name
/// Check if the given sub-name only contains an element name.
static bool isElementName(const char* subName)
{
return (subName != nullptr) && (*subName != 0) && findElementName(subName) == subName;
}
/** Iterate through the history of the give element name with a given callback
/**
* @brief Iterate through the history given an element name.
*
* Iterate through the history of the given element name with a given
* callback.
*
* @param[in] name: the input element name
* @param[in] cb: trace callback function.
*
* @param name: the input element name
* @param cb: trace callback with call signature.
* @sa TraceCallback
*/
void traceElement(const MappedName& name, TraceCallback cb) const
@@ -373,42 +572,62 @@ public:
_elementMap->traceElement(name, Tag, std::move(cb));
}
/** Flush an internal buffering for element mapping */
/// Flush internal buffers for element mapping.
virtual void flushElementMap() const;
//@}
/// @}
/**
* @name Save/restore
*
* @{
*/
/** @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;
/// Set the filename for persistence.
void setPersistenceFileName(const char* name) const;
/// Called before saving.
virtual void beforeSave() const;
/// Check if restore has failed.
bool isRestoreFailed() const
{
return _restoreFailed;
}
/// Reset the restore failure flag.
void resetRestoreFailure() const
{
_restoreFailed = true;
}
//@}
/// @}
/**
* Debugging method to dump an entire element map in human readable form to a stream
* @param stream
* @brief Dump the entire element map.
*
* Debugging method to dump an entire element map in human readable form to a stream.
*
* @param[in,out] stream The output stream.
*/
void dumpElementMap(std::ostream& stream) const;
/**
* Debugging method to dump an entire element map in human readable form into a string
* @return The string
* @brief Dump the entire element map to a string.
*
* Debugging method to dump an entire element map in human readable form
* into a string.
*
* @return The string with the element map.
*/
const std::string dumpElementMap() const;
protected:
/// from local to outside
/// Transform the point from local to outside.
inline Base::Vector3d transformPointToOutside(const Base::Vector3f& vec) const
{
// clang-format off
@@ -417,7 +636,8 @@ protected:
static_cast<double>(vec.z));
// clang-format on
}
/// from local to outside
/// Transform the points from local to outside.
template<typename Vec>
inline std::vector<Base::Vector3d> transformPointsToOutside(const std::vector<Vec>& input) const
{
@@ -435,6 +655,8 @@ protected:
return output;
// clang-format on
}
/// Transform the vector from local to outside.
inline Base::Vector3d transformVectorToOutside(const Base::Vector3f& vec) const
{
// clang-format off
@@ -445,6 +667,8 @@ protected:
static_cast<double>(vec.z));
// clang-format on
}
/// Transform the vectors from local to outside.
template<typename Vec>
std::vector<Base::Vector3d> transformVectorsToOutside(const std::vector<Vec>& input) const
{
@@ -463,7 +687,8 @@ protected:
return output;
// clang-format on
}
/// from local to inside
/// Transform the point from local to inside.
inline Base::Vector3f transformPointToInside(const Base::Vector3d& vec) const
{
Base::Matrix4D tmpM(getTransform());
@@ -475,48 +700,51 @@ protected:
}
public:
/**
* @brief The master tag.
*
* The master tag is used to identify the shape to its owner document
* object. It should be unique within the document. A tag of zero meanss
* that automatic element mapping is disabled.
*/
mutable long Tag {0};
/// String hasher for element name shortening
mutable App::StringHasherRef Hasher;
protected:
/**
* @brief Restore the element map from a stream.
*
* @param[in,out] stream The input stream.
* @param[in] count The number of items to restore.
*/
void restoreStream(std::istream& stream, std::size_t count);
/**
* @brief Read the elements from an XML reader.
*
* @param[in,out] reader The XML reader.
* @param[in] count The number of elements to read.
*/
void readElements(Base::XMLReader& reader, size_t count);
/// from local to outside
inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const
{
// clang-format off
return getTransform() * Base::Vector3d(static_cast<double>(vec.x),
static_cast<double>(vec.y),
static_cast<double>(vec.z));
// clang-format on
}
/// from local to inside
inline Base::Vector3f transformToInside(const Base::Vector3d& vec) const
{
Base::Matrix4D tmpM(getTransform());
tmpM.inverse();
Base::Vector3d tmp = tmpM * vec;
return Base::Vector3f(static_cast<float>(tmp.x),
static_cast<float>(tmp.y),
static_cast<float>(tmp.z));
}
protected:
/// Get the element map.
ElementMapPtr elementMap(bool flush = true) const;
/// Ensure there is an element map.
ElementMapPtr ensureElementMap(bool flush = true);
private:
ElementMapPtr _elementMap;
protected:
/// The persistence file name.
mutable std::string _persistenceName;
/// Flag to indicate restore failure.
mutable bool _restoreFailed = false;
};
} // namespace Data
ENABLE_BITMASK_OPERATORS(Data::SearchOption)
#endif
+1 -4
View File
@@ -23,8 +23,7 @@
* *
***************************************************************************/
#ifndef DATUMS_H
#define DATUMS_H
#pragma once
#include "GeoFeature.h"
#include "GeoFeatureGroupExtension.h"
@@ -254,5 +253,3 @@ private:
};
} // namespace App
#endif /* end of include guard: DATUMS_H */
+359 -209
View File
@@ -35,10 +35,12 @@
#include <list>
#include <algorithm>
#include <filesystem>
#include <format>
#include <boost/algorithm/string.hpp>
#include <boost/bimap.hpp>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/regex.hpp>
#include <random>
@@ -93,7 +95,6 @@ using Base::Console;
using Base::streq;
using Base::Writer;
using namespace App;
using namespace std;
using namespace boost;
using namespace zipios;
@@ -190,6 +191,7 @@ bool Document::undo(const int id)
mRedoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction;
mRedoTransactions.push_back(d->activeUndoTransaction);
d->activeUndoTransaction = nullptr;
d->bookedTransaction = 0;
mUndoMap.erase(mUndoTransactions.back()->getID());
delete mUndoTransactions.back();
@@ -242,6 +244,7 @@ bool Document::redo(const int id)
mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction;
mUndoTransactions.push_back(d->activeUndoTransaction);
d->activeUndoTransaction = nullptr;
d->bookedTransaction = 0;
mRedoMap.erase(mRedoTransactions.back()->getID());
delete mRedoTransactions.back();
@@ -271,10 +274,10 @@ void Document::changePropertyOfObject(TransactionalObject* obj,
}
if ((d->iUndoMode != 0) && !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->bookedTransaction == NullTransaction) {
d->bookedTransaction = GetApplication().getGlobalTransaction();
} else {
_openTransaction(GetApplication().getTransactionName(d->bookedTransaction), d->bookedTransaction);
}
}
}
@@ -329,71 +332,92 @@ std::vector<std::string> Document::getAvailableRedoNames() const
return vList;
}
void Document::openTransaction(const char* name) // NOLINT
int Document::openTransaction(TransactionName name, int tid) // NOLINT
{
if (isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Cannot open transaction while transacting");
}
return;
if (tid != NullTransaction && tid == d->bookedTransaction) {
return tid; // Early exit without warning
}
if (isTransactionLocked()) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Transaction locked, ignore new transaction '" << name.name << "'");
}
return 0;
}
GetApplication().setActiveTransaction(name ? name : "<empty>");
}
int Document::_openTransaction(const char* name, int id)
{
if (isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Cannot open transaction while transacting");
}
return 0;
}
if (d->iUndoMode != 0) {
// Avoid recursive calls that is possible while
// clearing the redo transactions and will cause
// a double deletion of some transaction and thus
// a segmentation fault
if (d->opentransaction) {
return 0;
}
Base::FlagToggler<> flag(d->opentransaction);
if ((id != 0) && mUndoMap.find(id) != mUndoMap.end()) {
throw Base::RuntimeError("invalid transaction id");
}
if (d->activeUndoTransaction) {
_commitTransaction(true);
}
_clearRedos();
d->activeUndoTransaction = new Transaction(id);
if (!name) {
name = "<empty>";
}
d->activeUndoTransaction->Name = name;
mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction;
id = d->activeUndoTransaction->getID();
signalOpenTransaction(*this, name);
auto& app = GetApplication();
auto activeDoc = app.getActiveDocument();
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);
}
return id;
if (name.name.empty()) {
name.name = "<empty>";
}
return 0;
return setActiveTransaction(name, tid);
}
int Document::openTransaction(std::string name, int tid)
{
return openTransaction(TransactionName {.name = name, .temporary = false}, tid);
}
void Document::renameTransaction(const char* name, const int id) const
int Document::_openTransaction(std::string name, int id)
{
if (name && d->activeUndoTransaction && d->activeUndoTransaction->getID() == id) {
if (isTransactionLocked() && id != d->bookedTransaction) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Transaction locked, ignore new transaction '" << name << "'");
}
}
if (isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Cannot open transaction while transacting");
}
return 0;
}
if (d->iUndoMode == 0) {
return 0;
}
// Avoid recursive calls that is possible while
// clearing the redo transactions and will cause
// a double deletion of some transaction and thus
// a segmentation fault
if (d->opentransaction) {
return 0;
}
Base::FlagToggler<> flag(d->opentransaction);
if ((id != 0) && mUndoMap.find(id) != mUndoMap.end()) {
throw Base::RuntimeError("invalid transaction id");
}
if (d->activeUndoTransaction) {
_commitTransaction(true);
}
_clearRedos();
// When id == 0, this creates a new id
// for instance, when there is no global transaction
// from the application to stick to
d->activeUndoTransaction = new Transaction(id);
if (name.empty()) {
name = "<empty>";
}
d->activeUndoTransaction->Name = name;
mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction;
id = d->activeUndoTransaction->getID();
signalOpenTransaction(*this, name);
Document* transactionInitiator = GetApplication().transactionInitiator(id);
if (transactionInitiator && transactionInitiator != this && !transactionInitiator->hasPendingTransaction()) {
std::string aname = std::format("-> {}", d->activeUndoTransaction->Name);
FC_LOG("auto transaction " << getName() << " -> " << transactionInitiator->getName());
transactionInitiator->_openTransaction(aname, id);
}
return id;
}
void Document::renameTransaction(const std::string& name, const int id) const
{
if (!name.empty() && d->activeUndoTransaction && d->activeUndoTransaction->getID() == id) {
if (boost::starts_with(d->activeUndoTransaction->Name, "-> ")) {
d->activeUndoTransaction->Name.resize(3);
}
@@ -403,48 +427,108 @@ void Document::renameTransaction(const char* name, const int id) const
d->activeUndoTransaction->Name += name;
}
}
int Document::setActiveTransaction(TransactionName name, int tid)
{
// Probably a group transaction situation
if (tid != NullTransaction) {
if (!GetApplication().transactionIsActive(tid)) {
FC_LOG("Could not set active transaction to inactive ID");
return NullTransaction;
}
if (d->bookedTransaction != NullTransaction && d->bookedTransaction != tid && !_commitTransaction(true)) {
FC_LOG("Could not book transaction for document");
return NullTransaction;
}
d->bookedTransaction = tid;
if (GetApplication().transactionTmpName(d->bookedTransaction)) {
GetApplication().setTransactionName(d->bookedTransaction, name);
}
return d->bookedTransaction;
}
// Rename the transaction if it had a tmp name
if (d->bookedTransaction != NullTransaction && GetApplication().transactionTmpName(d->bookedTransaction)) {
GetApplication().setTransactionName(d->bookedTransaction, name);
return d->bookedTransaction;
}
if (d->bookedTransaction != NullTransaction && !_commitTransaction(true)) {
FC_LOG("Could not book transaction for document");
return NullTransaction;
}
d->bookedTransaction = Transaction::getNewID();
GetApplication().setTransactionDescription(d->bookedTransaction, TransactionDescription {.initiator = this, .name = name});
return d->bookedTransaction;
}
void Document::lockTransaction()
{
d->TransactionLock++;
}
void Document::unlockTransaction()
{
if (d->TransactionLock > 0) {
d->TransactionLock--;
}
}
bool Document::isTransactionLocked() const
{
return d->TransactionLock > 0;
}
bool Document::transacting() const
{
return isPerformingTransaction() || d->committing;
}
void Document::_checkTransaction(DocumentObject* pcDelObj, const Property* What, int line)
{
// if the undo is active but no transaction open, open one!
if ((d->iUndoMode != 0) && !isPerformingTransaction()) {
if (!d->activeUndoTransaction) {
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)) {
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);
}
return;
if (d->iUndoMode == 0 || isPerformingTransaction() || d->activeUndoTransaction) {
return;
}
if (!testStatus(Restoring) || testStatus(Importing)) {
// Priority to a transaction that has been booked
// explicitly for this document, it there are none
// get a sticky transaction from application
if (!d->bookedTransaction) {
d->bookedTransaction = GetApplication().getGlobalTransaction();
}
if (d->bookedTransaction != NullTransaction) {
std::string name = GetApplication().getTransactionName(d->bookedTransaction);
bool ignore = false;
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 (!pcDelObj) {
return;
}
// When the object is going to be deleted we have to check if it has already been added
// to the undo transactions
std::list<Transaction*>::iterator it;
for (it = mUndoTransactions.begin(); it != mUndoTransactions.end(); ++it) {
if ((*it)->hasObject(pcDelObj)) {
_openTransaction("Delete");
break;
}
if (!ignore) {
_openTransaction(name, d->bookedTransaction);
}
return;
}
}
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
std::list<Transaction*>::iterator it;
for (it = mUndoTransactions.begin(); it != mUndoTransactions.end(); ++it) {
if ((*it)->hasObject(pcDelObj)) {
_openTransaction("Delete");
break;
}
}
}
@@ -473,29 +557,36 @@ void Document::commitTransaction() // NOLINT
}
if (d->activeUndoTransaction) {
GetApplication().closeActiveTransaction(false, d->activeUndoTransaction->getID());
// This will iterate over all documents and ask them to
// commit their transaction if their ID matches
GetApplication().commitTransaction(d->activeUndoTransaction->getID());
} else {
d->bookedTransaction = 0; // Reset booked transaction even if it was not used
}
}
void Document::_commitTransaction(const bool notify)
bool Document::_commitTransaction(const bool notify)
{
if (isPerformingTransaction()) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Cannot commit transaction while transacting");
}
return;
return false;
}
if (d->committing) {
// for a recursive call return without printing a warning
return;
return false;
}
d->bookedTransaction = 0;
if (d->activeUndoTransaction) {
Base::FlagToggler<> flag(d->committing);
Application::TransactionSignaller signaller(false, true);
const int id = d->activeUndoTransaction->getID();
mUndoTransactions.push_back(d->activeUndoTransaction);
d->activeUndoTransaction = nullptr;
// check the stack for the limits
if (mUndoTransactions.size() > d->UndoMaxStackSize) {
mUndoMap.erase(mUndoTransactions.front()->getID());
@@ -504,11 +595,12 @@ void Document::_commitTransaction(const bool notify)
}
signalCommitTransaction(*this);
// closeActiveTransaction() may call again _commitTransaction()
// commitTransaction() may call again _commitTransaction()
if (notify) {
GetApplication().closeActiveTransaction(false, id);
GetApplication().commitTransaction(id);
}
}
return true;
}
void Document::abortTransaction() const
@@ -520,7 +612,9 @@ void Document::abortTransaction() const
return;
}
if (d->activeUndoTransaction) {
GetApplication().closeActiveTransaction(true, d->activeUndoTransaction->getID());
GetApplication().abortTransaction(d->activeUndoTransaction->getID());
} else {
d->bookedTransaction = 0; // Reset booked transaction even if it was not used
}
}
@@ -532,6 +626,7 @@ void Document::_abortTransaction()
}
}
d->bookedTransaction = 0;
if (d->activeUndoTransaction) {
Base::FlagToggler<bool> flag(d->rollback);
Application::TransactionSignaller signaller(true, true);
@@ -575,7 +670,10 @@ int Document::getTransactionID(const bool undo, unsigned pos) const
for (; pos != 0U; ++rit, --pos) {}
return (*rit)->getID();
}
int Document::getBookedTransactionID() const
{
return d->bookedTransaction;
}
bool Document::isTransactionEmpty() const
{
return !d->activeUndoTransaction;
@@ -996,7 +1094,14 @@ void Document::Save(Base::Writer& writer) const
writer.incInd();
// NOTE: This differs from LS3 Code. Persisting this table
// forces the assertion in Writer.addFile(...): assert(!isForceXML()); to be removed
// see: https://github.com/FreeCAD/FreeCAD/issues/27489
//
// Original code in LS3:
// d->Hasher->setPersistenceFileName(0);
d->Hasher->setPersistenceFileName("StringHasher.Table");
for (const auto o : d->objectArray) {
o->beforeSave();
}
@@ -1251,96 +1356,133 @@ constexpr auto fcAttrDepObjName {"Name"};
constexpr auto fcAttrDepAllowPartial {"AllowPartial"};
constexpr auto fcElementObjectDep {"Dep"};
void Document::writeObjects(const std::vector<DocumentObject*>& obj,
Base::Writer& writer) const
void Document::writeObjectDeps(const std::vector<DocumentObject*>& objs,
Base::Writer& writer) const
{
// writing the features types
writer.incInd(); // indentation for 'Objects count'
writer.Stream() << writer.ind() << "<Objects Count=\"" << obj.size();
if (isExporting(nullptr) == 0U) {
writer.Stream() << "\" " << fcAttrDependencies << "=\"1";
}
writer.Stream() << "\">" << '\n';
for (auto o : objs) {
// clang-format off
const auto& outList = o->getOutList(DocumentObject::OutListNoHidden |
DocumentObject::OutListNoXLinked);
// clang-format on
writer.incInd(); // indentation for 'Object type'
if (isExporting(nullptr) == 0U) {
for (const auto o : obj) {
const auto& outList =
o->getOutList(DocumentObject::OutListNoHidden | DocumentObject::OutListNoXLinked);
writer.Stream() << writer.ind()
<< "<" << fcElementObjectDeps << " " << fcAttrDepObjName << "=\""
<< o->getNameInDocument() << "\" " << fcAttrDepCount << "=\""
<< outList.size();
if (outList.empty()) {
writer.Stream() << "\"/>" << '\n';
continue;
}
const int partial = o->canLoadPartial();
if (partial > 0) {
writer.Stream() << "\" " << fcAttrDepAllowPartial << "=\"" << partial;
}
writer.Stream() << "\">" << '\n';
writer.incInd();
for (const auto dep : outList) {
const auto name = dep ? dep->getNameInDocument() : "";
writer.Stream() << writer.ind()
<< "<" << fcElementObjectDep << " " << fcAttrDepObjName << "=\""
<< (name ? name : "") << "\"/>" << '\n';
}
writer.decInd();
writer.Stream() << writer.ind() << "</" << fcElementObjectDeps << ">" << '\n';
auto objName = o->getNameInDocument();
writer.Stream() << writer.ind()
<< "<" << fcElementObjectDeps
<< " " << fcAttrDepObjName << "=\""
<< (objName ? objName : "") << "\" "
<< fcAttrDepCount << "=\""
<< outList.size();
if (outList.empty()) {
writer.Stream() << "\"/>\n";
continue;
}
int partial = o->canLoadPartial();
if (partial > 0) {
writer.Stream() << "\" " << fcAttrDepAllowPartial << "=\"" << partial;
}
writer.Stream() << "\">\n";
writer.incInd();
for (auto dep : outList) {
auto depName = dep ? dep->getNameInDocument() : "";
writer.Stream() << writer.ind()
<< "<" << fcElementObjectDep
<< " " << fcAttrDepObjName << "=\""
<< (depName ? depName : "") << "\"/>\n";
}
writer.decInd();
writer.Stream() << writer.ind() << "</" << fcElementObjectDeps << ">\n";
}
}
std::vector<DocumentObject*>::const_iterator it;
for (it = obj.begin(); it != obj.end(); ++it) {
void Document::writeObjectType(const std::vector<DocumentObject*>& objs,
Base::Writer& writer) const
{
for (auto it : objs) {
writer.Stream() << writer.ind() << "<Object "
<< "type=\"" << (*it)->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()) {
std::string viewType = it->getViewProviderNameStored();
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)) {
if (it->testStatus(ObjectStatus::Error)) {
writer.Stream() << "Invalid=\"1\" ";
const auto desc = getErrorDescription(*it);
auto desc = getErrorDescription(it);
if (desc) {
writer.Stream() << "Error=\"" << Property::encodeAttribute(desc) << "\" ";
}
}
writer.Stream() << "/>" << '\n';
if (it->isFreezed()) {
writer.Stream() << "Freeze=\"1\" ";
}
writer.Stream() << "/>\n";
}
}
writer.decInd(); // indentation for 'Object type'
writer.Stream() << writer.ind() << "</Objects>" << '\n';
void Document::writeObjectData(const std::vector<DocumentObject*>& objs,
Base::Writer& writer) const
{
// writing the features itself
writer.Stream() << writer.ind() << "<ObjectData Count=\"" << obj.size() << "\">" << '\n';
writer.Stream() << writer.ind() << "<ObjectData Count=\"" << objs.size() << "\">\n";
writer.incInd(); // indentation for 'Object name'
for (it = obj.begin(); it != obj.end(); ++it) {
writer.Stream() << writer.ind() << "<Object name=\"" << (*it)->getExportName() << "\"";
if ((*it)->hasExtensions()) {
for (auto it : objs) {
writer.Stream() << writer.ind() << "<Object name=\"" << it->getExportName() << "\"";
if (it->hasExtensions()) {
writer.Stream() << " Extensions=\"True\"";
}
writer.Stream() << ">" << '\n';
(*it)->Save(writer);
writer.Stream() << writer.ind() << "</Object>" << '\n';
writer.Stream() << ">\n";
it->Save(writer);
writer.Stream() << writer.ind() << "</Object>\n";
}
writer.decInd(); // indentation for 'Object name'
writer.Stream() << writer.ind() << "</ObjectData>\n";
}
void Document::writeObjects(const std::vector<DocumentObject*>& objs,
Base::Writer& writer) const
{
std::ostream& str = writer.Stream();
// writing the features types
writer.incInd(); // indentation for 'Objects count'
str << writer.ind() << "<Objects Count=\"" << objs.size();
if (!isExporting(nullptr)) {
str << "\" " << fcAttrDependencies << "=\"1";
}
str << "\">\n";
writer.incInd(); // indentation for 'Object type'
if (!isExporting(nullptr)) {
writeObjectDeps(objs, writer);
}
writer.decInd(); // indentation for 'Object name'
writer.Stream() << writer.ind() << "</ObjectData>" << '\n';
writeObjectType(objs, writer);
writer.decInd(); // indentation for 'Object type'
str << writer.ind() << "</Objects>\n";
writeObjectData(objs, writer);
writer.decInd(); // indentation for 'Objects count'
// check for errors
if (writer.hasFailed()) {
std::cerr << "Output stream is in error state. As a result the "
"Document.xml file may be incomplete.\n";
// reset the error flags to try to safe the data files
writer.clear();
}
}
struct DepInfo
@@ -1514,6 +1656,11 @@ std::vector<DocumentObject*> Document::readObjects(Base::XMLReader& reader)
d->addRecomputeLog(reader.getAttribute<const char*>("Error"), obj);
}
}
if (reader.hasAttribute("Freeze")) {
if (reader.getAttribute<long>("Freeze") != 0) {
obj->freeze();
}
}
}
}
catch (const Base::Exception& e) {
@@ -2036,11 +2183,11 @@ bool Document::afterRestore(const std::vector<DocumentObject*>& objArray, bool c
return false;
}
// some link type property cannot restore link information until other
// objects has been restored. For example, PropertyExpressionEngine and
// PropertySheet with expression containing label reference. So we add the
// Property::afterRestore() interface to let them sort it out. Note, this
// API is not called in object dedpenency order, because the order
// Some link type properties cannot restore link information until other
// objects have been restored. For example, PropertyExpressionEngine and
// PropertySheet with expressions containing a label reference. So we add
// the Property::afterRestore() interface to let them sort it out. Note,
// this API is not called in object dependency order, because the order
// information is not ready yet.
std::map<DocumentObject*, std::vector<Property*>> propMap;
for (auto obj : objArray) {
@@ -2228,7 +2375,7 @@ vector<DocumentObject*> Document::getTouched() const
return result;
}
void Document::setClosable(const bool c) // NOLINT
void Document::setClosable(bool c) // NOLINT
{
setStatus(Document::Closable, c);
}
@@ -2508,7 +2655,7 @@ std::vector<Document*> Document::getDependentDocuments(const bool sort)
}
std::vector<Document*> Document::getDependentDocuments(std::vector<Document*> docs,
const bool sort)
const bool sort)
{
DependencyList depList;
std::map<Document*, Vertex> docMap;
@@ -2572,11 +2719,6 @@ std::vector<Document*> Document::getDependentDocuments(std::vector<Document*> do
return ret;
}
void Document::_rebuildDependencyList(const std::vector<DocumentObject*>& objs)
{
(void)objs;
}
/**
* @brief Signal that object identifiers, typically a property or document object has been renamed.
*
@@ -2821,10 +2963,10 @@ int Document::recompute(const std::vector<DocumentObject*>& objs,
std::vector<DocumentObject*>
DocumentP::partialTopologicalSort(const std::vector<DocumentObject*>& objects)
{
vector<DocumentObject*> ret;
std::vector<DocumentObject*> ret;
ret.reserve(objects.size());
// pairs of input and output degree
map<DocumentObject*, std::pair<int, int>> countMap;
std::map<DocumentObject*, std::pair<int, int>> countMap;
for (auto objectIt : objects) {
// we need inlist with unique entries
@@ -2850,7 +2992,7 @@ DocumentP::partialTopologicalSort(const std::vector<DocumentObject*>& objects)
// try input degree
auto degInIt = find_if(countMap.begin(),
countMap.end(),
[](pair<DocumentObject*, pair<int, int>> vertex) -> bool {
[](std::pair<DocumentObject*, std::pair<int, int>> vertex) -> bool {
return vertex.second.first == 0;
});
@@ -2885,11 +3027,11 @@ DocumentP::partialTopologicalSort(const std::vector<DocumentObject*>& objects)
while (removeVertex) {
removeVertex = false;
auto degOutIt = find_if(countMap.begin(),
countMap.end(),
[](pair<DocumentObject*, pair<int, int>> vertex) -> bool {
return vertex.second.second == 0;
});
auto degOutIt = std::find_if(countMap.begin(),
countMap.end(),
[](std::pair<DocumentObject*, std::pair<int, int>> vertex) -> bool {
return vertex.second.second == 0;
});
if (degOutIt != countMap.end()) {
removeVertex = true;
@@ -2928,9 +3070,9 @@ DocumentP::topologicalSort(const std::vector<DocumentObject*>& objects) const
{
// topological sort algorithm described here:
// https://de.wikipedia.org/wiki/Topologische_Sortierung#Algorithmus_f.C3.BCr_das_Topologische_Sortieren
vector<DocumentObject*> ret;
std::vector<DocumentObject*> ret;
ret.reserve(objects.size());
map<DocumentObject*, int> countMap;
std::map<DocumentObject*, int> countMap;
for (auto objectIt : objects) {
// We now support externally linked objects
@@ -2946,14 +3088,14 @@ DocumentP::topologicalSort(const std::vector<DocumentObject*>& objects) const
countMap[objectIt] = in.size();
}
auto rootObjeIt = find_if(countMap.begin(),
countMap.end(),
[](pair<DocumentObject*, int> count) -> bool {
return count.second == 0;
});
auto rootObjeIt = std::find_if(countMap.begin(),
countMap.end(),
[](std::pair<DocumentObject*, int> count) -> bool {
return count.second == 0;
});
if (rootObjeIt == countMap.end()) {
cerr << "Document::topologicalSort: cyclic dependency detected (no root object)" << '\n';
std::cerr << "Document::topologicalSort: cyclic dependency detected (no root object)" << '\n';
return ret;
}
@@ -2975,7 +3117,7 @@ DocumentP::topologicalSort(const std::vector<DocumentObject*>& objects) const
rootObjeIt = find_if(countMap.begin(),
countMap.end(),
[](pair<DocumentObject*, int> count) -> bool {
[](std::pair<DocumentObject*, int> count) -> bool {
return count.second == 0;
});
}
@@ -3098,7 +3240,7 @@ DocumentObject* Document::addObject(const char* sType,
AddObjectOption::SetNewStatus
| (isPartial ? AddObjectOption::SetPartialStatus : AddObjectOption::UnsetPartialStatus)
| (isNew ? AddObjectOption::DoSetup : AddObjectOption::None)
| AddObjectOption::ActivateObject,
| AddObjectOption::ActivateObject,
viewType);
// return the Object
@@ -3144,15 +3286,15 @@ Document::addObjects(const char* sType, const std::vector<std::string>& objectNa
return objects;
}
void Document::addObject(DocumentObject* pcObject, const char* pObjectName)
void Document::addObject(DocumentObject* obj, const char* name)
{
if (pcObject->getDocument()) {
if (obj->getDocument()) {
throw Base::RuntimeError("Document object is already added to a document");
}
pcObject->setDocument(this);
obj->setDocument(this);
_addObject(pcObject, pObjectName, AddObjectOption::SetNewStatus | AddObjectOption::ActivateObject);
_addObject(obj, name, AddObjectOption::SetNewStatus | AddObjectOption::ActivateObject);
}
void Document::_addObject(DocumentObject* pcObject, const char* pObjectName, AddObjectOptions options, const char* viewType)
@@ -3165,7 +3307,7 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName, Add
else {
ObjectName = getUniqueObjectName(pcObject->getTypeId().getName());
}
// insert in the name map
d->objectMap[ObjectName] = pcObject;
d->objectNameManager.addExactName(ObjectName);
@@ -3181,7 +3323,7 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName, Add
}
d->objectIdMap[pcObject->_Id] = pcObject;
d->objectArray.push_back(pcObject);
// do no transactions if we do a rollback!
if (!d->rollback) {
// Undo stuff
@@ -3200,9 +3342,9 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName, Add
if (!isPerformingTransaction() && options.testFlag(AddObjectOption::DoSetup)) {
pcObject->setupObject();
}
if (options.testFlag(AddObjectOption::SetNewStatus)) {
pcObject->setStatus(ObjectStatus::New, true);
pcObject->setStatus(ObjectStatus::New, true);
}
if (options.testFlag(AddObjectOption::SetPartialStatus) || options.testFlag(AddObjectOption::UnsetPartialStatus)) {
pcObject->setStatus(ObjectStatus::PartialObject, options.testFlag(AddObjectOption::SetPartialStatus));
@@ -3214,15 +3356,15 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName, Add
pcObject->_pcViewProviderName = viewType ? viewType : "";
signalNewObject(*pcObject);
// do no transactions if we do a rollback!
if (!d->rollback && d->activeUndoTransaction) {
signalTransactionAppend(*pcObject, d->activeUndoTransaction);
}
if (options.testFlag(AddObjectOption::ActivateObject)) {
d->activeObject = pcObject;
signalActivatedObject(*pcObject);
signalActivatedObject(*pcObject);
}
}
@@ -3235,6 +3377,14 @@ bool Document::containsObject(const DocumentObject* pcObject) const
return found != d->objectIdMap.end() && found->second == pcObject;
}
/// Remove an object out of the document
void Document::removeObject(const DocumentObject* object)
{
if (object->getDocument() == this) {
removeObject(object->getNameInDocument());
}
}
/// Remove an object out of the document
void Document::removeObject(const char* sName)
{
@@ -3259,8 +3409,8 @@ void Document::_removeObject(DocumentObject* pcObject, RemoveObjectOptions optio
FC_ERR("Cannot delete " << pcObject->getFullName() << " while recomputing");
return;
}
TransactionLocker tlock;
TransactionLocker tlock(this);
_checkTransaction(pcObject, nullptr, __LINE__);
@@ -3269,7 +3419,7 @@ void Document::_removeObject(DocumentObject* pcObject, RemoveObjectOptions optio
FC_ERR("Internal error, could not find " << pcObject->getFullName() << " to remove");
}
if (options.testFlag(RemoveObjectOption::PreserveChildrenVisibility)
if (options.testFlag(RemoveObjectOption::PreserveChildrenVisibility)
&& !d->rollback && d->activeUndoTransaction && pcObject->hasChildElement()) {
// Preserve link group sub object global visibilities. Normally those
// claimed object should be hidden in global coordinate space. However,
@@ -3277,7 +3427,7 @@ void Document::_removeObject(DocumentObject* pcObject, RemoveObjectOptions optio
// children, which may now in the global space. When the parent is
// undeleted, having its children shown in both the local and global
// coordinate space is very confusing. Hence, we preserve the visibility
// here
// here
for (auto& sub : pcObject->getSubObjects()) {
if (sub.empty()) {
continue;
@@ -3324,7 +3474,7 @@ void Document::_removeObject(DocumentObject* pcObject, RemoveObjectOptions optio
}
std::unique_ptr<DocumentObject> tobedestroyed;
if ((options.testFlag(RemoveObjectOption::MayDestroyOutOfTransaction) && !d->rollback && !d->activeUndoTransaction)
if ((options.testFlag(RemoveObjectOption::MayDestroyOutOfTransaction) && !d->rollback && !d->activeUndoTransaction)
|| (options.testFlag(RemoveObjectOption::DestroyOnRollback) && d->rollback)) {
// if not saved in undo -> delete object later
std::unique_ptr<DocumentObject> delobj(pos->second);
@@ -3340,13 +3490,13 @@ void Document::_removeObject(DocumentObject* pcObject, RemoveObjectOptions optio
break;
}
}
// In case the object gets deleted the pointer must be nullified
if (tobedestroyed) {
tobedestroyed->pcNameInDocument = nullptr;
}
// Erase last to avoid invalidating pcObject->pcNameInDocument
// Erase last to avoid invalidating pcObject->pcNameInDocument
// when it is still needed in Transaction::addObjectNew
d->objectMap.erase(pos);
}
+1051 -318
View File
File diff suppressed because it is too large Load Diff
+10
View File
@@ -198,6 +198,7 @@ class Document(PropertyContainer):
Args:
type: the type of the document object to create.
Call method supportedTypes() to get a list of possible values.
name: the optional name of the new object.
objProxy: the Python binding object to attach to the new document object.
viewProxy: the Python binding object to attach the view provider of this object.
@@ -446,3 +447,12 @@ class Document(PropertyContainer):
sort: whether to topologically sort the return list
"""
...
def getBookedTransactionID(self) -> int:
"""
getBookedTransactionID() -> int
Returns the currently booked transaction id, which is the id of the current transaction OR the id
the next transaction will stick to if no change has occured yet
"""
...
+4 -64
View File
@@ -140,12 +140,10 @@ 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",
Base::Console().warning("%s: %s links are out of scope. Out of scope links to: %s\n",
getTypeId().getName(),
objnames.c_str(),
getNameInDocument(),
scopenames.c_str());
objnames.c_str());
}
catch (const Base::Exception& e) {
e.reportException();
@@ -206,13 +204,6 @@ bool DocumentObject::recomputeFeature(bool recursive)
return isValid();
}
/**
* @brief Set this document object touched.
* Touching a document object does not mean to recompute it, it only means that
* other document objects that link it (i.e. its InList) will be recomputed.
* If it should be forced to recompute a document object then use
* \ref enforceRecompute() instead.
*/
void DocumentObject::touch(bool noRecompute)
{
if (!noRecompute) {
@@ -224,10 +215,6 @@ void DocumentObject::touch(bool noRecompute)
}
}
/**
* @brief Set this document object freezed.
* A freezed document object does not recompute ever.
*/
void DocumentObject::freeze()
{
StatusBits.set(ObjectStatus::Freeze);
@@ -250,10 +237,6 @@ void DocumentObject::freeze()
}
}
/**
* @brief Set this document object unfreezed.
* A freezed document object does not recompute ever.
*/
void DocumentObject::unfreeze(bool noRecompute)
{
StatusBits.reset(ObjectStatus::Freeze);
@@ -271,31 +254,16 @@ void DocumentObject::unfreeze(bool noRecompute)
touch(noRecompute);
}
/**
* @brief Check whether the document object is touched or not.
* @return true if document object is touched, false if not.
*/
bool DocumentObject::isTouched() const
{
return ExpressionEngine.isTouched() || StatusBits.test(ObjectStatus::Touch);
}
/**
* @brief Enforces this document object to be recomputed.
* This can be useful to recompute the feature without
* having to change one of its input properties.
*/
void DocumentObject::enforceRecompute()
{
touch(false);
}
/**
* @brief Check whether the document object must be recomputed or not.
* This means that the 'Enforce' flag is set or that \ref mustExecute()
* returns a value > 0.
* @return true if document object must be recomputed, false if not.
*/
bool DocumentObject::mustRecompute() const
{
if (StatusBits.test(ObjectStatus::Freeze)) {
@@ -646,7 +614,7 @@ bool DocumentObject::isInOutListRecursive(DocumentObject* linkTo) const
}
std::vector<std::list<App::DocumentObject*>>
DocumentObject::getPathsByOutList(App::DocumentObject* to) const
DocumentObject::getPathsByOutList(const App::DocumentObject* to) const
{
return _pDoc->getPathsByOutList(this, to);
}
@@ -1200,43 +1168,22 @@ DocumentObject* DocumentObject::getLinkedObject(bool recursive,
void DocumentObject::Save(Base::Writer& writer) const
{
if (this->isFreezed()) {
throw Base::AbortException("At least one object is frozen, unable to save.");
}
if (this->isAttachedToDocument()){
if (this->isAttachedToDocument()) {
writer.ObjectName = this->getNameInDocument();
}
App::ExtensionContainer::Save(writer);
}
/**
* @brief Associate the expression \expr with the object identifier \a path in this document object.
* @param path Target object identifier for the result of the expression
* @param expr Expression tree
*/
void DocumentObject::setExpression(const ObjectIdentifier& path, std::shared_ptr<Expression> expr)
{
ExpressionEngine.setValue(path, std::move(expr));
}
/**
* @brief Clear the expression of the object identifier \a path in this document object.
* @param path Target object identifier
*/
void DocumentObject::clearExpression(const ObjectIdentifier& path)
{
setExpression(path, std::shared_ptr<Expression>());
}
/**
* @brief Get expression information associated with \a path.
* @param path Object identifier
* @return Expression info, containing expression and optional comment.
*/
const PropertyExpressionEngine::ExpressionInfo
DocumentObject::getExpression(const ObjectIdentifier& path) const
{
@@ -1250,13 +1197,6 @@ DocumentObject::getExpression(const ObjectIdentifier& path) const
}
}
/**
* @brief Invoke ExpressionEngine's renameObjectIdentifier, to possibly rewrite expressions using
* the \a paths map with current and new identifiers.
*
* @param paths
*/
void DocumentObject::renameObjectIdentifiers(
const std::map<ObjectIdentifier, ObjectIdentifier>& paths)
{
+847 -306
View File
File diff suppressed because it is too large Load Diff
+25 -7
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_DOCUMENTOBJECTEXTENSION_H
#define APP_DOCUMENTOBJECTEXTENSION_H
#pragma once
#include "Extension.h"
@@ -97,10 +96,31 @@ public:
*/
virtual bool extensionGetSubObjects(std::vector<std::string>& ret, int reason) const;
/** Get the linked object
* @sa DocumentObject::getLinkedObject()
/**
* @brief Get the linked object of this extension.
*
* @return Return turn if handled, the linked object is returned in \c ret
* This method returns the linked object of this document object. If there
* is no linked object, it will return the container object of the
* extension.
*
* @param[out] ret The linked object is returned in this parameter.
*
* @param[in] recurse If true, it will recursively resolve the link until it
* reaches the final linked object.
*
* @param mat[in,out] If non-null, it is used as the current transformation
* matrix on input. On output it is used as the accumulated transformation
* up until the final linked object.
*
* @param[in] transform If false, then it will not accumulate the object's own
* placement into @p mat, which lets you override the object's placement.
*
* @param[in] depth This parameter indicates the level on which we are
* resolving the link.
*
* @return Returns true if the linked object is successfully retrieved and
* returned in @p ret. If the linked object is not found or is invalid, it
* returns false.
*/
virtual bool extensionGetLinkedObject(DocumentObject*& ret,
bool recursive,
@@ -123,5 +143,3 @@ public:
};
} // namespace App
#endif // APP_DOCUMENTOBJECTEXTENSION_H
+1 -5
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_DOCUMENTOBJECTFILEINCLUDED_H
#define APP_DOCUMENTOBJECTFILEINCLUDED_H
#pragma once
#include "DocumentObject.h"
#include "PropertyFile.h"
@@ -54,6 +53,3 @@ public:
};
} // namespace App
#endif // APP_DOCUMENTOBJECTFILEINCLUDED_H
+1 -5
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_DOCUMENTOBJECTGROUP_H
#define APP_DOCUMENTOBJECTGROUP_H
#pragma once
#include "DocumentObject.h"
#include "FeaturePython.h"
@@ -57,6 +56,3 @@ using DocumentObjectGroupPython = App::FeaturePythonT<DocumentObjectGroup>;
} // namespace App
#endif // APP_DOCUMENTOBJECTGROUP_H
+104 -54
View File
@@ -38,38 +38,49 @@ namespace sp = std::placeholders;
DocumentT::DocumentT() = default;
DocumentT::DocumentT(Document* doc)
{
document = doc->getName();
}
: document {doc->getName()}
{}
DocumentT::DocumentT(const std::string& name)
{
document = name;
}
DocumentT::DocumentT(std::string name)
: document {std::move(name)}
{}
DocumentT::DocumentT(const DocumentT& doc)
{
document = doc.document;
}
: document {doc.document}
{}
DocumentT::DocumentT(DocumentT&& doc) noexcept
: document {std::move(doc.document)}
{}
DocumentT::~DocumentT() = default;
void DocumentT::operator=(const DocumentT& doc)
DocumentT& DocumentT::operator=(const DocumentT& doc)
{
if (this == &doc) {
return;
if (this != &doc) {
document = doc.document;
}
document = doc.document;
return *this;
}
void DocumentT::operator=(const Document* doc)
DocumentT& DocumentT::operator=(DocumentT&& doc) noexcept
{
if (this != &doc) {
document = std::move(doc.document);
}
return *this;
}
DocumentT& DocumentT::operator=(const Document* doc)
{
document = doc->getName();
return *this;
}
void DocumentT::operator=(const std::string& name)
DocumentT& DocumentT::operator=(const std::string& name)
{
document = name;
return *this;
}
Document* DocumentT::getDocument() const
@@ -98,7 +109,7 @@ DocumentObjectT::DocumentObjectT(const DocumentObjectT& other)
*this = other;
}
DocumentObjectT::DocumentObjectT(DocumentObjectT&& other)
DocumentObjectT::DocumentObjectT(DocumentObjectT&& other) noexcept
{
*this = std::move(other);
}
@@ -145,7 +156,7 @@ DocumentObjectT& DocumentObjectT::operator=(const DocumentObjectT& obj)
return *this;
}
DocumentObjectT& DocumentObjectT::operator=(DocumentObjectT&& obj)
DocumentObjectT& DocumentObjectT::operator=(DocumentObjectT&& obj) noexcept
{
if (this == &obj) {
return *this;
@@ -157,7 +168,7 @@ DocumentObjectT& DocumentObjectT::operator=(DocumentObjectT&& obj)
return *this;
}
void DocumentObjectT::operator=(const DocumentObject* obj)
DocumentObjectT& DocumentObjectT::operator=(const DocumentObject* obj)
{
if (!obj || !obj->isAttachedToDocument()) {
object.clear();
@@ -171,9 +182,11 @@ void DocumentObjectT::operator=(const DocumentObject* obj)
document = obj->getDocument()->getName();
property.clear();
}
return *this;
}
void DocumentObjectT::operator=(const Property* prop)
DocumentObjectT& DocumentObjectT::operator=(const Property* prop)
{
if (!prop || !prop->hasName() || !prop->getContainer()
|| !prop->getContainer()->isDerivedFrom<App::DocumentObject>()) {
@@ -182,13 +195,14 @@ void DocumentObjectT::operator=(const Property* prop)
document.clear();
property.clear();
}
else {
auto obj = static_cast<App::DocumentObject*>(prop->getContainer());
else if (auto obj = freecad_cast<App::DocumentObject*>(prop->getContainer())) {
object = obj->getNameInDocument();
label = obj->Label.getValue();
document = obj->getDocument()->getName();
property = prop->getName();
}
return *this;
}
bool DocumentObjectT::operator==(const DocumentObjectT& other) const
@@ -217,8 +231,7 @@ std::string DocumentObjectT::getDocumentPython() const
DocumentObject* DocumentObjectT::getObject() const
{
DocumentObject* obj = nullptr;
Document* doc = getDocument();
if (doc) {
if (auto doc = getDocument()) {
obj = doc->getObject(object.c_str());
}
return obj;
@@ -229,6 +242,20 @@ const std::string& DocumentObjectT::getObjectName() const
return object;
}
const char* DocumentObjectT::getNameInDocument() const
{
return object.c_str();
}
bool DocumentObjectT::isAttachedToDocument() const
{
if (auto obj = getObject()) {
return obj->isAttachedToDocument();
}
return false;
}
const std::string& DocumentObjectT::getObjectLabel() const
{
return label;
@@ -258,9 +285,13 @@ std::string DocumentObjectT::getPropertyPython() const
Property* DocumentObjectT::getProperty() const
{
auto obj = getObject();
if (obj) {
return obj->getPropertyByName(property.c_str());
return getPropertyByName(property.c_str());
}
Property* DocumentObjectT::getPropertyByName(const char* name) const
{
if (auto obj = getObject()) {
return obj->getPropertyByName(name);
}
return nullptr;
}
@@ -271,7 +302,7 @@ SubObjectT::SubObjectT() = default;
SubObjectT::SubObjectT(const SubObjectT&) = default;
SubObjectT::SubObjectT(SubObjectT&& other)
SubObjectT::SubObjectT(SubObjectT&& other) noexcept
: DocumentObjectT(std::move(other))
, subname(std::move(other.subname))
{}
@@ -295,6 +326,8 @@ SubObjectT::SubObjectT(const char* docName, const char* objName, const char* s)
, subname(s ? s : "")
{}
SubObjectT::~SubObjectT() = default;
bool SubObjectT::operator<(const SubObjectT& other) const
{
if (getDocumentName() < other.getDocumentName()) {
@@ -323,18 +356,18 @@ SubObjectT& SubObjectT::operator=(const SubObjectT& other)
if (this == &other) {
return *this;
}
static_cast<DocumentObjectT&>(*this) = other;
static_cast<DocumentObjectT&>(*this) = other; // NOLINT
subname = other.subname;
return *this;
}
SubObjectT& SubObjectT::operator=(SubObjectT&& other)
SubObjectT& SubObjectT::operator=(SubObjectT&& other) noexcept
{
if (this == &other) {
return *this;
}
static_cast<DocumentObjectT&>(*this) = std::move(other);
subname = std::move(other.subname);
static_cast<DocumentObjectT&>(*this) = std::move(other);
return *this;
}
@@ -639,11 +672,14 @@ PropertyLinkT::PropertyLinkT(const std::vector<DocumentObject*>& objs)
}
str << "]";
toPython = str.str();
}
}
PropertyLinkT::PropertyLinkT(const std::vector<DocumentObject*>& objs,
const std::vector<std::string>& subNames)
PropertyLinkT::PropertyLinkT(
const std::vector<DocumentObject*>& objs,
const std::vector<std::string>& subNames
)
: PropertyLinkT()
{
if (!objs.empty() && objs.size() == subNames.size()) {
@@ -672,6 +708,7 @@ PropertyLinkT::PropertyLinkT(const std::vector<DocumentObject*>& objs,
}
str << "]";
toPython = str.str();
}
}
@@ -691,7 +728,8 @@ public:
if (doc) {
// NOLINTBEGIN
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(
std::bind(&Private::deletedDocument, this, sp::_1));
std::bind(&Private::deletedDocument, this, sp::_1)
);
// NOLINTEND
}
}
@@ -784,12 +822,15 @@ public:
// NOLINTBEGIN
indocument = true;
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(
std::bind(&Private::deletedDocument, this, sp::_1));
std::bind(&Private::deletedDocument, this, sp::_1)
);
App::Document* doc = obj->getDocument();
connectDocumentCreatedObject =
doc->signalNewObject.connect(std::bind(&Private::createdObject, this, sp::_1));
connectDocumentDeletedObject =
doc->signalDeletedObject.connect(std::bind(&Private::deletedObject, this, sp::_1));
connectDocumentCreatedObject = doc->signalNewObject.connect(
std::bind(&Private::createdObject, this, sp::_1)
);
connectDocumentDeletedObject = doc->signalDeletedObject.connect(
std::bind(&Private::deletedObject, this, sp::_1)
);
// NOLINTEND
}
}
@@ -864,11 +905,14 @@ DocumentObserver::DocumentObserver()
{
// NOLINTBEGIN
this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect(
std::bind(&DocumentObserver::slotCreatedDocument, this, sp::_1));
std::bind(&DocumentObserver::slotCreatedDocument, this, sp::_1)
);
this->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(
std::bind(&DocumentObserver::slotDeletedDocument, this, sp::_1));
std::bind(&DocumentObserver::slotDeletedDocument, this, sp::_1)
);
this->connectApplicationActivateDocument = App::GetApplication().signalActiveDocument.connect(
std::bind(&DocumentObserver::slotActivateDocument, this, sp::_1));
std::bind(&DocumentObserver::slotActivateDocument, this, sp::_1)
);
// NOLINTEND
}
@@ -901,15 +945,20 @@ void DocumentObserver::attachDocument(Document* doc)
// NOLINTBEGIN
this->connectDocumentCreatedObject = _document->signalNewObject.connect(
std::bind(&DocumentObserver::slotCreatedObject, this, sp::_1));
std::bind(&DocumentObserver::slotCreatedObject, this, sp::_1)
);
this->connectDocumentDeletedObject = _document->signalDeletedObject.connect(
std::bind(&DocumentObserver::slotDeletedObject, this, sp::_1));
std::bind(&DocumentObserver::slotDeletedObject, this, sp::_1)
);
this->connectDocumentChangedObject = _document->signalChangedObject.connect(
std::bind(&DocumentObserver::slotChangedObject, this, sp::_1, sp::_2));
std::bind(&DocumentObserver::slotChangedObject, this, sp::_1, sp::_2)
);
this->connectDocumentRecomputedObject = _document->signalRecomputedObject.connect(
std::bind(&DocumentObserver::slotRecomputedObject, this, sp::_1));
std::bind(&DocumentObserver::slotRecomputedObject, this, sp::_1)
);
this->connectDocumentRecomputed = _document->signalRecomputed.connect(
std::bind(&DocumentObserver::slotRecomputedDocument, this, sp::_1));
std::bind(&DocumentObserver::slotRecomputedDocument, this, sp::_1)
);
// NOLINTEND
}
}
@@ -941,8 +990,7 @@ void DocumentObserver::slotCreatedObject(const App::DocumentObject& /*Obj*/)
void DocumentObserver::slotDeletedObject(const App::DocumentObject& /*Obj*/)
{}
void DocumentObserver::slotChangedObject(const App::DocumentObject& /*Obj*/,
const App::Property& /*Prop*/)
void DocumentObserver::slotChangedObject(const App::DocumentObject& /*Obj*/, const App::Property& /*Prop*/)
{}
void DocumentObserver::slotRecomputedObject(const DocumentObject& /*Obj*/)
@@ -978,7 +1026,7 @@ void DocumentObjectObserver::removeFromObservation(App::DocumentObject* obj)
_objects.erase(obj);
}
void DocumentObjectObserver::slotCreatedDocument(const App::Document&)
void DocumentObjectObserver::slotCreatedDocument([[maybe_unused]] const App::Document& doc)
{}
void DocumentObjectObserver::slotDeletedDocument(const App::Document& Doc)
@@ -990,13 +1038,12 @@ void DocumentObjectObserver::slotDeletedDocument(const App::Document& Doc)
}
}
void DocumentObjectObserver::slotCreatedObject(const App::DocumentObject&)
void DocumentObjectObserver::slotCreatedObject([[maybe_unused]] const App::DocumentObject& obj)
{}
void DocumentObjectObserver::slotDeletedObject(const App::DocumentObject& Obj)
{
std::set<App::DocumentObject*>::iterator it =
_objects.find(const_cast<App::DocumentObject*>(&Obj));
auto it = _objects.find(const_cast<App::DocumentObject*>(&Obj));
if (it != _objects.end()) {
_objects.erase(it);
}
@@ -1005,7 +1052,10 @@ void DocumentObjectObserver::slotDeletedObject(const App::DocumentObject& Obj)
}
}
void DocumentObjectObserver::slotChangedObject(const App::DocumentObject&, const App::Property&)
void DocumentObjectObserver::slotChangedObject(
[[maybe_unused]] const App::DocumentObject& obj,
[[maybe_unused]] const App::Property& prop
)
{}
void DocumentObjectObserver::cancelObservation()
+42 -16
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_DOCUMENTOBSERVER_H
#define APP_DOCUMENTOBSERVER_H
#pragma once
#include <Base/BaseClass.h>
#include <Base/Bitmask.h>
@@ -56,17 +55,21 @@ public:
/*! Constructor */
DocumentT(Document*); // explicit bombs
/*! Constructor */
explicit DocumentT(const std::string&);
explicit DocumentT(std::string);
/*! Constructor */
DocumentT(const DocumentT&);
/*! Move constructor */
DocumentT(DocumentT&&) noexcept;
/*! Destructor */
~DocumentT();
/*! Assignment operator */
void operator=(const DocumentT&);
DocumentT& operator=(const DocumentT&);
/*! Move assignment operator */
DocumentT& operator=(DocumentT&&) noexcept;
/*! Assignment operator */
void operator=(const Document*);
DocumentT& operator=(const Document*);
/*! Assignment operator */
void operator=(const std::string&);
DocumentT& operator=(const std::string&);
bool operator==(const DocumentT& other) const
{
@@ -78,6 +81,11 @@ public:
return document < other.document;
}
explicit operator bool() const
{
return getDocument() != nullptr;
}
/*! Get a pointer to the document or 0 if it doesn't exist any more. */
Document* getDocument() const;
/*! Get the name of the document. */
@@ -104,7 +112,7 @@ public:
/*! Constructor */
DocumentObjectT(const DocumentObjectT&);
/*! Constructor */
DocumentObjectT(DocumentObjectT&&);
DocumentObjectT(DocumentObjectT&&) noexcept;
/*! Constructor */
explicit DocumentObjectT(const DocumentObject*);
/*! Constructor */
@@ -118,14 +126,24 @@ public:
/*! Assignment operator */
DocumentObjectT& operator=(const DocumentObjectT&);
/*! Assignment operator */
DocumentObjectT& operator=(DocumentObjectT&&);
DocumentObjectT& operator=(DocumentObjectT&&) noexcept;
/*! Assignment operator */
void operator=(const DocumentObject*);
DocumentObjectT& operator=(const DocumentObject*);
/*! Assignment operator */
void operator=(const Property*);
DocumentObjectT& operator=(const Property*);
/*! Equality operator */
bool operator==(const DocumentObjectT&) const;
bool operator<(const DocumentObjectT& other) const
{
return object < other.object;
}
explicit operator bool() const
{
return getObject() != nullptr;
}
/*! Get a pointer to the document or 0 if it doesn't exist any more. */
Document* getDocument() const;
/*! Get the name of the document. */
@@ -136,8 +154,13 @@ public:
DocumentObject* getObject() const;
/*! Get a pointer to the property or 0 if it doesn't exist any more. */
Property* getProperty() const;
/*! Get a pointer to the property by name or 0 if it doesn't exist any more. */
Property* getPropertyByName(const char* name) const;
/*! Get the name of the document object. */
const std::string& getObjectName() const;
/*! Get the name of the document object. */
const char* getNameInDocument() const;
bool isAttachedToDocument() const;
/*! Get the label of the document object. */
const std::string& getObjectLabel() const;
/*! Get the name of the property. */
@@ -172,11 +195,14 @@ public:
/*! Constructor */
SubObjectT();
/*! Destructor */
~SubObjectT();
/*! Constructor */
SubObjectT(const SubObjectT&);
/*! Constructor */
SubObjectT(SubObjectT&&);
SubObjectT(SubObjectT&&) noexcept;
/*! Constructor */
SubObjectT(const DocumentObjectT& obj, const char* subname);
@@ -194,7 +220,7 @@ public:
SubObjectT& operator=(const SubObjectT&);
/*! Assignment operator */
SubObjectT& operator=(SubObjectT&&);
SubObjectT& operator=(SubObjectT&&) noexcept;
/*! Assignment operator */
SubObjectT& operator=(const DocumentObjectT&);
@@ -357,7 +383,9 @@ public:
// disable
DocumentWeakPtrT(const DocumentWeakPtrT&) = delete;
DocumentWeakPtrT(DocumentWeakPtrT&&) = delete;
DocumentWeakPtrT& operator=(const DocumentWeakPtrT&) = delete;
DocumentWeakPtrT& operator=(DocumentWeakPtrT&&) = delete;
private:
class Private;
@@ -425,8 +453,6 @@ public:
private:
App::DocumentObject* _get() const noexcept;
private:
class Private;
std::unique_ptr<Private> d;
};
@@ -508,7 +534,9 @@ public:
// disable
WeakPtrT(const WeakPtrT&) = delete;
WeakPtrT(WeakPtrT&&) = delete;
WeakPtrT& operator=(const WeakPtrT&) = delete;
WeakPtrT& operator=(WeakPtrT&&) = delete;
private:
DocumentObjectWeakPtrT ptr;
@@ -628,5 +656,3 @@ struct std::hash<App::DocumentObjectWeakPtrT>
};
ENABLE_BITMASK_OPERATORS(App::SubObjectT::NormalizeOption)
#endif // APP_DOCUMENTOBSERVER_H
+1 -4
View File
@@ -23,8 +23,7 @@
***************************************************************************/
#ifndef APP_DOCUMENTOBSERVERPYTHON_H
#define APP_DOCUMENTOBSERVERPYTHON_H
#pragma once
#include <FCGlobal.h>
#include <fastsignals/signal.h>
@@ -165,5 +164,3 @@ private:
};
} // namespace App
#endif // APP_DOCUMENTOBSERVERPYTHON_H
+38 -11
View File
@@ -411,22 +411,40 @@ PyObject* DocumentPy::addObject(PyObject* args, PyObject* kwd)
PyObject* DocumentPy::removeObject(PyObject* args)
{
char* sName;
if (!PyArg_ParseTuple(args, "s", &sName)) {
return nullptr;
}
char* sName {};
if (PyArg_ParseTuple(args, "s", &sName)) {
DocumentObject* object = getDocumentPtr()->getObject(sName);
if (object) {
getDocumentPtr()->removeObject(sName);
Py_Return;
}
DocumentObject* pcFtr = getDocumentPtr()->getObject(sName);
if (pcFtr) {
getDocumentPtr()->removeObject(sName);
Py_Return;
}
else {
std::stringstream str;
str << "No document object found with name '" << sName << "'" << std::ends;
throw Py::ValueError(str.str());
}
PyErr_Clear();
PyObject* objpy {};
if (PyArg_ParseTuple(args, "O!", &App::DocumentObjectPy::Type, &objpy)) {
DocumentObject* object = static_cast<App::DocumentObjectPy*>(objpy)->getDocumentObjectPtr();
if (!object) {
PyErr_Format(PyExc_RuntimeError, "Invalid document object");
return nullptr;
}
if (object->getDocument() == getDocumentPtr()) {
getDocumentPtr()->removeObject(object);
Py_Return;
}
std::stringstream str;
str << "Document object is not part of this document";
throw Py::ValueError(str.str());
}
PyErr_SetString(PyExc_TypeError, "Expect str or DocumentObject");
return nullptr;
}
PyObject* DocumentPy::copyObject(PyObject* args, PyObject* kwd)
@@ -1157,6 +1175,15 @@ PyObject* DocumentPy::getDependentDocuments(PyObject* args)
}
PY_CATCH;
}
PyObject* DocumentPy::getBookedTransactionID(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
int tid = getDocumentPtr()->getBookedTransactionID();
return Py::new_reference_to(Py::Long(tid));
}
Py::Boolean DocumentPy::getRestoring() const
{
+65 -23
View File
@@ -26,6 +26,12 @@
#include <vector>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <Base/Reader.h>
#include <Base/Tools.h>
#include <Base/UniqueNameManager.h>
@@ -42,8 +48,38 @@ FC_LOG_LEVEL_INIT("Property", true, true)
using namespace App;
std::size_t CStringHasher::operator()(const char* s) const {
if (!s) {
return 0;
}
return boost::hash_range(s, s + std::strlen(s));
}
DynamicProperty::DynamicProperty() = default;
bool CStringHasher::operator()(const char* a, const char* b) const {
if (!a) {
return !b;
}
if (!b) {
return false;
}
return std::strcmp(a, b) == 0;
}
namespace bmi = boost::multi_index;
struct DynamicProperty::Impl {
bmi::multi_index_container<
PropData,
bmi::indexed_by<
bmi::hashed_unique<bmi::const_mem_fun<PropData, const char*, &PropData::getName>,
CStringHasher,
CStringHasher>,
bmi::hashed_unique<bmi::member<PropData, Property*, &PropData::property>>>>
props;
};
DynamicProperty::DynamicProperty(): impl(std::make_unique<Impl>()) {};
DynamicProperty::~DynamicProperty()
{
@@ -52,7 +88,7 @@ DynamicProperty::~DynamicProperty()
void DynamicProperty::clear()
{
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
for (auto& v : index) {
delete v.property;
}
@@ -61,7 +97,7 @@ void DynamicProperty::clear()
void DynamicProperty::getPropertyList(std::vector<Property*>& List) const
{
for (auto& v : props.get<0>()) {
for (auto& v : impl->props.get<0>()) {
List.push_back(v.property);
}
}
@@ -69,27 +105,27 @@ void DynamicProperty::getPropertyList(std::vector<Property*>& List) const
void DynamicProperty::getPropertyNamedList(
std::vector<std::pair<const char*, Property*>>& List) const
{
for (auto& v : props.get<0>()) {
for (auto& v : impl->props.get<0>()) {
List.emplace_back(v.getName(), v.property);
}
}
void DynamicProperty::visitProperties(const std::function<void(Property*)>& visitor) const {
for (auto& v : props.get<0>()) {
for (auto& v : impl->props.get<0>()) {
visitor(v.property);
}
}
void DynamicProperty::getPropertyMap(std::map<std::string,Property*>& Map) const
{
for (auto& v : props.get<0>()) {
for (auto& v : impl->props.get<0>()) {
Map[v.name] = v.property;
}
}
Property* DynamicProperty::getDynamicPropertyByName(const char* name) const
{
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
auto it = index.find(name);
if (it != index.end()) {
return it->property;
@@ -100,7 +136,7 @@ Property* DynamicProperty::getDynamicPropertyByName(const char* name) const
std::vector<std::string> DynamicProperty::getDynamicPropertyNames() const
{
std::vector<std::string> names;
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
names.reserve(index.size());
for (auto& v : index) {
names.push_back(v.name);
@@ -115,7 +151,7 @@ short DynamicProperty::getPropertyType(const Property* prop) const
short DynamicProperty::getPropertyType(const char* name) const
{
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
auto it = index.find(name);
if (it != index.end()) {
short attr = it->attr;
@@ -132,7 +168,7 @@ short DynamicProperty::getPropertyType(const char* name) const
const char* DynamicProperty::getPropertyGroup(const Property* prop) const
{
auto& index = props.get<1>();
auto& index = impl->props.get<1>();
auto it = index.find(const_cast<Property*>(prop));
if (it != index.end()) {
return it->group.c_str();
@@ -142,7 +178,7 @@ const char* DynamicProperty::getPropertyGroup(const Property* prop) const
const char* DynamicProperty::getPropertyGroup(const char* name) const
{
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
auto it = index.find(name);
if (it != index.end()) {
return it->group.c_str();
@@ -152,7 +188,7 @@ const char* DynamicProperty::getPropertyGroup(const char* name) const
const char* DynamicProperty::getPropertyDocumentation(const Property* prop) const
{
auto& index = props.get<1>();
auto& index = impl->props.get<1>();
auto it = index.find(const_cast<Property*>(prop));
if (it != index.end()) {
return it->doc.c_str();
@@ -160,9 +196,15 @@ const char* DynamicProperty::getPropertyDocumentation(const Property* prop) cons
return nullptr;
}
size_t DynamicProperty::size() const
{
return impl->props.size();
}
const char* DynamicProperty::getPropertyDocumentation(const char* name) const
{
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
auto it = index.find(name);
if (it != index.end()) {
return it->doc.c_str();
@@ -228,7 +270,7 @@ Property* DynamicProperty::addDynamicProperty(PropertyContainer& pc,
Property* pcProperty = static_cast<Property*>(propInstance);
auto res = props.get<0>().emplace(pcProperty, name, nullptr, group, doc, attr, ro, hidden);
auto res = impl->props.get<0>().emplace(pcProperty, name, nullptr, group, doc, attr, ro, hidden);
pcProperty->setContainer(&pc);
pcProperty->myName = res.first->name.c_str();
@@ -253,7 +295,7 @@ bool DynamicProperty::addProperty(Property* prop)
if (!prop || !prop->hasName()) {
return false;
}
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
#if BOOST_VERSION < 107500
if (index.count(prop->getName())) {
return false;
@@ -276,7 +318,7 @@ bool DynamicProperty::addProperty(Property* prop)
bool DynamicProperty::removeProperty(const Property* prop)
{
auto& index = props.get<1>();
auto& index = impl->props.get<1>();
auto it = index.find(const_cast<Property*>(prop));
if (it != index.end()) {
index.erase(it);
@@ -287,7 +329,7 @@ bool DynamicProperty::removeProperty(const Property* prop)
bool DynamicProperty::removeDynamicProperty(const char* name)
{
auto& index = props.get<0>();
auto& index = impl->props.get<0>();
auto it = index.find(name);
if (it != index.end()) {
if (it->property->testStatus(Property::LockDynamic)) {
@@ -333,7 +375,7 @@ std::string DynamicProperty::getUniquePropertyName(const PropertyContainer& pc,
void DynamicProperty::save(const Property* prop, Base::Writer& writer) const
{
auto& index = props.get<1>();
auto& index = impl->props.get<1>();
auto it = index.find(const_cast<Property*>(prop));
if (it != index.end()) {
auto& data = *it;
@@ -385,7 +427,7 @@ Property* DynamicProperty::restore(PropertyContainer& pc,
DynamicProperty::PropData DynamicProperty::getDynamicPropertyData(const Property* prop) const
{
auto& index = props.get<1>();
auto& index = impl->props.get<1>();
auto it = index.find(const_cast<Property*>(prop));
if (it != index.end()) {
return *it;
@@ -397,7 +439,7 @@ bool DynamicProperty::changeDynamicProperty(const Property* prop,
const char* group,
const char* doc)
{
auto& index = props.get<1>();
auto& index = impl->props.get<1>();
auto it = index.find(const_cast<Property*>(prop));
if (it == index.end()) {
return false;
@@ -414,7 +456,7 @@ bool DynamicProperty::changeDynamicProperty(const Property* prop,
bool DynamicProperty::renameDynamicProperty(Property* prop,
const char* newName)
{
auto& propIndex = props.get<1>();
auto& propIndex = impl->props.get<1>();
auto propIt = propIndex.find(prop);
if (propIt == propIndex.end()) {
return false;
@@ -436,7 +478,7 @@ bool DynamicProperty::renameDynamicProperty(Property* prop,
}
std::string oldName{data.getName()};
auto& nameIndex = props.get<0>();
auto& nameIndex = impl->props.get<0>();
auto nameIt = nameIndex.find(data.getName());
if (nameIt == nameIndex.end()) {
// This should never happen
@@ -458,7 +500,7 @@ bool DynamicProperty::renameDynamicProperty(Property* prop,
const char* DynamicProperty::getPropertyName(const Property* prop) const
{
auto& index = props.get<1>();
auto& index = impl->props.get<1>();
auto it = index.find(const_cast<Property*>(prop));
if (it != index.end()) {
return it->getName();
+10 -42
View File
@@ -23,19 +23,15 @@
***************************************************************************/
#ifndef SRC_APP_DYNAMICPROPERTY_H_
#define SRC_APP_DYNAMICPROPERTY_H_
#pragma once
#include <map>
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include <functional>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <FCGlobal.h>
@@ -51,27 +47,10 @@ namespace App
class Property;
class PropertyContainer;
namespace bmi = boost::multi_index;
struct CStringHasher
struct AppExport CStringHasher
{
inline std::size_t operator()(const char* s) const
{
if (!s) {
return 0;
}
return boost::hash_range(s, s + std::strlen(s));
}
inline bool operator()(const char* a, const char* b) const
{
if (!a) {
return !b;
}
if (!b) {
return false;
}
return std::strcmp(a, b) == 0;
}
std::size_t operator()(const char* s) const;
bool operator()(const char* a, const char* b) const;
};
/** This class implements an interface to add properties at run-time to an object
@@ -161,10 +140,7 @@ public:
void clear();
/// Get property count
size_t size() const
{
return props.size();
}
size_t size() const;
void save(const Property* prop, Base::Writer& writer) const;
@@ -218,16 +194,8 @@ private:
std::string getUniquePropertyName(const PropertyContainer& pc, const char* Name) const;
private:
bmi::multi_index_container<
PropData,
bmi::indexed_by<
bmi::hashed_unique<bmi::const_mem_fun<PropData, const char*, &PropData::getName>,
CStringHasher,
CStringHasher>,
bmi::hashed_unique<bmi::member<PropData, Property*, &PropData::property>>>>
props;
struct Impl;
std::unique_ptr<Impl> impl;
};
} // namespace App
#endif // SRC_APP_DYNAMICPROPERTY_H_
} // namespace App

Some files were not shown because too many files have changed in this diff Show More