Merge branch 'main' into weekly-build-dependencies

This commit is contained in:
Jackson Oursland
2025-04-17 23:12:20 -07:00
committed by GitHub
53 changed files with 1201 additions and 914 deletions
@@ -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?
-->
+11
View File
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
- package-ecosystem: pip
directory: /
schedule:
interval: daily
+6 -1
View File
@@ -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
+27
View File
@@ -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
+7 -2
View File
@@ -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 -1
View File
@@ -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"
+81
View File
@@ -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
+11 -6
View File
@@ -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: |
+10 -5
View File
@@ -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: |
+10 -5
View File
@@ -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: |
+11 -3
View File
@@ -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: |
+7 -2
View File
@@ -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: |
+13 -3
View File
@@ -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
+10 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}
}
+11
View File
@@ -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 */
//@{
-20
View File
@@ -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.
-5
View File
@@ -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};
+42
View File
@@ -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";
}
+3
View File
@@ -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
+5 -273
View File
@@ -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
View File
@@ -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>
+13
View File
@@ -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);
}
+11
View File
@@ -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);
}
+208 -239
View File
@@ -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>>
+1 -2
View File
@@ -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,
+1 -1
View File
@@ -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:
+4 -4
View File
@@ -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()
+5 -5
View File
@@ -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:
+6 -6
View File
@@ -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:
+5 -5
View File
@@ -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()
+5 -5
View File
@@ -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:
+5 -5
View File
@@ -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()
+3 -3
View File
@@ -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")
+5 -5
View File
@@ -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
+9 -5
View File
@@ -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);
+2
View File
@@ -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;
+5
View File
@@ -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
+12 -1
View File
@@ -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)
{
+1
View File
@@ -47,6 +47,7 @@ Q_SIGNALS:
void resizeFinished();
protected:
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* event) override;
bool viewportEvent(QEvent* e) override;
+2 -1
View File
@@ -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 + "°";