Merge branch 'master' into path_custom_source

This commit is contained in:
Morgan 'ARR\!' Allen
2023-04-20 18:39:18 -07:00
1987 changed files with 250634 additions and 243856 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
Checks: 'clang-diagnostic-*,clang-analyzer-*,boost-*,bugprone-*,
performance-*,readability-*,portability-*,modernize-*,cppcoreguidelines-*,
concurrency-*,-modernize-use-trailing-return-type, -modernize-use-nodiscard,
-readability-redundant-access-specifiers'
-readability-redundant-access-specifiers,-readability-qualified-auto'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
+3 -1
View File
@@ -63,4 +63,6 @@ b389f6e602eb42c07c21f37fbcd451e28dd9fbc4
48365a1df5286c7a5608cd3a5cce0def5e4d5380
dc5b3cb495002951c3a36c928c55108b0999bc3e
875f9eaad6a59abd70775c0b67a7f10d92128a5a
7a8a453746a8e4a845219948591fd17f4494a067
7a8a453746a8e4a845219948591fd17f4494a067
8b31d7deb09077bc0cce0ecf6de02c94db262a67
+110
View File
@@ -0,0 +1,110 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * *
# * Copyright (c) 2023 0penBrain. *
# * *
# * 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/>. *
# * *
# ***************************************************************************
# This workflow is a complementary one to the master CI.
# It aims at doing cleanup operations after a CI workflow ran.
# Being triggered when the master workflow ends allows it to run with necessary privileges.
# Indeed it always run with push-like rights even for PR events.
# In order to work, this cleanup workflow imposes name formatting for caches
# Caches that have to be cleaned (typically compiler caches) shall be named as below :
# ${MARK}-${CONTEXT}-${REF}-${ID}
# with :
# ${MARK} => A mark identifying a cache to be cleaned, defined as being "FC" (without quotes)
# ${CONTEXT} => A string identifying cache saving context, typically OS name or compiler name
# ${REF} => The full reference of the branch owning the cache (starting with "/refs/pull/" or "/refs/heads/")
# ${ID} => A cache unique identifier, generally an ascending number, in no case containing a '-' (hyphen) sign
name: FreeCAD CI cleaner
on:
workflow_run:
workflows: [FreeCAD master CI]
types:
- completed
env:
dryrun: false
concurrency:
group: FC-CI-cleaner
cancel-in-progress: false
jobs:
CachesCleanup:
runs-on: ubuntu-latest
env:
logdir: /tmp/log/
steps:
- name: Make needed directories
run: |
mkdir -p ${{ env.logdir }}
- name: Get existing caches for the repo
run: |
curl -H "Accept: application/vnd.github+json" -H "authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" $GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/caches > ${{ env.logdir }}caches.json
- name: Extract pull request caches
run: |
# Extract caches of which names starts with MARK and contains "/refs/pull/"
jq ".actions_caches | map(select(.key | startswith(\"FC-\"))) | map(select(.key | contains(\"refs/pull/\")))" ${{ env.logdir }}caches.json > ${{ env.logdir }}pulls.json
- name: Extract and delete pull request obsolete cache IDs
run: |
# Group the caches by MARK-CONTEXT-REF, sort by ascending last access datetime and keep all but the last as to be deleted
# As a consequence, for pull requests, only the most recent cache is kept (one for each context and for each PR)
PRID=$(jq "group_by(.key | .[:rindex(\"-\")]) | .[] | sort_by(.last_accessed_at) | .[:-1][].id" ${{ env.logdir }}pulls.json)
for id in $PRID
do
echo "Trying to delete pull request obsolete cache ID : $id"
if [ ${{ env.dryrun }} == "false" ]
then
curl -X DELETE -H "Accept: application/vnd.github+json" -H "authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" $GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/caches/$id
else
echo "DRYRUN: executing : curl -X DELETE -H \"Accept: application/vnd.github+json\" $GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/caches/$id"
fi
done
- name: Extract push caches
run: |
# Extract caches of which names starts with MARK and contains "/refs/heads/"
jq ".actions_caches | map(select(.key | startswith(\"FC-\"))) | map(select(.key | contains(\"refs/heads/\")))" ${{ env.logdir }}caches.json > ${{ env.logdir }}pushes.json
- name: Extract and delete push obsolete cache IDs
run: |
# Group the caches by MARK-CONTEXT-REF, sort by ascending last access datetime, keep all but the last 2 and keep all accessed for more than 1 hour as to be deleted
# As a consequence, for pushes (repo branches), at least 2 caches (for each context and for each branch) are kept, others are deleted if they have been useless for more than 1 hour
PSID=$(jq "group_by(.key | .[:rindex(\"-\")]) | .[] | sort_by(.last_accessed_at) | .[:-2][] | select((.last_accessed_at | if contains(\".\") then .[:rindex(\".\")]+\"Z\" else . end | fromdateiso8601) < (now | floor - 3600)) | .id" ${{ env.logdir }}pushes.json)
for id in $PSID
do
echo "Trying to delete push obsolete cache ID : $id"
if [ ${{ env.dryrun }} == "false" ]
then
curl -X DELETE -H "Accept: application/vnd.github+json" -H "authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" $GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/caches/$id
else
echo "DRYRUN: executing : curl -X DELETE -H \"Accept: application/vnd.github+json\" $GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/caches/$id"
fi
done
- name: Upload logs
if: always()
uses: actions/upload-artifact@v3
with:
name: ${{ github.job }}-Logs
path: |
${{ env.logdir }}
+25 -17
View File
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
@@ -41,13 +43,19 @@ jobs:
needs: [Prepare]
uses: ./.github/workflows/sub_buildUbuntu2004.yml
with:
artifactBasename: Build2004-${{ github.run_id }}
artifactBasename: Ubuntu_20-04-${{ github.run_id }}
Ubuntu_22-04:
needs: [Prepare]
uses: ./.github/workflows/sub_buildUbuntu2204.yml
with:
artifactBasename: Build2204-${{ github.run_id }}
artifactBasename: Ubuntu_22-04-${{ github.run_id }}
Windows:
needs: [Prepare]
uses: ./.github/workflows/sub_buildWindows.yml
with:
artifactBasename: Windows-${{ github.run_id }}
Lint:
needs: [Prepare]
@@ -59,7 +67,7 @@ jobs:
changedPythonFiles: ${{ needs.Prepare.outputs.changedPythonFiles }}
WrapUp:
needs: [Prepare, Ubuntu_20-04, Ubuntu_22-04, Lint]
needs: [Prepare, Ubuntu_20-04, Ubuntu_22-04, Windows, Lint]
if: always()
uses: ./.github/workflows/sub_wrapup.yml
with:
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
@@ -1,27 +1,29 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * Copyright (c) 2023 0penBrain. *
# * Copyright (c) 2023 FreeCAD Project Association *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * This file is part of FreeCAD. *
# * *
# * This program 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 Library General Public License for more details. *
# * 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. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
name: runCPPTests
description: "Run: C++ tests"
description: "Run C++ tests, generate log and report"
inputs:
testCommand:
@@ -37,8 +39,7 @@ inputs:
runs:
using: "composite"
steps:
- name: Run GTest unit tests
id: runGoogleTests
- name: Run C++ unit tests
shell: bash
run: stdbuf -oL -eL ${{ inputs.testCommand }} |& tee -a ${{ inputs.testLogFile }}
- name: Parse test results
@@ -1,26 +1,28 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
name: runPythonTests
description: "Linux: run Python tests, generate log and report"
description: "Run Python tests, generate log and report"
inputs:
testDescription:
@@ -0,0 +1,78 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * *
# * Copyright (c) 2023 0penBrain. *
# * *
# * 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/>. *
# * *
# ***************************************************************************
# This action aims at speeding up CI and reduce dependency to external resources
# by creating a cache of Ccache needed binaries then using it for CI runs rather
# than downloading every time.
#
# If it needs to be updated to another version, the process it to change
# 'downloadpath' and 'version' inputs below then delete the existing cache
# from Github interface so a new one is generated using new values.
name: getCcache
description: "Windows: tries to get a cached version of Ccache and create one if fails"
inputs:
ccachebindir:
description: "Directory where ccache binaries shall be stored"
required: true
# Below inputs shall generally not be provided as they won't be used if a cached version exists
# They are mainly used because Github do not support adding env variables in a composite action
ccachedownloadpath:
description: "Path where to download ccache"
required: false
default: https://github.com/ccache/ccache/releases/download/v4.7.4/
ccacheversion:
description: "Ccache version to be downloaded"
required: false
default: ccache-4.7.4-windows-x86_64
runs:
using: "composite"
steps:
- name: Create destination directory
shell: bash
run: |
mkdir -p ${{ inputs.ccachebindir }}
- name: Get cached version
uses: actions/cache/restore@v3
id: getCached
with:
path: ${{ inputs.ccachebindir }}
key: ccacheforwin
- name: Download ccache
shell: bash
if: steps.getCached.outputs.cache-hit != 'true'
run: |
curl -L -o ccache.zip ${{ inputs.ccachedownloadpath }}${{ inputs.ccacheversion }}.zip
7z x ccache.zip -o"ccachetemp" -r -y
cp -a ccachetemp/${{ inputs.ccacheversion }}/ccache.exe ${{ inputs.ccachebindir }}
cp -a ccachetemp/${{ inputs.ccacheversion }}/ccache.exe ${{ inputs.ccachebindir }}/cl.exe
rm ccache.zip
rm -rf ccachetemp
- name: Save version to cache
if: steps.getCached.outputs.cache-hit != 'true'
uses: actions/cache/save@v3
with:
path: ${{ inputs.ccachebindir }}
key: ${{ steps.getCached.outputs.cache-primary-key }}
@@ -0,0 +1,76 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * *
# * Copyright (c) 2023 0penBrain. *
# * *
# * 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/>. *
# * *
# ***************************************************************************
# This action aims at speeding up CI and reduce dependency to external resources
# by creating a cache of Libpack needed files then using it for CI runs rather
# than downloading every time.
#
# If it needs to be updated to another version, the process it to change
# 'downloadpath' and 'version' inputs below then delete the existing cache
# from Github interface so a new one is generated using new values.
name: getLibpack
description: "Windows: tries to get a cached version of Libpack and create one if fails"
inputs:
libpackdir:
description: "Directory where libpack files shall be stored"
required: true
# Below inputs shall generally not be provided as they won't be used if a cached version exists
# They are mainly used because Github do not support adding env variables in a composite action
libpackdownloadurl:
description: "URL where to download libpack"
required: false
default: https://github.com/FreeCAD/FreeCAD-LibPack/releases/download/2.8.2/LibPack-OCC76-V2-8.7z
libpackname:
description: "Libpack name (once downloaded)"
required: false
default: LibPack-OCC76-V2
runs:
using: "composite"
steps:
- name: Create destination directory
shell: bash
run: |
mkdir -p ${{ inputs.libpackdir }}
- name: Get cached version
uses: actions/cache/restore@v3
id: getCached
with:
path: ${{ inputs.libpackdir }}
key: libpackforwin
- name: Download libpack
shell: bash
if: steps.getCached.outputs.cache-hit != 'true'
run: |
curl -L -o libpack.7z ${{ inputs.libpackdownloadurl }}
7z x libpack.7z -o"libpacktemp" -r -y
mv libpacktemp/${{ inputs.libpackname }}/* ${{ inputs.libpackdir }}
rm -rf libpacktemp
- name: Save version to cache
if: steps.getCached.outputs.cache-hit != 'true'
uses: actions/cache/save@v3
with:
path: ${{ inputs.libpackdir }}
key: ${{ steps.getCached.outputs.cache-primary-key }}
+16 -14
View File
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
+16 -25
View File
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
@@ -136,17 +138,6 @@ jobs:
swig \
ccache \
xvfb
- name: Install Pivy version compatible with Python 3.10
run: |
sudo apt-get purge python3-pivy
cd /tmp/
git clone --depth 1 --branch 0.6.8 https://github.com/coin3d/pivy.git
cd pivy
mkdir build
cd build
cmake ..
make -j$(nproc)
sudo make install
- name: Make needed directories, files and initializations
id: Init
run: |
+146
View File
@@ -0,0 +1,146 @@
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
# This is a build and test workflow for CI of FreeCAD.
# This workflow aims at building and testing FreeCAD on Windows using MSVC.
name: Build Windows
on:
workflow_call:
inputs:
artifactBasename:
type: string
required: true
allowedToFail:
default: false
type: boolean
required: false
outputs:
reportFile:
value: ${{ jobs.Build.outputs.reportFile }}
jobs:
Build:
runs-on: windows-latest
continue-on-error: ${{ inputs.allowedToFail }}
env:
CCACHE_DIR: C:/FC/cache/
CCACHE_COMPILERCHECK: "%compiler%" # default:mtime
CCACHE_MAXSIZE: 1G
CCACHE_COMPRESS: true
CCACHE_COMPRESSLEVEL: 1
CCACHE_NOHASHDIR: true
CCACHE_DIRECT: true
#CCACHE_SLOPPINESS: "pch_defines,time_macros" # Can't get PCH to work on Windows
CCACHE_LOGFILE: C:/logs/ccache.log
## Have to use C:\ because not enough space on workspace drive
builddir: C:/FC/build/
libpackdir: C:/FC/libpack/
ccachebindir: C:/FC/ccache/
logdir: C:/logs/
reportdir: C:/report/
reportfilename: ${{ inputs.artifactBasename }}-report.md
outputs:
reportFile: ${{ steps.Init.outputs.reportFile }}
steps:
- name: Checking out source code
uses: actions/checkout@v3
- name: Make needed directories, files and initializations
id: Init
run: |
mkdir ${{ env.CCACHE_DIR }}
mkdir ${{ env.ccachebindir }}
mkdir ${{ env.libpackdir }}
mkdir ${{ env.builddir }}
mkdir ${{ env.logdir }}
mkdir ${{ env.reportdir }}
echo "reportFile=${{ env.reportfilename }}" >> $GITHUB_OUTPUT
- name: Get Ccache
uses: ./.github/workflows/actions/windows/getCcache
with:
ccachebindir: ${{ env.ccachebindir }}
- name: Get Libpack
uses: ./.github/workflows/actions/windows/getLibpack
with:
libpackdir: ${{ env.libpackdir }}
- name: Restore compiler cache
uses: pat-s/always-upload-cache@v3
with:
path: ${{ env.CCACHE_DIR }}
key: FC-Windows-${{ github.ref }}-${{ github.run_id }}
restore-keys: |
FC-Windows-${{ github.ref }}-
FC-Windows-
- name: Print Ccache statistics before build, reset stats and print config
run: |
. $env:ccachebindir\ccache -s
. $env:ccachebindir\ccache -z
. $env:ccachebindir\ccache -p
- name: Append Libpack bin directory to Path
if: false # Disabled because not enough to set FREECAD_COPY_LIBPACK_BIN_TO_BUILD=OFF
run: |
echo "${{ env.libpackdir }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Configuring CMake
run: >
cmake -B"${{ env.builddir }}" .
-DCMAKE_VS_NO_COMPILE_BATCHING=ON
-DCMAKE_BUILD_TYPE=Release
-DFREECAD_USE_PCH=OFF
-DFREECAD_RELEASE_PDB=OFF
-DFREECAD_LIBPACK_DIR="${{ env.libpackdir }}"
-DPYTHON_DEBUG_LIBRARY="${{ env.libpackdir }}bin/libs/python38_d.lib"
-DPYTHON_EXECUTABLE="${{ env.libpackdir }}bin/python.exe"
-DPYTHON_INCLUDE_DIR="${{ env.libpackdir }}bin/include"
-DPYTHON_LIBRARY="${{ env.libpackdir }}bin/libs/python38.lib"
-DXercesC_INCLUDE_DIR="${{ env.libpackdir }}include"
-DXercesC_LIBRARY_RELEASE="${{ env.libpackdir }}lib/xerces-c_3.lib"
-DXercesC_LIBRARY_DEBUG="${{ env.libpackdir }}lib/xerces-c_3D.lib"
-DFREECAD_COPY_DEPEND_DIRS_TO_BUILD=ON
-DFREECAD_COPY_LIBPACK_BIN_TO_BUILD=OFF
-DFREECAD_COPY_PLUGINS_BIN_TO_BUILD=ON
- name: Add msbuild to PATH
uses: microsoft/[email protected]
- name: Compiling sources
run: |
cd $env:builddir
msbuild ALL_BUILD.vcxproj /m /p:Configuration=Release /p:TrackFileAccess=false /p:CLToolPath=${{ env.ccachebindir }}
- name: Print Ccache statistics after build
run: |
. $env:ccachebindir\ccache -s
- name: Move libpack bin folder to build folder # Shorter in time than copying with CMake FREECAD_COPY_LIBPACK_BIN_TO_BUILD
run: |
Move-Item -Force -Path ${{ env.libpackdir }}bin -Destination ${{ env.builddir }}
- name: C++ unit tests
if: false # Disabled because seems to not exist on Windows build
timeout-minutes: 1
run: |
. ${{ env.builddir }}\test\Tests_run --gtest_output=json:${{ env.reportdir }}gtest_results.json # 2>&1 | tee -filepath ${{ env.logdir }}\unitTests.log
- name: FreeCAD CLI tests
run: |
. ${{ env.builddir }}\bin\FreeCADCmd -t 0 # 2>&1 | tee -filepath ${{ env.logdir }}\integrationTests.log
- name: Upload logs
if: always()
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.artifactBasename }}-Logs
path: |
${{ env.logdir }}
+25 -18
View File
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
@@ -91,7 +93,7 @@ on:
type: boolean
required: false
pylintDisable:
default: disable=C0302
default: C0302,C0303 # Trailing whitespaces (C0303) are already checked
type: string
required: false
pylintFailSilent:
@@ -310,7 +312,6 @@ jobs:
if: inputs.checkPylint && inputs.changedPythonFiles != '' && always()
continue-on-error: ${{ inputs.pylintFailSilent }}
run: |
set +e
pylintErrors=0
pylintWarnings=0
pylintRefactorings=0
@@ -319,8 +320,10 @@ jobs:
# List enabled pylint checks
pylint --list-msgs-enabled > ${{ env.logdir }}pylint-enabled-checks.log
# Run pylint on all python files
set +e
pylint --disable=${{ inputs.pylintDisable }} ${{ inputs.changedPythonFiles }} > ${{ env.logdir }}pylint.log
exitCode=$?
set -e
# If pylint has run successfully, write the Log to the console with the Problem Matchers
if [ -f ${{ env.logdir }}pylint.log ]
then
@@ -371,12 +374,13 @@ jobs:
if: inputs.checkBlack && inputs.changedPythonFiles != '' && always()
continue-on-error: ${{ inputs.blackFailSilent }}
run: |
set +e
blackReformats=0
blackFails=0
pip install black
set +e
black --check ${{ inputs.changedPythonFiles }} &> ${{ env.logdir }}black.log
exitCode=$?
set -e
# If black has run successfully, write the Log to the console with the Problem Matchers
if [ -f ${{ env.logdir }}black.log ]
then
@@ -583,7 +587,9 @@ jobs:
pip install codespell
wget https://raw.githubusercontent.com/codespell-project/codespell/master/codespell_lib/data/dictionary.txt
#wget https://raw.githubusercontent.com/codespell-project/codespell/master/codespell_lib/data/dictionary_rare.txt
set +e
misspellings=$( { codespell --quiet-level 3 --summary --count --ignore-words ${{ inputs.listIgnoredMisspelling }} --skip ${{ inputs.spellingIgnore }} -D dictionary.txt ${{ inputs.changedFiles }} > ${{ env.logdir }}codespell.log ; } 2>&1 )
set -e
# If codespell has run successfully, write the Log to the console with the Problem Matchers
if [ -f ${{ env.logdir }}codespell.log ]
then
@@ -612,7 +618,6 @@ jobs:
if: inputs.checkClangTidy && inputs.changedCppFiles != '' && always()
continue-on-error: ${{ inputs.clangTidyFailSilent }}
run: |
set +e
clangTidyErrors=0
clangTidyWarnings=0
clangTidyNotes=0
@@ -620,8 +625,10 @@ jobs:
#TODO: check where this "clang-tidy.yaml" goes ; shall this be put in the fixes ?
clang-tidy --quiet --format-style=${{ inputs.clangStyle }} --export-fixes=clang-tidy.yaml -checks=${{ inputs.clangTidyChecks }} -p build/ --explain-config &>> ${{ env.logdir }}clang-tidy-enabled-checks.log
# Run clang-tidy on all cpp files
set +e
clang-tidy --quiet --format-style=${{ inputs.clangStyle }} --export-fixes=clang-tidy.yaml -checks=${{ inputs.clangTidyChecks }} -p build/ ${{ inputs.changedCppFiles }} &>> ${{ env.logdir }}clang-tidy.log
exitCode=$?
set -e
# If clang-tidy has run successfully, write the Log to the console with the Problem Matchers
if [ -f ${{ env.logdir }}clang-tidy.log ]
then
+16 -14
View File
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
+16 -14
View File
@@ -1,21 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2023 0penBrain *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * Copyright (c) 2023 0penBrain. *
# * *
# * This program 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 Library General Public License for more details. *
# * This file is part of FreeCAD. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * 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/>. *
# * *
# ***************************************************************************
+1
View File
@@ -16,6 +16,7 @@
*.manifest
*.o
*.orig
*.output
qrc_*.cpp
BuildLog.htm
cmake_install.cmake
+27
View File
@@ -0,0 +1,27 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
files: |
(?x)^(
src/Mod/AddonManager|
tests/src
)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: mixed-line-ending
args: [--fix=lf]
- repo: https://github.com/psf/black
rev: 22.10.0
hooks:
- id: black
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v15.0.7
hooks:
- id: clang-format
+1
View File
@@ -0,0 +1 @@
environment.yml
+12
View File
@@ -0,0 +1,12 @@
{
"configurations": [
{
"name": "FreeCAD",
"includePath": ["${workspaceFolder}/**"],
"cStandard": "c17",
"cppStandard": "c++17",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
+18
View File
@@ -0,0 +1,18 @@
[
{
"name": "FreeCAD Linux",
"compilers": {
"C": "${workspaceFolder}/.conda/freecad/bin/cc",
"CXX": "${workspaceFolder}/.conda/freecad/bin/c++"
},
"environmentSetupScript": "${workspaceFolder}/.vscode/env.sh"
},
{
"name": "FreeCAD macOS",
"compilers": {
"C": "${workspaceFolder}/.conda/freecad/bin/clang",
"CXX": "${workspaceFolder}/.conda/freecad/bin/clang++"
},
"environmentSetupScript": "${workspaceFolder}/.vscode/env.sh"
}
]
Vendored Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
source activate freecad
+6
View File
@@ -0,0 +1,6 @@
{
"recommendations": [
"ms-vscode.cpptools-extension-pack",
"ms-python.python"
]
}
+48
View File
@@ -0,0 +1,48 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C/C++: Linux: build and debug FreeCAD",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/FreeCAD",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"preLaunchTask": "CMake: build"
},
{
"name": "C/C++: macOS: build and debug FreeCAD",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/FreeCAD",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "lldb",
"preLaunchTask": "CMake: build"
},
{
"name": "Python: Remote Attach",
"type": "python",
"request": "attach",
"preLaunchTask": "conda: activate environment",
"redirectOutput": true,
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}"
}
],
"justMyCode": false
}
]
}
+17
View File
@@ -0,0 +1,17 @@
{
"files.associations": {
"__config": "cpp",
"iosfwd": "cpp",
"vector": "cpp",
"tuple": "cpp"
},
"editor.formatOnType": true,
"cmake.preferredGenerators": ["Ninja", "NMake Makefiles"],
"cmake.cmakePath": "${workspaceFolder}/.conda/freecad/bin/cmake",
"cmake.configureSettings": {
"BUILD_WITH_CONDA:BOOL": "ON",
"BUILD_FEM_NETGEN:BOOL": "ON",
"FREECAD_USE_PYBIND11:BOOL": "ON",
"FREECAD_USE_EXTERNAL_SMESH:BOOL": "ON"
}
}
+58
View File
@@ -0,0 +1,58 @@
{
"tasks": [
{
"type": "shell",
"label": "conda: activate environment",
"command": "activate freecad",
"problemMatcher": [],
"detail": "Activate conda environment",
"group": "build"
},
{
"type": "cmake",
"label": "CMake: configure",
"command": "configure",
"problemMatcher": [],
"detail": "CMake template configure task",
"group": "build"
},
{
"type": "cmake",
"label": "CMake: build",
"command": "build",
"targets": ["all"],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"detail": "CMake template build task"
},
{
"type": "cmake",
"label": "CMake: test",
"command": "test",
"problemMatcher": [],
"detail": "CMake template test task",
"group": "build"
},
{
"type": "cmake",
"label": "CMake: clean",
"command": "clean",
"problemMatcher": [],
"detail": "CMake template clean task",
"group": "build"
},
{
"type": "cmake",
"label": "CMake: clean rebuild",
"command": "cleanRebuild",
"targets": ["all"],
"problemMatcher": [],
"detail": "CMake template clean rebuild task",
"group": "build"
}
],
"version": "2.0.0"
}
+32
View File
@@ -0,0 +1,32 @@
# Security Policy
The FreeCAD project is a FOSS (Free and Open-Source Software) project that has a community of thousands of users and
hundreds of developers worldwide. We encourage responsible reporting of security vulnerabilities that may affect users
of this software, and will endeavor to address these vulnerabilities when they are discovered.
## Bounties
FreeCAD does not have a program to pay bounties for security bugs. If you discover a vulnerability that affects a part
of the FreeCAD project (either directly in FreeCAD, in a library it depends on, or in any of the various other
subprojects such as our website, forums, etc.) we ask you to join the large community of volunteer contributors and
file a report about the issue.
Note that funds may be available from the [FreeCAD Project Association (FPA)](https://fpa.freecad.org) to pursue
security research and/or the development of fixes to any vulnerabilities discovered. However, vulnerabilities held as
hostage in demands for "bounties" will not be entertained. Contact the FPA at fpa@freecad.org for more information.
## Supported Versions
FreeCAD implements security fixes to the current release series, and to the current development on the master branch.
| Version | Supported |
|---------| ------------------ |
| 0.21 | :white_check_mark: |
| 0.20.2 | :white_check_mark: |
| < 0.20 | :x: |
## Reporting a Vulnerability
To report a vulnerability use GitHub's security reporting tool:
https://github.com/FreeCAD/FreeCAD/security/advisories/new
@@ -25,7 +25,6 @@ macro(InitializeFreeCADBuildOptions)
option(FREECAD_RELEASE_PDB "Create PDB files for Release version." ON)
option(FREECAD_RELEASE_SEH "Enable Structured Exception Handling for Release version." ON)
option(FREECAD_LIBPACK_USE "Use the LibPack to Build FreeCAD (only Win32 so far)." ON)
option(FREECAD_LIBPACK_USEPYSIDE "Use PySide in LibPack rather to PyQt and Swig." ON)
option(FREECAD_USE_PCH "Activate precompiled headers where it's used." ON)
if (DEFINED ENV{FREECAD_LIBPACK_DIR})
@@ -104,11 +103,9 @@ macro(InitializeFreeCADBuildOptions)
option(BUILD_TEMPLATE "Build the FreeCAD template module which is only for testing purposes" OFF)
option(BUILD_ADDONMGR "Build the FreeCAD addon manager module" ON)
option(BUILD_ARCH "Build the FreeCAD Architecture module" ON)
option(BUILD_COMPLETE "Build the FreeCAD complete module" OFF)
option(BUILD_DRAFT "Build the FreeCAD draft module" ON)
option(BUILD_DRAWING "Build the FreeCAD drawing module" OFF)
option(BUILD_IDF "Build the FreeCAD idf module" ON)
option(BUILD_IMAGE "Build the FreeCAD image module" ON)
option(BUILD_IMPORT "Build the FreeCAD import module" ON)
option(BUILD_INSPECTION "Build the FreeCAD inspection module" ON)
option(BUILD_JTREADER "Build the FreeCAD jt reader module" OFF)
-1
View File
@@ -88,7 +88,6 @@ RUN apt-get install -y \
python3-matplotlib \
python3-pivy \
python3-ply \
python3-pyqt5 \
python3-pyside2.* \
python3-pyside2.qtcore \
python3-pyside2.qtgui \
+5
View File
@@ -0,0 +1,5 @@
name: freecad
channels:
- conda-forge
dependencies:
- conda-devenv
+98
View File
@@ -0,0 +1,98 @@
name: freecad
channels:
- conda-forge
dependencies:
- kernel-headers_linux-64 # [linux and x86_64]
- libdrm-cos6-x86_64 # [linux and x86_64]
- libselinux-cos6-x86_64 # [linux and x86_64]
- libsepol-cos6-x86_64 # [linux and x86_64]
- libx11-common-cos6-x86_64 # [linux and x86_64]
- libx11-cos6-x86_64 # [linux and x86_64]
- libxau-cos6-x86_64 # [linux and x86_64]
- libxcb-cos6-x86_64 # [linux and x86_64]
- libxdamage-cos6-x86_64 # [linux and x86_64]
- libxext-cos6-x86_64 # [linux and x86_64]
- libxfixes-cos6-x86_64 # [linux and x86_64]
- libxi-cos6-x86_64 # [linux and x86_64]
- libxi-devel-cos6-x86_64 # [linux and x86_64]
- libxxf86vm-cos6-x86_64 # [linux and x86_64]
- mesa-dri-drivers-cos6-x86_64 # [linux and x86_64]
- mesa-dri1-drivers-cos6-x86_64 # [linux and x86_64]
- mesa-libegl-cos6-x86_64 # [linux and x86_64]
- mesa-libegl-devel-cos6-x86_64 # [linux and x86_64]
- mesa-libgl-cos6-x86_64 # [linux and x86_64]
- mesa-libgl-devel-cos6-x86_64 # [linux and x86_64]
- pixman-cos6-x86_64 # [linux and x86_64]
- sysroot_linux-64 # [linux and x86_64]
- xorg-x11-server-common-cos6-x86_64 # [linux and x86_64]
- xorg-x11-server-xvfb-cos6-x86_64 # [linux and x86_64]
- kernel-headers_linux-aarch64 # [linux and aarch64]
- libdrm-cos7-aarch64 # [linux and aarch64]
- libglvnd-cos7-aarch64 # [linux and aarch64]
- libglvnd-glx-cos7-aarch64 # [linux and aarch64]
- libselinux-cos7-aarch64 # [linux and aarch64]
- libsepol-cos7-aarch64 # [linux and aarch64]
- libx11-common-cos7-aarch64 # [linux and aarch64]
- libx11-cos7-aarch64 # [linux and aarch64]
- libxau-cos7-aarch64 # [linux and aarch64]
- libxcb-cos7-aarch64 # [linux and aarch64]
- libxdamage-cos7-aarch64 # [linux and aarch64]
- libxext-cos7-aarch64 # [linux and aarch64]
- libxfixes-cos7-aarch64 # [linux and aarch64]
- libxi-cos7-aarch64 # [linux and aarch64]
- libxi-devel-cos7-aarch64 # [linux and aarch64]
- libxxf86vm-cos7-aarch64 # [linux and aarch64]
- mesa-dri-drivers-cos7-aarch64 # [linux and aarch64]
- mesa-khr-devel-cos7-aarch64 # [linux and aarch64]
- mesa-libegl-cos7-aarch64 # [linux and aarch64]
- mesa-libegl-devel-cos7-aarch64 # [linux and aarch64]
- mesa-libgbm-cos7-aarch64 # [linux and aarch64]
- mesa-libgl-cos7-aarch64 # [linux and aarch64]
- mesa-libgl-devel-cos7-aarch64 # [linux and aarch64]
- mesa-libglapi-cos7-aarch64 # [linux and aarch64]
- pixman-cos7-aarch64 # [linux and aarch64]
- sysroot_linux-aarch64 # [linux and aarch64]
- xorg-x11-server-common-cos7-aarch64 # [linux and aarch64]
- xorg-x11-server-xvfb-cos7-aarch64 # [linux and aarch64]
- sed # [unix]
- boost
- boost-cpp
- cmake
- coin3d
- compilers
- conda-build
- conda-devenv
- conda-smithy
- debugpy
- doxygen
- eigen
- freetype
- gmsh
- graphviz
- hdf5
- libcxx<16
- matplotlib
- ninja
- numpy
- occt==7.6.3
- openssl==3.0.8
- pcl
- pip
- pivy
- pkg-config
- ply
- pybind11
- pyside2
- python
- pyyaml
- qt
- qt-main
- qt-webengine
- six
- smesh==9.9
- swig
- vtk
- xerces-c
- zlib
- pip:
- ptvsd
+82 -77
View File
@@ -7,19 +7,17 @@
# Maintainers: keep this list of plugins up to date
# List plugins in %%{_libdir}/%{name}/lib, less '.so' and 'Gui.so', here
%global plugins Fem FreeCAD PathApp Image Import Inspection Mesh MeshPart Part Points Raytracing ReverseEngineering Robot Sketcher Start Web PartDesignGui _PartDesign Path PathGui Spreadsheet SpreadsheetGui area DraftUtils DraftUtils libDriver libDriverDAT libDriverSTL libDriverUNV libE57Format libMEFISTO2 libSMDS libSMESH libSMESHDS libStdMeshers Measure TechDraw TechDrawGui libarea-native Surface SurfaceGui PathSimulator
%global plugins Fem FreeCAD PathApp Import Inspection Mesh MeshPart Part Points Raytracing ReverseEngineering Robot Sketcher Start Web PartDesignGui _PartDesign Path PathGui Spreadsheet SpreadsheetGui area DraftUtils DraftUtils libDriver libDriverDAT libDriverSTL libDriverUNV libE57Format libMEFISTO2 libSMDS libSMESH libSMESHDS libStdMeshers Measure TechDraw TechDrawGui libarea-native Surface SurfaceGui PathSimulator
# Some configuration options for other environments
# rpmbuild --with=bundled_zipios: use bundled version of zipios++
%global bundled_zipios %{?_with_bundled_zipios: 1} %{?!_with_bundled_zipios: 0}
%global bundled_zipios %{?_with_bundled_zipios: 1} %{?!_with_bundled_zipios: 1}
# rpmbuild --without=bundled_pycxx: don't use bundled version of pycxx
%global bundled_pycxx %{?_without_bundled_pycxx: 0} %{?!_without_bundled_pycxx: 1}
# rpmbuild --without=bundled_smesh: don't use bundled version of Salome's Mesh
%global bundled_smesh %{?_without_bundled_smesh: 0} %{?!_without_bundled_smesh: 1}
#Hack to force zipios
%global bundled_zipios %{?_with_bundled_zipios: 1} %{?!_with_bundled_zipios: 1}
# Prevent RPM from doing its magical 'build' directory for now
%global __cmake_in_source_build 0
@@ -35,8 +33,8 @@
Name: %{name}
Epoch: 1
Version: 0.21
Release: pre_{{{git_commit_no}}}%{?dist}
Version: 0.21
Release: pre_32806%{?dist}
Summary: A general purpose 3D CAD modeler
Group: Applications/Engineering
@@ -44,94 +42,100 @@ License: LGPLv2+
URL: http://www.freecadweb.org/
Source0: https://github.com/%{github_name}/FreeCAD/archive/%{branch}.tar.gz
# Utilities
BuildRequires: cmake gcc-c++ gettext dos2unix
BuildRequires: doxygen swig graphviz
BuildRequires: gcc-gfortran
BuildRequires: desktop-file-utils
BuildRequires: git
BuildRequires: fmt-devel
BuildRequires: tbb-devel
# Development Libraries
BuildRequires: Coin4-devel
%if 0%{?fedora} < 35
BuildRequires: Inventor-devel
%endif
BuildRequires: freeimage-devel
BuildRequires: libXmu-devel
BuildRequires: mesa-libEGL-devel
BuildRequires: mesa-libGLU-devel
BuildRequires: opencascade-devel
BuildRequires: Coin4-devel
BuildRequires: python3-devel
BuildRequires: python3-matplotlib
BuildRequires: python3-pivy
BuildRequires: boost-devel
BuildRequires: boost-python3-devel
BuildRequires: eigen3-devel
BuildRequires: freeimage-devel
BuildRequires: libXmu-devel
%if 0%{?fedora} < 35
BuildRequires: Inventor-devel
%endif
# Qt5 dependencies
BuildRequires: qt5-qtwebengine-devel
#BuildRequires: qt5-qtwebkit-devel
BuildRequires: qt5-qtsvg-devel
BuildRequires: qt5-qttools-static
BuildRequires: qt5-qtxmlpatterns-devel
BuildRequires: fmt-devel
BuildRequires: xerces-c
BuildRequires: xerces-c-devel
BuildRequires: libspnav-devel
BuildRequires: python3-shiboken2-devel
BuildRequires: python3-pyside2-devel
BuildRequires: pyside2-tools
%if ! %{bundled_smesh}
BuildRequires: smesh-devel
%endif
BuildRequires: netgen-mesher-devel
BuildRequires: netgen-mesher-devel-private
%if ! %{bundled_zipios}
BuildRequires: zipios++-devel
%endif
%if ! %{bundled_pycxx}
BuildRequires: python3-pycxx-devel
%endif
BuildRequires: libicu-devel
BuildRequires: vtk-devel
BuildRequires: openmpi-devel
BuildRequires: med-devel
BuildRequires: libkdtree++-devel
BuildRequires: pcl-devel
BuildRequires: python3
BuildRequires: libglvnd-devel
#BuildRequires: zlib-devel
# For appdata
%if 0%{?fedora}
BuildRequires: libappstream-glib
%endif
BuildRequires: libglvnd-devel
BuildRequires: libicu-devel
BuildRequires: libkdtree++-devel
BuildRequires: libspnav-devel
%if 0%{?fedora} < 37
BuildRequires: libusb-devel
%else
BuildRequires: libusb1-devel
%endif
BuildRequires: med-devel
BuildRequires: mesa-libEGL-devel
BuildRequires: mesa-libGLU-devel
BuildRequires: netgen-mesher-devel
BuildRequires: netgen-mesher-devel-private
BuildRequires: python3-pivy
BuildRequires: mesa-libEGL-devel
BuildRequires: openmpi-devel
BuildRequires: pcl-devel
BuildRequires: pyside2-tools
BuildRequires: python3
BuildRequires: python3-devel
BuildRequires: python3-matplotlib
%if ! %{bundled_pycxx}
BuildRequires: python3-pycxx-devel
%endif
BuildRequires: python3-pyside2-devel
BuildRequires: python3-shiboken2-devel
BuildRequires: qt5-qtwebengine-devel
BuildRequires: qt5-qtwebkit-devel
BuildRequires: qt5-qtsvg-devel
BuildRequires: qt5-qttools-static
BuildRequires: qt5-qtxmlpatterns-devel
%if ! %{bundled_smesh}
BuildRequires: smesh-devel
%endif
BuildRequires: tbb-devel
BuildRequires: vtk-devel
BuildRequires: xerces-c
BuildRequires: xerces-c-devel
%if ! %{bundled_zipios}
BuildRequires: zipios++-devel
%endif
BuildRequires: zlib-devel
# Packages separated because they are noarch, but not optional so require them
# here.
Requires: %{name}-data = %{epoch}:%{version}-%{release}
# Obsolete old doc package since it's required for functionality.
Obsoletes: %{name}-doc < 0.13-5
Requires: hicolor-icon-theme
Requires: fmt
Requires: hicolor-icon-theme
Requires: python3-collada
Requires: python3-matplotlib
Requires: python3-pivy
Requires: python3-matplotlib
Requires: python3-collada
Requires: python3-pyside2
Requires: qt5-assistant
Requires: qt5-assistant
%if %{bundled_smesh}
Provides: bundled(smesh) = %{bundled_smesh_version}
%endif
%if %{bundled_pycxx}
Provides: bundled(python-pycxx)
%endif
Recommends: python3-pysolar
Recommends: python3-pysolar
# plugins and private shared libs in %%{_libdir}/freecad/lib are private;
# prevent private capabilities being advertised in Provides/Requires
@@ -165,7 +169,6 @@ Data files for FreeCAD
%prep
%autosetup -p1 -n FreeCAD-%{branch}
# Remove bundled pycxx if we're not using it
%if ! %{bundled_pycxx}
rm -rf src/CXX
@@ -177,12 +180,9 @@ rm -rf src/zipios++
# src/Base/Reader.cpp src/Base/Writer.h
%endif
# Fix encodings
dos2unix -k src/Mod/Test/unittestgui.py \
data/License.txt
# Removed bundled libraries
%build
rm -rf build && mkdir build && cd build
@@ -215,7 +215,6 @@ LDFLAGS='-Wl,--as-needed -Wl,--no-undefined'; export LDFLAGS
-DOpenGL_GL_PREFERENCE=GLVND \
-DCOIN3D_INCLUDE_DIR=%{_includedir}/Coin4 \
-DCOIN3D_DOC_PATH=%{_datadir}/Coin4/Coin \
-DFREECAD_USE_EXTERNAL_PIVY=TRUE \
-DUSE_OCC=TRUE \
%if ! %{bundled_smesh}
-DFREECAD_USE_EXTERNAL_SMESH=TRUE \
@@ -237,8 +236,8 @@ LDFLAGS='-Wl,--as-needed -Wl,--no-undefined'; export LDFLAGS
make fc_version
for I in src/Build/Version.h src/Build/Version.h.out; do
sed -i 's,FCRevision \"Unknown\",FCRevision \"%{release} (Git)\",' $I
sed -i 's,FCRepositoryURL \"Unknown\",FCRepositoryURL \"git://github.com/FreeCAD/FreeCAD.git master\",' $I
sed -i 's,FCRevision \"Unknown\",FCRevision \"%{release} (Git)\",' $I
sed -i 's,FCRepositoryURL \"Unknown\",FCRepositoryURL \"git://github.com/FreeCAD/FreeCAD.git master\",' $I
done
%{make_build}
@@ -280,8 +279,7 @@ popd
# Remove obsolete Start_Page.html
rm -f %{buildroot}%{_docdir}/%{name}/Start_Page.html
# Belongs in %%license not %%doc
#No longer present?
#rm -f %{buildroot}%{_docdir}/freecad/ThirdPartyLibraries.html
rm -f %{buildroot}%{_docdir}/freecad/ThirdPartyLibraries.html
# Remove header from external library that's erroneously installed
rm -f %{buildroot}%{_libdir}/%{name}/include/E57Format/E57Export.h
@@ -310,11 +308,15 @@ for p in %{plugins}; do
fi
done
# Bytecompile Python modules
%py_byte_compile %{__python3} %{buildroot}%{_libdir}/%{name}
%check
desktop-file-validate \
%{buildroot}%{_datadir}/applications/org.freecadweb.FreeCAD.desktop
%{?fedora:appstream-util validate-relax --nonet \
%{buildroot}/%{_metainfodir}/*.appdata.xml}
%{buildroot}%{_metainfodir}/*.appdata.xml}
%post
@@ -335,16 +337,14 @@ fi
%files
%license data/License.txt
%exclude %{_docdir}/%{name}/%{name}.*
%exclude %{_docdir}/%{name}/ThirdPartyLibraries.html
%{_bindir}/*
%{_metainfodir}/*
%dir %{_libdir}/%{name}
%{_libdir}/%{name}/bin/
%{_libdir}/%{name}/%{_lib}/
%{_libdir}/%{name}/Mod/
%{_libdir}/%{name}/Ext/
%{_libdir}/%{name}/Mod/
%{_datadir}/applications/*
%{_datadir}/icons/hicolor/scalable/*
%{_datadir}/pixmaps/*
@@ -354,3 +354,8 @@ fi
%files data
%{_datadir}/%{name}/
%{_docdir}/%{name}/LICENSE.html
%changelog
+22 -6
View File
@@ -1,6 +1,22 @@
matplotlib==3.0.2
PySide==1.2.4
# PySide2==5.12.0
Shiboken==1.2.2
six==1.12.0
Markdown==3.2.2
area==1.1.1
cog==0.6.1
ConfigParser==5.3.0
defusedxml==0.7.1
ifcopenshell==0.7.0.230318
ladybug==0.0.2
matplotlib==3.6.3
numpy==1.24.2
opencamlib==2023.1.11
packaging==23.0
Pivy==0.6.8
ply==3.11
ptvsd==4.3.2
pyNastran==1.3.4
pyshp==2.3.1
PySide2==5.15.2.1
pysolar==0.10
PyYAML==6.0
requests==2.28.2
rpdb2==2.0.0.1.2
sets==0.3.2
vermin==1.5.1
+1
View File
@@ -33,6 +33,7 @@
#include <cfloat>
#include <memory>
#include <cstdint>
#include <vector>
#include "E57Exception.h"
+23 -50
View File
@@ -94,6 +94,7 @@
#include "FeaturePython.h"
#include "GeoFeature.h"
#include "GeoFeatureGroupExtension.h"
#include "ImagePlane.h"
#include "InventorObject.h"
#include "Link.h"
#include "LinkBaseExtensionPy.h"
@@ -106,6 +107,7 @@
#include "Part.h"
#include "PartPy.h"
#include "Placement.h"
#include "ProgramOptionsUtilities.h"
#include "Property.h"
#include "PropertyContainer.h"
#include "PropertyExpressionEngine.h"
@@ -216,6 +218,18 @@ init_freecad_module(void)
return PyModule_Create(&FreeCADModuleDef);
}
PyMODINIT_FUNC
init_image_module()
{
static struct PyModuleDef ImageModuleDef = {
PyModuleDef_HEAD_INIT,
"Image", "", -1,
nullptr,
nullptr, nullptr, nullptr, nullptr
};
return PyModule_Create(&ImageModuleDef);
}
Application::Application(std::map<std::string,std::string> &mConfig)
: _mConfig(mConfig), _pActiveDoc(nullptr), _isRestoring(false),_allowPartial(false)
, _isClosingAll(false), _objCount(-1), _activeTransactionID(0)
@@ -253,6 +267,10 @@ void Application::setupPythonTypes()
};
PyObject* pConsoleModule = PyModule_Create(&ConsoleModuleDef);
// fake Image module
PyObject* imageModule = init_image_module();
PyDict_SetItemString(modules, "Image", imageModule);
// introducing additional classes
// NOTE: To finish the initialization of our own type objects we must
@@ -2009,6 +2027,7 @@ void Application::initTypes()
App::PropertyTime ::init();
App::PropertyUltimateTensileStrength ::init();
App::PropertyVacuumPermittivity ::init();
App::PropertyVelocity ::init();
App::PropertyVolume ::init();
App::PropertyVolumeFlowRate ::init();
App::PropertyVolumetricThermalExpansionCoefficient::init();
@@ -2052,12 +2071,13 @@ void Application::initTypes()
App::DocumentObjectGroup ::init();
App::DocumentObjectGroupPython ::init();
App::DocumentObjectFileIncluded::init();
Image::ImagePlane ::init();
App::InventorObject ::init();
App::VRMLObject ::init();
App::Annotation ::init();
App::AnnotationLabel ::init();
App::MeasureDistance ::init();
App ::MaterialObject ::init();
App::MaterialObject ::init();
App::MaterialObjectPython ::init();
App::TextDocument ::init();
App::Placement ::init();
@@ -2126,53 +2146,6 @@ void Application::initTypes()
}
namespace {
pair<string, string> customSyntax(const string& s)
{
#if defined(FC_OS_MACOSX)
if (s.find("-psn_") == 0)
return make_pair(string("psn"), s.substr(5));
#endif
if (s.find("-display") == 0)
return make_pair(string("display"), string("null"));
else if (s.find("-style") == 0)
return make_pair(string("style"), string("null"));
else if (s.find("-graphicssystem") == 0)
return make_pair(string("graphicssystem"), string("null"));
else if (s.find("-widgetcount") == 0)
return make_pair(string("widgetcount"), string(""));
else if (s.find("-geometry") == 0)
return make_pair(string("geometry"), string("null"));
else if (s.find("-font") == 0)
return make_pair(string("font"), string("null"));
else if (s.find("-fn") == 0)
return make_pair(string("fn"), string("null"));
else if (s.find("-background") == 0)
return make_pair(string("background"), string("null"));
else if (s.find("-bg") == 0)
return make_pair(string("bg"), string("null"));
else if (s.find("-foreground") == 0)
return make_pair(string("foreground"), string("null"));
else if (s.find("-fg") == 0)
return make_pair(string("fg"), string("null"));
else if (s.find("-button") == 0)
return make_pair(string("button"), string("null"));
else if (s.find("-btn") == 0)
return make_pair(string("btn"), string("null"));
else if (s.find("-name") == 0)
return make_pair(string("name"), string("null"));
else if (s.find("-title") == 0)
return make_pair(string("title"), string("null"));
else if (s.find("-visual") == 0)
return make_pair(string("visual"), string("null"));
// else if (s.find("-ncols") == 0)
// return make_pair(string("ncols"), boost::program_options::value<int>(1));
// else if (s.find("-cmap") == 0)
// return make_pair(string("cmap"), string("null"));
else if ('@' == s[0])
return std::make_pair(string("response-file"), s.substr(1));
else
return make_pair(string(), string());
}
void parseProgramOptions(int ac, char ** av, const string& exe, variables_map& vm)
{
@@ -2292,7 +2265,7 @@ void parseProgramOptions(int ac, char ** av, const string& exe, variables_map& v
try {
store( boost::program_options::command_line_parser(args).
options(cmdline_options).positional(p).extra_parser(customSyntax).run(), vm);
options(cmdline_options).positional(p).extra_parser(Util::customSyntax).run(), vm);
std::ifstream ifs("FreeCAD.cfg");
if (ifs)
@@ -2339,7 +2312,7 @@ void parseProgramOptions(int ac, char ** av, const string& exe, variables_map& v
copy(tok.begin(), tok.end(), back_inserter(args));
// Parse the file and store the options
store( boost::program_options::command_line_parser(args).
options(cmdline_options).positional(p).extra_parser(customSyntax).run(), vm);
options(cmdline_options).positional(p).extra_parser(Util::customSyntax).run(), vm);
}
}
+7
View File
@@ -147,6 +147,7 @@ SET(Document_CPP_SRCS
GeoFeature.cpp
GeoFeatureGroupExtensionPyImp.cpp
GeoFeatureGroupExtension.cpp
ImagePlane.cpp
OriginGroupExtensionPyImp.cpp
OriginGroupExtension.cpp
PartPyImp.cpp
@@ -192,6 +193,7 @@ SET(Document_HPP_SRCS
FeatureTest.h
GeoFeature.h
GeoFeatureGroupExtension.h
ImagePlane.h
OriginGroupExtension.h
Part.h
Origin.h
@@ -262,6 +264,8 @@ SET(FreeCADApp_CPP_SRCS
ComplexGeoDataPyImp.cpp
Enumeration.cpp
IndexedName.cpp
MappedElement.cpp
MappedName.cpp
Material.cpp
MaterialPyImp.cpp
Metadata.cpp
@@ -277,8 +281,11 @@ SET(FreeCADApp_HPP_SRCS
Color.h
ColorModel.h
ComplexGeoData.h
ElementMap.h
Enumeration.h
IndexedName.h
MappedName.h
MappedElement.h
Material.h
Metadata.h
)
+27 -10
View File
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PropertyContainerPy"
Name="DocumentPy"
Twin="Document"
TwinPointer="Document"
Include="App/Document.h"
Namespace="App"
FatherInclude="App/PropertyContainerPy.h"
<PythonExport
Father="PropertyContainerPy"
Name="DocumentPy"
Twin="Document"
TwinPointer="Document"
Include="App/Document.h"
Namespace="App"
FatherInclude="App/PropertyContainerPy.h"
FatherNamespace="App">
<Documentation>
<Author Licence="LGPL" Name="Juergen Riegel" EMail="[email protected]" />
@@ -104,6 +104,23 @@ attach (Boolean): if True, then bind the document object first before adding to
viewType (String): override the view provider type directly, only effective when attach is False.</UserDocu>
</Documentation>
</Methode>
<Methode Name="addProperty">
<Documentation>
<UserDocu>
addProperty(string, string) -- Add a generic property.
The first argument specifies the type, the second the
name of the property.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeProperty">
<Documentation>
<UserDocu>
removeProperty(string) -- Remove a generic property.
Note, you can only remove user-defined properties but not built-in ones.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeObject">
<Documentation>
<UserDocu>Remove an object from the document</UserDocu>
@@ -113,7 +130,7 @@ viewType (String): override the view provider type directly, only effective when
<Documentation>
<UserDocu>
copyObject(object, with_dependencies=False, return_all=False)
Copy an object or objects from another document to this document.
Copy an object or objects from another document to this document.
object: can either a single object or sequence of objects
with_dependencies: if True, all internal dependent objects are copied too.
@@ -127,7 +144,7 @@ return_all: if True, return all copied objects, or else return only the copied
<UserDocu>
moveObject(object, bool with_dependencies = False)
Transfers an object from another document to this document.
object: can either a single object or sequence of objects
with_dependencies: if True, all internal dependent objects are copied too.
</UserDocu>
+45 -14
View File
@@ -40,6 +40,37 @@
using namespace App;
PyObject* DocumentPy::addProperty(PyObject *args)
{
char *sType,*sName=nullptr,*sGroup=nullptr,*sDoc=nullptr;
short attr=0;
std::string sDocStr;
PyObject *ro = Py_False, *hd = Py_False;
if (!PyArg_ParseTuple(args, "s|ssethO!O!", &sType,&sName,&sGroup,"utf-8",&sDoc,&attr,
&PyBool_Type, &ro, &PyBool_Type, &hd))
return nullptr;
if (sDoc) {
sDocStr = sDoc;
PyMem_Free(sDoc);
}
getDocumentPtr()->addDynamicProperty(sType,sName,sGroup,sDocStr.c_str(),attr,
Base::asBoolean(ro), Base::asBoolean(hd));
return Py::new_reference_to(this);
}
PyObject* DocumentPy::removeProperty(PyObject *args)
{
char *sName;
if (!PyArg_ParseTuple(args, "s", &sName))
return nullptr;
bool ok = getDocumentPtr()->removeDynamicProperty(sName);
return Py_BuildValue("O", (ok ? Py_True : Py_False));
}
// returns a string which represent the object e.g. when printed in python
std::string DocumentPy::representation() const
{
@@ -363,13 +394,13 @@ PyObject* DocumentPy::importLinks(PyObject *args)
objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
}
}
else {
Base::PyTypeCheck(&obj, &DocumentObjectPy::Type,
"Expect first argument to be either a document object, sequence of document objects or None");
if (obj)
objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
}
else {
Base::PyTypeCheck(&obj, &DocumentObjectPy::Type,
"Expect first argument to be either a document object, sequence of document objects or None");
if (obj)
objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
}
if (objs.empty())
objs = getDocumentPtr()->getObjects();
@@ -380,7 +411,7 @@ PyObject* DocumentPy::importLinks(PyObject *args)
for (size_t i=0;i<ret.size();++i)
tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
return Py::new_reference_to(tuple);
}
}
PY_CATCH
}
@@ -857,20 +888,20 @@ PyObject* DocumentPy::getLinksTo(PyObject *args)
return nullptr;
PY_TRY {
Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type document object");
Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type document object");
DocumentObject *obj = nullptr;
if (pyobj)
obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
if (pyobj)
obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
std::set<DocumentObject *> links;
getDocumentPtr()->getLinksTo(links,obj,options,count);
Py::Tuple ret(links.size());
int i=0;
for (auto o : links)
ret.setItem(i++,Py::Object(o->getPyObject(),true));
return Py::new_reference_to(ret);
}
}
PY_CATCH
}
+48
View File
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* Copyright (c) 2018-2022 Zheng, Lei (realthunder) *
* <[email protected]> *
* Copyright (c) 2023 FreeCAD Project Association *
* *
* 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/>. *
* *
***************************************************************************/
#ifndef DATA_ELEMENTMAP_H
#define DATA_ELEMENTMAP_H
#include "FCGlobal.h"
#include "IndexedName.h"
namespace Data {
static constexpr const char *POSTFIX_TAG = ";:H";
static constexpr const char *POSTFIX_DECIMAL_TAG = ";:T";
static constexpr const char *POSTFIX_EXTERNAL_TAG = ";:X";
static constexpr const char *POSTFIX_CHILD = ";:C";
static constexpr const char *POSTFIX_INDEX = ";:I";
static constexpr const char *POSTFIX_UPPER = ";:U";
static constexpr const char *POSTFIX_LOWER = ";:L";
static constexpr const char *POSTFIX_MOD = ";:M";
static constexpr const char *POSTFIX_GEN = ";:G";
static constexpr const char *POSTFIX_MODGEN = ";:MG";
static constexpr const char *POSTFIX_DUPLICATE = ";D";
} // namespace data
#endif // DATA_ELEMENTMAP_H
+1 -1
View File
@@ -1320,7 +1320,7 @@ void NumberExpression::_toString(std::ostream &ss, bool,int) const
// https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
// https://www.boost.org/doc/libs/1_63_0/libs/multiprecision/doc/html/boost_multiprecision/tut/limits/constants.html
boost::io::ios_flags_saver ifs(ss);
ss << std::setprecision(std::numeric_limits<double>::digits10 + 1) << getValue();
ss << std::setprecision(std::numeric_limits<double>::digits10) << getValue();
/* Trim of any extra spaces */
//while (s.size() > 0 && s[s.size() - 1] == ' ')
+1
View File
@@ -61,6 +61,7 @@ extern int column;
%option noyywrap nounput
/* UTF-8 unicode regular expressions. */
/* http://www.unicode.org/reports/tr44/#General_Category_Values */
Cc ([\x00-\x1f\x7f]|\xc2[\x80-\x9f])
Cf (\xc2\xad|\xd8[\x80-\x85\x9c]|\xdb\x9d|\xdc\x8f|\xe1(\xa0\x8e)|\xe2(\x80[\x8b-\x8f\xaa-\xae]|\x81[\xa0-\xa4\xa6-\xaf])|\xef(\xbb\xbf|\xbf[\xb9-\xbb])|\xf0(\x91(\x82\xbd))|\xf3(\xa0(\x80\x81)))
+6 -3
View File
@@ -1,3 +1,6 @@
# Description for bash script
flex -olex.ExpressionParser.c < ExpressionParser.l
bison -oExpressionParser.tab.c ExpressionParser.y
#!/usr/bin/env sh
cd "$(dirname "$0")"
flex -v -olex.ExpressionParser.c ExpressionParser.l
bison -d -v -Wall -oExpressionParser.tab.c ExpressionParser.y
File diff suppressed because it is too large Load Diff
+8 -10
View File
@@ -36,7 +36,6 @@ std::stack<FunctionExpression::Function> functions; /**< Function
#define yyerror ExpressionParser_yyerror
%}
/* Bison declarations. */
%token FUNC
%token ONE
%token NUM
@@ -66,16 +65,14 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%type <string_or_identifier> document
%type <string_or_identifier> object
%type <ivalue> integer
%left ONE NUM INTEGER CONSTANT
%left EQ NEQ LT GT GTE LTE
%left '?' ':'
%precedence EQ NEQ LT GT GTE LTE
%precedence ':'
%left MINUSSIGN '+'
%left '*' '/' '%'
%precedence NUM_AND_UNIT
%left '^' /* exponentiation */
%left EXPONENT
%left NEG /* negation--unary minus */
%left POS /* unary plus */
%left '^'
%precedence NEG
%precedence POS
%destructor { delete $$; } num range exp cond unit_exp indexable
%destructor { delete $$; } <component>
@@ -105,6 +102,7 @@ exp: num { $$ = $1;
| indexable { $$ = $1; }
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1.first, std::move($1.second), $2); }
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
| '(' exp ')' { $$ = $2; }
;
num: ONE { $$ = new NumberExpression(DocumentObject, Quantity($1)); }
@@ -129,6 +127,7 @@ cond: exp EQ exp { $$ = new OperatorExpression(Do
| exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); }
| exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); }
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
| '(' cond ')' { $$ = $2; }
;
unit_exp: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
@@ -206,8 +205,7 @@ indexer
;
indexable
: '(' exp ')' { $$ = $2; }
| identifier indexer { $$ = new VariableExpression(DocumentObject,$1); $$->addComponent($2); }
: identifier indexer { $$ = new VariableExpression(DocumentObject,$1); $$->addComponent($2); }
| indexable indexer { $1->addComponent(std::move($2)); $$ = $1; }
| indexable '.' IDENTIFIER { $1->addComponent(Expression::createComponent($3)); $$ = $1; }
;
+27 -20
View File
@@ -192,6 +192,32 @@ def InitApplications():
else:
Log('Init: Initializing ' + Dir + '(Init.py not found)... ignore\n')
def processMetadataFile(MetadataFile):
meta = FreeCAD.Metadata(MetadataFile)
if not meta.supportsCurrentFreeCAD():
Msg(f'NOTICE: {meta.Name} does not support this version of FreeCAD, so is being skipped\n')
return None
content = meta.Content
if "workbench" in content:
workbenches = content["workbench"]
for workbench in workbenches:
if not workbench.supportsCurrentFreeCAD():
Msg(f'NOTICE: {meta.Name} content item {workbench.Name} does not support this version of FreeCAD, so is being skipped\n')
return None
subdirectory = workbench.Name if not workbench.Subdirectory else workbench.Subdirectory
subdirectory = subdirectory.replace("/",os.path.sep)
subdirectory = os.path.join(Dir, subdirectory)
#classname = workbench.Classname
sys.path.insert(0,subdirectory)
PathExtension.append(subdirectory)
RunInitPy(subdirectory)
def tryProcessMetadataFile(MetadataFile):
try:
processMetadataFile(MetadataFile)
except Exception as exc:
Err(str(exc))
for Dir in ModDict.values():
if ((Dir != '') & (Dir != 'CVS') & (Dir != '__init__.py')):
stopFile = os.path.join(Dir, "ADDON_DISABLED")
@@ -202,26 +228,7 @@ def InitApplications():
PathExtension.append(Dir)
MetadataFile = os.path.join(Dir, "package.xml")
if os.path.exists(MetadataFile):
meta = FreeCAD.Metadata(MetadataFile)
if not meta.supportsCurrentFreeCAD():
Msg(f'NOTICE: {meta.Name} does not support this version of FreeCAD, so is being skipped\n')
continue
content = meta.Content
if "workbench" in content:
workbenches = content["workbench"]
for workbench in workbenches:
if not workbench.supportsCurrentFreeCAD():
Msg(f'NOTICE: {meta.Name} content item {workbench.Name} does not support this version of FreeCAD, so is being skipped\n')
continue
subdirectory = workbench.Name if not workbench.Subdirectory else workbench.Subdirectory
subdirectory = subdirectory.replace("/",os.path.sep)
subdirectory = os.path.join(Dir, subdirectory)
#classname = workbench.Classname
sys.path.insert(0,subdirectory)
PathExtension.append(subdirectory)
RunInitPy(subdirectory)
else:
pass # The package content says there are no workbenches here, so just skip
tryProcessMetadataFile(MetadataFile)
else:
RunInitPy(Dir)
@@ -26,18 +26,35 @@
using namespace Image;
using namespace App;
PROPERTY_SOURCE(Image::ImagePlane, App::GeoFeature)
ImagePlane::ImagePlane()
: XPixelsPerMeter{1000.0}
, YPixelsPerMeter{1000.0}
{
ADD_PROPERTY_TYPE( ImageFile,(nullptr) , "ImagePlane",Prop_None,"File of the image");
ADD_PROPERTY_TYPE( XSize, (100), "ImagePlane",Prop_None,"Size of a pixel in X");
ADD_PROPERTY_TYPE( YSize, (100), "ImagePlane",Prop_None,"Size of a pixel in Y");
ADD_PROPERTY_TYPE( ImageFile,(nullptr) , "ImagePlane",App::Prop_None,"File of the image");
ADD_PROPERTY_TYPE( XSize, (100), "ImagePlane",App::Prop_None,"Size of a pixel in X");
ADD_PROPERTY_TYPE( YSize, (100), "ImagePlane",App::Prop_None,"Size of a pixel in Y");
}
ImagePlane::~ImagePlane()
int ImagePlane::getXSizeInPixel()
{
return int(XSize.getValue() * XPixelsPerMeter / 1000);
}
int ImagePlane::getYSizeInPixel()
{
return int(YSize.getValue() * YPixelsPerMeter / 1000);
}
void ImagePlane::setXSizeInPixel(int value)
{
XSize.setValue(double(value) * 1000.0 / XPixelsPerMeter);
}
void ImagePlane::setYSizeInPixel(int value)
{
YSize.setValue(double(value) * 1000.0 / YPixelsPerMeter);
}
@@ -20,37 +20,44 @@
* *
***************************************************************************/
#ifndef Image_ImagePlane_H
#define Image_ImagePlane_H
#ifndef App_ImagePlane_H
#define App_ImagePlane_H
#include <App/GeoFeature.h>
#include <App/PropertyFile.h>
#include <App/PropertyUnits.h>
#include <Mod/Image/ImageGlobal.h>
namespace Image
{
class ImageExport ImagePlane : public App::GeoFeature
class AppExport ImagePlane : public App::GeoFeature
{
PROPERTY_HEADER_WITH_OVERRIDE(Image::ImagePlane);
public:
/// Constructor
ImagePlane();
~ImagePlane() override;
~ImagePlane() override = default;
App::PropertyFileIncluded ImageFile;
App::PropertyLength XSize;
App::PropertyLength YSize;
int getXSizeInPixel();
int getYSizeInPixel();
void setXSizeInPixel(int);
void setYSizeInPixel(int);
double XPixelsPerMeter;
double YPixelsPerMeter;
/// returns the type name of the ViewProvider
const char* getViewProviderName() const override {
return "ImageGui::ViewProviderImagePlane";
return "Gui::ViewProviderImagePlane";
}
};
} //namespace Image
#endif // Image_ImagePlane_H
#endif // App_ImagePlane_H
+24
View File
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************************************
* *
* Copyright (c) 2022 Zheng, Lei (realthunder) <[email protected]> *
* Copyright (c) 2023 FreeCAD Project Association *
* *
* 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/>. *
* *
**************************************************************************************************/
#include "PreCompiled.h"
#include "MappedElement.h"
+105
View File
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************************************
* *
* Copyright (c) 2022 Zheng, Lei (realthunder) <[email protected]> *
* Copyright (c) 2023 FreeCAD Project Association *
* *
* 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/>. *
* *
**************************************************************************************************/
#ifndef APP_MAPPED_ELEMENT_H
#define APP_MAPPED_ELEMENT_H
#include "ComplexGeoData.h"
#include "IndexedName.h"
#include "MappedName.h"
namespace App
{
class DocumentObject;
}
namespace Data
{
/// A MappedElement combines a MappedName and and IndexedName into a single entity and provides
/// simple comparison operators for the combination (including operator< so that the entity can
/// be sorted, or used in sorted containers).
struct AppExport MappedElement
{
IndexedName index;
MappedName name;
MappedElement() = default;
MappedElement(const IndexedName& idx, MappedName n)
: index(idx),
name(std::move(n))
{}
MappedElement(MappedName n, const IndexedName& idx)
: index(idx),
name(std::move(n))
{}
~MappedElement() = default;
MappedElement(const MappedElement& other) = default;
MappedElement(MappedElement&& other) noexcept
: index(other.index),
name(std::move(other.name))
{}
MappedElement& operator=(MappedElement&& other) noexcept
{
this->index = other.index;
this->name = std::move(other.name);
return *this;
}
MappedElement& operator=(const MappedElement& other) = default;
bool operator==(const MappedElement& other) const
{
return this->index == other.index && this->name == other.name;
}
bool operator!=(const MappedElement& other) const
{
return this->index != other.index || this->name != other.name;
}
/// For sorting purposes, one MappedElement is considered "less" than another if its index
/// compares less (which is first alphabetical, and then by numeric index). If the index of this
/// MappedElement is the same, then the names are compared lexicographically.
bool operator<(const MappedElement& other) const
{
int res = this->index.compare(other.index);
if (res < 0) {
return true;
}
if (res > 0) {
return false;
}
return this->name < other.name;
}
};
}// namespace Data
#endif// APP_MAPPED_ELEMENT_H
@@ -1,23 +1,53 @@
/***************************************************************************
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
/****************************************************************************
* Copyright (c) 2020 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <unordered_set>
#endif
//#include <boost/functional/hash.hpp>
#include "MappedName.h"
using namespace Data;
void MappedName::compact()
{
if (this->raw) {
this->data = QByteArray(this->data.constData(), this->data.size());
this->raw = false;
}
#if 0
static std::unordered_set<QByteArray, ByteArrayHasher> PostfixSet;
if (this->postfix.size()) {
auto res = PostfixSet.insert(this->postfix);
if (!res.second)
self->postfix = *res.first;
}
#endif
}
+908
View File
@@ -0,0 +1,908 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* Copyright (c) 2022 Zheng, Lei (realthunder) <[email protected]>*
* Copyright (c) 2023 FreeCAD Project Association *
* *
* 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/>. *
* *
***************************************************************************/
#ifndef APP_MAPPED_NAME_H
#define APP_MAPPED_NAME_H
#include <string>
#include <boost/algorithm/string/predicate.hpp>
#include <QByteArray>
#include <QHash>
#include "ComplexGeoData.h"
#include "IndexedName.h"
namespace Data
{
// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
/// The MappedName class maintains a two-part name: the first part ("data") is considered immutable
/// once created, while the second part ("postfix") can be modified/appended to by later operations.
/// It uses shared data when possible (see the fromRawData() members). Despite storing data and
/// postfix separately, they can be accessed via calls to size(), operator[], etc. as though they
/// were a single array.
class AppExport MappedName
{
public:
/// Create a MappedName from a C string, optionally prefixed by an element map prefix, which
/// will be omitted from the stored MappedName.
///
/// \param name The new name. A deep copy is made.
/// \param size Optional, the length of the name string. If not provided, the string must be
/// null-terminated.
explicit MappedName(const char* name, int size = -1)
: raw(false)
{
if (!name) {
return;
}
if (boost::starts_with(name, ComplexGeoData::elementMapPrefix())) {
name += ComplexGeoData::elementMapPrefix().size();
}
data = size < 0 ? QByteArray(name) : QByteArray(name, size);
}
/// Create a MappedName from a C++ std::string, optionally prefixed by an element map prefix,
/// which will be omitted from the stored MappedName.
///
/// \param name The new name. A deep copy is made.
explicit MappedName(const std::string& nameString)
: raw(false)
{
auto size = nameString.size();
const char* name = nameString.c_str();
if (boost::starts_with(nameString, ComplexGeoData::elementMapPrefix())) {
name += ComplexGeoData::elementMapPrefix().size();
size -= ComplexGeoData::elementMapPrefix().size();
}
data = QByteArray(name, static_cast<int>(size));
}
/// Create a MappedName from an IndexedName. If non-zero, the numerical part of the IndexedName
/// is appended as text to the MappedName. In that case the memory is *not* shared between the
/// original IndexedName and the MappedName.
explicit MappedName(const IndexedName& element)
: data(QByteArray::fromRawData(element.getType(), qstrlen(element.getType()))),
raw(true)
{
if (element.getIndex() > 0) {
this->data += QByteArray::number(element.getIndex());
this->raw = false;
}
}
MappedName()
: raw(false)
{}
MappedName(const MappedName& other) = default;
/// Copy constructor with start position offset and optional size. The data is *not* reused.
///
/// \param other The MappedName to copy
/// \param startPosition an integer offset to start the copy from
/// \param size the number of bytes to copy.
/// \see append() for details about how the copy behaves for various sizes and start positions
MappedName(const MappedName& other, int startPosition, int size = -1)
: raw(false)
{
append(other, startPosition, size);
}
/// Copy constructor with additional postfix
///
/// \param other The mapped name to copy. Its data and postfix become the new MappedName's data
/// \param postfix The postfix for the new MappedName
MappedName(const MappedName& other, const char* postfix)
: data(other.data + other.postfix),
postfix(postfix),
raw(false)
{}
/// Move constructor
MappedName(MappedName&& other) noexcept
: data(std::move(other.data)),
postfix(std::move(other.postfix)),
raw(other.raw)
{}
~MappedName() = default;
/// Construct a MappedName from raw character data (including null characters, if size is
/// provided). No copy is made: the data is used in place.
///
/// \param name The raw data to use.
/// \param size The number of bytes to access. If omitted, name must be null-terminated.
/// \return a new MappedName with name as its data.
static MappedName fromRawData(const char* name, int size = -1)
{
MappedName res;
if (name) {
res.data =
QByteArray::fromRawData(name, size >= 0 ? size : static_cast<int>(qstrlen(name)));
res.raw = true;
}
return res;
}
/// Construct a MappedName from QByteArray data (including any embedded null characters).
///
/// \param data The original data. No copy is made, the data is shared with the other instance.
/// \return a new MappedName with data as its data.
static MappedName fromRawData(const QByteArray& data)
{
return fromRawData(data.constData(), data.size());
}
/// Construct a MappedName from another MappedName
///
/// \param other The MappedName to copy from. The data is usually not copied, but in some
/// cases a partial copy may be made to support a slice that extends across other's data into
/// its postfix.
/// \param startPosition The position to start the reference at.
/// \param size The number of bytes to access. If omitted, continues from startPosition
/// to the end of available data (including postfix).
/// \return a new MappedName sharing (possibly a subset of) data with other.
/// \see append() for details about how the copy behaves for various sizes and start positions
static MappedName fromRawData(const MappedName& other, int startPosition, int size = -1)
{
if (startPosition < 0) {
startPosition = 0;
}
if (startPosition >= other.size()) {
return {};
}
if (startPosition >= other.data.size()) {
return {other, startPosition, size};
}
MappedName res;
res.raw = true;
if (size < 0) {
size = other.size() - startPosition;
}
if (size < other.data.size() - startPosition) {
res.data = QByteArray::fromRawData(other.data.constData() + startPosition, size);
}
else {
res.data = QByteArray::fromRawData(other.data.constData() + startPosition,
other.data.size() - startPosition);
size -= other.data.size() - startPosition;
if (size == other.postfix.size()) {
res.postfix = other.postfix;
}
else if (size != 0) {
res.postfix.append(other.postfix.constData(), size);
}
}
return res;
}
/// Share data with another MappedName
MappedName& operator=(const MappedName& other) = default;
/// Create a new MappedName from a std::string: the string's data is copied.
MappedName& operator=(const std::string& other)
{
*this = MappedName(other);
return *this;
}
/// Create a new MappedName from a const char *. The character data is copied.
MappedName& operator=(const char* other)
{
*this = MappedName(other);
return *this;
}
/// Move-construct a MappedName
MappedName& operator=(MappedName&& other) noexcept
{
this->data = std::move(other.data);
this->postfix = std::move(other.postfix);
this->raw = other.raw;
return *this;
}
/// Write to a stream as the name with postfix directly appended to it. Note that there is no
/// special handling for null or non-ASCII characters, they are simply written to the stream.
friend std::ostream& operator<<(std::ostream& stream, const MappedName& mappedName)
{
stream.write(mappedName.data.constData(), mappedName.data.size());
stream.write(mappedName.postfix.constData(), mappedName.postfix.size());
return stream;
}
/// Two MappedNames are equal if the concatenation of their data and postfix is equal. The
/// individual data and postfix may NOT be equal in this case.
bool operator==(const MappedName& other) const
{
if (this->size() != other.size()) {
return false;
}
if (this->data.size() == other.data.size()) {
return this->data == other.data && this->postfix == other.postfix;
}
const auto& smaller = this->data.size() < other.data.size() ? *this : other;
const auto& larger = this->data.size() < other.data.size() ? other : *this;
if (!larger.data.startsWith(smaller.data)) {
return false;
}
QByteArray tmp = QByteArray::fromRawData(larger.data.constData() + smaller.data.size(),
larger.data.size() - smaller.data.size());
if (!smaller.postfix.startsWith(tmp)) {
return false;
}
tmp = QByteArray::fromRawData(smaller.postfix.constData() + tmp.size(),
smaller.postfix.size() - tmp.size());
return tmp == larger.postfix;
}
bool operator!=(const MappedName& other) const
{
return !(this->operator==(other));
}
/// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS
/// argument's postfix with the RHS argument's data and postfix appended to it.
MappedName operator+(const MappedName& other) const
{
MappedName res(*this);
res += other;
return res;
}
/// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS
/// argument's postfix with the RHS argument appended to it. The character data is copied.
MappedName operator+(const char* other) const
{
MappedName res(*this);
res += other;
return res;
}
/// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS
/// argument's postfix with the RHS argument appended to it. The character data is copied.
MappedName operator+(const std::string& other) const
{
MappedName res(*this);
res += other;
return res;
}
/// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS
/// argument's postfix with the RHS argument appended to it.
MappedName operator+(const QByteArray& other) const
{
MappedName res(*this);
res += other;
return res;
}
/// Appends other to this instance's postfix. other must be a null-terminated C string. The
/// character data from the string is copied.
MappedName& operator+=(const char* other)
{
if (other && (other[0] != 0)) {
this->postfix.append(other, -1);
}
return *this;
}
/// Appends other to this instance's postfix. The character data from the string is copied.
MappedName& operator+=(const std::string& other)
{
if (!other.empty()) {
this->postfix.reserve(this->postfix.size() + static_cast<int>(other.size()));
this->postfix.append(other.c_str(), static_cast<int>(other.size()));
}
return *this;
}
/// Appends other to this instance's postfix. The data may be either copied or shared, depending
/// on whether this->postfix is empty (in which case the data is shared) or non-empty (in which
/// case it is copied).
MappedName& operator+=(const QByteArray& other)
{
this->postfix += other;
return *this;
}
/// Appends other to this instance's postfix, unless this is empty, in which case this acts
/// like operator=, and makes this instance's data equal to other's data, and this instance's
/// postfix equal to the other instance's postfix.
MappedName& operator+=(const MappedName& other)
{
append(other);
return *this;
}
/// Add dataToAppend to this MappedName. If the current name is empty, this becomes the new
/// data element. If this MappedName already has data, then the data is appended to the postfix.
///
/// \param dataToAppend The data to add. A deep copy is made.
/// \param size The number of bytes to copy. If omitted, dataToAppend must be null-terminated.
void append(const char* dataToAppend, int size = -1)
{
if (dataToAppend && (size != 0)) {
if (size < 0) {
size = static_cast<int>(qstrlen(dataToAppend));
}
if (empty()) {
this->data.append(dataToAppend, size);
}
else {
this->postfix.append(dataToAppend, size);
}
}
}
/// Treating both this and other as single continuous byte arrays, append other to this. If this
/// is empty, then other's data is shared with this instance's data beginning at startPosition.
/// If this is *not* empty, then all data is appended to the postfix. If the copy crosses the
/// boundary between other's data and its postfix, then if this instance was empty, the new
/// data stops where other's data stops, and the remainder of the copy is placed in the suffix.
/// Otherwise the copy simply continues as though there was no distinction between other's
/// data and suffix.
///
/// \param other The MappedName to obtain the data from. The data is shared when possible,
/// depending on the details of startPosition, size, and this->empty().
/// \param startPosition The byte to start the copy at. Must be a positive non-zero integer less
/// than the length of other's combined data + postfix.
/// \param size The number of bytes to copy. Must not overrun the end of other's combined data
/// storage when taking startPosition into consideration.
void append(const MappedName& other, int startPosition = 0, int size = -1)
{
// enforce 0 <= startPosition <= other.size
if (startPosition < 0) {
startPosition = 0;
}
else if (startPosition > other.size()) {
return;
}
// enforce 0 <= size <= other.size - startPosition
if (size < 0 || size > other.size() - startPosition) {
size = other.size() - startPosition;
}
if (startPosition < other.data.size())// if starting inside data
{
int count = size;
// make sure count doesn't exceed data size and end up in postfix
if (count > other.data.size() - startPosition) {
count = other.data.size() - startPosition;
}
// if this is empty append in data else append in postfix
if (startPosition == 0 && count == other.data.size() && this->empty()) {
this->data = other.data;
this->raw = other.raw;
}
else {
append(other.data.constData() + startPosition, count);
}
// setup startPosition and count to continue appending the remainder to postfix
startPosition = 0;
size -= count;
}
else// else starting inside postfix
{
startPosition -= other.data.size();
}
// if there is still data to be added to postfix
if (size != 0) {
if (startPosition == 0 && size == other.postfix.size()) {
if (this->empty()) {
this->data = other.postfix;
}
else if (this->postfix.isEmpty()) {
this->postfix = other.postfix;
}
else {
this->postfix += other.postfix;
}
}
else {
append(other.postfix.constData() + startPosition, size);
}
}
}
/// Create a std::string from this instance, starting at startPosition, and extending len bytes.
///
/// \param startPosition The offset into the data
/// \param len The number of bytes to output
/// \return A new std::string containing the bytes copied from this instance's data and postfix
/// (depending on startPosition and len).
/// \note No effort is made to ensure that these are valid ASCII characters, and it is possible
/// the data includes embedded null characters, non-ASCII data, etc.
std::string toString(int startPosition = 0, int len = -1) const
{
std::string res;
return appendToBuffer(res, startPosition, len);
}
/// Given a (possibly non-empty) std::string buffer, append this instance to it, starting at a
/// specified position, and continuing for a specified number of bytes.
///
/// \param buffer The string buffer to append to.
/// \param startPosition The position in this instance's data/postfix to start at (defaults to
/// zero). Must be less than the total length of the data plus the postfix.
/// \param len The number of bytes to append. If omitted, defaults to appending all available
/// data starting at startPosition.
/// \return A pointer to the beginning of the appended data within buffer.
/// \note No effort is made to ensure that these are valid ASCII characters, and it is possible
/// the data includes embedded null characters, non-ASCII data, etc.
const char* appendToBuffer(std::string& buffer, int startPosition = 0, int len = -1) const
{
std::size_t offset = buffer.size();
int count = this->size();
if (startPosition < 0) {
startPosition = 0;
}
else if (startPosition >= count) {
return buffer.c_str() + buffer.size();
}
if (len < 0 || len > count - startPosition) {
len = count - startPosition;
}
buffer.reserve(buffer.size() + len);
if (startPosition < this->data.size()) {
count = this->data.size() - startPosition;
if (len < count) {
count = len;
}
buffer.append(this->data.constData() + startPosition, count);
len -= count;
}
buffer.append(this->postfix.constData(), len);
return buffer.c_str() + offset;
}
// if offset is inside data return data, if offset is > data.size
//(ends up in postfix) return postfix
const char* toConstString(int offset, int& size) const
{
if (offset < 0) {
offset = 0;
}
if (offset > this->data.size()) {
offset -= this->data.size();
if (offset > this->postfix.size()) {
size = 0;
return "";
}
size = this->postfix.size() - offset;
return this->postfix.constData() + offset;
}
size = this->data.size() - offset;
return this->data.constData() + offset;
}
/// Get access to raw byte data. When possible, data is shared between this instance and the
/// returned QByteArray. If the combination of offset and size results in data that crosses the
/// boundary between this->data and this->postfix, the data must be copied in order to provide
/// access as a continuous array of bytes.
///
/// \param offset The start position of the raw data access.
/// \param size The number of bytes to access. If omitted, the resulting QByteArray includes
/// everything starting from offset to the end, including any postfix data.
/// \return A new QByteArray that shares data with this instance if possible, or is a new copy
/// if required by offset and size.
QByteArray toRawBytes(int offset = 0, int size = -1) const
{
if (offset < 0) {
offset = 0;
}
if (offset >= this->size()) {
return {};
}
if (size < 0 || size > this->size() - offset) {
size = this->size() - offset;
}
if (offset >= this->data.size()) {
offset -= this->data.size();
return QByteArray::fromRawData(this->postfix.constData() + offset, size);
}
if (size <= this->data.size() - offset) {
return QByteArray::fromRawData(this->data.constData() + offset, size);
}
QByteArray res(this->data.constData() + offset, this->data.size() - offset);
res.append(this->postfix.constData(), size - this->data.size() + offset);
return res;
}
/// Direct access to the stored QByteArray of data. A copy is never made.
const QByteArray& dataBytes() const
{
return this->data;
}
/// Direct access to the stored QByteArray of postfix. A copy is never made.
const QByteArray& postfixBytes() const
{
return this->postfix;
}
/// Convenience function providing access to the pointer to the beginning of the postfix data.
const char* constPostfix() const
{
return this->postfix.constData();
}
// No constData() because 'data' is allowed to contain raw data, which may not end with 0.
/// Provide access to the content of this instance. If either postfix or data is empty, no copy
/// is made and the original QByteArray is returned, sharing data with this instance. If this
/// instance contains both data and postfix, a new QByteArray is created and stores a copy of
/// the data and postfix concatenated together.
QByteArray toBytes() const
{
if (this->postfix.isEmpty()) {
return this->data;
}
if (this->data.isEmpty()) {
return this->postfix;
}
return this->data + this->postfix;
}
/// Create an IndexedName from the data portion of this MappedName. If this data has a postfix,
/// the function returns an empty IndexedName. The function will fail if this->data contains
/// anything other than the ASCII letter a-z, A-Z, and the underscore, with an optional integer
/// suffix, returning an empty IndexedName (e.g. an IndexedName that evaluates to boolean
/// false and isNull() == true).
///
/// \return a new IndexedName that shares its data with this instance's data member.
IndexedName toIndexedName() const
{
if (this->postfix.isEmpty()) {
return IndexedName(this->data);
}
return IndexedName();
}
/// Create and return a string version of this MappedName prefixed by the ComplexGeoData element
/// map prefix, if this MappedName cannot be converted to an indexed name.
std::string toPrefixedString() const
{
std::string res;
appendToBufferWithPrefix(res);
return res;
}
/// Append this MappedName to a provided string buffer, including the ComplexGeoData element
/// map prefix if the MappedName cannot be converted to an IndexedName.
///
/// \param buf A (possibly non-empty) string to append this MappedName to.
/// \return A pointer to the beginning of the buffer.
const char* appendToBufferWithPrefix(std::string& buf) const
{
if (!toIndexedName()) {
buf += ComplexGeoData::elementMapPrefix();
}
appendToBuffer(buf);
return buf.c_str();
}
/// Equivalent to C++20 operator<=>. Performs byte-by-byte comparison of this and other,
/// starting at the first byte and continuing through both data and postfix, ignoring which is
/// which. If the combined data and postfix members are of unequal size but start with the same
/// data, the shorter array is considered "less than" the longer.
int compare(const MappedName& other) const
{
int thisSize = this->size();
int otherSize = other.size();
for (int i = 0, count = std::min(thisSize, otherSize); i < count; ++i) {
char thisChar = this->operator[](i);
char otherChar = other[i];
if (thisChar < otherChar) {
return -1;
}
if (thisChar > otherChar) {
return 1;
}
}
if (thisSize < otherSize) {
return -1;
}
if (thisSize > otherSize) {
return 1;
}
return 0;
}
/// \see compare()
bool operator<(const MappedName& other) const
{
return compare(other) < 0;
}
/// Treat this MappedName as a single continuous array of bytes, beginning with data and
/// continuing through postfix. No bounds checking is performed when compiled in release mode.
char operator[](int index) const
{
if (index < 0) {
index = 0;
}
if (index >= this->data.size()) {
if (index - this->data.size() > this->postfix.size() - 1) {
index = this->postfix.size() - 1;
}
return this->postfix[index - this->data.size()];
}
return this->data[index];
}
/// Treat this MappedName as a single continuous array of bytes, returning the combined size
/// of the data and postfix.
int size() const
{
return this->data.size() + this->postfix.size();
}
/// Treat this MappedName as a single continuous array of bytes, returning true only if both
/// data and prefix are empty.
bool empty() const
{
return this->data.isEmpty() && this->postfix.isEmpty();
}
/// Returns true if this is shared data, or false if a unique copy has been made.
/// It is safe to access data only if it has been copied prior. To force a copy
/// please \see compact()
bool isRaw() const
{
return this->raw;
}
/// If this is shared data, a new unshared copy is made and returned. If it is already unshared
/// no new copy is made, a new instance is returned that shares is data with the current
/// instance.
MappedName copy() const
{
if (!this->raw) {
return *this;
}
MappedName res;
res.data.append(this->data.constData(), this->data.size());
res.postfix = this->postfix;
return res;
}
/// Ensure that this data is unshared, making a copy if necessary.
void compact();
/// Boolean conversion is the inverse of empty(), returning true if there is data in either the
/// data or postfix, and false if there is nothing in either.
explicit operator bool() const
{
return !empty();
}
/// Reset this instance, clearing anything in data and postfix.
void clear()
{
this->data.clear();
this->postfix.clear();
this->raw = false;
}
/// Find a string of characters in this MappedName. The bytes must occur either entirely in the
/// data, or entirely in the postfix: a string that overlaps the two will not be found.
///
/// \param searchTarget A null-terminated C string to search for.
/// \param startPosition A byte offset to start the search at.
/// \return The position of the target in this instance, or -1 if the target is not found.
int find(const char* searchTarget, int startPosition = 0) const
{
if (!searchTarget) {
return -1;
}
if (startPosition < 0) {
startPosition = 0;
}
if (startPosition < this->data.size()) {
int res = this->data.indexOf(searchTarget, startPosition);
if (res >= 0) {
return res;
}
startPosition = 0;
}
else {
startPosition -= this->data.size();
}
int res = this->postfix.indexOf(searchTarget, startPosition);
if (res < 0) {
return res;
}
return res + this->data.size();
}
/// Find a string of characters in this MappedName. The bytes must occur either entirely in the
/// data, or entirely in the postfix: a string that overlaps the two will not be found.
///
/// \param searchTarget A string to search for.
/// \param startPosition A byte offset to start the search at.
/// \return The position of the target in this instance, or -1 if the target is not found.
int find(const std::string& searchTarget, int startPosition = 0) const
{
return find(searchTarget.c_str(), startPosition);
}
/// Find a string of characters in this MappedName, starting at the back of postfix and
/// proceeding in reverse through the data. The bytes must occur either entirely in the
/// data, or entirely in the postfix: a string that overlaps the two will not be found.
///
/// \param searchTarget A null-terminated C string to search for.
/// \param startPosition A byte offset to start the search at. Negative numbers are supported
/// and count back from the end of the concatenated data (as in QByteArray::lastIndexOf()).
/// \return The position of the target in this instance, or -1 if the target is not found.
int rfind(const char* searchTarget, int startPosition = -1) const
{
if (!searchTarget) {
return -1;
}
if (startPosition < 0
|| startPosition >= this->data.size()) {
if (startPosition >= data.size()) {
startPosition -= data.size();
}
int res = this->postfix.lastIndexOf(searchTarget, startPosition);
if (res >= 0) {
return res + this->data.size();
}
startPosition = -1;
}
return this->data.lastIndexOf(searchTarget, startPosition);
}
/// Find a string in this MappedName, starting at the back of postfix and proceeding in reverse
/// through the data. The bytes must occur either entirely in the data, or entirely in the
/// postfix: a string that overlaps the two will not be found.
///
/// \param searchTarget A null-terminated C string to search for.
/// \param startPosition A byte offset to start the search at. Negative numbers are supported
/// and count back from the end of the concatenated data (as in QByteArray::lastIndexOf()).
/// \return The position of the target in this instance, or -1 if the target is not found.
int rfind(const std::string& searchTarget, int startPosition = -1) const
{
return rfind(searchTarget.c_str(), startPosition);
}
/// Returns true if this MappedName ends with the search target. If there is a postfix, only the
/// postfix is considered. If not, then only the data is considered. A search string that
/// overlaps the two will not be found.
bool endsWith(const char* searchTarget) const
{
if (!searchTarget) {
return false;
}
if (this->postfix.size() != 0) {
return this->postfix.endsWith(searchTarget);
}
return this->data.endsWith(searchTarget);
}
/// Returns true if this MappedName ends with the search target. If there is a postfix, only the
/// postfix is considered. If not, then only the data is considered. A search string that
/// overlaps the two will not be found.
bool endsWith(const std::string& searchTarget) const
{
return endsWith(searchTarget.c_str());
}
/// Returns true if this MappedName starts with the search target. If there is a postfix, only
/// the postfix is considered. If not, then only the data is considered. A search string that
/// overlaps the two will not be found.
///
/// \param searchTarget An array of bytes to match
/// \param offset An offset to perform the match at
/// \return True if this MappedName begins with the target bytes
bool startsWith(const QByteArray& searchTarget, int offset = 0) const
{
if (searchTarget.size() > size() - offset) {
return false;
}
if ((offset != 0)
|| ((this->data.size() != 0) && this->data.size() < searchTarget.size())) {
return toRawBytes(offset, searchTarget.size()) == searchTarget;
}
if (this->data.size() != 0) {
return this->data.startsWith(searchTarget);
}
return this->postfix.startsWith(searchTarget);
}
/// Returns true if this MappedName starts with the search target. If there is a postfix, only
/// the postfix is considered. If not, then only the data is considered. A search string that
/// overlaps the two will not be found.
///
/// \param searchTarget An array of bytes to match
/// \param offset An offset to perform the match at
/// \return True if this MappedName begins with the target bytes
bool startsWith(const char* searchTarget, int offset = 0) const
{
if (!searchTarget) {
return false;
}
return startsWith(
QByteArray::fromRawData(searchTarget, static_cast<int>(qstrlen(searchTarget))), offset);
}
/// Returns true if this MappedName starts with the search target. If there is a postfix, only
/// the postfix is considered. If not, then only the data is considered. A search string that
/// overlaps the two will not be found.
///
/// \param searchTarget A string to match
/// \param offset An offset to perform the match at
/// \return True if this MappedName begins with the target bytes
bool startsWith(const std::string& searchTarget, int offset = 0) const
{
return startsWith(
QByteArray::fromRawData(searchTarget.c_str(), static_cast<int>(searchTarget.size())),
offset);
}
/// Get a hash for this MappedName
std::size_t hash() const
{
return qHash(data, qHash(postfix));
}
private:
QByteArray data;
QByteArray postfix;
bool raw;
};
// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
}// namespace Data
#endif// APP_MAPPED_NAME_H
+83
View File
@@ -0,0 +1,83 @@
/***************************************************************************
* Copyright (c) 2002 Jürgen Riegel <[email protected]> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License (LGPL) *
* as published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* for detail see the LICENCE text file. *
* *
* 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with FreeCAD; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
* *
***************************************************************************/
#ifndef PROGRAMOPTIONSUTILITIES_H
#define PROGRAMOPTIONSUTILITIES_H
#include <algorithm>
#include <array>
#include <string>
namespace App::Util{
std::pair<std::string, std::string> customSyntax(std::string_view strIn)
{
if(strIn.size() < 2) {
return{};
}
char leadChr {strIn[0]};
std::string rest {strIn.substr(1)};
if (leadChr == '@') {
return {"response-file", rest};
}
if (leadChr != '-') {
return {};
}
#if defined(FC_OS_MACOSX)
if (rest.find("psn_") == 0) {
return {"psn", rest.substr(4)};
}
#endif
if(rest == "widgetcount"){
return {rest, ""};
}
constexpr std::array knowns {"display",
"style",
"graphicssystem",
"geometry",
"font",
"fn",
"background",
"bg",
"foreground",
"fg",
"button",
"btn",
"name",
"title",
"visual"};
if(std::find(knowns.begin(), knowns.end(), rest) != knowns.end()) {
return {rest, "null"};
}
return {};
}
} // namespace
#endif// PROGRAMOPTIONSUTILITIES_H
+3 -1
View File
@@ -136,7 +136,9 @@ void PropertyPythonObject::fromString(const std::string& repr)
state.apply(args);
}
else if (this->object.hasAttr("__dict__")) {
this->object.setAttr("__dict__", res);
if (!res.isNone()) {
this->object.setAttr("__dict__", res);
}
}
else {
this->object = res;
+1 -1
View File
@@ -89,7 +89,7 @@ void PropertyQuantity::setPyObject(PyObject *value)
{
// Set the unit if Unit object supplied, else check the unit
// and set the value
if (PyObject_TypeCheck(value, &(UnitPy::Type))) {
Base::UnitPy *pcObject = static_cast<Base::UnitPy*>(value);
Base::Unit unit = *(pcObject->getUnitPtr());
+36
View File
@@ -0,0 +1,36 @@
<RCC>
<qresource prefix="/translations">
<file>App_be.qm</file>
<file>App_eu.qm</file>
<file>App_fr.qm</file>
<file>App_hu.qm</file>
<file>App_pl.qm</file>
<file>App_ru.qm</file>
<file>App_sl.qm</file>
<file>App_ka.qm</file>
<file>App_it.qm</file>
<file>App_hr.qm</file>
<file>App_es-ES.qm</file>
<file>App_zh-TW.qm</file>
<file>App_de.qm</file>
<file>App_sr.qm</file>
<file>App_sr-CS.qm</file>
<file>App_tr.qm</file>
<file>App_pt-BR.qm</file>
<file>App_ja.qm</file>
<file>App_ca.qm</file>
<file>App_nl.qm</file>
<file>App_uk.qm</file>
<file>App_cs.qm</file>
<file>App_zh-CN.qm</file>
<file>App_el.qm</file>
<file>App_es-AR.qm</file>
<file>App_sv-SE.qm</file>
<file>App_fi.qm</file>
<file>App_pt-PT.qm</file>
<file>App_val-ES.qm</file>
<file>App_ro.qm</file>
<file>App_gl.qm</file>
<file>App_ko.qm</file>
</qresource>
</RCC>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="423"/>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation type="unfinished"></translation>
</message>
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="be" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Захоўвае апошні выбар карыстальніка адносна таго, ці варта ўжываць наладу CopyOnChange да ўсіх спасылак, якія спасылаюцца на адзін і той жа аб'ект, які наладжваецца</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Без назвы</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ca" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Sense nom</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="cs" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Nepojmenovaný</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Speichert die letzte Benutzerwahl, ob die CopyOnChange-Einstellungen auf alle Verknüpfungen
angewendet werden soll, die das gleiche konfigurierbare Objekt referenzieren</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Unbenannt</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="el" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Ανώνυμο</translation>
</message>
</context>
</TS>
Binary file not shown.
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="es-AR" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Guarda la última opción de usuario acerca de si aplicar la configuración de CopyOnChange a todos los enlaces que hacen referencia al mismo objeto configurable</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Sin nombre</translation>
</message>
</context>
</TS>
Binary file not shown.
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="es-ES" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Guarda la última opción de usuario acerca de si aplicar la configuración de CopyOnChange a todos los enlaces que hacen referencia al mismo objeto configurable</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Sin nombre</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="eu" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Izenik gabea</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fi" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Nimetön</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Enregistre le dernier choix de l'utilisateur concernant l'application de la configuration CopyOnChange à tous les liens qui font référence au même objet configurable
</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Sans nom</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="gl" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Sen nome</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="hr" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Neimenovano</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="hu" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Tárolja a felhasználó legutóbbi döntését, hogy a CopyOnChange beállítás minden hivatkozásra alkalmazható-e,
amelyek ugyanarra a konfigurálható tárgyra hivatkoznak</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Névtelen</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="it" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Senza nome</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ja" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Unnamed</translation>
</message>
</context>
</TS>
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ka" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation> , CopyOnChange , </translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation></translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ko" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation></translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="nl" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Bewaart de laatste keuze van de gebruiker om CopyOnChange instellingen toe te passen op alle links
die verwijzen naar hetzelfde configureerbare object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Naamloos</translation>
</message>
</context>
</TS>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="pl" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Przechowuje ostatni wybór użytkownika, czy zastosować ustawienie "Kopiuj przy zmianie" do wszystkich linków,
które odnoszą się do tego samego obiektu konfigurowalnego</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Nienazwany</translation>
</message>
</context>
</TS>
Binary file not shown.
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="pt-BR" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation>Armazena a última escolha do usuário para aplicar a configuração Cópia Na Mudança (CopyOnChange) em todos os links
que referenciam o mesmo objeto configurável</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Sem nome</translation>
</message>
</context>
</TS>
Binary file not shown.
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="pt-PT" sourcelanguage="en">
<context>
<name>LinkParams</name>
<message>
<location filename="../../Link.cpp" line="119"/>
<source>Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</source>
<translation type="unfinished">Stores the last user choice of whether to apply CopyOnChange setup to all links
that reference the same configurable object</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="441"/>
<source>Unnamed</source>
<translation>Sem nome</translation>
</message>
</context>
</TS>

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