Merge branch 'main' into weekly-build-dependencies
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<!--
|
||||
The FreeCAD community thanks you for your contribution!
|
||||
By creating a Pull Request you agree to the contributing policy. The complete policy can be found in the root of the source tree (CONTRIBUTING.md) or at https://github.com/FreeCAD/FreeCAD/blob/main/CONTRIBUTING.md
|
||||
|
||||
This template provides guidance on creating a PR that can be reviewed and approved as quickly as possible. Comments may be safely deleted.
|
||||
|
||||
Unless you know exactly what you're doing, please leave the checkbox 'Allow edits by maintainers' enabled. This will allow maintainers to help you.
|
||||
-->
|
||||
|
||||
## Description
|
||||
<!-- Include a brief summary of the changes. -->
|
||||
|
||||
## Issues
|
||||
<!-- link to individual issues this PR closes by referencing the issue number (e.g., fixes #1234, closes #4321). -->
|
||||
|
||||
## Before and After Images
|
||||
<!-- If your proposed changes affect the FreeCAD GUI, add before and after screenshots -->
|
||||
|
||||
|
||||
|
||||
<!-- Notes on the PR Review Process
|
||||
|
||||
The following section describes what the maintainers consider when reviewing your Pull Request. These items may not require you to take any action. This information is provided for context. Understanding what we consider will help you prepare your request for speedy approval.
|
||||
|
||||
You can find additional documentation about these guidelines in the [Developers handbook](https://freecad.github.io/DevelopersHandbook).
|
||||
|
||||
Alignment (Does the PR align with the goals and interests of the project?)
|
||||
- Does the PR have at least one issue linked, which this PR closes?
|
||||
- Has the conversation on the PR and related issue(s) reached consensus?
|
||||
- If the PR affects the GUI, is the Design Working Group (DWG) aware and have they had time to review and comment?
|
||||
- If the PR affects the GUI, did the contributor include before/after images?
|
||||
- If the PR affects standards and workflow, is the CAD Working Group (CWG) aware and have they had time to review/comment?
|
||||
|
||||
Impact (Does the change affect other parts of the project?)
|
||||
- Has the impact on documentation been considered and appropriate action taken?
|
||||
- Has the impact on translation been considered appropriate action taken?
|
||||
- Will the PR affect existing user documents?
|
||||
|
||||
Code Quality (Is code well-written and maintainable?)
|
||||
- Does the PR warrant a review by the Code Quality Working Group (CQWG)?
|
||||
- Does the change include tests?
|
||||
- Is the PR rebased on the current main branch with unnecessary commits squashed?
|
||||
|
||||
Release (Are there considerations related to release timing?)
|
||||
- Has the PR been considered for backporting to the latest release branch?
|
||||
- Have the release notes been considered/updated?
|
||||
-->
|
||||
@@ -0,0 +1,11 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
@@ -57,6 +57,11 @@ jobs:
|
||||
env:
|
||||
logdir: /tmp/log/
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Make needed directories
|
||||
run: |
|
||||
mkdir -p ${{ env.logdir }}
|
||||
@@ -103,7 +108,7 @@ jobs:
|
||||
done
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ github.job }}-Logs
|
||||
path: |
|
||||
|
||||
@@ -20,9 +20,14 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: '🧹 Tag & close stale unconfirmed bugs'
|
||||
id: stale_issues
|
||||
uses: actions/[email protected]
|
||||
uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: -1
|
||||
@@ -49,7 +54,7 @@ jobs:
|
||||
|
||||
- name: '🧹 Close stale requested feedback issues'
|
||||
id: awaiting_issues
|
||||
uses: actions/[email protected]
|
||||
uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: -1
|
||||
@@ -77,7 +82,7 @@ jobs:
|
||||
|
||||
- name: '🧹 Tag & close inactive issues'
|
||||
id: inactive_issues
|
||||
uses: actions/[email protected]
|
||||
uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: -1
|
||||
@@ -108,7 +113,7 @@ jobs:
|
||||
|
||||
- name: '🧹 Tag & close inactive PRs'
|
||||
id: inactive_pr
|
||||
uses: actions/[email protected]
|
||||
uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: -1
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Dependency Review Action
|
||||
#
|
||||
# This Action will scan dependency manifest files that change as part of a Pull Request,
|
||||
# surfacing known-vulnerable versions of the packages declared or updated in the PR.
|
||||
# Once installed, if the workflow run is marked as required,
|
||||
# PRs introducing known-vulnerable packages will be blocked from merging.
|
||||
#
|
||||
# Source repository: https://github.com/actions/dependency-review-action
|
||||
name: 'Dependency Review'
|
||||
on: [pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
dependency-review:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@67d4f4bd7a9b17a0db54d2a7519187c65e339de8 # v4
|
||||
@@ -16,6 +16,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Get dates for last month
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -30,13 +35,13 @@ jobs:
|
||||
echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Run issue-metrics tool
|
||||
uses: github/issue-metrics@v3
|
||||
uses: github/issue-metrics@4f29f34d9d831fe224cbc6c8a0d711415ebd01b1 # v3.1.1
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SEARCH_QUERY: 'repo:FreeCAD/FreeCAD is:issue created:${{ env.last_month }}'
|
||||
|
||||
- name: Create issue
|
||||
uses: peter-evans/create-issue-from-file@v4
|
||||
uses: peter-evans/create-issue-from-file@433e51abf769039ee20ba1293a088ca19d573b7f # v4.0.1
|
||||
with:
|
||||
title: Monthly issue metrics report
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -9,6 +9,9 @@ on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -17,7 +20,12 @@ jobs:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
configuration-path: ".github/labels.yml"
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# This workflow uses actions that are not certified by GitHub. They are provided
|
||||
# by a third-party and are governed by separate terms of service, privacy
|
||||
# policy, and support documentation.
|
||||
|
||||
name: Scorecard supply-chain security
|
||||
on:
|
||||
# For Branch-Protection check. Only the default branch is supported. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
|
||||
branch_protection_rule:
|
||||
# To guarantee Maintained check is occasionally updated. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
||||
schedule:
|
||||
- cron: '20 7 * * 2'
|
||||
push:
|
||||
branches: ["main"]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecard analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Needed to publish results and get a badge (see publish_results below).
|
||||
id-token: write
|
||||
contents: read
|
||||
actions: read
|
||||
# To allow GraphQL ListCommits to work
|
||||
issues: read
|
||||
pull-requests: read
|
||||
# To detect SAST tools
|
||||
checks: read
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecards on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
|
||||
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
||||
|
||||
# Public repositories:
|
||||
# - Publish results to OpenSSF REST API for easy access by consumers
|
||||
# - Allows the repository to include the Scorecard badge.
|
||||
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories:
|
||||
# - `publish_results` will always be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -69,6 +69,11 @@ jobs:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Set Platform Environment Variables
|
||||
shell: bash -l {0}
|
||||
env:
|
||||
@@ -81,7 +86,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Add GCC Problem Matcher
|
||||
if: runner.os == 'Linux'
|
||||
@@ -106,13 +111,13 @@ jobs:
|
||||
mkdir -p ${{ env.reportdir }}
|
||||
echo "reportFile=${{ env.reportfilename }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: prefix-dev/[email protected].7
|
||||
- uses: prefix-dev/setup-pixi@19eac09b398e3d0c747adc7921926a6d802df4da # v0.8.8
|
||||
with:
|
||||
pixi-version: v0.45.0
|
||||
cache: false
|
||||
|
||||
- name: Restore Compiler Cache
|
||||
uses: actions/cache/restore@v4
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: FC-${{ env.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
|
||||
@@ -195,14 +200,14 @@ jobs:
|
||||
|
||||
- name: Save Compiler Cache
|
||||
if: always()
|
||||
uses: actions/cache/save@v4
|
||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: FC-${{ env.cacheKey }}-${{ github.ref }}-${{ github.run_id }}
|
||||
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ inputs.artifactBasename }}-${{ matrix.os }}-Logs
|
||||
path: |
|
||||
@@ -211,7 +216,7 @@ jobs:
|
||||
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ env.reportfilename }}
|
||||
path: |
|
||||
|
||||
@@ -71,8 +71,13 @@ jobs:
|
||||
reportFile: ${{ steps.Init.outputs.reportFile }}
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checking out source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install FreeCAD dependencies
|
||||
@@ -94,7 +99,7 @@ jobs:
|
||||
compiler: ${{ env.CXX }}
|
||||
qt_major_version: 5
|
||||
- name: Restore Compiler Cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
save-always: true
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
@@ -108,7 +113,7 @@ jobs:
|
||||
ccache -z
|
||||
ccache -p
|
||||
- name: Install cmake
|
||||
uses: jwlawson/actions-setup-cmake@v2
|
||||
uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2.0.2
|
||||
with:
|
||||
cmake-version: '3.31.6'
|
||||
- name: CMake Configure
|
||||
@@ -179,7 +184,7 @@ jobs:
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ inputs.artifactBasename }}-Logs
|
||||
path: |
|
||||
@@ -187,7 +192,7 @@ jobs:
|
||||
/var/crash/*FreeCAD*
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ env.reportfilename }}
|
||||
path: |
|
||||
|
||||
@@ -62,8 +62,13 @@ jobs:
|
||||
reportFile: ${{ steps.Init.outputs.reportFile }}
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checking out source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Make needed directories, files and initializations
|
||||
@@ -85,7 +90,7 @@ jobs:
|
||||
with:
|
||||
libpackdir: ${{ env.libpackdir }}
|
||||
- name: Restore compiler cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
save-always: true
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
@@ -99,7 +104,7 @@ jobs:
|
||||
. $env:ccachebindir\ccache -z
|
||||
. $env:ccachebindir\ccache -p
|
||||
- name: Install cmake
|
||||
uses: jwlawson/actions-setup-cmake@v2
|
||||
uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2.0.2
|
||||
with:
|
||||
cmake-version: '3.31.6'
|
||||
- name: Configuring CMake
|
||||
@@ -115,7 +120,7 @@ jobs:
|
||||
-DFREECAD_COPY_LIBPACK_BIN_TO_BUILD=ON
|
||||
-DFREECAD_COPY_PLUGINS_BIN_TO_BUILD=ON
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0
|
||||
- name: Compiling sources
|
||||
run: |
|
||||
cd $env:builddir
|
||||
@@ -133,7 +138,7 @@ jobs:
|
||||
. ${{ env.builddir }}\bin\FreeCADCmd -t 0 # 2>&1 | tee -filepath ${{ env.logdir }}\integrationTests.log
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ inputs.artifactBasename }}-Logs
|
||||
path: |
|
||||
|
||||
@@ -168,6 +168,9 @@ on:
|
||||
reportFile:
|
||||
value: ${{ jobs.Lint.outputs.reportFile }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
Lint:
|
||||
@@ -185,8 +188,13 @@ jobs:
|
||||
reportFile: ${{ steps.Init.outputs.reportFile }}
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -335,7 +343,7 @@ jobs:
|
||||
|
||||
- name: Upload logs and fixes
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ inputs.artifactBasename }}-Logs
|
||||
path: |
|
||||
@@ -344,7 +352,7 @@ jobs:
|
||||
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ env.reportfilename }}
|
||||
path: |
|
||||
|
||||
@@ -71,6 +71,11 @@ jobs:
|
||||
changedCppFiles: ${{ steps.Output.outputs.changedCppFiles }}
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Make needed directories, files and initializations
|
||||
id: Init
|
||||
run: |
|
||||
@@ -148,14 +153,14 @@ jobs:
|
||||
echo "" >> $GITHUB_OUTPUT
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ inputs.artifactBasename }}-Logs
|
||||
path: |
|
||||
${{ env.logdir }}
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ env.reportfilename }}
|
||||
path: |
|
||||
|
||||
@@ -12,7 +12,12 @@ jobs:
|
||||
outputs:
|
||||
build_tag: ${{ steps.tag_build.outputs.build_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
submodules: 'recursive'
|
||||
@@ -68,6 +73,11 @@ jobs:
|
||||
remove-android: 'true' # (frees ~9 GB)
|
||||
remove-cached-tools: 'true' # (frees ~8.3 GB)
|
||||
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Set Platform Environment Variables
|
||||
shell: bash -l {0}
|
||||
env:
|
||||
@@ -80,13 +90,13 @@ jobs:
|
||||
echo 'RATTLER_CACHE_DIR=D:\rattler' >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
submodules: 'recursive'
|
||||
|
||||
- uses: prefix-dev/[email protected].3
|
||||
- uses: prefix-dev/setup-pixi@19eac09b398e3d0c747adc7921926a6d802df4da # v0.8.8
|
||||
with:
|
||||
pixi-version: v0.42.1
|
||||
cache: false
|
||||
|
||||
@@ -39,6 +39,9 @@ on:
|
||||
type: string
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
WrapUp:
|
||||
@@ -50,11 +53,16 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Make needed directories, files and initializations
|
||||
run: |
|
||||
mkdir -p ${{ env.artifactsDownloadDir }}
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||
with:
|
||||
path: ${{ env.artifactsDownloadDir }}
|
||||
- name: Save input data to file
|
||||
@@ -111,7 +119,7 @@ jobs:
|
||||
cat report.md >> $GITHUB_STEP_SUMMARY
|
||||
- name: Delete used artifacts
|
||||
continue-on-error: true
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
uses: geekyeggo/delete-artifact@f275313e70c08f6120db482d7a6b98377786765b # v5.1.0
|
||||
with:
|
||||
name: |
|
||||
${{ env.usedArtifacts }}
|
||||
|
||||
+3
-3
@@ -1,16 +1,16 @@
|
||||
area==1.1.1
|
||||
cog==0.6.1
|
||||
ConfigParser==5.3.0
|
||||
ConfigParser==7.2.0
|
||||
defusedxml==0.7.1
|
||||
ifcopenshell==0.7.0.230318
|
||||
ladybug-core==0.42.2
|
||||
matplotlib==3.6.3
|
||||
numpy==1.24.2
|
||||
opencamlib==2023.1.11
|
||||
packaging==23.0
|
||||
packaging==24.2
|
||||
Pivy==0.6.8
|
||||
ply==3.11
|
||||
debugpy==1.6.7
|
||||
debugpy==1.8.14
|
||||
pyNastran==1.3.4
|
||||
pyshp==2.3.1
|
||||
PySide2==5.15.2.1
|
||||
|
||||
+268
-23
@@ -64,7 +64,10 @@
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QRegularExpression>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
#include <Inventor/C/basic.h>
|
||||
#include <LibraryVersions.h>
|
||||
|
||||
#include <App/MaterialPy.h>
|
||||
@@ -125,7 +128,6 @@
|
||||
#include "OriginGroupExtension.h"
|
||||
#include "OriginGroupExtensionPy.h"
|
||||
#include "SuppressibleExtension.h"
|
||||
#include "SuppressibleExtensionPy.h"
|
||||
#include "Part.h"
|
||||
#include "GeoFeaturePy.h"
|
||||
#include "Placement.h"
|
||||
@@ -172,6 +174,7 @@ FC_LOG_LEVEL_INIT("App", true, true)
|
||||
|
||||
using namespace App;
|
||||
namespace sp = std::placeholders;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
//==========================================================================
|
||||
// Application
|
||||
@@ -2384,28 +2387,10 @@ void parseProgramOptions(int ac, char ** av, const std::string& exe, boost::prog
|
||||
|
||||
void processProgramOptions(const boost::program_options::variables_map& vm, std::map<std::string,std::string>& mConfig)
|
||||
{
|
||||
if (vm.count("version")) {
|
||||
if (vm.count("version") && !vm.count("verbose")) {
|
||||
std::stringstream str;
|
||||
str << mConfig["ExeName"] << " " << mConfig["ExeVersion"]
|
||||
<< " Revision: " << mConfig["BuildRevision"] << '\n';
|
||||
if (vm.count("verbose")) {
|
||||
str << "\nLibrary versions:\n";
|
||||
str << "boost " << BOOST_LIB_VERSION << '\n';
|
||||
str << "Coin3D " << fcCoin3dVersion << '\n';
|
||||
str << "Eigen3 " << fcEigen3Version << '\n';
|
||||
#ifdef OCC_VERSION_STRING_EXT
|
||||
str << "OCC " << OCC_VERSION_STRING_EXT << '\n';
|
||||
#endif
|
||||
str << "Qt " << QT_VERSION_STR << '\n';
|
||||
str << "Python " << PY_VERSION << '\n';
|
||||
str << "PySide " << fcPysideVersion << '\n';
|
||||
str << "shiboken " << fcShibokenVersion << '\n';
|
||||
#ifdef SMESH_VERSION_STR
|
||||
str << "SMESH " << SMESH_VERSION_STR << '\n';
|
||||
#endif
|
||||
str << "VTK " << fcVtkVersion << '\n';
|
||||
str << "xerces-c " << fcXercescVersion << '\n';
|
||||
}
|
||||
throw Base::ProgramInformation(str.str());
|
||||
}
|
||||
|
||||
@@ -2535,6 +2520,7 @@ void processProgramOptions(const boost::program_options::variables_map& vm, std:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -2658,8 +2644,6 @@ void Application::initConfig(int argc, char ** argv)
|
||||
_pConsoleObserverStd->bWrn = false;
|
||||
_pConsoleObserverStd->bErr = false;
|
||||
}
|
||||
if (mConfig["Verbose"] == "Strict")
|
||||
Base::Console().UnsetConsoleMode(Base::ConsoleSingleton::Verbose);
|
||||
|
||||
// file logging Init ===========================================================
|
||||
if (mConfig["LoggingFile"] == "1") {
|
||||
@@ -2670,7 +2654,7 @@ void Application::initConfig(int argc, char ** argv)
|
||||
_pConsoleObserverFile = nullptr;
|
||||
|
||||
// Banner ===========================================================
|
||||
if (mConfig["RunMode"] != "Cmd") {
|
||||
if (mConfig["RunMode"] != "Cmd" && !(vm.count("verbose") && vm.count("version"))) {
|
||||
// Remove banner if FreeCAD is invoked via the -c command as regular
|
||||
// Python interpreter
|
||||
if (mConfig["Verbose"] != "Strict")
|
||||
@@ -2781,6 +2765,11 @@ void Application::initConfig(int argc, char ** argv)
|
||||
|
||||
|
||||
logStatus();
|
||||
|
||||
if (vm.count("verbose") && vm.count("version")) {
|
||||
Application::_pcSingleton = new Application(mConfig);
|
||||
throw Base::ProgramInformation(Application::verboseVersionEmitMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::SaveEnv(const char* s)
|
||||
@@ -3549,3 +3538,259 @@ std::string Application::FindHomePath(const char* sCall)
|
||||
#else
|
||||
# error "std::string Application::FindHomePath(const char*) not implemented"
|
||||
#endif
|
||||
|
||||
QString Application::prettyProductInfoWrapper()
|
||||
{
|
||||
auto productName = QSysInfo::prettyProductName();
|
||||
#ifdef FC_OS_MACOSX
|
||||
auto macosVersionFile =
|
||||
QStringLiteral("/System/Library/CoreServices/.SystemVersionPlatform.plist");
|
||||
auto fi = QFileInfo(macosVersionFile);
|
||||
if (fi.exists() && fi.isReadable()) {
|
||||
auto plistFile = QFile(macosVersionFile);
|
||||
plistFile.open(QIODevice::ReadOnly);
|
||||
while (!plistFile.atEnd()) {
|
||||
auto line = plistFile.readLine();
|
||||
if (line.contains("ProductUserVisibleVersion")) {
|
||||
auto nextLine = plistFile.readLine();
|
||||
if (nextLine.contains("<string>")) {
|
||||
QRegularExpression re(QStringLiteral("\\s*<string>(.*)</string>"));
|
||||
auto matches = re.match(QString::fromUtf8(nextLine));
|
||||
if (matches.hasMatch()) {
|
||||
productName = QStringLiteral("macOS ") + matches.captured(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef FC_OS_WIN64
|
||||
QSettings regKey {
|
||||
QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
|
||||
QSettings::NativeFormat};
|
||||
if (regKey.contains(QStringLiteral("CurrentBuildNumber"))) {
|
||||
auto buildNumber = regKey.value(QStringLiteral("CurrentBuildNumber")).toInt();
|
||||
if (buildNumber > 0) {
|
||||
if (buildNumber < 9200) {
|
||||
productName = QStringLiteral("Windows 7 build %1").arg(buildNumber);
|
||||
}
|
||||
else if (buildNumber < 10240) {
|
||||
productName = QStringLiteral("Windows 8 build %1").arg(buildNumber);
|
||||
}
|
||||
else if (buildNumber < 22000) {
|
||||
productName = QStringLiteral("Windows 10 build %1").arg(buildNumber);
|
||||
}
|
||||
else {
|
||||
productName = QStringLiteral("Windows 11 build %1").arg(buildNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return productName;
|
||||
}
|
||||
|
||||
void Application::addModuleInfo(QTextStream& str, const QString& modPath, bool& firstMod)
|
||||
{
|
||||
QFileInfo mod(modPath);
|
||||
if (mod.isHidden()) { // Ignore hidden directories
|
||||
return;
|
||||
}
|
||||
if (firstMod) {
|
||||
firstMod = false;
|
||||
str << "Installed mods: \n";
|
||||
}
|
||||
str << " * " << (mod.isDir() ? QDir(modPath).dirName() : mod.fileName());
|
||||
try {
|
||||
auto metadataFile =
|
||||
std::filesystem::path(mod.absoluteFilePath().toStdString()) / "package.xml";
|
||||
if (std::filesystem::exists(metadataFile)) {
|
||||
App::Metadata metadata(metadataFile);
|
||||
if (metadata.version() != App::Meta::Version()) {
|
||||
str << QLatin1String(" ") + QString::fromStdString(metadata.version().str());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
auto what = QString::fromUtf8(e.what()).trimmed().replace(QChar::fromLatin1('\n'),
|
||||
QChar::fromLatin1(' '));
|
||||
str << " (Malformed metadata: " << what << ")";
|
||||
}
|
||||
QFileInfo disablingFile(mod.absoluteFilePath(), QStringLiteral("ADDON_DISABLED"));
|
||||
if (disablingFile.exists()) {
|
||||
str << " (Disabled)";
|
||||
}
|
||||
|
||||
str << "\n";
|
||||
}
|
||||
|
||||
QString Application::getValueOrEmpty(const std::map<std::string, std::string>& map, const std::string& key) {
|
||||
auto it = map.find(key);
|
||||
return (it != map.end()) ? QString::fromStdString(it->second) : QString();
|
||||
}
|
||||
|
||||
void Application::getVerboseCommonInfo(QTextStream& str, const std::map<std::string,std::string>& mConfig)
|
||||
{
|
||||
std::map<std::string, std::string>::iterator it;
|
||||
const QString deskEnv =
|
||||
QProcessEnvironment::systemEnvironment().value(QStringLiteral("XDG_CURRENT_DESKTOP"),
|
||||
QString());
|
||||
const QString deskSess =
|
||||
QProcessEnvironment::systemEnvironment().value(QStringLiteral("DESKTOP_SESSION"),
|
||||
QString());
|
||||
|
||||
const QString major = getValueOrEmpty(mConfig, "BuildVersionMajor");
|
||||
const QString minor = getValueOrEmpty(mConfig, "BuildVersionMinor");
|
||||
const QString point = getValueOrEmpty(mConfig, "BuildVersionPoint");
|
||||
const QString suffix = getValueOrEmpty(mConfig, "BuildVersionSuffix");
|
||||
const QString build = getValueOrEmpty(mConfig, "BuildRevision");
|
||||
const QString buildDate = getValueOrEmpty(mConfig, "BuildRevisionDate");
|
||||
|
||||
QStringList deskInfoList;
|
||||
QString deskInfo;
|
||||
|
||||
if (!deskEnv.isEmpty()) {
|
||||
deskInfoList.append(deskEnv);
|
||||
}
|
||||
if (!deskSess.isEmpty()) {
|
||||
deskInfoList.append(deskSess);
|
||||
}
|
||||
|
||||
const QString sysType = QSysInfo::productType();
|
||||
if (sysType != QLatin1String("windows") && sysType != QLatin1String("macos")) {
|
||||
QString sessionType = QProcessEnvironment::systemEnvironment().value(QStringLiteral("XDG_SESSION_TYPE"),
|
||||
QString());
|
||||
if (sessionType == QLatin1String("x11")) {
|
||||
sessionType = QStringLiteral("xcb");
|
||||
}
|
||||
deskInfoList.append(sessionType);
|
||||
}
|
||||
if (!deskInfoList.isEmpty()) {
|
||||
deskInfo = QLatin1String(" (") + deskInfoList.join(QLatin1String("/")) + QLatin1String(")");
|
||||
}
|
||||
|
||||
str << "OS: " << prettyProductInfoWrapper() << deskInfo << '\n';
|
||||
if (QSysInfo::buildCpuArchitecture() == QSysInfo::currentCpuArchitecture()) {
|
||||
str << "Architecture: " << QSysInfo::buildCpuArchitecture() << "\n";
|
||||
}
|
||||
else {
|
||||
str << "Architecture: " << QSysInfo::buildCpuArchitecture()
|
||||
<< "(running on: " << QSysInfo::currentCpuArchitecture() << ")\n";
|
||||
}
|
||||
str << "Version: " << major << "." << minor << "." << point << suffix << "." << build;
|
||||
|
||||
#ifdef FC_CONDA
|
||||
str << " Conda";
|
||||
#endif
|
||||
#ifdef FC_FLATPAK
|
||||
str << " Flatpak";
|
||||
#endif
|
||||
const char* appimage = getenv("APPIMAGE");
|
||||
if (appimage) {
|
||||
str << " AppImage";
|
||||
}
|
||||
const char* snap = getenv("SNAP_REVISION");
|
||||
if (snap) {
|
||||
str << " Snap " << snap;
|
||||
}
|
||||
str << '\n';
|
||||
str << "Build date: " << buildDate << "\n";
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
str << "Build type: Debug\n";
|
||||
#elif defined(NDEBUG)
|
||||
str << "Build type: Release\n";
|
||||
#elif defined(CMAKE_BUILD_TYPE)
|
||||
str << "Build type: " << CMAKE_BUILD_TYPE << '\n';
|
||||
#else
|
||||
str << "Build type: Unknown\n";
|
||||
#endif
|
||||
const QString buildRevisionBranch = getValueOrEmpty(mConfig, "BuildRevisionBranch");
|
||||
if (!buildRevisionBranch.isEmpty()) {
|
||||
str << "Branch: " << buildRevisionBranch << '\n';
|
||||
}
|
||||
const QString buildRevisionHash = getValueOrEmpty(mConfig, "BuildRevisionHash");
|
||||
if (!buildRevisionHash.isEmpty()) {
|
||||
str << "Hash: " << buildRevisionHash << '\n';
|
||||
}
|
||||
// report also the version numbers of the most important libraries in FreeCAD
|
||||
str << "Python " << PY_VERSION << ", ";
|
||||
str << "Qt " << QT_VERSION_STR << ", ";
|
||||
str << "Coin " << COIN_VERSION << ", ";
|
||||
str << "Vtk " << fcVtkVersion << ", ";
|
||||
str << "boost " << BOOST_LIB_VERSION << ", ";
|
||||
str << "Eigen3 " << fcEigen3Version << ", ";
|
||||
str << "PySide " << fcPysideVersion << '\n';
|
||||
str << "shiboken " << fcShibokenVersion << ", ";
|
||||
#ifdef SMESH_VERSION_STR
|
||||
str << "SMESH " << SMESH_VERSION_STR << ", ";
|
||||
#endif
|
||||
str << "xerces-c " << fcXercescVersion << ", ";
|
||||
|
||||
const char* cmd = "import ifcopenshell\n"
|
||||
"version = ifcopenshell.version";
|
||||
PyObject * ifcopenshellVer = nullptr;
|
||||
|
||||
try {
|
||||
ifcopenshellVer = Base::Interpreter().getValue(cmd, "version");
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Log("%s (safe to ignore, unless using the BIM workbench and IFC).\n", e.what());
|
||||
}
|
||||
|
||||
if (ifcopenshellVer) {
|
||||
const char* ifcopenshellVerAsStr = PyUnicode_AsUTF8(ifcopenshellVer);
|
||||
|
||||
if (ifcopenshellVerAsStr) {
|
||||
str << "IfcOpenShell " << ifcopenshellVerAsStr << ", ";
|
||||
}
|
||||
Py_DECREF(ifcopenshellVer);
|
||||
}
|
||||
|
||||
#if defined(HAVE_OCC_VERSION)
|
||||
str << "OCC " << OCC_VERSION_MAJOR << "." << OCC_VERSION_MINOR << "." << OCC_VERSION_MAINTENANCE
|
||||
#ifdef OCC_VERSION_DEVELOPMENT
|
||||
<< "." OCC_VERSION_DEVELOPMENT
|
||||
#endif
|
||||
<< '\n';
|
||||
#endif
|
||||
QLocale loc;
|
||||
str << "Locale: " << QLocale::languageToString(loc.language()) << "/"
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
|
||||
<< QLocale::countryToString(loc.country())
|
||||
#else
|
||||
<< QLocale::territoryToString(loc.territory())
|
||||
#endif
|
||||
<< " (" << loc.name() << ")";
|
||||
if (loc != QLocale::system()) {
|
||||
loc = QLocale::system();
|
||||
str << " [ OS: " << QLocale::languageToString(loc.language()) << "/"
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
|
||||
<< QLocale::countryToString(loc.country())
|
||||
#else
|
||||
<< QLocale::territoryToString(loc.territory())
|
||||
#endif
|
||||
<< " (" << loc.name() << ") ]";
|
||||
}
|
||||
str << "\n";
|
||||
}
|
||||
|
||||
void Application::getVerboseAddOnsInfo(QTextStream& str, const std::map<std::string,std::string>& mConfig) {
|
||||
// Add installed module information:
|
||||
const auto modDir = fs::path(Application::getUserAppDataDir()) / "Mod";
|
||||
bool firstMod = true;
|
||||
if (fs::exists(modDir) && fs::is_directory(modDir)) {
|
||||
for (const auto& mod : fs::directory_iterator(modDir)) {
|
||||
auto dirName = mod.path().string();
|
||||
addModuleInfo(str, QString::fromStdString(dirName), firstMod);
|
||||
}
|
||||
}
|
||||
const QString additionalModules = getValueOrEmpty(mConfig, "AdditionalModulePaths");
|
||||
|
||||
if (!additionalModules.isEmpty()) {
|
||||
auto mods = additionalModules.split(QChar::fromLatin1(';'));
|
||||
for (const auto& mod : mods) {
|
||||
addModuleInfo(str, mod, firstMod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define SRC_APP_APPLICATION_H_
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <QtCore/qtextstream.h>
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
@@ -433,6 +434,16 @@ public:
|
||||
static std::string getHelpDir();
|
||||
//@}
|
||||
|
||||
/** @name Verbose Information */
|
||||
//@{
|
||||
static void getVerboseCommonInfo(QTextStream& str, const std::map<std::string,std::string>& mConfig);
|
||||
static void getVerboseAddOnsInfo(QTextStream& str, const std::map<std::string,std::string>& mConfig);
|
||||
static void addModuleInfo(QTextStream& str, const QString& modPath, bool& firstMod);
|
||||
static QString prettyProductInfoWrapper();
|
||||
static QString getValueOrEmpty(const std::map<std::string, std::string>& map, const std::string& key);
|
||||
static constexpr const char* verboseVersionEmitMessage{"verbose_version"};
|
||||
//@}
|
||||
|
||||
/** @name Link handling */
|
||||
//@{
|
||||
|
||||
|
||||
@@ -168,26 +168,6 @@ ConsoleSingleton::~ConsoleSingleton()
|
||||
//**************************************************************************
|
||||
// methods
|
||||
|
||||
/**
|
||||
* sets the console in a special mode
|
||||
*/
|
||||
void ConsoleSingleton::SetConsoleMode(ConsoleMode mode)
|
||||
{
|
||||
if (mode & Verbose) {
|
||||
_bVerbose = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unsets the console from a special mode
|
||||
*/
|
||||
void ConsoleSingleton::UnsetConsoleMode(ConsoleMode mode)
|
||||
{
|
||||
if (mode & Verbose) {
|
||||
_bVerbose = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \a type can be OR'ed with any of the FreeCAD_ConsoleMsgType flags to enable -- if \a b is true --
|
||||
* or to disable -- if \a b is false -- a console observer with name \a sObs.
|
||||
|
||||
@@ -814,10 +814,6 @@ public:
|
||||
MsgType_Notification = 32, // Special message to for notifications to the user
|
||||
};
|
||||
|
||||
/// Change mode
|
||||
void SetConsoleMode(ConsoleMode mode);
|
||||
/// Change mode
|
||||
void UnsetConsoleMode(ConsoleMode mode);
|
||||
/// Enables or disables message types of a certain console observer
|
||||
ConsoleMsgFlags SetEnabledMsgType(const char* sObs, ConsoleMsgFlags type, bool on);
|
||||
/// Checks if message types of a certain console observer are enabled
|
||||
@@ -869,7 +865,6 @@ private:
|
||||
static PyObject* sPyGetStatus(PyObject* self, PyObject* args);
|
||||
static PyObject* sPyGetObservers(PyObject* self, PyObject* args);
|
||||
|
||||
bool _bVerbose {true};
|
||||
bool _bCanRefresh {true};
|
||||
ConnectionMode connectionMode {Direct};
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <QMessageLogContext>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
#include <QScreen>
|
||||
#include <QStatusBar>
|
||||
#include <QStyle>
|
||||
#include <QTextStream>
|
||||
@@ -2631,3 +2632,44 @@ App::Document* Application::reopen(App::Document* doc)
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
void Application::getVerboseDPIStyleInfo(QTextStream& str) {
|
||||
// Add Stylesheet/Theme/Qtstyle information
|
||||
std::string styleSheet =
|
||||
App::GetApplication()
|
||||
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow")
|
||||
->GetASCII("StyleSheet");
|
||||
std::string theme =
|
||||
App::GetApplication()
|
||||
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow")
|
||||
->GetASCII("Theme");
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
|
||||
std::string style = qApp->style()->name().toStdString();
|
||||
#else
|
||||
std::string style =
|
||||
App::GetApplication()
|
||||
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow")
|
||||
->GetASCII("QtStyle");
|
||||
if (style.empty()) {
|
||||
style = "Qt default";
|
||||
}
|
||||
#endif
|
||||
if (styleSheet.empty()) {
|
||||
styleSheet = "unset";
|
||||
}
|
||||
if (theme.empty()) {
|
||||
theme = "unset";
|
||||
}
|
||||
|
||||
str << "Stylesheet/Theme/QtStyle: " << QString::fromStdString(styleSheet) << "/"
|
||||
<< QString::fromStdString(theme) << "/" << QString::fromStdString(style) << "\n";
|
||||
|
||||
// Add DPI information
|
||||
str << "Logical DPI/Physical DPI/Pixel Ratio: "
|
||||
<< QApplication::primaryScreen()->logicalDotsPerInch()
|
||||
<< "/"
|
||||
<< QApplication::primaryScreen()->physicalDotsPerInch()
|
||||
<< "/"
|
||||
<< QApplication::primaryScreen()->devicePixelRatio()
|
||||
<< "\n";
|
||||
}
|
||||
@@ -252,6 +252,9 @@ public:
|
||||
void tryClose( QCloseEvent * e );
|
||||
//@}
|
||||
|
||||
/// get verbose DPI and style info
|
||||
static void getVerboseDPIStyleInfo(QTextStream& str);
|
||||
|
||||
/// whenever GUI is about to start with the main window hidden
|
||||
static bool hiddenMainWindow();
|
||||
/// return the status bits
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <CXX/WrapPython.h>
|
||||
#include <Gui/Application.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <LibraryVersions.h>
|
||||
@@ -62,59 +63,6 @@ using namespace Gui;
|
||||
using namespace Gui::Dialog;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static QString prettyProductInfoWrapper()
|
||||
{
|
||||
auto productName = QSysInfo::prettyProductName();
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
|
||||
#ifdef FC_OS_MACOSX
|
||||
auto macosVersionFile =
|
||||
QStringLiteral("/System/Library/CoreServices/.SystemVersionPlatform.plist");
|
||||
auto fi = QFileInfo(macosVersionFile);
|
||||
if (fi.exists() && fi.isReadable()) {
|
||||
auto plistFile = QFile(macosVersionFile);
|
||||
plistFile.open(QIODevice::ReadOnly);
|
||||
while (!plistFile.atEnd()) {
|
||||
auto line = plistFile.readLine();
|
||||
if (line.contains("ProductUserVisibleVersion")) {
|
||||
auto nextLine = plistFile.readLine();
|
||||
if (nextLine.contains("<string>")) {
|
||||
QRegularExpression re(QStringLiteral("\\s*<string>(.*)</string>"));
|
||||
auto matches = re.match(QString::fromUtf8(nextLine));
|
||||
if (matches.hasMatch()) {
|
||||
productName = QStringLiteral("macOS ") + matches.captured(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FC_OS_WIN64
|
||||
QSettings regKey {
|
||||
QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
|
||||
QSettings::NativeFormat};
|
||||
if (regKey.contains(QStringLiteral("CurrentBuildNumber"))) {
|
||||
auto buildNumber = regKey.value(QStringLiteral("CurrentBuildNumber")).toInt();
|
||||
if (buildNumber > 0) {
|
||||
if (buildNumber < 9200) {
|
||||
productName = QStringLiteral("Windows 7 build %1").arg(buildNumber);
|
||||
}
|
||||
else if (buildNumber < 10240) {
|
||||
productName = QStringLiteral("Windows 8 build %1").arg(buildNumber);
|
||||
}
|
||||
else if (buildNumber < 22000) {
|
||||
productName = QStringLiteral("Windows 10 build %1").arg(buildNumber);
|
||||
}
|
||||
else {
|
||||
productName = QStringLiteral("Windows 11 build %1").arg(buildNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return productName;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
AboutDialogFactory* AboutDialogFactory::factory = nullptr;
|
||||
@@ -296,7 +244,7 @@ void AboutDialog::setupLabels()
|
||||
ui->labelBuildDate->setText(date);
|
||||
|
||||
QString os = ui->labelBuildOS->text();
|
||||
os.replace(QStringLiteral("Unknown"), prettyProductInfoWrapper());
|
||||
os.replace(QStringLiteral("Unknown"), App::Application::prettyProductInfoWrapper());
|
||||
ui->labelBuildOS->setText(os);
|
||||
|
||||
QString architecture = ui->labelBuildRunArchitecture->text();
|
||||
@@ -527,230 +475,14 @@ void AboutDialog::linkActivated(const QUrl& link)
|
||||
licenseView->setSource(link);
|
||||
}
|
||||
|
||||
void AboutDialog::addModuleInfo(QTextStream& str, const QString& modPath, bool& firstMod)
|
||||
{
|
||||
QFileInfo mod(modPath);
|
||||
if (mod.isHidden()) { // Ignore hidden directories
|
||||
return;
|
||||
}
|
||||
if (firstMod) {
|
||||
firstMod = false;
|
||||
str << "Installed mods: \n";
|
||||
}
|
||||
str << " * " << (mod.isDir() ? QDir(modPath).dirName() : mod.fileName());
|
||||
try {
|
||||
auto metadataFile =
|
||||
std::filesystem::path(mod.absoluteFilePath().toStdString()) / "package.xml";
|
||||
if (std::filesystem::exists(metadataFile)) {
|
||||
App::Metadata metadata(metadataFile);
|
||||
if (metadata.version() != App::Meta::Version()) {
|
||||
str << QLatin1String(" ") + QString::fromStdString(metadata.version().str());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
auto what = QString::fromUtf8(e.what()).trimmed().replace(QChar::fromLatin1('\n'),
|
||||
QChar::fromLatin1(' '));
|
||||
str << " (Malformed metadata: " << what << ")";
|
||||
}
|
||||
QFileInfo disablingFile(mod.absoluteFilePath(), QStringLiteral("ADDON_DISABLED"));
|
||||
if (disablingFile.exists()) {
|
||||
str << " (Disabled)";
|
||||
}
|
||||
|
||||
str << "\n";
|
||||
}
|
||||
|
||||
void AboutDialog::copyToClipboard()
|
||||
{
|
||||
QString data;
|
||||
QTextStream str(&data);
|
||||
std::map<std::string, std::string>& config = App::Application::Config();
|
||||
std::map<std::string, std::string>::iterator it;
|
||||
QString exe = QString::fromStdString(App::Application::getExecutableName());
|
||||
|
||||
QString major = QString::fromStdString(config["BuildVersionMajor"]);
|
||||
QString minor = QString::fromStdString(config["BuildVersionMinor"]);
|
||||
QString point = QString::fromStdString(config["BuildVersionPoint"]);
|
||||
QString suffix = QString::fromStdString(config["BuildVersionSuffix"]);
|
||||
QString build = QString::fromStdString(config["BuildRevision"]);
|
||||
QString buildDate = QString::fromStdString(config["BuildRevisionDate"]);
|
||||
|
||||
QString deskEnv =
|
||||
QProcessEnvironment::systemEnvironment().value(QStringLiteral("XDG_CURRENT_DESKTOP"),
|
||||
QString());
|
||||
QString deskSess =
|
||||
QProcessEnvironment::systemEnvironment().value(QStringLiteral("DESKTOP_SESSION"),
|
||||
QString());
|
||||
QStringList deskInfoList;
|
||||
QString deskInfo;
|
||||
|
||||
if (!deskEnv.isEmpty()) {
|
||||
deskInfoList.append(deskEnv);
|
||||
}
|
||||
if (!deskSess.isEmpty()) {
|
||||
deskInfoList.append(deskSess);
|
||||
}
|
||||
if (qGuiApp->platformName() != QLatin1String("windows")
|
||||
&& qGuiApp->platformName() != QLatin1String("cocoa")) {
|
||||
deskInfoList.append(qGuiApp->platformName());
|
||||
}
|
||||
if (!deskInfoList.isEmpty()) {
|
||||
deskInfo = QLatin1String(" (") + deskInfoList.join(QLatin1String("/")) + QLatin1String(")");
|
||||
}
|
||||
|
||||
str << "OS: " << prettyProductInfoWrapper() << deskInfo << '\n';
|
||||
if (QSysInfo::buildCpuArchitecture() == QSysInfo::currentCpuArchitecture()) {
|
||||
str << "Architecture: " << QSysInfo::buildCpuArchitecture() << "\n";
|
||||
}
|
||||
else {
|
||||
str << "Architecture: " << QSysInfo::buildCpuArchitecture()
|
||||
<< "(running on: " << QSysInfo::currentCpuArchitecture() << ")\n";
|
||||
}
|
||||
str << "Version: " << major << "." << minor << "." << point << suffix << "." << build;
|
||||
#ifdef FC_CONDA
|
||||
str << " Conda";
|
||||
#endif
|
||||
#ifdef FC_FLATPAK
|
||||
str << " Flatpak";
|
||||
#endif
|
||||
char* appimage = getenv("APPIMAGE");
|
||||
if (appimage) {
|
||||
str << " AppImage";
|
||||
}
|
||||
char* snap = getenv("SNAP_REVISION");
|
||||
if (snap) {
|
||||
str << " Snap " << snap;
|
||||
}
|
||||
str << '\n';
|
||||
str << "Build date: " << buildDate << "\n";
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
str << "Build type: Debug\n";
|
||||
#elif defined(NDEBUG)
|
||||
str << "Build type: Release\n";
|
||||
#elif defined(CMAKE_BUILD_TYPE)
|
||||
str << "Build type: " << CMAKE_BUILD_TYPE << '\n';
|
||||
#else
|
||||
str << "Build type: Unknown\n";
|
||||
#endif
|
||||
it = config.find("BuildRevisionBranch");
|
||||
if (it != config.end()) {
|
||||
str << "Branch: " << QString::fromStdString(it->second) << '\n';
|
||||
}
|
||||
it = config.find("BuildRevisionHash");
|
||||
if (it != config.end()) {
|
||||
str << "Hash: " << QString::fromStdString(it->second) << '\n';
|
||||
}
|
||||
// report also the version numbers of the most important libraries in FreeCAD
|
||||
str << "Python " << PY_VERSION << ", ";
|
||||
str << "Qt " << QT_VERSION_STR << ", ";
|
||||
str << "Coin " << COIN_VERSION << ", ";
|
||||
str << "Vtk " << fcVtkVersion << ", ";
|
||||
|
||||
const char* cmd = "import ifcopenshell\n"
|
||||
"version = ifcopenshell.version";
|
||||
PyObject * ifcopenshellVer = nullptr;
|
||||
|
||||
try {
|
||||
ifcopenshellVer = Base::Interpreter().getValue(cmd, "version");
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Log("%s (safe to ignore, unless using the BIM workbench and IFC).\n", e.what());
|
||||
}
|
||||
|
||||
if (ifcopenshellVer) {
|
||||
const char* ifcopenshellVerAsStr = PyUnicode_AsUTF8(ifcopenshellVer);
|
||||
|
||||
if (ifcopenshellVerAsStr) {
|
||||
str << "IfcOpenShell " << ifcopenshellVerAsStr << ", ";
|
||||
}
|
||||
Py_DECREF(ifcopenshellVer);
|
||||
}
|
||||
|
||||
#if defined(HAVE_OCC_VERSION)
|
||||
str << "OCC " << OCC_VERSION_MAJOR << "." << OCC_VERSION_MINOR << "." << OCC_VERSION_MAINTENANCE
|
||||
#ifdef OCC_VERSION_DEVELOPMENT
|
||||
<< "." OCC_VERSION_DEVELOPMENT
|
||||
#endif
|
||||
<< '\n';
|
||||
#endif
|
||||
QLocale loc;
|
||||
str << "Locale: " << QLocale::languageToString(loc.language()) << "/"
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
|
||||
<< QLocale::countryToString(loc.country())
|
||||
#else
|
||||
<< QLocale::territoryToString(loc.territory())
|
||||
#endif
|
||||
<< " (" << loc.name() << ")";
|
||||
if (loc != QLocale::system()) {
|
||||
loc = QLocale::system();
|
||||
str << " [ OS: " << QLocale::languageToString(loc.language()) << "/"
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
|
||||
<< QLocale::countryToString(loc.country())
|
||||
#else
|
||||
<< QLocale::territoryToString(loc.territory())
|
||||
#endif
|
||||
<< " (" << loc.name() << ") ]";
|
||||
}
|
||||
str << "\n";
|
||||
|
||||
// Add Stylesheet/Theme/Qtstyle information
|
||||
std::string styleSheet =
|
||||
App::GetApplication()
|
||||
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow")
|
||||
->GetASCII("StyleSheet");
|
||||
std::string theme =
|
||||
App::GetApplication()
|
||||
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow")
|
||||
->GetASCII("Theme");
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
|
||||
std::string style = qApp->style()->name().toStdString();
|
||||
#else
|
||||
std::string style =
|
||||
App::GetApplication()
|
||||
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow")
|
||||
->GetASCII("QtStyle");
|
||||
if (style.empty()) {
|
||||
style = "Qt default";
|
||||
}
|
||||
#endif
|
||||
if (styleSheet.empty()) {
|
||||
styleSheet = "unset";
|
||||
}
|
||||
if (theme.empty()) {
|
||||
theme = "unset";
|
||||
}
|
||||
|
||||
str << "Stylesheet/Theme/QtStyle: " << QString::fromStdString(styleSheet) << "/"
|
||||
<< QString::fromStdString(theme) << "/" << QString::fromStdString(style) << "\n";
|
||||
|
||||
// Add DPI information
|
||||
str << "Logical DPI/Physical DPI/Pixel Ratio: "
|
||||
<< QApplication::primaryScreen()->logicalDotsPerInch()
|
||||
<< "/"
|
||||
<< QApplication::primaryScreen()->physicalDotsPerInch()
|
||||
<< "/"
|
||||
<< QApplication::primaryScreen()->devicePixelRatio()
|
||||
<< "\n";
|
||||
|
||||
// Add installed module information:
|
||||
auto modDir = fs::path(App::Application::getUserAppDataDir()) / "Mod";
|
||||
bool firstMod = true;
|
||||
if (fs::exists(modDir) && fs::is_directory(modDir)) {
|
||||
for (const auto& mod : fs::directory_iterator(modDir)) {
|
||||
auto dirName = mod.path().string();
|
||||
addModuleInfo(str, QString::fromStdString(dirName), firstMod);
|
||||
}
|
||||
}
|
||||
auto additionalModules = config.find("AdditionalModulePaths");
|
||||
|
||||
if (additionalModules != config.end()) {
|
||||
auto mods = QString::fromStdString(additionalModules->second).split(QChar::fromLatin1(';'));
|
||||
for (const auto& mod : mods) {
|
||||
addModuleInfo(str, mod, firstMod);
|
||||
}
|
||||
}
|
||||
App::Application::getVerboseCommonInfo(str, config);
|
||||
Gui::Application::getVerboseDPIStyleInfo(str);
|
||||
App::Application::getVerboseAddOnsInfo(str, config);
|
||||
|
||||
QClipboard* cb = QApplication::clipboard();
|
||||
cb->setText(data);
|
||||
|
||||
+246
-219
@@ -1,245 +1,274 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<author/>
|
||||
<comment/>
|
||||
<exportmacro/>
|
||||
<class>Gui::Dialog::DlgCustomActions</class>
|
||||
<widget class="QWidget" name="Gui::Dialog::DlgCustomActions">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>523</width>
|
||||
<width>564</width>
|
||||
<height>383</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Macros</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="GroupBox7">
|
||||
<property name="title">
|
||||
<string>Setup Custom Macros</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item rowspan="9" row="0" column="0">
|
||||
<widget class="QTreeWidget" name="actionListWidget">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="TextLabel1_3">
|
||||
<property name="text">
|
||||
<string>Macro:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="4">
|
||||
<widget class="QComboBox" name="actionMacros"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="TextLabel3">
|
||||
<property name="text">
|
||||
<string>Menu text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="actionMenu"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="TextLabel2_2">
|
||||
<property name="text">
|
||||
<string>Tool tip:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="actionToolTip">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>0</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="TextLabel3_2">
|
||||
<property name="text">
|
||||
<string>Status text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="actionStatus"/>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="TextLabel2">
|
||||
<property name="text">
|
||||
<string>What's this:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="actionWhatsThis"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="TextLabel1">
|
||||
<property name="text">
|
||||
<string>Accelerator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" colspan="4">
|
||||
<widget class="Gui::AccelLineEdit" name="actionAccel"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="TextLabel5_2">
|
||||
<property name="text">
|
||||
<string>Pixmap</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QToolButton" name="buttonChoosePixmap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy>
|
||||
<hsizetype>0</hsizetype>
|
||||
<vsizetype>0</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<widget class="QLabel" name="pixmapLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="4" colspan="2">
|
||||
<spacer>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QPushButton" name="buttonAddAction">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="actionListWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="TextLabel1_3">
|
||||
<property name="text">
|
||||
<string>Macro:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="TextLabel3">
|
||||
<property name="text">
|
||||
<string>Menu text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="TextLabel2_2">
|
||||
<property name="text">
|
||||
<string>Tool tip:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="TextLabel3_2">
|
||||
<property name="text">
|
||||
<string>Status text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="TextLabel2">
|
||||
<property name="text">
|
||||
<string>What's this:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="TextLabel1">
|
||||
<property name="text">
|
||||
<string>Accelerator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="Gui::AccelLineEdit" name="actionAccel"/>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="TextLabel5_2">
|
||||
<property name="text">
|
||||
<string>Pixmap</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonChoosePixmap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="pixmapLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="actionMacros"/>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="actionMenu"/>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="actionToolTip">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="actionStatus"/>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="actionWhatsThis"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAddAction">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonRemoveAction">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonReplaceAction">
|
||||
<property name="text">
|
||||
<string>Replace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>41</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2" colspan="2">
|
||||
<widget class="QPushButton" name="buttonRemoveAction">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="4">
|
||||
<widget class="QPushButton" name="buttonReplaceAction">
|
||||
<property name="text">
|
||||
<string>Replace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="5">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint">
|
||||
<size>
|
||||
<width>41</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -250,8 +279,6 @@
|
||||
<class>Gui::AccelLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Gui/Widgets.h</header>
|
||||
<container>0</container>
|
||||
<pixmap/>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
#include <QString>
|
||||
|
||||
// FreeCAD Base header
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
@@ -91,6 +93,17 @@ int main(int argc, char** argv)
|
||||
exit(1);
|
||||
}
|
||||
catch (const Base::ProgramInformation& e) {
|
||||
if (std::strcmp(e.what(), App::Application::verboseVersionEmitMessage) == 0) {
|
||||
QString data;
|
||||
QTextStream str(&data);
|
||||
const std::map<std::string, std::string> config = App::Application::Config();
|
||||
|
||||
App::Application::getVerboseCommonInfo(str, config);
|
||||
App::Application::getVerboseAddOnsInfo(str, config);
|
||||
|
||||
std::cout << data.toStdString();
|
||||
exit(0);
|
||||
}
|
||||
std::cout << e.what();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -250,6 +250,17 @@ int main(int argc, char** argv)
|
||||
catch (const Base::ProgramInformation& e) {
|
||||
QApplication app(argc, argv);
|
||||
QString msg = QString::fromUtf8(e.what());
|
||||
if (msg == QLatin1String(App::Application::verboseVersionEmitMessage)) {
|
||||
QString data;
|
||||
QTextStream str(&data);
|
||||
const std::map<std::string, std::string> config = App::Application::Config();
|
||||
|
||||
App::Application::getVerboseCommonInfo(str, config);
|
||||
Gui::Application::getVerboseDPIStyleInfo(str);
|
||||
App::Application::getVerboseAddOnsInfo(str, config);
|
||||
|
||||
msg = data;
|
||||
}
|
||||
DisplayInfo(msg);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -29,9 +29,6 @@
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/Datums.h>
|
||||
#include <App/Document.h>
|
||||
@@ -88,7 +85,6 @@
|
||||
#include "AssemblyUtils.h"
|
||||
#include "JointGroup.h"
|
||||
#include "ViewGroup.h"
|
||||
#include "SimulationGroup.h"
|
||||
|
||||
FC_LOG_LEVEL_INIT("Assembly", true, true, true)
|
||||
|
||||
@@ -1091,77 +1087,82 @@ void Assembly::AssemblyObject::create_mbdSimulationParameters(App::DocumentObjec
|
||||
std::shared_ptr<ASMTJoint> AssemblyObject::makeMbdJointOfType(App::DocumentObject* joint,
|
||||
JointType type)
|
||||
{
|
||||
if (type == JointType::Fixed) {
|
||||
if (bundleFixed) {
|
||||
return nullptr;
|
||||
}
|
||||
return CREATE<ASMTFixedJoint>::With();
|
||||
}
|
||||
else if (type == JointType::Revolute) {
|
||||
return CREATE<ASMTRevoluteJoint>::With();
|
||||
}
|
||||
else if (type == JointType::Cylindrical) {
|
||||
return CREATE<ASMTCylindricalJoint>::With();
|
||||
}
|
||||
else if (type == JointType::Slider) {
|
||||
return CREATE<ASMTTranslationalJoint>::With();
|
||||
}
|
||||
else if (type == JointType::Ball) {
|
||||
return CREATE<ASMTSphericalJoint>::With();
|
||||
}
|
||||
else if (type == JointType::Distance) {
|
||||
return makeMbdJointDistance(joint);
|
||||
}
|
||||
else if (type == JointType::Parallel) {
|
||||
return CREATE<ASMTParallelAxesJoint>::With();
|
||||
}
|
||||
else if (type == JointType::Perpendicular) {
|
||||
return CREATE<ASMTPerpendicularJoint>::With();
|
||||
}
|
||||
else if (type == JointType::Angle) {
|
||||
double angle = fabs(Base::toRadians(getJointDistance(joint)));
|
||||
if (fmod(angle, 2 * std::numbers::pi) < Precision::Confusion()) {
|
||||
switch (type) {
|
||||
case JointType::Fixed:
|
||||
if (bundleFixed) {
|
||||
return nullptr;
|
||||
}
|
||||
return CREATE<ASMTFixedJoint>::With();
|
||||
|
||||
case JointType::Revolute:
|
||||
return CREATE<ASMTRevoluteJoint>::With();
|
||||
|
||||
case JointType::Cylindrical:
|
||||
return CREATE<ASMTCylindricalJoint>::With();
|
||||
|
||||
case JointType::Slider:
|
||||
return CREATE<ASMTTranslationalJoint>::With();
|
||||
|
||||
case JointType::Ball:
|
||||
return CREATE<ASMTSphericalJoint>::With();
|
||||
|
||||
case JointType::Distance:
|
||||
return makeMbdJointDistance(joint);
|
||||
|
||||
case JointType::Parallel:
|
||||
return CREATE<ASMTParallelAxesJoint>::With();
|
||||
}
|
||||
else {
|
||||
|
||||
case JointType::Perpendicular:
|
||||
return CREATE<ASMTPerpendicularJoint>::With();
|
||||
|
||||
case JointType::Angle: {
|
||||
double angle = fabs(Base::toRadians(getJointDistance(joint)));
|
||||
if (fmod(angle, 2 * std::numbers::pi) < Precision::Confusion()) {
|
||||
return CREATE<ASMTParallelAxesJoint>::With();
|
||||
}
|
||||
auto mbdJoint = CREATE<ASMTAngleJoint>::With();
|
||||
mbdJoint->theIzJz = angle;
|
||||
return mbdJoint;
|
||||
}
|
||||
}
|
||||
else if (type == JointType::RackPinion) {
|
||||
auto mbdJoint = CREATE<ASMTRackPinionJoint>::With();
|
||||
mbdJoint->pitchRadius = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == JointType::Screw) {
|
||||
int slidingIndex = slidingPartIndex(joint);
|
||||
if (slidingIndex == 0) { // invalid this joint needs a slider
|
||||
|
||||
case JointType::RackPinion: {
|
||||
auto mbdJoint = CREATE<ASMTRackPinionJoint>::With();
|
||||
mbdJoint->pitchRadius = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case JointType::Screw: {
|
||||
int slidingIndex = slidingPartIndex(joint);
|
||||
if (slidingIndex == 0) { // invalid this joint needs a slider
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (slidingIndex != 1) {
|
||||
swapJCS(joint); // make sure that sliding is first.
|
||||
}
|
||||
|
||||
auto mbdJoint = CREATE<ASMTScrewJoint>::With();
|
||||
mbdJoint->pitch = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case JointType::Gears: {
|
||||
auto mbdJoint = CREATE<ASMTGearJoint>::With();
|
||||
mbdJoint->radiusI = getJointDistance(joint);
|
||||
mbdJoint->radiusJ = getJointDistance2(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case JointType::Belt: {
|
||||
auto mbdJoint = CREATE<ASMTGearJoint>::With();
|
||||
mbdJoint->radiusI = getJointDistance(joint);
|
||||
mbdJoint->radiusJ = -getJointDistance2(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (slidingIndex != 1) {
|
||||
swapJCS(joint); // make sure that sliding is first.
|
||||
}
|
||||
|
||||
auto mbdJoint = CREATE<ASMTScrewJoint>::With();
|
||||
mbdJoint->pitch = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == JointType::Gears) {
|
||||
auto mbdJoint = CREATE<ASMTGearJoint>::With();
|
||||
mbdJoint->radiusI = getJointDistance(joint);
|
||||
mbdJoint->radiusJ = getJointDistance2(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == JointType::Belt) {
|
||||
auto mbdJoint = CREATE<ASMTGearJoint>::With();
|
||||
mbdJoint->radiusI = getJointDistance(joint);
|
||||
mbdJoint->radiusJ = -getJointDistance2(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ASMTJoint> AssemblyObject::makeMbdJointDistance(App::DocumentObject* joint)
|
||||
@@ -1173,186 +1174,154 @@ std::shared_ptr<ASMTJoint> AssemblyObject::makeMbdJointDistance(App::DocumentObj
|
||||
auto* obj1 = getLinkedObjFromRef(joint, "Reference1");
|
||||
auto* obj2 = getLinkedObjFromRef(joint, "Reference2");
|
||||
|
||||
if (type == DistanceType::PointPoint) {
|
||||
// Point to point distance, or ball joint if distance=0.
|
||||
double distance = getJointDistance(joint);
|
||||
if (distance < Precision::Confusion()) {
|
||||
return CREATE<ASMTSphericalJoint>::With();
|
||||
switch (type) {
|
||||
case DistanceType::PointPoint: {
|
||||
// Point to point distance, or ball joint if distance=0.
|
||||
double distance = getJointDistance(joint);
|
||||
if (distance < Precision::Confusion()) {
|
||||
return CREATE<ASMTSphericalJoint>::With();
|
||||
}
|
||||
auto mbdJoint = CREATE<ASMTSphSphJoint>::With();
|
||||
mbdJoint->distanceIJ = distance;
|
||||
return mbdJoint;
|
||||
}
|
||||
auto mbdJoint = CREATE<ASMTSphSphJoint>::With();
|
||||
mbdJoint->distanceIJ = distance;
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Edge - edge cases
|
||||
else if (type == DistanceType::LineLine) {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::LineCircle) {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint) + getEdgeRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::CircleCircle) {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getEdgeRadius(obj1, elt1) + getEdgeRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
// TODO : other cases od edge-edge : Ellipse, parabola, hyperbola...
|
||||
// Edge - edge cases
|
||||
case DistanceType::LineLine: {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Face - Face cases
|
||||
else if (type == DistanceType::PlanePlane) {
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::PlaneCylinder) {
|
||||
auto mbdJoint = CREATE<ASMTLineInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::PlaneSphere) {
|
||||
auto mbdJoint = CREATE<ASMTPointInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::PlaneCone) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::PlaneTorus) {
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::CylinderCylinder) {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::CylinderSphere) {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::CylinderCone) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::CylinderTorus) {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::ConeCone) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::ConeTorus) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::ConeSphere) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::TorusTorus) {
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::TorusSphere) {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::SphereSphere) {
|
||||
auto mbdJoint = CREATE<ASMTSphSphJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
case DistanceType::LineCircle: {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint) + getEdgeRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Point - Face cases
|
||||
else if (type == DistanceType::PointPlane) {
|
||||
auto mbdJoint = CREATE<ASMTPointInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::PointCylinder) {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint) + getFaceRadius(obj1, elt1);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::PointSphere) {
|
||||
auto mbdJoint = CREATE<ASMTSphSphJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint) + getFaceRadius(obj1, elt1);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::PointCone) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::PointTorus) {
|
||||
// TODO
|
||||
}
|
||||
case DistanceType::CircleCircle: {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getEdgeRadius(obj1, elt1) + getEdgeRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Edge - Face cases
|
||||
else if (type == DistanceType::LinePlane) {
|
||||
auto mbdJoint = CREATE<ASMTLineInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::LineCylinder) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::LineSphere) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::LineCone) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::LineTorus) {
|
||||
// TODO
|
||||
}
|
||||
// Face - Face cases
|
||||
case DistanceType::PlanePlane: {
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
else if (type == DistanceType::CurvePlane) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::CurveCylinder) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::CurveSphere) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::CurveCone) {
|
||||
// TODO
|
||||
}
|
||||
else if (type == DistanceType::CurveTorus) {
|
||||
// TODO
|
||||
}
|
||||
case DistanceType::PlaneCylinder: {
|
||||
auto mbdJoint = CREATE<ASMTLineInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Point - Edge cases
|
||||
else if (type == DistanceType::PointLine) {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
else if (type == DistanceType::PointCurve) {
|
||||
// For other curves we do a point in plane-of-the-curve.
|
||||
// Maybe it would be best tangent / distance to the conic?
|
||||
// For arcs and circles we could use ASMTRevSphJoint. But is it better than pointInPlane?
|
||||
auto mbdJoint = CREATE<ASMTPointInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
case DistanceType::PlaneSphere: {
|
||||
auto mbdJoint = CREATE<ASMTPointInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::PlaneTorus: {
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// by default we make a planar joint.
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
case DistanceType::CylinderCylinder: {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::CylinderSphere: {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::CylinderTorus: {
|
||||
auto mbdJoint = CREATE<ASMTRevCylJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::TorusTorus: {
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::TorusSphere: {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::SphereSphere: {
|
||||
auto mbdJoint = CREATE<ASMTSphSphJoint>::With();
|
||||
mbdJoint->distanceIJ =
|
||||
getJointDistance(joint) + getFaceRadius(obj1, elt1) + getFaceRadius(obj2, elt2);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Point - Face cases
|
||||
case DistanceType::PointPlane: {
|
||||
auto mbdJoint = CREATE<ASMTPointInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::PointCylinder: {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint) + getFaceRadius(obj1, elt1);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::PointSphere: {
|
||||
auto mbdJoint = CREATE<ASMTSphSphJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint) + getFaceRadius(obj1, elt1);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Edge - Face cases
|
||||
case DistanceType::LinePlane: {
|
||||
auto mbdJoint = CREATE<ASMTLineInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
// Point - Edge cases
|
||||
case DistanceType::PointLine: {
|
||||
auto mbdJoint = CREATE<ASMTCylSphJoint>::With();
|
||||
mbdJoint->distanceIJ = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
case DistanceType::PointCurve: {
|
||||
// For other curves we do a point in plane-of-the-curve.
|
||||
// Maybe it would be best tangent / distance to the conic?
|
||||
// For arcs and circles we could use ASMTRevSphJoint. But is it better than
|
||||
// pointInPlane?
|
||||
auto mbdJoint = CREATE<ASMTPointInPlaneJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
|
||||
default: {
|
||||
// by default we make a planar joint.
|
||||
auto mbdJoint = CREATE<ASMTPlanarJoint>::With();
|
||||
mbdJoint->offset = getJointDistance(joint);
|
||||
return mbdJoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<MbD::ASMTJoint>>
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <App/FeaturePython.h>
|
||||
#include <App/Part.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
#include "SimulationGroup.h"
|
||||
|
||||
#include <OndselSolver/enum.h>
|
||||
|
||||
@@ -130,7 +129,7 @@ public:
|
||||
std::shared_ptr<MbD::ASMTPart> part;
|
||||
Base::Placement offsetPlc; // This is the offset within the bundled parts
|
||||
};
|
||||
MbDPartData getMbDData(App::DocumentObject* obj);
|
||||
MbDPartData getMbDData(App::DocumentObject* part);
|
||||
std::shared_ptr<MbD::ASMTMarker> makeMbdMarker(std::string& name, Base::Placement& plc);
|
||||
std::vector<std::shared_ptr<MbD::ASMTJoint>> makeMbdJoint(App::DocumentObject* joint);
|
||||
std::shared_ptr<MbD::ASMTJoint> makeMbdJointOfType(App::DocumentObject* joint,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>580</width>
|
||||
<width>640</width>
|
||||
<height>691</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
@@ -68,11 +68,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="%\\nG17 G21 G40 G49 G80 G90\\nM08"',
|
||||
help='set commands to be issued before the first command, default="%\\nG17 G21 G40 G49 G80 G90\\nM08\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05 M09\\nG17 G90 G80 G40\\nM30"',
|
||||
help='set commands to be issued after the last command, default="M05 M09\\nG17 G90 G80 G40\\nM30\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -202,7 +202,7 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
@@ -247,8 +247,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
|
||||
@@ -193,8 +193,8 @@ def export(objectslist, filename, argstring):
|
||||
):
|
||||
gcode += ";T{}={}\n".format(item.ToolNumber, item.Name)
|
||||
gcode += linenumber() + ";begin preamble\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
@@ -221,8 +221,8 @@ def export(objectslist, filename, argstring):
|
||||
gcode += linenumber() + line
|
||||
for line in SAFETYBLOCK.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
|
||||
@@ -59,11 +59,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17\\nG90\\nG80\\nG40"',
|
||||
help='set commands to be issued before the first command, default="G17\\nG90\\nG80\\nG40\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M09\\nM05\\nG80\\nG40\\nG17\\nG90\\nM30"',
|
||||
help='set commands to be issued after the last command, default="M09\\nM05\\nG80\\nG40\\nG17\\nG90\\nM30\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G70)"
|
||||
@@ -225,8 +225,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(T)" + "BEGIN PREAMBLE$\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
for obj in objectslist:
|
||||
@@ -289,8 +289,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(T)" + "BEGIN POSTAMBLE$\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
# Following is required by Dynapath Controls to signify "EOF" when loading in to control
|
||||
# from external media. The control strips the "E" off as part of the load process.
|
||||
gcode += "E\n"
|
||||
|
||||
@@ -86,11 +86,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17\\nG90\\nG80\\nG40"',
|
||||
help='set commands to be issued before the first command, default="G17\\nG90\\nG80\\nG40\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M09\\nM05\\nG80\\nG40\\nG17\\nG90\\nM30"',
|
||||
help='set commands to be issued after the last command, default="M09\\nM05\\nG80\\nG40\\nG17\\nG90\\nM30\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -231,8 +231,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
for obj in objectslist:
|
||||
@@ -255,8 +255,8 @@ def export(objectslist, filename, argstring):
|
||||
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
print("show editor: {}".format(SHOW_EDITOR))
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
|
||||
@@ -114,11 +114,11 @@ parser.add_argument(
|
||||
)
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help="set commands to be issued before the first command",
|
||||
help='set commands to be issued before the first command, default=""',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help="set commands to be issued after the last command",
|
||||
help='set commands to be issued after the last command, default="M5\\n"',
|
||||
)
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument("--inches", action="store_true", help="convert output for US imperial mode")
|
||||
@@ -235,8 +235,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
# verify if PREAMBLE have changed UNITS
|
||||
if "G21" in PREAMBLE:
|
||||
UNITS = "G21"
|
||||
@@ -310,8 +310,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
# show the gCode result dialog
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
|
||||
@@ -160,8 +160,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
for obj in objectslist:
|
||||
|
||||
@@ -183,8 +183,8 @@ def export(objectslist, filename, argstring):
|
||||
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
|
||||
@@ -65,11 +65,11 @@ parser.add_argument(
|
||||
)
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble", help='set commands to be issued before the first command, default="G90"'
|
||||
"--preamble", help='set commands to be issued before the first command, default="G90\\n"'
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M8\\nG90 G40\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M8\\nG90 G40\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -207,7 +207,7 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
@@ -251,8 +251,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
|
||||
@@ -60,11 +60,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90"',
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM6 T0\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM6 T0\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -220,7 +220,7 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(BEGIN PREAMBLE)\n"
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
@@ -276,8 +276,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(BEGIN POSTAMBLE)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += "%\n"
|
||||
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
|
||||
@@ -123,11 +123,11 @@ parser.add_argument(
|
||||
)
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17 G90"',
|
||||
help='set commands to be issued before the first command, default="G17 G90\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M5\\nG17 G90\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M5\\nG17 G90\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -283,8 +283,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
# verify if PREAMBLE have changed MOTION_MODE or UNITS
|
||||
if "G90" in PREAMBLE:
|
||||
MOTION_MODE = "G90"
|
||||
@@ -370,8 +370,8 @@ def export(objectslist, filename, argstring):
|
||||
gcode += linenumber() + "(Block-enable: 1)\n"
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
# show the gCode result dialog
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
|
||||
@@ -56,11 +56,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="M05 S0\\nG90"',
|
||||
help='set commands to be issued before the first command, default="M05 S0\\nG90\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05 S0\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M05 S0\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -198,7 +198,7 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
@@ -221,8 +221,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
|
||||
@@ -56,11 +56,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90"',
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -196,7 +196,7 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
@@ -252,8 +252,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
final = gcode
|
||||
|
||||
@@ -56,11 +56,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90"',
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -196,7 +196,7 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
@@ -255,8 +255,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
|
||||
@@ -156,7 +156,7 @@ parser.add_argument(
|
||||
"--preamble", help='set commands to be issued before the first command, default=""'
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble", help='set commands to be issued after the last command, default="M5"'
|
||||
"--postamble", help='set commands to be issued after the last command, default="M5\\n"'
|
||||
)
|
||||
parser.add_argument("--tool-change", action="store_true", help="Insert M6 for all tool changes")
|
||||
parser.add_argument(
|
||||
@@ -334,8 +334,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble:
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
# Write these settings AFTER the preamble,
|
||||
# to prevent the preamble from changing these:
|
||||
@@ -409,8 +409,8 @@ def export(objectslist, filename, argstring):
|
||||
gcode += linenumber() + "(Block-enable: 1)\n"
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
# Optionally add a final XYZ position to the end of the gcode:
|
||||
if RETURN_TO:
|
||||
|
||||
@@ -154,7 +154,7 @@ parser.add_argument(
|
||||
"--preamble", help='set commands to be issued before the first command, default=""'
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble", help='set commands to be issued after the last command, default="M5"'
|
||||
"--postamble", help='set commands to be issued after the last command, default="M5\\n"'
|
||||
)
|
||||
parser.add_argument("--tool-change", action="store_true", help="Insert M6 for all tool changes")
|
||||
parser.add_argument(
|
||||
@@ -332,8 +332,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble:
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
# Write these settings AFTER the preamble,
|
||||
# to prevent the preamble from changing these:
|
||||
@@ -407,8 +407,8 @@ def export(objectslist, filename, argstring):
|
||||
gcode += linenumber() + "(Block-enable: 1)\n"
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(Begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
# Optionally add a final XYZ position to the end of the gcode:
|
||||
if RETURN_TO:
|
||||
|
||||
@@ -68,11 +68,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="4", help="number of digits of precision, default=4")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17\\nG90"',
|
||||
help='set commands to be issued before the first command, default="G17\\nG90\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G90\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G90\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument("--IP_ADDR", help="IP Address for machine target machine")
|
||||
parser.add_argument(
|
||||
@@ -228,8 +228,8 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
for obj in objectslist:
|
||||
@@ -252,8 +252,8 @@ def export(objectslist, filename, argstring):
|
||||
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
|
||||
@@ -256,11 +256,11 @@ parser.add_argument(
|
||||
parser.add_argument("--precision", default="3", help="number of digits of precision, default=3")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17\nG90\nG54"',
|
||||
help='set commands to be issued before the first command, default="G17\\nG54\\G40\\nG49\\nG90\\nG80\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05\nM30"',
|
||||
help='set commands to be issued after the last command, default="M05\\nG17\\nG54\\nG0\\nG90\\nG80\\nM30\\n"',
|
||||
)
|
||||
parser.add_argument("--inches", action="store_true", help="lengths in [in], G20")
|
||||
parser.add_argument("--metric", action="store_true", help="lengths in [mm], G21")
|
||||
@@ -443,7 +443,7 @@ def export(objectslist, filename, argstring):
|
||||
# if isinstance(obj.Proxy, Path.Tool.Controller.ToolController):
|
||||
# gcode += append("(T{}={})\n".format(obj.ToolNumber, item.Name))
|
||||
# error: global name 'PathScripts' is not defined
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += append(line + "\n")
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += append("(preamble: done)\n")
|
||||
|
||||
@@ -68,11 +68,11 @@ parser.add_argument("--precision", default="3", help="number of digits of precis
|
||||
parser.add_argument("--fixed-length", default="0", help="use fixed length coordinates, default=0")
|
||||
parser.add_argument(
|
||||
"--preamble",
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90"',
|
||||
help='set commands to be issued before the first command, default="G17 G54 G40 G49 G80 G90\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--postamble",
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM2"',
|
||||
help='set commands to be issued after the last command, default="M05\\nG17 G54 G90 G80 G40\\nM2\\n"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--inches", action="store_true", help="Convert output for US imperial mode (G20)"
|
||||
@@ -271,7 +271,7 @@ def export(objectslist, filename, argstring):
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + COMMENT_CHAR + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(False):
|
||||
for line in PREAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
if not OMIT_UNITS:
|
||||
gcode += linenumber() + UNITS + ENDLINE + "\n"
|
||||
@@ -353,8 +353,8 @@ def export(objectslist, filename, argstring):
|
||||
# do the post_amble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + COMMENT_CHAR + "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
for line in POSTAMBLE.splitlines():
|
||||
gcode += linenumber() + line + "\n"
|
||||
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
final = gcode
|
||||
|
||||
@@ -98,12 +98,11 @@ App::DocumentObjectExecReturn* Feature::recompute()
|
||||
FC_ERR("Failed to recompute suppressed feature " << getFullName());
|
||||
}
|
||||
|
||||
Shape.setValue(getBaseTopoShape(true));
|
||||
|
||||
if (!failed) {
|
||||
updateSuppressedShape();
|
||||
}
|
||||
else {
|
||||
Shape.setValue(getBaseTopoShape(true));
|
||||
}
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
@@ -121,7 +120,6 @@ void Feature::setMaterialToBodyMaterial()
|
||||
|
||||
void Feature::updateSuppressedShape()
|
||||
{
|
||||
auto baseShape = getBaseTopoShape(true);
|
||||
TopoShape res(getID());
|
||||
TopoShape shape = Shape.getShape();
|
||||
shape.setPlacement(Base::Placement());
|
||||
@@ -139,7 +137,6 @@ void Feature::updateSuppressedShape()
|
||||
res.makeElementCompound(generated);
|
||||
res.setPlacement(Placement.getValue());
|
||||
}
|
||||
Shape.setValue(baseShape);
|
||||
SuppressedShape.setValue(res);
|
||||
}
|
||||
|
||||
@@ -196,6 +193,13 @@ void Feature::onChanged(const App::Property *prop)
|
||||
body->ShapeMaterial.setValue(ShapeMaterial.getValue());
|
||||
}
|
||||
}
|
||||
} else if (prop == &Suppressed){
|
||||
if (Suppressed.getValue()) {
|
||||
SuppressedPlacement = Placement.getValue();
|
||||
} else {
|
||||
Placement.setValue(SuppressedPlacement);
|
||||
SuppressedPlacement = Base::Placement();
|
||||
}
|
||||
}
|
||||
}
|
||||
Part::Feature::onChanged(prop);
|
||||
|
||||
@@ -60,6 +60,8 @@ public:
|
||||
|
||||
/// Keep a copy of suppressed shapes so that we can restore them (and maybe display them)
|
||||
Part::PropertyPartShape SuppressedShape;
|
||||
/// Keep a copy of the placement before suppression to restore it back when unsuppressed, fix #20205
|
||||
Base::Placement SuppressedPlacement;
|
||||
App::DocumentObjectExecReturn* recompute() override;
|
||||
|
||||
short mustExecute() const override;
|
||||
|
||||
@@ -3324,6 +3324,11 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point)
|
||||
// FIXME: we should be able to transfer these to new curves smoothly
|
||||
// auto geo = getGeometry(GeoId);
|
||||
const auto* geoAsCurve = getGeometry<Part::GeomCurve>(GeoId);
|
||||
|
||||
if (geoAsCurve == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool isOriginalCurveConstruction = GeometryFacade::getConstruction(geoAsCurve);
|
||||
|
||||
//******************* Step A => Detection of intersection - Common to all Geometries
|
||||
|
||||
@@ -56,7 +56,18 @@
|
||||
using namespace SpreadsheetGui;
|
||||
using namespace Spreadsheet;
|
||||
using namespace App;
|
||||
namespace sp = std::placeholders;
|
||||
|
||||
void SheetViewHeader::mouseMoveEvent(QMouseEvent* e)
|
||||
{
|
||||
// for some reason QWidget::setCursor() has no effect in QGraphicsView
|
||||
// therefore we resort to override cursor
|
||||
const QCursor currentCursor = this->cursor();
|
||||
QHeaderView::mouseMoveEvent(e);
|
||||
const QCursor newerCursor = this->cursor();
|
||||
if (newerCursor != currentCursor) {
|
||||
qApp->setOverrideCursor(newerCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void SheetViewHeader::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
|
||||
@@ -47,6 +47,7 @@ Q_SIGNALS:
|
||||
void resizeFinished();
|
||||
|
||||
protected:
|
||||
void mouseMoveEvent(QMouseEvent* e) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
bool viewportEvent(QEvent* e) override;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -1140,7 +1141,7 @@ protected:
|
||||
TechDraw::pointPair pp = dim->getLinearPoints();
|
||||
float dx = pp.first().x - pp.second().x;
|
||||
float dy = pp.first().y - pp.second().y;
|
||||
int alpha = round(Base::toDegrees(abs(atan(type == "DistanceY" ? (dx / dy) : (dy / dx)))));
|
||||
int alpha = std::round(Base::toDegrees(std::abs<float>(std::atan(type == "DistanceY" ? (dx / dy) : (dy / dx)))));
|
||||
std::string sAlpha = std::to_string(alpha);
|
||||
std::string formatSpec = dim->FormatSpec.getStrValue();
|
||||
formatSpec = formatSpec + " x" + sAlpha + "°";
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef _PreComp_
|
||||
# include <QApplication>
|
||||
# include <QMessageBox>
|
||||
# include <cmath>
|
||||
# include <sstream>
|
||||
# include <BRepGProp.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
@@ -2062,7 +2063,7 @@ void execCreateHorizChamferDimension(Gui::Command* cmd) {
|
||||
dim->Y.setValue(-yMax);
|
||||
float dx = allVertexes[0].point.x - allVertexes[1].point.x;
|
||||
float dy = allVertexes[0].point.y - allVertexes[1].point.y;
|
||||
float alpha = round(Base::toDegrees(abs(atan(dy / dx))));
|
||||
float alpha = std::round(Base::toDegrees(std::abs<float>(std::atan(dy / dx))));
|
||||
std::string sAlpha = std::to_string((int)alpha);
|
||||
std::string formatSpec = dim->FormatSpec.getStrValue();
|
||||
formatSpec = formatSpec + " x" + sAlpha + "°";
|
||||
@@ -2130,7 +2131,7 @@ void execCreateVertChamferDimension(Gui::Command* cmd) {
|
||||
dim->Y.setValue(-mid.y);
|
||||
float dx = allVertexes[0].point.x - allVertexes[1].point.x;
|
||||
float dy = allVertexes[0].point.y - allVertexes[1].point.y;
|
||||
float alpha = round(Base::toDegrees(abs(atan(dx / dy))));
|
||||
float alpha = std::round(Base::toDegrees(std::abs<float>(std::atan(dx / dy))));
|
||||
std::string sAlpha = std::to_string((int)alpha);
|
||||
std::string formatSpec = dim->FormatSpec.getStrValue();
|
||||
formatSpec = formatSpec + " x" + sAlpha + "°";
|
||||
|
||||
Reference in New Issue
Block a user