Merge branch 'master' into alafr-arch-structure
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
Thank you for creating a pull request to contribute to FreeCAD! To ease integration, please confirm the following:
|
||||
Thank you for creating a pull request to contribute to FreeCAD! To ease integration, we ask you to conform to the following items. Pull requests which don't satisfy all the items below might be rejected. If you are in doubt with any of the items below, don't hesitate to ask for help in the [FreeCAD forum](https://forum.freecadweb.org/viewforum.php?f=10)!
|
||||
|
||||
- [ ] Branch rebased on latest master `git pull --rebase upstream master`
|
||||
- [ ] Unit tests confirmed to pass by running `./bin/FreeCAD --run-test 0`
|
||||
- [ ] Commit message is [well-written](https://chris.beams.io/posts/git-commit/)
|
||||
- [ ] Commit message includes `issue #<id>` or `fixes #<id>` where `<id>` is the [associated MantisBT](https://freecadweb.org/wiki/tracker#GitHub_and_MantisBT) issue id if one exists
|
||||
- [ ] Your pull request is confined strictly to a single module. That is, all the files changed by your pull request are either in `App`, `Base`, `Gui` or one of the `Mod` subfolders. If you need to make changes in several locations, make several pull requests and wait for the first one to be merged before submitting the next ones
|
||||
- [ ] In case your pull request does more than just fixing small bugs, make sure you discussed your ideas with other developers on the FreeCAD forum
|
||||
- [ ] Your branch is [rebased](https://git-scm.com/docs/git-rebase) on latest master `git pull --rebase upstream master`
|
||||
- [ ] All FreeCAD unit tests are confirmed to pass by running `./bin/FreeCAD --run-test 0`
|
||||
- [ ] All commit messages are [well-written](https://chris.beams.io/posts/git-commit/) ex: `Fixes typo in Draft Move command text`
|
||||
- [ ] Your pull request is well written and has a good description, and its title starts with the module name, ex: `Draft: Fixed typos`
|
||||
- [ ] Commit messages include `issue #<id>` or `fixes #<id>` where `<id>` is the [FreeCAD bug tracker issue number](https://freecadweb.org/wiki/tracker#GitHub_and_MantisBT) in case a particular commit solves or is related to an existing issue on the tracker. Ex: `Draft: fix typos - fixes #0004805`
|
||||
|
||||
And please remember to update the Wiki with the features added or changed once this PR is merged.
|
||||
**Note**: If you don't have wiki access, then please mention your contribution on the [0.19 Changelog Forum Thread](https://forum.freecadweb.org/viewtopic.php?f=10&t=34586).
|
||||
|
||||
+32
-35
@@ -1,4 +1,4 @@
|
||||
####
|
||||
######
|
||||
#
|
||||
# Travis-CI configuration file for FreeCAD.
|
||||
#
|
||||
@@ -17,7 +17,7 @@
|
||||
#
|
||||
# DEPLOY: Repo setting to deploy (defaults to no deploy to reduce
|
||||
# Travis build times. Set DEPLOY=1 to enable in repo settings.
|
||||
####
|
||||
######
|
||||
env:
|
||||
global:
|
||||
- GENERATOR="Unix Makefiles"
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
env:
|
||||
- CC=clang-10
|
||||
- CXX=clang++-10
|
||||
- CMAKE_ARGS="-DPYTHON_EXECUTABLE=/usr/bin/python3 -DBUILD_FEM_NETGEN=ON -DBUILD_QT5=ON"
|
||||
- CMAKE_ARGS="-DPYTHON_EXECUTABLE=/usr/bin/python3 -DBUILD_FEM_NETGEN=ON"
|
||||
- CACHE_NAME=JOB1
|
||||
|
||||
- os: linux
|
||||
@@ -86,35 +86,22 @@ jobs:
|
||||
- CXX=g++-10
|
||||
- CC_FOR_BUILD=gcc-10
|
||||
- CXX_FOR_BUILD=g++-10
|
||||
- CMAKE_ARGS="-DCMAKE_CXX_COMPILER=/usr/bin/c++ -DCMAKE_C_COMPILER=/usr/bin/cc -DPYTHON_EXECUTABLE=/usr/bin/python3 -DBUILD_FEM_NETGEN=ON -DBUILD_QT5=ON"
|
||||
- CMAKE_ARGS="-DCMAKE_CXX_COMPILER=/usr/bin/c++ -DCMAKE_C_COMPILER=/usr/bin/cc -DPYTHON_EXECUTABLE=/usr/bin/python3 -DBUILD_FEM_NETGEN=ON"
|
||||
- CACHE_NAME=JOB2
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
language: cpp
|
||||
compiler: gcc-7
|
||||
cache: ccache
|
||||
env:
|
||||
- CC=gcc-7
|
||||
- CXX=g++-7
|
||||
- CC_FOR_BUILD=gcc-7
|
||||
- CXX_FOR_BUILD=g++-7
|
||||
- CMAKE_ARGS="-DCMAKE_CXX_COMPILER=/usr/bin/c++ -DCMAKE_C_COMPILER=/usr/bin/cc"
|
||||
- CACHE_NAME=JOB3
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode11.6
|
||||
language: cpp
|
||||
cache:
|
||||
- ccache: true
|
||||
- directories:
|
||||
- $HOME/.ccache
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
- /usr/local/Homebrew
|
||||
env:
|
||||
- CMAKE_OPTS="-DCMAKE_CXX_COMPILER_LAUNCHER=/usr/local/bin/ccache -DBUILD_QT5=ON -DUSE_PYTHON3=1 -DCMAKE_CXX_FLAGS='-std=c++11' -DBUILD_FEM_NETGEN=1 -DBUILD_FEM=1 -DBUILD_TECHDRAW=0 -DCMAKE_PREFIX_PATH='/usr/local/opt/qt/lib/cmake;/usr/local/opt/nglib/Contents/Resources' -DBUILD_FEM_NETGEN:BOOL=ON -DFREECAD_USE_EXTERNAL_KDL=ON -DCMAKE_BUILD_TYPE=Release"
|
||||
- PATH=/usr/local/bin:$PATH
|
||||
- CACHE_NAME=OSX1
|
||||
# - os: osx
|
||||
# osx_image: xcode11.6
|
||||
# language: cpp
|
||||
# cache:
|
||||
# - ccache: true
|
||||
# - directories:
|
||||
# - $HOME/.ccache
|
||||
# - $HOME/Library/Caches/Homebrew
|
||||
# - /usr/local/Homebrew
|
||||
# env:
|
||||
# - CMAKE_OPTS="-DBUILD_QT5=ON -DBUILD_ENABLE_CXX_STD='C++17' -DUSE_PYTHON3=1 -DCMAKE_CXX_FLAGS='-Wno-deprecated-declarations' -DBUILD_FEM_NETGEN=1 -DBUILD_FEM=1 -DBUILD_TECHDRAW=0 -DCMAKE_PREFIX_PATH='/usr/local/opt/qt/lib/cmake;/usr/local/opt/nglib/Contents/Resources' -DBUILD_FEM_NETGEN:BOOL=ON -DFREECAD_USE_EXTERNAL_KDL=ON -DCMAKE_BUILD_TYPE=Release"
|
||||
# - PATH=/usr/local/bin:$PATH
|
||||
# - CACHE_NAME=OSX1
|
||||
|
||||
- os: windows
|
||||
language: cpp
|
||||
@@ -228,7 +215,9 @@ before_install:
|
||||
brew --config
|
||||
brew update
|
||||
brew upgrade
|
||||
brew install python@3.8
|
||||
brew install python@3.9
|
||||
brew unlink [email protected]
|
||||
brew link --overwrite --force [email protected]
|
||||
rm /usr/local/bin/python
|
||||
ln -s /usr/local/bin/python3 /usr/local/bin/python
|
||||
pip3 install six
|
||||
@@ -242,8 +231,15 @@ before_install:
|
||||
brew install boost
|
||||
brew install boost-python3
|
||||
brew tap FreeCAD/freecad
|
||||
|
||||
brew install --verbose --only-dependencies freecad --with-packaging-utils
|
||||
brew install freecad/freecad/coin
|
||||
brew install freecad/freecad/nglib
|
||||
brew install freecad/freecad/med-file
|
||||
brew install freecad/freecad/opencamlib
|
||||
brew install freecad/freecad/shiboken2
|
||||
brew install freecad/freecad/pyside2
|
||||
brew install freecad/freecad/pyside2-tools
|
||||
brew install freecad/freecad/pivy
|
||||
brew install freecad/freecad/matplotlib
|
||||
|
||||
##Install the 3DConnexion frameworks
|
||||
if [ ! -d /Library/Frameworks/3DconnexionClient.framework ]; then
|
||||
@@ -329,9 +325,10 @@ script:
|
||||
# if [ "${TRAVIS_OS_NAME}" == "osx" ]; then sudo gtimeout -s KILL make -j2 install; fi
|
||||
cat $HOME/.ccache/ccache.conf
|
||||
ccache -z -s
|
||||
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then export PATH="/usr/local/opt/ccacche/libexec:$PATH"; sudo gtimeout -s KILL 7200 make -j2 install; fi
|
||||
df -h
|
||||
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then export PATH="/usr/local/opt/ccacche/libexec:$PATH"; sudo gtimeout -s KILL 7200 make -j2; [ $? == 124 ] && { ccache -s; return 0; } fi
|
||||
if [ "${TRAVIS_OS_NAME}" == "linux" ]; then sudo timeout -k 175m 170m make -j2 install || true; fi
|
||||
# sudo make -j2 install
|
||||
sudo make -j2 install
|
||||
ccache -s
|
||||
${INSTALLED_APP_PATH} --console --run-test 0 || travis_terminate 1
|
||||
${INSTALLED_APP_PATH} --log-file /tmp/FreeCAD_installed.log &
|
||||
|
||||
+10
-5
@@ -1,5 +1,5 @@
|
||||
# april 2020, the oldest we have to support : Ununtu 16.04 LTS (Xenial)
|
||||
cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
|
||||
# March 2021, the oldest we have to support : Ununtu 18.04 LTS
|
||||
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
|
||||
|
||||
# policy CMP0072 was introduced with CMake 3.11
|
||||
# relates to FindOpenGL module
|
||||
@@ -17,8 +17,8 @@ project(FreeCAD)
|
||||
|
||||
set(PACKAGE_VERSION_NAME "Vulcan")
|
||||
set(PACKAGE_VERSION_MAJOR "0")
|
||||
set(PACKAGE_VERSION_MINOR "19")
|
||||
set(PACKAGE_VERSION_PATCH "16100")
|
||||
set(PACKAGE_VERSION_MINOR "20")
|
||||
set(PACKAGE_VERSION_PATCH "0")
|
||||
set(PACKAGE_VERSION_SUFFIX "dev") # either "dev" for development snapshot or "" (empty string)
|
||||
set(FREECAD_VERSION_PATCH "0") # number of patch release (e.g. "4" for the 0.18.4 release)
|
||||
|
||||
@@ -50,6 +50,12 @@ if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(PyCXX REQUIRED)
|
||||
SetupOpenCasCade()
|
||||
if(BUILD_GUI)
|
||||
# Do this before the check for SMESH because it depends on vtk
|
||||
# that may have its own OpenGL check but possibly fails and leaves
|
||||
# OPENGL_gl_LIBRARY empty that results into linker errors
|
||||
SetupOpenGL()
|
||||
endif(BUILD_GUI)
|
||||
SetupSalomeSMESH()
|
||||
if (BUILD_FEM_NETGEN)
|
||||
find_package(NETGEN)
|
||||
@@ -64,7 +70,6 @@ if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER)
|
||||
SetupFreetype()
|
||||
|
||||
if(BUILD_GUI)
|
||||
SetupOpenGL()
|
||||
SetupCoin3D()
|
||||
SetupSpaceball()
|
||||
SetupShibokenAndPyside()
|
||||
|
||||
@@ -9,5 +9,45 @@
|
||||
# include <${OCC_INCLUDE_DIR}/Standard_Version.hxx>
|
||||
#endif
|
||||
|
||||
|
||||
/* No need for Boost (version info is always included in the source) */
|
||||
/* No need for Coin (version info is always included in the source) */
|
||||
/* No need for Python (version info is always included in the source) */
|
||||
/* No need for Qt (version info is always included in the source) */
|
||||
/* No need for zlib (version info is always included in the source) */
|
||||
|
||||
// No CMake version info for SMESH, libarea, Zipios, or KDL
|
||||
|
||||
// Eigen3
|
||||
constexpr char * FC_EIGEN3_VERSION = "${EIGEN3_VERSION}";
|
||||
|
||||
// FreeType
|
||||
constexpr char * FC_FREETYPE_VERSION = "${FREETYPE_VERSION_STRING}";
|
||||
|
||||
// pcl
|
||||
constexpr char * FC_PCL_VERSION = "${PCL_VERSION}";
|
||||
|
||||
// PyCXX
|
||||
constexpr char * FC_PYCXX_VERSION = "${PYCXX_VERSION}";
|
||||
|
||||
// PySide
|
||||
constexpr char * FC_PYSIDE_VERSION = "${PySide2_VERSION}";
|
||||
|
||||
// PyBind
|
||||
constexpr char * FC_PYBIND11_VERSION = "${pybind11_VERSION}";
|
||||
|
||||
// Shiboken
|
||||
constexpr char * FC_SHIBOKEN_VERSION = "${Shiboken2_VERSION}";
|
||||
|
||||
// vtk
|
||||
constexpr char * FC_VTK_VERSION = "${VTK_VERSION}";
|
||||
|
||||
// Xerces-C
|
||||
constexpr char * FC_XERCESC_VERSION = "${XercesC_VERSION}";
|
||||
|
||||
// Pivy
|
||||
constexpr char * FC_PIVY_VERSION = "${PIVY_VERSION}";
|
||||
|
||||
|
||||
#endif // LIBRARY_VERSIONS_H
|
||||
|
||||
|
||||
@@ -25,31 +25,30 @@ Overview
|
||||
* **Freedom to build what you want** FreeCAD is an open-source parametric 3D
|
||||
modeler made primarily to design real-life objects of any size.
|
||||
Parametric modeling allows you to easily modify your design by going back into
|
||||
your model history and changing its parameters.
|
||||
your model history to change its parameters.
|
||||
|
||||
* **Create 3D from 2D & back** FreeCAD allows you to sketch geometry constrained
|
||||
* **Create 3D from 2D and back** FreeCAD lets you to sketch geometry constrained
|
||||
2D shapes and use them as a base to build other objects.
|
||||
It contains many components to adjust dimensions or extract design details from
|
||||
3D models to create high quality production ready drawings.
|
||||
3D models to create high quality production-ready drawings.
|
||||
|
||||
* **Designed for your needs** FreeCAD is designed to fit a wide range of uses
|
||||
including product design, mechanical engineering and architecture.
|
||||
Whether you are a hobbyist, a programmer, an experienced CAD user,
|
||||
a student or a teacher, you will feel right at home with FreeCAD.
|
||||
including product design, mechanical engineering and architecture,
|
||||
whether you are a hobbyist, programmer, experienced CAD user, student or teacher.
|
||||
|
||||
* **Cross platform** FreeCAD runs on Windows, Mac and Linux
|
||||
* **Cross platform** FreeCAD runs on Windows, macOS and Linux operating systems.
|
||||
|
||||
* **Underlying technology**
|
||||
* **OpenCASCADE** A powerful geometry kernel, the most important component of FreeCAD
|
||||
* **Coin3D library** Open Inventor-compliant 3D scene representation model
|
||||
* **Python** FreeCAD offers a broad Python API
|
||||
* **Qt** Graphical User Interface built with Qt
|
||||
* **Qt** Graphical user interface built with Qt
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Precompiled (installable) packages are available for Windows and Mac on the
|
||||
Precompiled (installable) packages are available for Windows and macOS on the
|
||||
[Releases page](https://github.com/FreeCAD/FreeCAD/releases).
|
||||
|
||||
On most Linux distributions, FreeCAD is directly installable from the
|
||||
@@ -73,21 +72,39 @@ Compiling
|
||||
---------
|
||||
|
||||
Compiling FreeCAD requires installation of several libraries and their
|
||||
development files such as OpenCASCADe, Coin and Qt, listed in the
|
||||
pages below. Once this is done, FreeCAD can be simply compiled with
|
||||
cMake. On Windows, these libraries are bundled and offered by the
|
||||
development files such as OCCT (Open Cascade), Coin and Qt, listed in the
|
||||
pages below. Once this is done, FreeCAD can be compiled with
|
||||
CMake. On Windows, these libraries are bundled and offered by the
|
||||
FreeCAD team in a convenient package. On Linux, they are usually found
|
||||
in your distribution's repositories, and on Mac OSX and other platforms
|
||||
you will usually need to compile them yourself.
|
||||
in your distribution's repositories, and on macOS and other platforms,
|
||||
you will usually have to compile them yourself.
|
||||
|
||||
The pages below contain up-to-date build instructions:
|
||||
|
||||
- [Linux](https://wiki.freecadweb.org/Compile_on_Linux)
|
||||
- [Windows](https://wiki.freecadweb.org/Compile_on_Windows)
|
||||
- [Mac OSX](https://wiki.freecadweb.org/Compile_on_MacOS)
|
||||
- [macOS](https://wiki.freecadweb.org/Compile_on_MacOS)
|
||||
- [Cygwin](https://wiki.freecadweb.org/Compile_on_Cygwin)
|
||||
- [MinGW](https://wiki.freecadweb.org/Compile_on_MinGW)
|
||||
|
||||
|
||||
Reporting Issues
|
||||
---------
|
||||
|
||||
To report an issue please:
|
||||
- First post to forum to verify the issue;
|
||||
- Link forum thread to bug tracker ticket and vice-a-versa;
|
||||
- Use the most updated stable or development versions of FreeCAD;
|
||||
- Post version info from eg. `Help > About FreeCAD > Copy to clipboard`;
|
||||
- Post a Step-By-Step explanation on how to recreate the issue;
|
||||
- Upload an example file to demonstrate problem.
|
||||
|
||||
For more detail see:
|
||||
- [Wiki Page about the Bug Tracker](https://wiki.freecadweb.org/Tracker)
|
||||
- [Bug Tracker](https://tracker.freecadweb.org)
|
||||
- [Help Forum](http://forum.freecadweb.org/viewforum.php?f=3)
|
||||
|
||||
|
||||
Usage & Getting help
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -105,5 +105,21 @@ ENDIF (WIN32)
|
||||
IF(COIN3D_LIBRARIES)
|
||||
SET( COIN3D_FOUND "YES" )
|
||||
message(STATUS "Coin3D libraries found")
|
||||
|
||||
IF(NOT COIN3D_VERSION)
|
||||
file(READ "${COIN3D_INCLUDE_DIRS}/Inventor/C/basic.h" _coin3d_basic_h)
|
||||
string(REGEX MATCH "define[ \t]+COIN_MAJOR_VERSION[ \t]+([0-9?])" _coin3d_major_version_match "${_coin3d_basic_h}")
|
||||
set(COIN3D_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+COIN_MINOR_VERSION[ \t]+([0-9?])" _coin3d_minor_version_match "${_coin3d_basic_h}")
|
||||
set(COIN3D_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+COIN_MICRO_VERSION[ \t]+([0-9?])" _coin3d_micro_version_match "${_coin3d_basic_h}")
|
||||
set(COIN3D_MICRO_VERSION "${CMAKE_MATCH_1}")
|
||||
set(COIN3D_VERSION "${COIN3D_MAJOR_VERSION}.${COIN3D_MINOR_VERSION}.${COIN3D_MICRO_VERSION}")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT PIVY_VERSION)
|
||||
execute_process (COMMAND ${Python3_EXECUTABLE} -c "import pivy as p; print(p.__version__,end='')" OUTPUT_VARIABLE PIVY_VERSION)
|
||||
ENDIF()
|
||||
|
||||
ENDIF(COIN3D_LIBRARIES)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# MEDFILE_LIBRARIES
|
||||
# MEDFILE_C_LIBRARIES
|
||||
# MEDFILE_F_LIBRARIES
|
||||
# MEDFILE_VERSION
|
||||
#
|
||||
# The CMake (or environment) variable MEDFILE_ROOT_DIR can be set to
|
||||
# guide the detection and indicate a root directory to look into.
|
||||
@@ -56,3 +57,14 @@ ENDIF(MEDFILE_F_LIBRARIES)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MEDFile REQUIRED_VARS MEDFILE_INCLUDE_DIRS MEDFILE_LIBRARIES)
|
||||
|
||||
IF(meddotH)
|
||||
FILE(READ "${meddotH}" _med_h)
|
||||
STRING(REGEX MATCH "define[ \t]+MED_MAJOR_NUM[ \t]+([0-9?])" _med_major_version_match "${_med_h}")
|
||||
SET(MED_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||
STRING(REGEX MATCH "define[ \t]+MED_MINOR_NUM[ \t]+([0-9?])" _med_minor_version_match "${_med_h}")
|
||||
SET(MED_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||
STRING(REGEX MATCH "define[ \t]+MED_RELEASE_NUM[ \t]+([0-9?])" _med_release_version_match "${_med_h}")
|
||||
SET(MED_RELEASE_VERSION "${CMAKE_MATCH_1}")
|
||||
SET(MEDFILE_VERSION "${MED_MAJOR_VERSION}.${MED_MINOR_VERSION}.${MED_RELEASE_VERSION}")
|
||||
ENDIF()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# MATPLOTLIB_VERSION_PATCH - the patch version number of matplotlib
|
||||
# MATPLOTLIB_PATH_DIRS - path to the matplotlib include files
|
||||
|
||||
IF(PYTHONINTERP_FOUND)
|
||||
IF(Python3_Interpreter_FOUND)
|
||||
# Try to import matplotlib into Python interpreter. Python
|
||||
# interpreter was found previously as required package, so
|
||||
# don't take care about this.
|
||||
|
||||
@@ -37,6 +37,12 @@ else(OCE_FOUND) #look for OpenCASCADE
|
||||
# we first try to find opencascade directly:
|
||||
if(NOT OCCT_CMAKE_FALLBACK)
|
||||
find_package(OpenCASCADE CONFIG QUIET)
|
||||
if(NOT (CMAKE_VERSION VERSION_LESS 3.6.0))
|
||||
get_property(flags DIRECTORY PROPERTY COMPILE_DEFINITIONS)
|
||||
# OCCT 7.5 adds this define that causes hundreds of compiler warnings with Qt5.x, so remove it again
|
||||
list(FILTER flags EXCLUDE REGEX [[GL_GLEXT_LEGACY]])
|
||||
set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS ${flags})
|
||||
endif()
|
||||
endif(NOT OCCT_CMAKE_FALLBACK)
|
||||
if(OpenCASCADE_FOUND)
|
||||
set(OCC_FOUND ${OpenCASCADE_FOUND})
|
||||
@@ -156,6 +162,8 @@ if(OCC_FOUND)
|
||||
)
|
||||
if(OCC_VERSION_STRING VERSION_LESS 6.7.3)
|
||||
list(APPEND OCC_OCAF_LIBRARIES TKAdvTools)
|
||||
elseif(NOT OCC_VERSION_STRING VERSION_LESS 7.5.0)
|
||||
list(APPEND OCC_OCAF_LIBRARIES TKRWMesh)
|
||||
endif(OCC_VERSION_STRING VERSION_LESS 6.7.3)
|
||||
message(STATUS "-- Found OCE/OpenCASCADE version: ${OCC_VERSION_STRING}")
|
||||
message(STATUS "-- OCE/OpenCASCADE include directory: ${OCC_INCLUDE_DIR}")
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# PYCXX_SOURCE_DIR
|
||||
# PYCXX_FOUND
|
||||
# PYCXX_SOURCES
|
||||
# PYCXX_VERSION
|
||||
#
|
||||
# The PYCXX_*_DIR variables can be set to tell this module where
|
||||
# the files are.
|
||||
|
||||
@@ -55,10 +55,10 @@ MACRO(PYSIDE_WRAP_UI outfiles)
|
||||
else()
|
||||
# Especially on Open Build Service we don't want changing date like
|
||||
# pyside2-uic generates in comments at beginning., which is why
|
||||
# we follow the tool command with in-place sed.
|
||||
# we follow the tool command with a POSIX-friendly sed.
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
|
||||
COMMAND "${PYSIDE2UICBINARY}" ${UICOPTIONS} "${infile}" -o "${outfile}"
|
||||
COMMAND sed -i "/^# /d" "${outfile}"
|
||||
COMMAND sed "/^# /d" "${outfile}" >"${outfile}.tmp" && mv "${outfile}.tmp" "${outfile}"
|
||||
MAIN_DEPENDENCY "${infile}"
|
||||
)
|
||||
endif()
|
||||
@@ -85,7 +85,7 @@ MACRO(PYSIDE_WRAP_RC outfiles)
|
||||
# we follow the tool command with in-place sed.
|
||||
ADD_CUSTOM_COMMAND(OUTPUT "${outfile}"
|
||||
COMMAND "${PYSIDE2RCCBINARY}" ${RCCOPTIONS} "${infile}" ${PY_ATTRIBUTE} -o "${outfile}"
|
||||
COMMAND sed -i "/^# /d" "${outfile}"
|
||||
COMMAND sed "/^# /d" "${outfile}" >"${outfile}.tmp" && mv "${outfile}.tmp" "${outfile}"
|
||||
MAIN_DEPENDENCY "${infile}"
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
# Try to find PySide utilities, PYSIDEUIC4 and PYSIDERCC4:
|
||||
# PYSIDEUIC4BINARY - Location of PYSIDEUIC4 executable
|
||||
# PYSIDERCC4BINARY - Location of PYSIDERCC4 executable
|
||||
# PYSIDE_TOOLS_FOUND - PySide utilities found.
|
||||
|
||||
# Also provides macro similar to FindQt4.cmake's WRAP_UI and WRAP_RC,
|
||||
# for the automatic generation of Python code from Qt4's user interface
|
||||
# ('.ui') and resource ('.qrc') files. These macros are called:
|
||||
# - PYSIDE_WRAP_UI
|
||||
# - PYSIDE_WRAP_RC
|
||||
|
||||
IF(PYSIDEUIC4BINARY AND PYSIDERCC4BINARY)
|
||||
# Already in cache, be silent
|
||||
set(PYSIDE_TOOLS_FOUND_QUIETLY TRUE)
|
||||
ENDIF(PYSIDEUIC4BINARY AND PYSIDERCC4BINARY)
|
||||
|
||||
if(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
#pyside tools are often in same location as python interpreter
|
||||
get_filename_component(PYTHON_BIN_DIR ${PYTHON_EXECUTABLE} PATH)
|
||||
set(PYSIDE_BIN_DIR ${PYTHON_BIN_DIR})
|
||||
endif(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
FIND_PROGRAM(PYSIDEUIC4BINARY NAMES python2-pyside-uic pyside-uic pyside-uic-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} HINTS ${PYSIDE_BIN_DIR})
|
||||
FIND_PROGRAM(PYSIDERCC4BINARY NAMES pyside-rcc pyside-rcc-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} HINTS ${PYSIDE_BIN_DIR})
|
||||
|
||||
MACRO(PYSIDE_WRAP_UI outfiles)
|
||||
FOREACH(it ${ARGN})
|
||||
GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
|
||||
GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
|
||||
SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/ui_${outfile}.py)
|
||||
#ADD_CUSTOM_TARGET(${it} ALL
|
||||
# DEPENDS ${outfile}
|
||||
#)
|
||||
if(WIN32)
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
|
||||
COMMAND ${PYSIDEUIC4BINARY} ${infile} -o ${outfile}
|
||||
MAIN_DEPENDENCY ${infile}
|
||||
)
|
||||
else(WIN32)
|
||||
# Especially on Open Build Service we don't want changing date like
|
||||
# pyside-uic generates in comments at beginning, which is why
|
||||
# we follow the tool command with in-place sed.
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
|
||||
COMMAND "${PYSIDEUIC4BINARY}" "${infile}" -o "${outfile}"
|
||||
COMMAND sed -i "/^# /d" "${outfile}"
|
||||
MAIN_DEPENDENCY "${infile}"
|
||||
)
|
||||
endif(WIN32)
|
||||
list(APPEND ${outfiles} ${outfile})
|
||||
ENDFOREACH(it)
|
||||
ENDMACRO (PYSIDE_WRAP_UI)
|
||||
|
||||
MACRO(PYSIDE_WRAP_RC outfiles)
|
||||
FOREACH(it ${ARGN})
|
||||
GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
|
||||
GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
|
||||
SET(outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}_rc.py")
|
||||
#ADD_CUSTOM_TARGET(${it} ALL
|
||||
# DEPENDS ${outfile}
|
||||
#)
|
||||
if (${PYTHON_VERSION_MAJOR} LESS 3)
|
||||
SET(PY_ATTRIBUTE "")
|
||||
else (${PYTHON_VERSION_MAJOR} LESS 3)
|
||||
SET(PY_ATTRIBUTE "-py3")
|
||||
endif (${PYTHON_VERSION_MAJOR} LESS 3)
|
||||
if(WIN32)
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
|
||||
COMMAND ${PYSIDERCC4BINARY} ${infile} ${PY_ATTRIBUTE} -o ${outfile}
|
||||
MAIN_DEPENDENCY ${infile}
|
||||
)
|
||||
else(WIN32)
|
||||
# Especially on Open Build Service we don't want changing date like
|
||||
# pyside-rcc generates in comments at beginning, which is why
|
||||
# we follow the tool command with in-place sed.
|
||||
ADD_CUSTOM_COMMAND(OUTPUT "${outfile}"
|
||||
COMMAND "${PYSIDERCC4BINARY}" "${infile}" ${PY_ATTRIBUTE} -o "${outfile}"
|
||||
COMMAND sed -i "/^# /d" "${outfile}"
|
||||
MAIN_DEPENDENCY "${infile}"
|
||||
)
|
||||
endif(WIN32)
|
||||
list(APPEND ${outfiles} ${outfile})
|
||||
ENDFOREACH(it)
|
||||
ENDMACRO (PYSIDE_WRAP_RC)
|
||||
|
||||
IF(EXISTS ${PYSIDEUIC4BINARY} AND EXISTS ${PYSIDERCC4BINARY})
|
||||
set(PYSIDE_TOOLS_FOUND TRUE)
|
||||
ENDIF(EXISTS ${PYSIDEUIC4BINARY} AND EXISTS ${PYSIDERCC4BINARY})
|
||||
|
||||
if(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY)
|
||||
if (NOT PySideTools_FIND_QUIETLY)
|
||||
message(STATUS "Found PySide Tools: ${PYSIDEUIC4BINARY}, ${PYSIDERCC4BINARY}")
|
||||
endif (NOT PySideTools_FIND_QUIETLY)
|
||||
else(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY)
|
||||
if(PySideTools_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "PySideTools could not be found, but are required.")
|
||||
else(PySideTools_FIND_REQUIRED)
|
||||
if (NOT PySideTools_FIND_QUIETLY)
|
||||
message(STATUS "PySideTools: not found.")
|
||||
endif (NOT PySideTools_FIND_QUIETLY)
|
||||
endif(PySideTools_FIND_REQUIRED)
|
||||
endif(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY)
|
||||
@@ -1,164 +0,0 @@
|
||||
# - Try to find Windows Installer XML
|
||||
# See http://wix.sourceforge.net
|
||||
#
|
||||
# The following variables are optionally searched for defaults
|
||||
# WIX_ROOT_DIR: Base directory of WIX2 tree to use.
|
||||
#
|
||||
# The following are set after configuration is done:
|
||||
# WIX_FOUND
|
||||
# WIX_ROOT_DIR
|
||||
# WIX_CANDLE
|
||||
# WIX_LIGHT
|
||||
#
|
||||
# 2009/02 Petr Pytelka (pyta at lightcomp.cz)
|
||||
#
|
||||
|
||||
MACRO(DBG_MSG _MSG)
|
||||
# MESSAGE(STATUS "${CMAKE_CURRENT_LIST_FILE}(${CMAKE_CURRENT_LIST_LINE}):\n ${_MSG}")
|
||||
ENDMACRO(DBG_MSG)
|
||||
|
||||
|
||||
# typical root dirs of installations, exactly one of them is used
|
||||
SET (WIX_POSSIBLE_ROOT_DIRS
|
||||
"${WIX_ROOT_DIR}"
|
||||
"$ENV{WIX_ROOT_DIR}"
|
||||
"$ENV{ProgramFiles}/Windows Installer XML"
|
||||
)
|
||||
|
||||
|
||||
#DBG_MSG("DBG (WIX_POSSIBLE_ROOT_DIRS=${WIX_POSSIBLE_ROOT_DIRS}")
|
||||
|
||||
#
|
||||
# select exactly ONE WIX base directory/tree
|
||||
# to avoid mixing different version headers and libs
|
||||
#
|
||||
FIND_PATH(WIX_ROOT_DIR
|
||||
NAMES
|
||||
bin/candle.exe
|
||||
bin/light.exe
|
||||
PATHS ${WIX_POSSIBLE_ROOT_DIRS})
|
||||
DBG_MSG("WIX_ROOT_DIR=${WIX_ROOT_DIR}")
|
||||
|
||||
|
||||
#
|
||||
# Logic selecting required libs and headers
|
||||
#
|
||||
SET(WIX_FOUND OFF)
|
||||
IF(WIX_ROOT_DIR)
|
||||
SET(WIX_FOUND ON)
|
||||
ENDIF(WIX_ROOT_DIR)
|
||||
|
||||
|
||||
# display help message
|
||||
IF(NOT WIX_FOUND)
|
||||
# make FIND_PACKAGE friendly
|
||||
IF(NOT WIX_FIND_QUIETLY)
|
||||
IF(WIX_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR
|
||||
"Windows Installer XML required but some files not found. Please specify it's location with WIX_ROOT_DIR env. variable.")
|
||||
ELSE(WIX_FIND_REQUIRED)
|
||||
MESSAGE(STATUS
|
||||
"ERROR: Windows Installer XML was not found.")
|
||||
ENDIF(WIX_FIND_REQUIRED)
|
||||
ENDIF(NOT WIX_FIND_QUIETLY)
|
||||
ELSE(NOT WIX_FOUND)
|
||||
SET(WIX_CANDLE ${WIX_ROOT_DIR}/bin/candle.exe)
|
||||
SET(WIX_LIGHT ${WIX_ROOT_DIR}/bin/light.exe)
|
||||
# MESSAGE(STATUS "Windows Installer XML found.")
|
||||
ENDIF(NOT WIX_FOUND)
|
||||
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
WIX_ROOT_DIR
|
||||
WIX_CANDLE
|
||||
WIX_LIGHT
|
||||
)
|
||||
|
||||
#
|
||||
# Call wix compiler
|
||||
#
|
||||
# Parameters:
|
||||
# _sources - name of list with sources
|
||||
# _obj - name of list for target objects
|
||||
#
|
||||
MACRO(WIX_COMPILE _sources _objs _extra_dep)
|
||||
DBG_MSG("WIX compile: ${${_sources}}")
|
||||
FOREACH (_current_FILE ${${_sources}})
|
||||
GET_FILENAME_COMPONENT(_tmp_FILE ${_current_FILE} ABSOLUTE)
|
||||
GET_FILENAME_COMPONENT(_basename ${_tmp_FILE} NAME_WE)
|
||||
|
||||
SET (SOURCE_WIX_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${_current_FILE} )
|
||||
DBG_MSG("WIX source file: ${SOURCE_WIX_FILE}")
|
||||
|
||||
# Check whether source exists
|
||||
IF(EXISTS ${SOURCE_WIX_FILE})
|
||||
ELSE(EXISTS ${SOURCE_WIX_FILE})
|
||||
MESSAGE(FATAL_ERROR "Path not exists: ${SOURCE_WIX_FILE}")
|
||||
ENDIF(EXISTS ${SOURCE_WIX_FILE})
|
||||
|
||||
SET (OUTPUT_WIXOBJ ${_basename}.wixobj )
|
||||
|
||||
DBG_MSG("WIX output: ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_WIXOBJ}")
|
||||
DBG_MSG("WIX command: ${WIX_CANDLE}")
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_WIXOBJ}
|
||||
COMMAND ${WIX_CANDLE}
|
||||
ARGS ${WIX_CANDLE_FLAGS} ${SOURCE_WIX_FILE}
|
||||
DEPENDS ${SOURCE_WIX_FILE} ${${_extra_dep}}
|
||||
COMMENT "Compiling ${SOURCE_WIX_FILE} -> ${OUTPUT_WIXOBJ}"
|
||||
)
|
||||
SET(${_objs} ${${_objs}} ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_WIXOBJ} )
|
||||
DBG_MSG("WIX compile output: ${${_objs}}")
|
||||
|
||||
ENDFOREACH (_current_FILE)
|
||||
ENDMACRO(WIX_COMPILE)
|
||||
|
||||
#
|
||||
# Call wix compiler
|
||||
#
|
||||
# Parameters:
|
||||
# _sources - name of list with sources
|
||||
# _obj - name of list for target objects
|
||||
#
|
||||
MACRO(WIX_COMPILE_ALL _target _sources _extra_dep)
|
||||
DBG_MSG("WIX compile all: ${${_sources}}, dependencies: ${${_extra_dep}}")
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${_target}
|
||||
COMMAND ${WIX_CANDLE}
|
||||
ARGS ${WIX_CANDLE_FLAGS} -out "${_target}" ${${_sources}}
|
||||
DEPENDS ${${_sources}} ${${_extra_dep}}
|
||||
COMMENT "Compiling ${${_sources}} -> ${_target}"
|
||||
)
|
||||
|
||||
ENDMACRO(WIX_COMPILE_ALL)
|
||||
|
||||
|
||||
#
|
||||
# Link MSI file
|
||||
#
|
||||
# Parameters
|
||||
# _target - Name of target file
|
||||
# _sources - Name of list with sources
|
||||
#
|
||||
MACRO(WIX_LINK _target _sources _loc_files)
|
||||
DBG_MSG("WIX command: ${WIX_LIGHT}\n WIX target: ${_target} objs: ${${_sources}}")
|
||||
|
||||
SET( WIX_LINK_FLAGS_A "" )
|
||||
# Add localization
|
||||
FOREACH (_current_FILE ${${_loc_files}})
|
||||
SET( WIX_LINK_FLAGS_A ${WIX_LINK_FLAGS_A} -loc "${_current_FILE}" )
|
||||
DBG_MSG("WIX link localization: ${_current_FILE}")
|
||||
ENDFOREACH (_current_FILE)
|
||||
DBG_MSG("WIX link flags: ${WIX_LINK_FLAGS_A}")
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${_target}
|
||||
COMMAND ${WIX_LIGHT}
|
||||
ARGS ${WIX_LINK_FLAGS_A} -out "${_target}" ${${_sources}}
|
||||
DEPENDS ${${_sources}}
|
||||
COMMENT "Linking ${${_sources}} -> ${_target}"
|
||||
)
|
||||
|
||||
ENDMACRO(WIX_LINK)
|
||||
@@ -1,51 +0,0 @@
|
||||
# Locate Xerces-C include paths and libraries
|
||||
# Xerces-C can be found at http://xml.apache.org/xerces-c/
|
||||
# Written by Frederic Heem, frederic.heem _at_ telsey.it
|
||||
# Modified by Jos van den Oever
|
||||
|
||||
# This module defines
|
||||
# XercesC_INCLUDE_DIRS, where to find ptlib.h, etc.
|
||||
# XercesC_LIBRARIES, the libraries to link against to use pwlib.
|
||||
# XercesC_FOUND, If false, don't try to use pwlib.
|
||||
|
||||
FIND_PATH(XercesC_INCLUDE_DIRS xercesc/dom/DOM.hpp
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
"[HKEY_CURRENT_USER\\software\\xerces-c\\src]"
|
||||
"[HKEY_CURRENT_USER\\xerces-c\\src]"
|
||||
$ENV{XERCESCROOT}/src/
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(XercesC_LIBRARIES
|
||||
NAMES
|
||||
xerces-c
|
||||
xerces-c_3
|
||||
PATHS
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
"[HKEY_CURRENT_USER\\software\\xerces-c\\lib]"
|
||||
"[HKEY_CURRENT_USER\\xerces-c\\lib]"
|
||||
$ENV{XERCESCROOT}/${LIB_DESTINATION}
|
||||
/usr/local/${LIB_DESTINATION}
|
||||
/usr/${LIB_DESTINATION}
|
||||
)
|
||||
|
||||
# if the include a the library are found then we have it
|
||||
IF(XercesC_INCLUDE_DIRS AND XercesC_LIBRARIES)
|
||||
SET(XercesC_FOUND "YES" )
|
||||
IF(NOT XERCESC__FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Xerces-C: ${XercesC_LIBRARIES}")
|
||||
ENDIF(NOT XERCESC__FIND_QUIETLY)
|
||||
ELSE(XercesC_INCLUDE_DIRS AND XercesC_LIBRARIES)
|
||||
IF(XERCESC_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Xerces-C was not found.")
|
||||
ENDIF(XERCESC_FIND_REQUIRED)
|
||||
IF(NOT XERCESC__FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Xerces-C was not found.")
|
||||
ENDIF(NOT XERCESC__FIND_QUIETLY)
|
||||
ENDIF(XercesC_INCLUDE_DIRS AND XercesC_LIBRARIES)
|
||||
|
||||
#MARK_AS_ADVANCED(
|
||||
# XercesC_INCLUDE_DIRS
|
||||
# XercesC_LIBRARIES
|
||||
#)
|
||||
@@ -28,22 +28,18 @@ macro(CompilerChecksAndSetups)
|
||||
OUTPUT_VARIABLE CMAKE_CXX_COMPILER_VERSION)
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX AND NOT CMAKE_CXX_COMPILER_VERSION)
|
||||
|
||||
# Enabled C++11 for Freecad 0.17 and later
|
||||
if (FREECAD_VERSION VERSION_GREATER 0.16)
|
||||
set(BUILD_ENABLE_CXX_STD "C++11" CACHE STRING "Enable C++ standard")
|
||||
# Enabled C++17 for Freecad 0.20 and later
|
||||
set(BUILD_ENABLE_CXX_STD "C++17" CACHE STRING "Enable C++ standard")
|
||||
set_property(CACHE BUILD_ENABLE_CXX_STD PROPERTY STRINGS
|
||||
"C++11"
|
||||
"C++14"
|
||||
"C++17"
|
||||
"C++20"
|
||||
)
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
|
||||
message(FATAL_ERROR "FreeCAD 0.17 and later requires C++11. G++ must be 4.7 or later, the used version is ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
elseif(CMAKE_COMPILER_IS_CLANGXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3)
|
||||
message(FATAL_ERROR "FreeCAD 0.17 and later requires C++11. Clang must be 3.3 or later, the used version is ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3)
|
||||
message(FATAL_ERROR "FreeCAD 0.20 and later requires C++17. G++ must be 7.3 or later, the used version is ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
elseif(CMAKE_COMPILER_IS_CLANGXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
message(FATAL_ERROR "FreeCAD 0.20 and later requires C++17. Clang must be 6.0 or later, the used version is ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
endif()
|
||||
endif(FREECAD_VERSION VERSION_GREATER 0.16)
|
||||
|
||||
# Escape the two plus chars as otherwise cmake complains about invalid regex
|
||||
if(${BUILD_ENABLE_CXX_STD} MATCHES "C\\+\\+20")
|
||||
|
||||
@@ -31,18 +31,8 @@ macro(InitializeFreeCADBuildOptions)
|
||||
if (DEFINED ENV{FREECAD_LIBPACK_DIR})
|
||||
set(FREECAD_LIBPACK_DIR $ENV{FREECAD_LIBPACK_DIR} CACHE PATH "Directory of the FreeCAD LibPack")
|
||||
message(STATUS "Found libpack env variable: ${FREECAD_LIBPACK_DIR}")
|
||||
if (EXISTS ${FREECAD_LIBPACK_DIR}/lib/Qt5Core.lib)
|
||||
option(BUILD_QT5 "Build with Qt5." ON)
|
||||
else()
|
||||
option(BUILD_QT5 "Build with Qt5." OFF)
|
||||
endif()
|
||||
else()
|
||||
set(FREECAD_LIBPACK_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Directory of the FreeCAD LibPack")
|
||||
if (EXISTS ${FREECAD_LIBPACK_DIR}/lib/Qt5Core.lib)
|
||||
option(BUILD_QT5 "Build with Qt5." ON)
|
||||
else()
|
||||
option(BUILD_QT5 "Build with Qt5." OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LIBPACK_FOUND OFF )
|
||||
@@ -68,10 +58,10 @@ macro(InitializeFreeCADBuildOptions)
|
||||
message(STATUS "Visit: https://github.com/apeltauer/FreeCAD/releases/ for Windows libpack downloads.")
|
||||
endif()
|
||||
else(MSVC)
|
||||
option(BUILD_QT5 "Build with Qt5." OFF)
|
||||
option(FREECAD_LIBPACK_USE "Use the LibPack to Build FreeCAD (only Win32 so far)." OFF)
|
||||
set(FREECAD_LIBPACK_DIR "" CACHE PATH "Directory of the FreeCAD LibPack")
|
||||
endif(MSVC)
|
||||
option(BUILD_QT5 "Build with Qt5." ON)
|
||||
|
||||
# https://blog.kitware.com/constraining-values-with-comboboxes-in-cmake-cmake-gui/
|
||||
set(FREECAD_USE_OCC_VARIANT "Community Edition" CACHE STRING "Official OpenCASCADE version or community edition")
|
||||
@@ -160,7 +150,7 @@ macro(InitializeFreeCADBuildOptions)
|
||||
|
||||
if(MSVC)
|
||||
option(BUILD_FEM_NETGEN "Build the FreeCAD FEM module with the NETGEN mesher" ON)
|
||||
option(FREECAD_USE_PCL "Build the features that use PCL libs" ON)
|
||||
option(FREECAD_USE_PCL "Build the features that use PCL libs" OFF) # 3/5/2021 current LibPack uses non-C++17 FLANN
|
||||
option(FREECAD_USE_3DCONNEXION "Use the 3D connexion SDK to support 3d mouse." ON)
|
||||
elseif(APPLE)
|
||||
find_library(3DCONNEXIONCLIENT_FRAMEWORK 3DconnexionClient)
|
||||
|
||||
@@ -13,7 +13,7 @@ macro(PrintFinalReport)
|
||||
message(STATUS "Standard: Requires C++${CMAKE_CXX_STANDARD}")
|
||||
|
||||
# Qt5 needs/sets PYTHON_CONFIG_SUFFIX regarding Shiboken
|
||||
message(STATUS "Python: [${PYTHON_EXECUTABLE}] [${PYTHON_CONFIG_SUFFIX}]")
|
||||
message(STATUS "Python: ${PYTHON_VERSION_STRING} [${PYTHON_EXECUTABLE}] [${PYTHON_CONFIG_SUFFIX}]")
|
||||
|
||||
if(DEFINED PCL_FOUND)
|
||||
message(STATUS "PCL: ${PCL_VERSION}")
|
||||
@@ -27,13 +27,13 @@ macro(PrintFinalReport)
|
||||
message(STATUS "pybind11: not enabled")
|
||||
endif(DEFINED pybind11_FOUND)
|
||||
|
||||
message(STATUS "Boost: ${Boost_VERSION}")
|
||||
message(STATUS "Boost: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION} (${Boost_VERSION})")
|
||||
|
||||
message(STATUS "XercesC: [${XercesC_LIBRARIES}] [${XercesC_INCLUDE_DIRS}]")
|
||||
message(STATUS "XercesC: ${XercesC_VERSION} [${XercesC_LIBRARIES}] [${XercesC_INCLUDE_DIRS}]")
|
||||
|
||||
message(STATUS "ZLIB: ${ZLIB_VERSION_STRING}")
|
||||
|
||||
message(STATUS "PyCXX: [${PYCXX_INCLUDE_DIR}]")
|
||||
message(STATUS "PyCXX: ${PYCXX_VERSION} [${PYCXX_INCLUDE_DIR}]")
|
||||
|
||||
message(STATUS "OCC: ${OCC_VERSION_STRING} [${OCC_LIBRARIES}] [${OCC_LIBRARY_DIR}] [${OCC_INCLUDE_DIR}]")
|
||||
|
||||
@@ -42,7 +42,7 @@ macro(PrintFinalReport)
|
||||
message(STATUS "SMESH: ${SMESH_VERSION_MAJOR}.${SMESH_VERSION_MINOR}.${SMESH_VERSION_PATCH}.${SMESH_VERSION_TWEAK}")
|
||||
else(FREECAD_USE_EXTERNAL_SMESH)
|
||||
message(STATUS "SMESH: build internal")
|
||||
message(STATUS " MEDFile: [${MEDFILE_LIBRARIES}] [${MEDFILE_INCLUDE_DIRS}]")
|
||||
message(STATUS " MEDFile: ${MEDFILE_VERSION} [${MEDFILE_LIBRARIES}] [${MEDFILE_INCLUDE_DIRS}]")
|
||||
message(STATUS " HDF5: ${HDF5_VERSION}")
|
||||
message(STATUS " VTK: ${VTK_VERSION}")
|
||||
endif(FREECAD_USE_EXTERNAL_SMESH)
|
||||
@@ -70,88 +70,76 @@ macro(PrintFinalReport)
|
||||
message(STATUS "Eigen3: not found")
|
||||
endif(DEFINED EIGEN3_FOUND)
|
||||
|
||||
if(NOT BUILD_QT5)
|
||||
message(STATUS "Qt4: ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}")
|
||||
if(QT_QTWEBKIT_FOUND)
|
||||
message(STATUS "QtWebKit: found")
|
||||
else(QT_QTWEBKIT_FOUND)
|
||||
message(STATUS "QtWebKit: not found")
|
||||
endif(QT_QTWEBKIT_FOUND)
|
||||
message(STATUS "Shiboken: ${Shiboken_VERSION} [${SHIBOKEN_INCLUDE_DIR}]")
|
||||
message(STATUS "PySide: ${PySide_VERSION} [${PYSIDE_INCLUDE_DIR}]")
|
||||
message(STATUS "PySideTools: [${PYSIDEUIC4BINARY}] [${PYSIDERCC4BINARY}]")
|
||||
else(NOT BUILD_QT5)
|
||||
message(STATUS "Qt5Core: ${Qt5Core_VERSION}")
|
||||
message(STATUS "Qt5Network: ${Qt5Network_VERSION}")
|
||||
message(STATUS "Qt5Xml: ${Qt5Xml_VERSION}")
|
||||
message(STATUS "Qt5XmlPatterns: ${Qt5XmlPatterns_VERSION}")
|
||||
if (BUILD_GUI)
|
||||
message(STATUS "Qt5Widgets: ${Qt5Widgets_VERSION}")
|
||||
message(STATUS "Qt5PrintSupport: ${Qt5PrintSupport_VERSION}")
|
||||
message(STATUS "Qt5OpenGL: ${Qt5OpenGL_VERSION}")
|
||||
message(STATUS "Qt5Svg: ${Qt5Svg_VERSION}")
|
||||
message(STATUS "Qt5UiTools: ${Qt5UiTools_VERSION}")
|
||||
message(STATUS "Qt5Concurrent: ${Qt5Concurrent_VERSION}")
|
||||
if(BUILD_WEB)
|
||||
if (Qt5WebKitWidgets_FOUND)
|
||||
message(STATUS "Qt5WebKitWidgets: ${Qt5WebKitWidgets_VERSION}")
|
||||
endif()
|
||||
if (Qt5WebEngineWidgets_FOUND)
|
||||
message(STATUS "Qt5WebEngineWidgets: ${Qt5WebEngineWidgets_VERSION}")
|
||||
endif()
|
||||
else(BUILD_WEB)
|
||||
message(STATUS "Qt5WebKitWidgets: not needed (BUILD_WEB)")
|
||||
message(STATUS "Qt5WebEngineWidgets: not needed (BUILD_WEB)")
|
||||
endif(BUILD_WEB)
|
||||
if(${Qt5WinExtras_FOUND})
|
||||
message(STATUS "Qt5WinExtras: ${Qt5WinExtras_VERSION}")
|
||||
message(STATUS "Qt5Core: ${Qt5Core_VERSION}")
|
||||
message(STATUS "Qt5Network: ${Qt5Network_VERSION}")
|
||||
message(STATUS "Qt5Xml: ${Qt5Xml_VERSION}")
|
||||
message(STATUS "Qt5XmlPatterns: ${Qt5XmlPatterns_VERSION}")
|
||||
if (BUILD_GUI)
|
||||
message(STATUS "Qt5Widgets: ${Qt5Widgets_VERSION}")
|
||||
message(STATUS "Qt5PrintSupport: ${Qt5PrintSupport_VERSION}")
|
||||
message(STATUS "Qt5OpenGL: ${Qt5OpenGL_VERSION}")
|
||||
message(STATUS "Qt5Svg: ${Qt5Svg_VERSION}")
|
||||
message(STATUS "Qt5UiTools: ${Qt5UiTools_VERSION}")
|
||||
message(STATUS "Qt5Concurrent: ${Qt5Concurrent_VERSION}")
|
||||
if(BUILD_WEB)
|
||||
if (Qt5WebKitWidgets_FOUND)
|
||||
message(STATUS "Qt5WebKitWidgets: ${Qt5WebKitWidgets_VERSION}")
|
||||
endif()
|
||||
if (Qt5WebEngineWidgets_FOUND)
|
||||
message(STATUS "Qt5WebEngineWidgets: ${Qt5WebEngineWidgets_VERSION}")
|
||||
endif()
|
||||
else(BUILD_WEB)
|
||||
message(STATUS "Qt5WebKitWidgets: not needed (BUILD_WEB)")
|
||||
message(STATUS "Qt5WebEngineWidgets: not needed (BUILD_WEB)")
|
||||
endif(BUILD_WEB)
|
||||
if(${Qt5WinExtras_FOUND})
|
||||
message(STATUS "Qt5WinExtras: ${Qt5WinExtras_VERSION}")
|
||||
endif()
|
||||
|
||||
else(BUILD_GUI)
|
||||
message(STATUS "Qt5Widgets: not needed")
|
||||
message(STATUS "Qt5PrintSupport: not needed")
|
||||
message(STATUS "Qt5OpenGL: not needed")
|
||||
message(STATUS "Qt5Svg: not needed")
|
||||
message(STATUS "Qt5UiTools: not needed")
|
||||
message(STATUS "Qt5Concurrent: not needed")
|
||||
message(STATUS "Qt5WebKitWidgets: not needed")
|
||||
endif(BUILD_GUI)
|
||||
else(BUILD_GUI)
|
||||
message(STATUS "Qt5Widgets: not needed")
|
||||
message(STATUS "Qt5PrintSupport: not needed")
|
||||
message(STATUS "Qt5OpenGL: not needed")
|
||||
message(STATUS "Qt5Svg: not needed")
|
||||
message(STATUS "Qt5UiTools: not needed")
|
||||
message(STATUS "Qt5Concurrent: not needed")
|
||||
message(STATUS "Qt5WebKitWidgets: not needed")
|
||||
endif(BUILD_GUI)
|
||||
|
||||
if(DEFINED MACPORTS_PREFIX)
|
||||
if(DEFINED Shiboken_FOUND)
|
||||
message(STATUS "Shiboken: ${Shiboken_VERSION} [${SHIBOKEN_INCLUDE_DIR}]")
|
||||
else(DEFINED Shiboken_FOUND)
|
||||
message(STATUS "Shiboken: not found (only searched if MACPORTS_PREFIX is defined)")
|
||||
endif(DEFINED Shiboken_FOUND)
|
||||
if(DEFINED PySide_FOUND)
|
||||
message(STATUS "PySide: ${PySide_VERSION} [${PYSIDE_INCLUDE_DIR}]")
|
||||
if(NOT PYSIDE_INCLUDE_DIR)
|
||||
message(STATUS " IncludeDir: Unable to find, python version mismatch?")
|
||||
endif(NOT PYSIDE_INCLUDE_DIR)
|
||||
else(DEFINED PySide_FOUND)
|
||||
message(STATUS "PySide: not found (only searched if MACPORTS_PREFIX is defined)")
|
||||
endif(DEFINED PySide_FOUND)
|
||||
endif(DEFINED MACPORTS_PREFIX)
|
||||
|
||||
if(DEFINED Shiboken2_FOUND)
|
||||
message(STATUS "Shiboken2: ${Shiboken2_VERSION} [${Shiboken2_DIR}] [${SHIBOKEN_INCLUDE_DIR}]")
|
||||
else(DEFINED Shiboken2_FOUND)
|
||||
message(STATUS "Shiboken2: not found")
|
||||
endif(DEFINED Shiboken2_FOUND)
|
||||
if(DEFINED PySide2_FOUND)
|
||||
message(STATUS "PySide2: ${PySide2_VERSION} [${PYSIDE_INCLUDE_DIR}]")
|
||||
if(DEFINED MACPORTS_PREFIX)
|
||||
if(DEFINED Shiboken_FOUND)
|
||||
message(STATUS "Shiboken: ${Shiboken_VERSION} [${SHIBOKEN_INCLUDE_DIR}]")
|
||||
else(DEFINED Shiboken_FOUND)
|
||||
message(STATUS "Shiboken: not found (only searched if MACPORTS_PREFIX is defined)")
|
||||
endif(DEFINED Shiboken_FOUND)
|
||||
if(DEFINED PySide_FOUND)
|
||||
message(STATUS "PySide: ${PySide_VERSION} [${PYSIDE_INCLUDE_DIR}]")
|
||||
if(NOT PYSIDE_INCLUDE_DIR)
|
||||
message(STATUS " IncludeDir: Unable to find, python version mismatch?")
|
||||
endif(NOT PYSIDE_INCLUDE_DIR)
|
||||
else(DEFINED PySide2_FOUND)
|
||||
message(STATUS "PySide2: not found")
|
||||
endif(DEFINED PySide2_FOUND)
|
||||
if(DEFINED PYSIDE2_TOOLS_FOUND)
|
||||
message(STATUS "PySide2Tools: [${PYSIDE2UICBINARY}] [${PYSIDE2RCCBINARY}]")
|
||||
else(DEFINED PYSIDE2_TOOLS_FOUND)
|
||||
message(STATUS "PySide2Tools: not found")
|
||||
endif(DEFINED PYSIDE2_TOOLS_FOUND)
|
||||
endif(NOT BUILD_QT5)
|
||||
else(DEFINED PySide_FOUND)
|
||||
message(STATUS "PySide: not found (only searched if MACPORTS_PREFIX is defined)")
|
||||
endif(DEFINED PySide_FOUND)
|
||||
endif(DEFINED MACPORTS_PREFIX)
|
||||
|
||||
if(DEFINED Shiboken2_FOUND)
|
||||
message(STATUS "Shiboken2: ${Shiboken2_VERSION} [${Shiboken2_DIR}] [${SHIBOKEN_INCLUDE_DIR}]")
|
||||
else(DEFINED Shiboken2_FOUND)
|
||||
message(STATUS "Shiboken2: not found")
|
||||
endif(DEFINED Shiboken2_FOUND)
|
||||
if(DEFINED PySide2_FOUND)
|
||||
message(STATUS "PySide2: ${PySide2_VERSION} [${PYSIDE_INCLUDE_DIR}]")
|
||||
if(NOT PYSIDE_INCLUDE_DIR)
|
||||
message(STATUS " IncludeDir: Unable to find, python version mismatch?")
|
||||
endif(NOT PYSIDE_INCLUDE_DIR)
|
||||
else(DEFINED PySide2_FOUND)
|
||||
message(STATUS "PySide2: not found")
|
||||
endif(DEFINED PySide2_FOUND)
|
||||
if(DEFINED PYSIDE2_TOOLS_FOUND)
|
||||
message(STATUS "PySide2Tools: [${PYSIDE2UICBINARY}] [${PYSIDE2RCCBINARY}]")
|
||||
else(DEFINED PYSIDE2_TOOLS_FOUND)
|
||||
message(STATUS "PySide2Tools: not found")
|
||||
endif(DEFINED PYSIDE2_TOOLS_FOUND)
|
||||
|
||||
if(FREECAD_USE_FREETYPE)
|
||||
if(DEFINED FREETYPE_FOUND)
|
||||
@@ -163,9 +151,11 @@ macro(PrintFinalReport)
|
||||
message(STATUS "Freetype: disabled")
|
||||
endif(FREECAD_USE_FREETYPE)
|
||||
|
||||
message(STATUS "OpenGLU: ${OPENGL_glu_LIBRARY} [${OPENGL_glu_LIBRARY}][${OPENGL_INCLUDE_DIR}]")
|
||||
message(STATUS "OpenGL: ${OPENGL_gl_LIBRARY}")
|
||||
message(STATUS "OpenGLU: [${OPENGL_glu_LIBRARY}][${OPENGL_INCLUDE_DIR}]")
|
||||
|
||||
message(STATUS "Coin3D: [${COIN3D_LIBRARIES}] [${COIN3D_INCLUDE_DIRS}]")
|
||||
message(STATUS "Coin3D: ${COIN3D_VERSION} [${COIN3D_LIBRARIES}] [${COIN3D_INCLUDE_DIRS}]")
|
||||
message(STATUS "Pivy: ${PIVY_VERSION}")
|
||||
|
||||
|
||||
if (WIN32)
|
||||
@@ -223,8 +213,7 @@ macro(PrintFinalReport)
|
||||
file(COPY ${FREECAD_LIBPACK_DIR}/plugins/styles DESTINATION ${CMAKE_BINARY_DIR}/bin)
|
||||
file(COPY ${FREECAD_LIBPACK_DIR}/plugins/printsupport DESTINATION ${CMAKE_BINARY_DIR}/bin)
|
||||
file(COPY ${FREECAD_LIBPACK_DIR}/resources DESTINATION ${CMAKE_BINARY_DIR})
|
||||
file(COPY ${FREECAD_LIBPACK_DIR}/bin/Lib/site-packages/PySide2/translations/qtwebengine_locales
|
||||
DESTINATION ${CMAKE_BINARY_DIR}/bin)
|
||||
file(COPY ${FREECAD_LIBPACK_DIR}/translations/qtwebengine_locales DESTINATION ${CMAKE_BINARY_DIR}/translations)
|
||||
message(STATUS "... end copying.\n=======================================\n")
|
||||
endif(FREECAD_COPY_DEPEND_DIRS_TO_BUILD)
|
||||
|
||||
@@ -258,7 +247,7 @@ macro(PrintFinalReport)
|
||||
install(DIRECTORY ${FREECAD_LIBPACK_DIR}/plugins/sqldrivers DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(DIRECTORY ${FREECAD_LIBPACK_DIR}/plugins/styles DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(DIRECTORY ${FREECAD_LIBPACK_DIR}/plugins/printsupport DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(DIRECTORY ${FREECAD_LIBPACK_DIR}/bin/Lib/site-packages/PySide2/translations/qtwebengine_locales DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(DIRECTORY ${FREECAD_LIBPACK_DIR}/translations/qtwebengine_locales DESTINATION ${CMAKE_INSTALL_PREFIX}/translations)
|
||||
install(DIRECTORY ${FREECAD_LIBPACK_DIR}/resources DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(DIRECTORY ${FREECAD_LIBPACK_DIR}/bin DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
message(STATUS "Created install commands for INSTALL target.\n")
|
||||
|
||||
@@ -3,10 +3,10 @@ macro(SetupMatplotlib)
|
||||
|
||||
find_package(Matplotlib)
|
||||
if (MATPLOTLIB_FOUND)
|
||||
message(STATUS "-- matplotlib-${MATPLOTLIB_VERSION} has been found.")
|
||||
message(STATUS "Found Matplotlib: ${MATPLOTLIB_PATH_DIRS} (found version \"${MATPLOTLIB_VERSION}\")")
|
||||
else(MATPLOTLIB_FOUND)
|
||||
message("=====================================================\n"
|
||||
"matplotlib not found, Plot module won't be available.\n"
|
||||
"Matplotlib not found, Plot module won't be available.\n"
|
||||
"=====================================================\n")
|
||||
endif(MATPLOTLIB_FOUND)
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
macro(SetupPython)
|
||||
# -------------------------------- Python --------------------------------
|
||||
|
||||
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=677598
|
||||
# Acceptable versions of Python
|
||||
set(Python_ADDITIONAL_VERSIONS "2.7")
|
||||
|
||||
# For building on OS X
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT BUILD_WITH_CONDA)
|
||||
|
||||
@@ -118,32 +114,49 @@ macro(SetupPython)
|
||||
|
||||
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT BUILD_WITH_CONDA)
|
||||
|
||||
find_package(PythonInterp REQUIRED)
|
||||
|
||||
# Issue in cmake prevents finding pythonlibs 3.x when python 2.7 is present
|
||||
# setting NOTFOUND here resolves the issue
|
||||
set(PYTHON_INCLUDE_DIR "NOTFOUND")
|
||||
set(PYTHON_LIBRARY "NOTFOUND")
|
||||
|
||||
set(Python_ADDITIONAL_VERSIONS ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
|
||||
if (NOT DEFINED PYTHON_VERSION_STRING)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
else (NOT DEFINED PYTHON_VERSION_STRING)
|
||||
find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT)
|
||||
endif(NOT DEFINED PYTHON_VERSION_STRING)
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.12")
|
||||
set(Python_ADDITIONAL_VERSIONS ${Python_ADDITIONAL_VERSIONS} "3.10" "3.9" "3.8" "3.7" "3.6")
|
||||
find_package(PythonInterp REQUIRED)
|
||||
set(Python_ADDITIONAL_VERSIONS ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
|
||||
if (NOT DEFINED PYTHON_VERSION_STRING)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
else (NOT DEFINED PYTHON_VERSION_STRING)
|
||||
find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT)
|
||||
endif(NOT DEFINED PYTHON_VERSION_STRING)
|
||||
if(NOT PYTHONLIBS_FOUND)
|
||||
message(FATAL_ERROR "=================================\n"
|
||||
"Python not found, install Python!\n"
|
||||
"=================================\n")
|
||||
endif()
|
||||
|
||||
# For forward compatibility with new CMake scripts
|
||||
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
set(Python3_LIBRARIES ${PYTHON_LIBRARIES})
|
||||
set(Python3_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS})
|
||||
set(Python3_LIBRARY_DIRS ${PYTHON_LIBRARY_DIRS})
|
||||
set(Python3_VERSION ${PYTHON_VERSION_STRING})
|
||||
set(Python3_VERSION_MAJOR ${PYTHON_VERSION_MAJOR})
|
||||
set(Python3_VERSION_MINOR ${PYTHON_VERSION_MINOR})
|
||||
set(Python3_VERSION_PATCH ${PYTHON_VERSION_PATCH})
|
||||
set(Python3_Interpreter_FOUND ${PYTHONINTERP_FOUND})
|
||||
else()
|
||||
find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
|
||||
|
||||
|
||||
if(NOT PYTHONLIBS_FOUND)
|
||||
message(FATAL_ERROR "=================================\n"
|
||||
"Python not found, install Python!\n"
|
||||
"=================================\n")
|
||||
else(NOT PYTHONLIBS_FOUND)
|
||||
# prevent python3 lower than 3.3 (not enough utf8<->unicode tools)
|
||||
if(PYTHON_VERSION_MAJOR EQUAL 3)
|
||||
if(PYTHON_VERSION_MINOR LESS 4)
|
||||
message(FATAL_ERROR "To build FreeCAD with Python3, you need at least version 3.4\n")
|
||||
endif(PYTHON_VERSION_MINOR LESS 4)
|
||||
endif(PYTHON_VERSION_MAJOR EQUAL 3)
|
||||
endif(NOT PYTHONLIBS_FOUND)
|
||||
# For backwards compatibility with old CMake scripts
|
||||
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
|
||||
set(PYTHON_LIBRARIES ${Python3_LIBRARIES})
|
||||
set(PYTHON_INCLUDE_DIRS ${Python3_INCLUDE_DIRS})
|
||||
set(PYTHON_LIBRARY_DIRS ${Python3_LIBRARY_DIRS})
|
||||
set(PYTHON_VERSION_STRING ${Python3_VERSION})
|
||||
set(PYTHON_VERSION_MAJOR ${Python3_VERSION_MAJOR})
|
||||
set(PYTHON_VERSION_MINOR ${Python3_VERSION_MINOR})
|
||||
set(PYTHON_VERSION_PATCH ${Python3_VERSION_PATCH})
|
||||
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
|
||||
endif()
|
||||
|
||||
# prevent python3 lower than 3.6
|
||||
if (${PYTHON_VERSION_STRING} VERSION_LESS "3.6")
|
||||
message(FATAL_ERROR "To build FreeCAD you need at least Python 3.6\n")
|
||||
endif()
|
||||
|
||||
endmacro(SetupPython)
|
||||
|
||||
@@ -1,117 +1,53 @@
|
||||
# -------------------------------- Qt --------------------------------
|
||||
|
||||
if (NOT BUILD_QT5)
|
||||
# If using MacPorts, help the Qt4 finder.
|
||||
if(MACPORTS_PREFIX)
|
||||
if(NOT QT_QMAKE_EXECUTABLE)
|
||||
set(QT_QMAKE_EXECUTABLE ${MACPORTS_PREFIX}/libexec/qt4/bin/qmake)
|
||||
endif()
|
||||
endif()
|
||||
find_package(Qt5Core REQUIRED)
|
||||
|
||||
set(QT_MIN_VERSION 4.5.0)
|
||||
set(QT_USE_QTNETWORK TRUE)
|
||||
set(QT_USE_QTXML TRUE)
|
||||
if(BUILD_GUI)
|
||||
set(QT_USE_QTOPENGL TRUE)
|
||||
set(QT_USE_QTSVG TRUE)
|
||||
set(QT_USE_QTUITOOLS TRUE)
|
||||
set(QT_USE_QTWEBKIT TRUE)
|
||||
endif(BUILD_GUI)
|
||||
|
||||
find_package(Qt4)# REQUIRED
|
||||
|
||||
include(${QT_USE_FILE})
|
||||
|
||||
if(NOT QT4_FOUND)
|
||||
message(FATAL_ERROR "========================\n"
|
||||
"Qt4 libraries not found.\n"
|
||||
"========================\n")
|
||||
endif(NOT QT4_FOUND)
|
||||
|
||||
if(NOT QT_QTWEBKIT_FOUND)
|
||||
message("========================================================\n"
|
||||
"Qt Webkit not found, will not build browser integration.\n"
|
||||
"========================================================\n")
|
||||
endif(NOT QT_QTWEBKIT_FOUND)
|
||||
|
||||
# This is a special version of the built in macro qt4_wrap_cpp
|
||||
# It is required since moc'ed files are now included instead of being added to projects directly
|
||||
# It adds a reverse dependency to solve this
|
||||
# This has the unfortunate side effect that some files are always rebuilt
|
||||
# There is probably a cleaner solution than this
|
||||
macro(fc_wrap_cpp outfiles)
|
||||
# get include dirs
|
||||
QT4_GET_MOC_FLAGS(moc_flags)
|
||||
QT4_EXTRACT_OPTIONS(moc_files moc_options moc_target ${ARGN})
|
||||
# fixes bug 0000585: bug with boost 1.48
|
||||
set(moc_options ${moc_options} -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
|
||||
|
||||
foreach(it ${moc_files})
|
||||
get_filename_component(it ${it} ABSOLUTE)
|
||||
QT4_MAKE_OUTPUT_FILE(${it} moc_ cpp outfile)
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
|
||||
COMMAND ${QT_MOC_EXECUTABLE}
|
||||
ARGS ${moc_options} ${it} -o ${outfile}
|
||||
MAIN_DEPENDENCY ${it}
|
||||
)
|
||||
set(${outfiles} ${${outfiles}} ${outfile})
|
||||
add_file_dependencies(${it} ${outfile})
|
||||
endforeach(it)
|
||||
endmacro(fc_wrap_cpp)
|
||||
|
||||
elseif (BUILD_QT5)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(Qt5XmlPatterns REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
if(BUILD_GUI)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5PrintSupport REQUIRED)
|
||||
find_package(Qt5OpenGL REQUIRED)
|
||||
find_package(Qt5Svg REQUIRED)
|
||||
find_package(Qt5UiTools REQUIRED)
|
||||
if (BUILD_WEB)
|
||||
if (${FREECAD_USE_QTWEBMODULE} MATCHES "Qt Webkit")
|
||||
find_package(Qt5WebKitWidgets REQUIRED)
|
||||
elseif(${FREECAD_USE_QTWEBMODULE} MATCHES "Qt WebEngine")
|
||||
# For FreeCAD 0.20, pegged to Ubutu 18.04 LTS:
|
||||
if(${Qt5Core_VERSION} VERSION_LESS "5.9")
|
||||
message (FATAL_ERROR "FreeCAD v0.20 requires Qt5 5.9 or later")
|
||||
endif()
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(Qt5XmlPatterns REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
if(BUILD_GUI)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5PrintSupport REQUIRED)
|
||||
find_package(Qt5OpenGL REQUIRED)
|
||||
find_package(Qt5Svg REQUIRED)
|
||||
find_package(Qt5UiTools REQUIRED)
|
||||
if (BUILD_WEB)
|
||||
if (${FREECAD_USE_QTWEBMODULE} MATCHES "Qt Webkit")
|
||||
find_package(Qt5WebKitWidgets REQUIRED)
|
||||
elseif(${FREECAD_USE_QTWEBMODULE} MATCHES "Qt WebEngine")
|
||||
find_package(Qt5WebEngineWidgets REQUIRED)
|
||||
else() # Automatic
|
||||
find_package(Qt5WebKitWidgets QUIET)
|
||||
if(NOT Qt5WebKitWidgets_FOUND)
|
||||
find_package(Qt5WebEngineWidgets REQUIRED)
|
||||
if (Qt5WebEngineWidgets_VERSION VERSION_LESS 5.7.0)
|
||||
message(FATAL_ERROR "** Minimum supported Qt5WebEngine version is 5.7.0!\n")
|
||||
endif()
|
||||
else() # Automatic
|
||||
find_package(Qt5WebKitWidgets QUIET)
|
||||
if(NOT Qt5WebKitWidgets_FOUND)
|
||||
find_package(Qt5WebEngineWidgets REQUIRED)
|
||||
if (Qt5WebEngineWidgets_VERSION VERSION_LESS 5.7.0)
|
||||
message(FATAL_ERROR "** Minimum supported Qt5WebEngine version is 5.7.0!\n")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(MSVC AND ${Qt5Core_VERSION} VERSION_GREATER "5.2.0")
|
||||
find_package(Qt5WinExtras QUIET)
|
||||
endif()
|
||||
endif(BUILD_GUI)
|
||||
endif()
|
||||
if(MSVC)
|
||||
find_package(Qt5WinExtras QUIET)
|
||||
endif()
|
||||
endif(BUILD_GUI)
|
||||
|
||||
# This is a special version of the built in macro qt5_wrap_cpp
|
||||
# It is required since moc'ed files are now included instead of being added to projects directly
|
||||
# It adds a reverse dependency to solve this
|
||||
# This has the unfortunate side effect that some files are always rebuilt
|
||||
# There is probably a cleaner solution than this
|
||||
macro(fc_wrap_cpp outfiles )
|
||||
# get include dirs
|
||||
qt5_get_moc_flags(moc_flags)
|
||||
set(moc_files ${ARGN})
|
||||
# fixes bug 0000585: bug with boost 1.48
|
||||
set(moc_options ${moc_options} -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
|
||||
# This is a special version of the built in macro qt5_wrap_cpp
|
||||
# It is required since moc'ed files are now included instead of being added to projects directly
|
||||
# It adds a reverse dependency to solve this
|
||||
# This has the unfortunate side effect that some files are always rebuilt
|
||||
# There is probably a cleaner solution than this
|
||||
macro(fc_wrap_cpp outfiles )
|
||||
# get include dirs
|
||||
qt5_get_moc_flags(moc_flags)
|
||||
set(moc_files ${ARGN})
|
||||
|
||||
foreach(it ${moc_files})
|
||||
get_filename_component(it ${it} ABSOLUTE)
|
||||
qt5_make_output_file(${it} moc_ cpp outfile)
|
||||
qt5_create_moc_command(${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}" "${moc_depends}")
|
||||
set(${outfiles} ${${outfiles}} ${outfile})
|
||||
add_file_dependencies(${it} ${outfile})
|
||||
endforeach(it)
|
||||
endmacro(fc_wrap_cpp)
|
||||
endif (NOT BUILD_QT5)
|
||||
foreach(it ${moc_files})
|
||||
get_filename_component(it ${it} ABSOLUTE)
|
||||
qt5_make_output_file(${it} moc_ cpp outfile)
|
||||
qt5_create_moc_command(${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}" "${moc_depends}")
|
||||
set(${outfiles} ${${outfiles}} ${outfile})
|
||||
add_file_dependencies(${it} ${outfile})
|
||||
endforeach(it)
|
||||
endmacro(fc_wrap_cpp)
|
||||
|
||||
@@ -1,140 +1,91 @@
|
||||
macro(SetupShibokenAndPyside)
|
||||
# -------------------------------- Shiboken/PySide ------------------------
|
||||
|
||||
if(BUILD_QT5)
|
||||
# set(PYTHON_SUFFIX -python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
|
||||
# Below are two variables that can be left empty for standard python 3 version,
|
||||
# but must be set by the user for different python versions such as 2.7, 3.5 ...
|
||||
if (PYTHON_VERSION_MAJOR LESS 3)
|
||||
set(PYTHON_CONFIG_SUFFIX -python2.7 CACHE STRING "Shiboken cmake file suffix. If left empty, system default will be used: <ShibokenConfigPYTHON_CONFIG_SUFFIX.cmake>")
|
||||
set(PYTHON_BASENAME -python2.7 CACHE STRING "Same as PYTHON_SUFFIX but for PySide. If left empty, PYTHON_SUFFIX will be used: <PySideConfigPYTHON_BASENAME.cmake>")
|
||||
else()
|
||||
#set(PYTHON_CONFIG_SUFFIX "" CACHE STRING "Shiboken cmake file suffix. If left empty, system default will be used: <ShibokenConfigPYTHON_CONFIG_SUFFIX.cmake>")
|
||||
#set(PYTHON_BASENAME "" CACHE STRING "Same as PYTHON_SUFFIX but for PySide. If left empty, PYTHON_SUFFIX will be used: <PySideConfigPYTHON_BASENAME.cmake>")
|
||||
if(DEFINED MACPORTS_PREFIX)
|
||||
find_package(Shiboken REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
|
||||
find_package(PySide REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
|
||||
endif(DEFINED MACPORTS_PREFIX)
|
||||
|
||||
# Shiboken2Config.cmake may explicitly set CMAKE_BUILD_TYPE to Release which causes
|
||||
# CMake to fail to create Makefiles for a debug build.
|
||||
# So as a workaround we save and restore the value after checking for Shiboken2.
|
||||
set (SAVE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
|
||||
find_package(Shiboken2 QUIET)# REQUIRED
|
||||
set (CMAKE_BUILD_TYPE ${SAVE_BUILD_TYPE})
|
||||
if (Shiboken2_FOUND)
|
||||
# Shiboken2 config file was found but it may use the wrong Python version
|
||||
# Try to get the matching config suffix and repeat finding the package
|
||||
set(SHIBOKEN_PATTERN .cpython-${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})
|
||||
|
||||
file(GLOB SHIBOKEN_CONFIG "${Shiboken2_DIR}/Shiboken2Config${SHIBOKEN_PATTERN}*.cmake")
|
||||
if (SHIBOKEN_CONFIG)
|
||||
get_filename_component(SHIBOKEN_CONFIG_SUFFIX ${SHIBOKEN_CONFIG} NAME)
|
||||
string(SUBSTRING ${SHIBOKEN_CONFIG_SUFFIX} 15 -1 SHIBOKEN_CONFIG_SUFFIX)
|
||||
string(REPLACE ".cmake" "" PYTHON_CONFIG_SUFFIX ${SHIBOKEN_CONFIG_SUFFIX})
|
||||
message(STATUS "PYTHON_CONFIG_SUFFIX: ${PYTHON_CONFIG_SUFFIX}")
|
||||
find_package(Shiboken2 QUIET)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEFINED MACPORTS_PREFIX)
|
||||
find_package(Shiboken REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
|
||||
find_package(PySide REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
|
||||
endif(DEFINED MACPORTS_PREFIX)
|
||||
# pyside2 changed its cmake files, this is the dance we have
|
||||
# to dance to be compatible with the old (<5.12) and the new versions (>=5.12)
|
||||
if(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken2::libshiboken)
|
||||
get_property(SHIBOKEN_INCLUDE_DIR TARGET Shiboken2::libshiboken PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken2::libshiboken)
|
||||
|
||||
# Shiboken2Config.cmake may explicitly set CMAKE_BUILD_TYPE to Release which causes
|
||||
# CMake to fail to create Makefiles for a debug build.
|
||||
# So as a workaround we save and restore the value after checking for Shiboken2.
|
||||
set (SAVE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
|
||||
find_package(Shiboken2 QUIET)# REQUIRED
|
||||
set (CMAKE_BUILD_TYPE ${SAVE_BUILD_TYPE})
|
||||
if (Shiboken2_FOUND)
|
||||
# Shiboken2 config file was found but it may use the wrong Python version
|
||||
# Try to get the matching config suffix and repeat finding the package
|
||||
if (PYTHON_VERSION_MAJOR LESS 3)
|
||||
set(SHIBOKEN_PATTERN -python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
|
||||
else()
|
||||
set(SHIBOKEN_PATTERN .cpython-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR})
|
||||
endif()
|
||||
if(NOT SHIBOKEN_INCLUDE_DIR)
|
||||
message("====================\n"
|
||||
"shiboken2 not found.\n"
|
||||
"====================\n")
|
||||
endif(NOT SHIBOKEN_INCLUDE_DIR)
|
||||
|
||||
file(GLOB SHIBOKEN_CONFIG "${Shiboken2_DIR}/Shiboken2Config${SHIBOKEN_PATTERN}*.cmake")
|
||||
if (SHIBOKEN_CONFIG)
|
||||
get_filename_component(SHIBOKEN_CONFIG_SUFFIX ${SHIBOKEN_CONFIG} NAME)
|
||||
string(SUBSTRING ${SHIBOKEN_CONFIG_SUFFIX} 15 -1 SHIBOKEN_CONFIG_SUFFIX)
|
||||
string(REPLACE ".cmake" "" PYTHON_CONFIG_SUFFIX ${SHIBOKEN_CONFIG_SUFFIX})
|
||||
message(STATUS "PYTHON_CONFIG_SUFFIX: ${PYTHON_CONFIG_SUFFIX}")
|
||||
find_package(Shiboken2 QUIET)
|
||||
endif()
|
||||
endif()
|
||||
find_package(PySide2 QUIET)# REQUIRED
|
||||
|
||||
# pyside2 changed its cmake files, this is the dance we have
|
||||
# to dance to be compatible with the old (<5.12) and the new versions (>=5.12)
|
||||
if(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken2::libshiboken)
|
||||
get_property(SHIBOKEN_INCLUDE_DIR TARGET Shiboken2::libshiboken PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken2::libshiboken)
|
||||
if(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide2::pyside2)
|
||||
get_property(PYSIDE_INCLUDE_DIR TARGET PySide2::pyside2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide2::pyside2)
|
||||
|
||||
if(NOT SHIBOKEN_INCLUDE_DIR)
|
||||
message("====================\n"
|
||||
"shiboken2 not found.\n"
|
||||
"====================\n")
|
||||
endif(NOT SHIBOKEN_INCLUDE_DIR)
|
||||
if(NOT PYSIDE_INCLUDE_DIR)
|
||||
message("==================\n"
|
||||
"PySide2 not found.\n"
|
||||
"==================\n")
|
||||
endif(NOT PYSIDE_INCLUDE_DIR)
|
||||
|
||||
find_package(PySide2 QUIET)# REQUIRED
|
||||
find_package(PySide2Tools QUIET) #REQUIRED # PySide2 utilities (pyside2-uic & pyside2-rcc)
|
||||
if(NOT PYSIDE2_TOOLS_FOUND)
|
||||
message("=======================\n"
|
||||
"PySide2Tools not found.\n"
|
||||
"=======================\n")
|
||||
endif(NOT PYSIDE2_TOOLS_FOUND)
|
||||
|
||||
if(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide2::pyside2)
|
||||
get_property(PYSIDE_INCLUDE_DIR TARGET PySide2::pyside2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide2::pyside2)
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Ext/PySide)
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/__init__.py "# PySide wrapper\n"
|
||||
"from PySide2 import __version__\n"
|
||||
"from PySide2 import __version_info__\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtCore.py "from PySide2.QtCore import *\n\n"
|
||||
"#QCoreApplication.CodecForTr=0\n"
|
||||
"#QCoreApplication.UnicodeUTF8=1\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtGui.py "from PySide2.QtGui import *\n"
|
||||
"from PySide2.QtWidgets import *\n"
|
||||
"QHeaderView.setResizeMode = QHeaderView.setSectionResizeMode\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtSvg.py "from PySide2.QtSvg import *\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtUiTools.py "from PySide2.QtUiTools import *\n")
|
||||
|
||||
if(NOT PYSIDE_INCLUDE_DIR)
|
||||
message("==================\n"
|
||||
"PySide2 not found.\n"
|
||||
"==================\n")
|
||||
endif(NOT PYSIDE_INCLUDE_DIR)
|
||||
|
||||
find_package(PySide2Tools QUIET) #REQUIRED # PySide2 utilities (pyside2-uic & pyside2-rcc)
|
||||
if(NOT PYSIDE2_TOOLS_FOUND)
|
||||
message("=======================\n"
|
||||
"PySide2Tools not found.\n"
|
||||
"=======================\n")
|
||||
endif(NOT PYSIDE2_TOOLS_FOUND)
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Ext/PySide)
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/__init__.py "# PySide wrapper\n"
|
||||
"from PySide2 import __version__\n"
|
||||
"from PySide2 import __version_info__\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtCore.py "from PySide2.QtCore import *\n\n"
|
||||
"#QCoreApplication.CodecForTr=0\n"
|
||||
"#QCoreApplication.UnicodeUTF8=1\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtGui.py "from PySide2.QtGui import *\n"
|
||||
"from PySide2.QtWidgets import *\n"
|
||||
"QHeaderView.setResizeMode = QHeaderView.setSectionResizeMode\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtSvg.py "from PySide2.QtSvg import *\n")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtUiTools.py "from PySide2.QtUiTools import *\n")
|
||||
|
||||
if(APPLE AND NOT BUILD_WITH_CONDA)
|
||||
install(
|
||||
DIRECTORY
|
||||
${CMAKE_BINARY_DIR}/Ext/PySide
|
||||
DESTINATION
|
||||
MacOS
|
||||
)
|
||||
else()
|
||||
install(
|
||||
DIRECTORY
|
||||
${CMAKE_BINARY_DIR}/Ext/PySide
|
||||
DESTINATION
|
||||
Ext
|
||||
)
|
||||
endif()
|
||||
else(BUILD_QT5)
|
||||
# set(PYTHON_SUFFIX -python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
|
||||
# Below are two variables that can be left empty for standard python 3 version,
|
||||
# but must be set by the user for different python versions such as 2.7, 3.5 ...
|
||||
if (PYTHON_VERSION_MAJOR LESS 3)
|
||||
set(PYTHON_CONFIG_SUFFIX -python2.7 CACHE STRING "Shiboken cmake file suffix. If left empty, system default will be used: <ShibokenConfigPYTHON_CONFIG_SUFFIX.cmake>")
|
||||
set(PYTHON_BASENAME -python2.7 CACHE STRING "Same as PYTHON_SUFFIX but for PySide. If left empty, PYTHON_SUFFIX will be used: <PySideConfigPYTHON_BASENAME.cmake>")
|
||||
else()
|
||||
set(PYTHON_CONFIG_SUFFIX "" CACHE STRING "Shiboken cmake file suffix. If left empty, system default will be used: <ShibokenConfigPYTHON_CONFIG_SUFFIX.cmake>")
|
||||
set(PYTHON_BASENAME "" CACHE STRING "Same as PYTHON_SUFFIX but for PySide. If left empty, PYTHON_SUFFIX will be used: <PySideConfigPYTHON_BASENAME.cmake>")
|
||||
endif()
|
||||
|
||||
if(DEFINED MACPORTS_PREFIX)
|
||||
find_package(Shiboken REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
|
||||
find_package(PySide REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
|
||||
endif(DEFINED MACPORTS_PREFIX)
|
||||
|
||||
find_package(Shiboken)# REQUIRED
|
||||
if(NOT SHIBOKEN_INCLUDE_DIR)
|
||||
message(FATAL_ERROR "===================\n"
|
||||
"shiboken not found.\n"
|
||||
"===================\n")
|
||||
endif(NOT SHIBOKEN_INCLUDE_DIR)
|
||||
|
||||
find_package(PySide)# REQUIRED
|
||||
if(NOT PYSIDE_INCLUDE_DIR)
|
||||
message(FATAL_ERROR "=================\n"
|
||||
"PySide not found.\n"
|
||||
"=================\n")
|
||||
endif(NOT PYSIDE_INCLUDE_DIR)
|
||||
|
||||
find_package(PySideTools REQUIRED) # PySide utilities (pyside-uic & pyside-rcc)
|
||||
endif(BUILD_QT5)
|
||||
if(APPLE AND NOT BUILD_WITH_CONDA)
|
||||
install(
|
||||
DIRECTORY
|
||||
${CMAKE_BINARY_DIR}/Ext/PySide
|
||||
DESTINATION
|
||||
MacOS
|
||||
)
|
||||
else()
|
||||
install(
|
||||
DIRECTORY
|
||||
${CMAKE_BINARY_DIR}/Ext/PySide
|
||||
DESTINATION
|
||||
Ext
|
||||
)
|
||||
endif()
|
||||
|
||||
# If shiboken cannot be found the build option will be set to OFF
|
||||
if(SHIBOKEN_INCLUDE_DIR)
|
||||
@@ -143,19 +94,11 @@ macro(SetupShibokenAndPyside)
|
||||
option(FREECAD_USE_SHIBOKEN "Links to the shiboken library at build time. If OFF its Python module is imported at runtime" OFF)
|
||||
|
||||
# Now try to import the shiboken Python module and print a warning if it can't be loaded
|
||||
if(BUILD_QT5)
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} -c "import shiboken2"
|
||||
RESULT_VARIABLE FAILURE
|
||||
OUTPUT_VARIABLE PRINT_OUTPUT
|
||||
)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} -c "import shiboken"
|
||||
RESULT_VARIABLE FAILURE
|
||||
OUTPUT_VARIABLE PRINT_OUTPUT
|
||||
)
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} -c "import shiboken2"
|
||||
RESULT_VARIABLE FAILURE
|
||||
OUTPUT_VARIABLE PRINT_OUTPUT
|
||||
)
|
||||
|
||||
if(FAILURE)
|
||||
message("=================================\n"
|
||||
@@ -172,36 +115,19 @@ macro(SetupShibokenAndPyside)
|
||||
endif()
|
||||
|
||||
# Independent of the build option PySide modules must be loaded at runtime. Print a warning if it fails.
|
||||
if(BUILD_QT5)
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} -c "import PySide2;import os;print(os.path.dirname(PySide2.__file__), end='')"
|
||||
RESULT_VARIABLE FAILURE
|
||||
OUTPUT_VARIABLE PRINT_OUTPUT
|
||||
)
|
||||
if(FAILURE)
|
||||
message("================================\n"
|
||||
"PySide2 Python module not found.\n"
|
||||
"================================\n")
|
||||
else()
|
||||
message(STATUS "===============================================\n"
|
||||
"PySide2 Python module found at ${PRINT_OUTPUT}.\n"
|
||||
"===============================================\n")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} -c "import PySide2;import os;print(os.path.dirname(PySide2.__file__), end='')"
|
||||
RESULT_VARIABLE FAILURE
|
||||
OUTPUT_VARIABLE PRINT_OUTPUT
|
||||
)
|
||||
if(FAILURE)
|
||||
message("================================\n"
|
||||
"PySide2 Python module not found.\n"
|
||||
"================================\n")
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} -c "import PySide;import os;print(os.path.dirname(PySide.__file__))"
|
||||
RESULT_VARIABLE FAILURE
|
||||
OUTPUT_VARIABLE PRINT_OUTPUT
|
||||
)
|
||||
if(FAILURE)
|
||||
message("===============================\n"
|
||||
"PySide Python module not found.\n"
|
||||
"===============================\n")
|
||||
else()
|
||||
message(STATUS "==============================================\n"
|
||||
"PySide Python module found at ${PRINT_OUTPUT}.\n"
|
||||
"==============================================\n")
|
||||
endif()
|
||||
message(STATUS "===============================================\n"
|
||||
"PySide2 Python module found at ${PRINT_OUTPUT}.\n"
|
||||
"===============================================\n")
|
||||
endif()
|
||||
|
||||
endmacro(SetupShibokenAndPyside)
|
||||
|
||||
@@ -5,8 +5,75 @@ path_classifiers:
|
||||
- "src/Mod/Import/App/config_control_design.py"
|
||||
- "src/Mod/Import/App/ifc2x3.py"
|
||||
- "src/Mod/Import/App/ifc4.py"
|
||||
library:
|
||||
- "src/zipios++/"
|
||||
- "src/3rdParty/"
|
||||
- "src/Mod/Import/App/SCL"
|
||||
- "src/CXX/"
|
||||
template:
|
||||
- "src/Tools/examplePy2wiki.py"
|
||||
- "src/Mode/TemplatePyMod/"
|
||||
unmaintained:
|
||||
- "src/Mod/Robot/"
|
||||
- "src/Mod/Ship/"
|
||||
legacy:
|
||||
- "src/Mod/Assembly/"
|
||||
- "src/Mod/Drawing/"
|
||||
- "src/Mod/Raytracing/"
|
||||
- "src/Mod/Spreadsheet/App/Spreadsheet_legacy.py"
|
||||
- "src/Mod/OpenSCAD/prototype.py"
|
||||
|
||||
extraction:
|
||||
javascript:
|
||||
index:
|
||||
filters:
|
||||
exclude: "**/translations/*.ts"
|
||||
cpp:
|
||||
prepare:
|
||||
packages:
|
||||
- "cmake"
|
||||
- "cmake-gui"
|
||||
- "libboost-date-time-dev"
|
||||
- "libboost-dev"
|
||||
- "libboost-filesystem-dev"
|
||||
- "libboost-graph-dev"
|
||||
- "libboost-iostreams-dev"
|
||||
- "libboost-program-options-dev"
|
||||
- "libboost-python-dev"
|
||||
- "libboost-regex-dev"
|
||||
- "libboost-serialization-dev"
|
||||
- "libboost-thread-dev"
|
||||
- "libcoin-dev"
|
||||
- "libeigen3-dev"
|
||||
- "libgts-bin"
|
||||
- "libgts-dev"
|
||||
- "libkdtree++-dev"
|
||||
- "libmedc-dev"
|
||||
- "libocct-data-exchange-dev"
|
||||
- "libocct-ocaf-dev"
|
||||
- "libocct-visualization-dev"
|
||||
- "libopencv-dev"
|
||||
- "libproj-dev"
|
||||
- "libpyside2-dev"
|
||||
- "libshiboken2-dev"
|
||||
- "libspnav-dev"
|
||||
- "libvtk7-dev"
|
||||
- "libx11-dev"
|
||||
- "libxerces-c-dev"
|
||||
- "libzipios++-dev"
|
||||
- "occt-draw"
|
||||
- "pyside2-tools"
|
||||
- "python3-dev"
|
||||
- "python3-matplotlib"
|
||||
- "python3-pivy"
|
||||
- "python3-ply"
|
||||
- "python3-pyside2.qtcore"
|
||||
- "python3-pyside2uic"
|
||||
- "qtbase5-dev"
|
||||
- "qttools5-dev"
|
||||
- "swig"
|
||||
configure:
|
||||
command: "cmake ./ -DPYTHON_EXECUTABLE=/usr/bin/python3 -DBUILD_GUI=OFF -DBUILD_ARCH=OFF\
|
||||
\ -DBUILD_DRAWING=OFF -DBUILD_IMAGE=OFF -DBUILD_INSPECTION=OFF -DBUILD_OPENSCAD=OFF\
|
||||
\ -DBUILD_RAYTRACING=OFF -DBUILD_REVERSEENGINEERING=OFF -DBUILD_SURFACE=OFF -DBUILD_START=OFF\
|
||||
\ -DBUILD_ROBOT=OFF -DBUILD_PATH=OFF -DBUILD_FEM=OFF"
|
||||
|
||||
@@ -245,6 +245,9 @@ mv %{buildroot}%{_libdir}/%{name}/share/metainfo/* %{buildroot}%{_metainfodir}/
|
||||
mkdir %{buildroot}%{_datadir}/applications/
|
||||
mv %{buildroot}%{_libdir}/%{name}/share/applications/* %{buildroot}%{_datadir}/applications/
|
||||
|
||||
mkdir -p %{buildroot}%{_datadir}/thumbnailers/
|
||||
mv %{buildroot}%{_libdir}/%{name}/share/thumbnailers/* %{buildroot}%{_datadir}/thumbnailers/
|
||||
|
||||
mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/
|
||||
mv %{buildroot}%{_libdir}/%{name}/share/icons/hicolor/scalable/* %{buildroot}%{_datadir}/icons/hicolor/scalable/
|
||||
|
||||
@@ -264,7 +267,8 @@ popd
|
||||
# Remove obsolete Start_Page.html
|
||||
rm -f %{buildroot}%{_docdir}/%{name}/Start_Page.html
|
||||
# Belongs in %%license not %%doc
|
||||
rm -f %{buildroot}%{_docdir}/freecad/ThirdPartyLibraries.html
|
||||
#No longer present?
|
||||
#rm -f %{buildroot}%{_docdir}/freecad/ThirdPartyLibraries.html
|
||||
|
||||
# Bug maintainers to keep %%{plugins} macro up to date.
|
||||
#
|
||||
@@ -330,7 +334,10 @@ fi
|
||||
%{_datadir}/icons/hicolor/scalable/*
|
||||
%{_datadir}/pixmaps/*
|
||||
%{_datadir}/mime/packages/*
|
||||
%{_datadir}/thumbnailers/*
|
||||
|
||||
%files data
|
||||
%{_datadir}/%{name}/
|
||||
%{_docdir}/%{name}/%{name}.q*
|
||||
%{_docdir}/%{name}/CONTRIBUTORS
|
||||
%{_docdir}/%{name}/LICENSE.html
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
// avoid name collision with std::byte in C++17
|
||||
#define NOCRYPT
|
||||
#define NOGDI
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#pragma comment(lib,"winmm.lib")
|
||||
|
||||
+4
-1
@@ -106,8 +106,11 @@ namespace GEOMUtils
|
||||
* \brief Sort shapes in the list by their coordinates.
|
||||
* \param SL The list of shapes to sort.
|
||||
*/
|
||||
struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
|
||||
struct CompareShapes
|
||||
{
|
||||
typedef TopoDS_Shape first_argument_type;
|
||||
typedef TopoDS_Shape second_argument_type;
|
||||
typedef bool result_type;
|
||||
CompareShapes (bool isOldSorting)
|
||||
: myIsOldSorting(isOldSorting) {}
|
||||
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ namespace SMESH{
|
||||
class SMESHCONTROLS_EXPORT Functor
|
||||
{
|
||||
public:
|
||||
~Functor(){}
|
||||
virtual ~Functor(){}
|
||||
virtual void SetMesh( const SMDS_Mesh* theMesh ) = 0;
|
||||
virtual SMDSAbs_ElementType GetType() const = 0;
|
||||
};
|
||||
|
||||
+5
-4
@@ -51,13 +51,14 @@ class SMESH_EXPORT Unexpect { //save / retrieve unexpected exceptions treatment
|
||||
PVF old;
|
||||
public :
|
||||
#ifndef WNT
|
||||
// std::set_unexpected has been removed in C++17
|
||||
Unexpect( PVF f )
|
||||
{ old = std::set_unexpected(f); }
|
||||
~Unexpect() { std::set_unexpected(old); }
|
||||
{ /*old = std::set_unexpected(f);*/old = f; }
|
||||
~Unexpect() { /*std::set_unexpected(old);*/ }
|
||||
#else
|
||||
Unexpect( PVF f )
|
||||
{ old = std::set_unexpected(f); }
|
||||
~Unexpect() { std::set_unexpected(old); }
|
||||
{ old = ::set_unexpected(f); }
|
||||
~Unexpect() { ::set_unexpected(old); }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
+3
-2
@@ -39,9 +39,10 @@ class UTILS_EXPORT Unexpect { //save / retrieve unexpected exceptions treatment
|
||||
PVF old;
|
||||
public :
|
||||
#ifndef WIN32
|
||||
// std::set_unexpected has been removed in C++17
|
||||
Unexpect( PVF f )
|
||||
{ old = std::set_unexpected(f); }
|
||||
~Unexpect() { std::set_unexpected(old); }
|
||||
{ /*old = std::set_unexpected(f);*/old = f; }
|
||||
~Unexpect() { /*std::set_unexpected(old);*/ }
|
||||
#else
|
||||
Unexpect( PVF f )
|
||||
{ old = ::set_unexpected(f); }
|
||||
|
||||
+52
-57
@@ -30,6 +30,7 @@
|
||||
# include <sstream>
|
||||
# include <exception>
|
||||
# include <ios>
|
||||
# include <functional>
|
||||
# if defined(FC_OS_LINUX) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
|
||||
# include <unistd.h>
|
||||
# include <pwd.h>
|
||||
@@ -128,8 +129,6 @@
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/token_functions.hpp>
|
||||
#include <boost_bind_bind.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QProcessEnvironment>
|
||||
@@ -138,7 +137,7 @@ using namespace App;
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace boost::program_options;
|
||||
namespace bp = boost::placeholders;
|
||||
namespace sp = std::placeholders;
|
||||
|
||||
|
||||
// scriptings (scripts are built-in but can be overridden by command line option)
|
||||
@@ -199,7 +198,6 @@ PyDoc_STRVAR(Base_doc,
|
||||
"like vector, matrix, bounding box, placement, rotation, axis, ...\n"
|
||||
);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
// This is called via the PyImport_AppendInittab mechanism called
|
||||
// during initialization, to make the built-in __FreeCADBase__
|
||||
// module known to Python.
|
||||
@@ -228,7 +226,6 @@ init_freecad_module(void)
|
||||
};
|
||||
return PyModule_Create(&FreeCADModuleDef);
|
||||
}
|
||||
#endif
|
||||
|
||||
Application::Application(std::map<std::string,std::string> &mConfig)
|
||||
: _mConfig(mConfig), _pActiveDoc(0), _isRestoring(false),_allowPartial(false)
|
||||
@@ -242,7 +239,6 @@ Application::Application(std::map<std::string,std::string> &mConfig)
|
||||
|
||||
// setting up Python binding
|
||||
Base::PyGILStateLocker lock;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* modules = PyImport_GetModuleDict();
|
||||
|
||||
__AppMethods = Application::Methods;
|
||||
@@ -252,12 +248,8 @@ Application::Application(std::map<std::string,std::string> &mConfig)
|
||||
pAppModule = init_freecad_module();
|
||||
PyDict_SetItemString(modules, "FreeCAD", pAppModule);
|
||||
}
|
||||
#else
|
||||
PyObject* pAppModule = Py_InitModule3("FreeCAD", Application::Methods, FreeCAD_doc);
|
||||
#endif
|
||||
Py::Module(pAppModule).setAttr(std::string("ActiveDocument"),Py::None());
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static struct PyModuleDef ConsoleModuleDef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"__FreeCADConsole__", Console_doc, -1,
|
||||
@@ -265,9 +257,6 @@ Application::Application(std::map<std::string,std::string> &mConfig)
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
PyObject* pConsoleModule = PyModule_Create(&ConsoleModuleDef);
|
||||
#else
|
||||
PyObject* pConsoleModule = Py_InitModule3("__FreeCADConsole__", ConsoleSingleton::Methods, Console_doc);
|
||||
#endif
|
||||
|
||||
// introducing additional classes
|
||||
|
||||
@@ -285,16 +274,13 @@ Application::Application(std::map<std::string,std::string> &mConfig)
|
||||
// binding classes from the base module. At a later stage we should
|
||||
// remove these types from the FreeCAD module.
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* pBaseModule = PyImport_ImportModule ("__FreeCADBase__");
|
||||
if (!pBaseModule) {
|
||||
PyErr_Clear();
|
||||
pBaseModule = init_freecad_base_module();
|
||||
PyDict_SetItemString(modules, "__FreeCADBase__", pBaseModule);
|
||||
}
|
||||
#else
|
||||
PyObject* pBaseModule = Py_InitModule3("__FreeCADBase__", NULL, Base_doc);
|
||||
#endif
|
||||
|
||||
Base::BaseExceptionFreeCADError = PyErr_NewException("Base.FreeCADError", PyExc_RuntimeError, NULL);
|
||||
Py_INCREF(Base::BaseExceptionFreeCADError);
|
||||
PyModule_AddObject(pBaseModule, "FreeCADError", Base::BaseExceptionFreeCADError);
|
||||
@@ -344,7 +330,6 @@ Application::Application(std::map<std::string,std::string> &mConfig)
|
||||
PyModule_AddObject(pAppModule, "Qt", pTranslateModule);
|
||||
|
||||
//insert Units module
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static struct PyModuleDef UnitsModuleDef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"Units", "The Unit API", -1,
|
||||
@@ -352,14 +337,8 @@ Application::Application(std::map<std::string,std::string> &mConfig)
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
PyObject* pUnitsModule = PyModule_Create(&UnitsModuleDef);
|
||||
#else
|
||||
PyObject* pUnitsModule = Py_InitModule3("Units", Base::UnitsApi::Methods,"The Unit API");
|
||||
#endif
|
||||
Base::Interpreter().addType(&Base::QuantityPy ::Type,pUnitsModule,"Quantity");
|
||||
// make sure to set the 'nb_true_divide' slot
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
Base::QuantityPy::Type.tp_as_number->nb_true_divide = Base::QuantityPy::Type.tp_as_number->nb_divide;
|
||||
#endif
|
||||
Base::Interpreter().addType(&Base::UnitPy ::Type,pUnitsModule,"Unit");
|
||||
|
||||
Py_INCREF(pUnitsModule);
|
||||
@@ -449,26 +428,26 @@ Document* Application::newDocument(const char * Name, const char * UserName, boo
|
||||
_pActiveDoc = DocMap[name];
|
||||
|
||||
// connect the signals to the application for the new document
|
||||
_pActiveDoc->signalBeforeChange.connect(boost::bind(&App::Application::slotBeforeChangeDocument, this, bp::_1, bp::_2));
|
||||
_pActiveDoc->signalChanged.connect(boost::bind(&App::Application::slotChangedDocument, this, bp::_1, bp::_2));
|
||||
_pActiveDoc->signalNewObject.connect(boost::bind(&App::Application::slotNewObject, this, bp::_1));
|
||||
_pActiveDoc->signalDeletedObject.connect(boost::bind(&App::Application::slotDeletedObject, this, bp::_1));
|
||||
_pActiveDoc->signalBeforeChangeObject.connect(boost::bind(&App::Application::slotBeforeChangeObject, this, bp::_1, bp::_2));
|
||||
_pActiveDoc->signalChangedObject.connect(boost::bind(&App::Application::slotChangedObject, this, bp::_1, bp::_2));
|
||||
_pActiveDoc->signalRelabelObject.connect(boost::bind(&App::Application::slotRelabelObject, this, bp::_1));
|
||||
_pActiveDoc->signalActivatedObject.connect(boost::bind(&App::Application::slotActivatedObject, this, bp::_1));
|
||||
_pActiveDoc->signalUndo.connect(boost::bind(&App::Application::slotUndoDocument, this, bp::_1));
|
||||
_pActiveDoc->signalRedo.connect(boost::bind(&App::Application::slotRedoDocument, this, bp::_1));
|
||||
_pActiveDoc->signalRecomputedObject.connect(boost::bind(&App::Application::slotRecomputedObject, this, bp::_1));
|
||||
_pActiveDoc->signalRecomputed.connect(boost::bind(&App::Application::slotRecomputed, this, bp::_1));
|
||||
_pActiveDoc->signalBeforeRecompute.connect(boost::bind(&App::Application::slotBeforeRecompute, this, bp::_1));
|
||||
_pActiveDoc->signalOpenTransaction.connect(boost::bind(&App::Application::slotOpenTransaction, this, bp::_1, bp::_2));
|
||||
_pActiveDoc->signalCommitTransaction.connect(boost::bind(&App::Application::slotCommitTransaction, this, bp::_1));
|
||||
_pActiveDoc->signalAbortTransaction.connect(boost::bind(&App::Application::slotAbortTransaction, this, bp::_1));
|
||||
_pActiveDoc->signalStartSave.connect(boost::bind(&App::Application::slotStartSaveDocument, this, bp::_1, bp::_2));
|
||||
_pActiveDoc->signalFinishSave.connect(boost::bind(&App::Application::slotFinishSaveDocument, this, bp::_1, bp::_2));
|
||||
_pActiveDoc->signalBeforeChange.connect(std::bind(&App::Application::slotBeforeChangeDocument, this, sp::_1, sp::_2));
|
||||
_pActiveDoc->signalChanged.connect(std::bind(&App::Application::slotChangedDocument, this, sp::_1, sp::_2));
|
||||
_pActiveDoc->signalNewObject.connect(std::bind(&App::Application::slotNewObject, this, sp::_1));
|
||||
_pActiveDoc->signalDeletedObject.connect(std::bind(&App::Application::slotDeletedObject, this, sp::_1));
|
||||
_pActiveDoc->signalBeforeChangeObject.connect(std::bind(&App::Application::slotBeforeChangeObject, this, sp::_1, sp::_2));
|
||||
_pActiveDoc->signalChangedObject.connect(std::bind(&App::Application::slotChangedObject, this, sp::_1, sp::_2));
|
||||
_pActiveDoc->signalRelabelObject.connect(std::bind(&App::Application::slotRelabelObject, this, sp::_1));
|
||||
_pActiveDoc->signalActivatedObject.connect(std::bind(&App::Application::slotActivatedObject, this, sp::_1));
|
||||
_pActiveDoc->signalUndo.connect(std::bind(&App::Application::slotUndoDocument, this, sp::_1));
|
||||
_pActiveDoc->signalRedo.connect(std::bind(&App::Application::slotRedoDocument, this, sp::_1));
|
||||
_pActiveDoc->signalRecomputedObject.connect(std::bind(&App::Application::slotRecomputedObject, this, sp::_1));
|
||||
_pActiveDoc->signalRecomputed.connect(std::bind(&App::Application::slotRecomputed, this, sp::_1));
|
||||
_pActiveDoc->signalBeforeRecompute.connect(std::bind(&App::Application::slotBeforeRecompute, this, sp::_1));
|
||||
_pActiveDoc->signalOpenTransaction.connect(std::bind(&App::Application::slotOpenTransaction, this, sp::_1, sp::_2));
|
||||
_pActiveDoc->signalCommitTransaction.connect(std::bind(&App::Application::slotCommitTransaction, this, sp::_1));
|
||||
_pActiveDoc->signalAbortTransaction.connect(std::bind(&App::Application::slotAbortTransaction, this, sp::_1));
|
||||
_pActiveDoc->signalStartSave.connect(std::bind(&App::Application::slotStartSaveDocument, this, sp::_1, sp::_2));
|
||||
_pActiveDoc->signalFinishSave.connect(std::bind(&App::Application::slotFinishSaveDocument, this, sp::_1, sp::_2));
|
||||
_pActiveDoc->signalChangePropertyEditor.connect(
|
||||
boost::bind(&App::Application::slotChangePropertyEditor, this, bp::_1, bp::_2));
|
||||
std::bind(&App::Application::slotChangePropertyEditor, this, sp::_1, sp::_2));
|
||||
|
||||
// make sure that the active document is set in case no GUI is up
|
||||
{
|
||||
@@ -802,9 +781,9 @@ std::vector<Document*> Application::openDocuments(const std::vector<std::string>
|
||||
return res;
|
||||
}
|
||||
|
||||
Document* Application::openDocumentPrivate(const char * FileName,
|
||||
Document* Application::openDocumentPrivate(const char * FileName,
|
||||
const char *propFileName, const char *label,
|
||||
bool isMainDoc, bool createView,
|
||||
bool isMainDoc, bool createView,
|
||||
const std::set<std::string> &objNames)
|
||||
{
|
||||
FileInfo File(FileName);
|
||||
@@ -831,12 +810,12 @@ Document* Application::openDocumentPrivate(const char * FileName,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(it->second->testStatus(App::Document::PartialDoc)
|
||||
if(it->second->testStatus(App::Document::PartialDoc)
|
||||
|| it->second->testStatus(App::Document::PartialRestore)) {
|
||||
// Here means a document is already partially loaded, but the document
|
||||
// is requested again, either partial or not. We must check if the
|
||||
// is requested again, either partial or not. We must check if the
|
||||
// document contains the required object
|
||||
|
||||
|
||||
if(isMainDoc) {
|
||||
// Main document must be open fully, so close and reopen
|
||||
closeDocument(it->first.c_str());
|
||||
@@ -1039,7 +1018,7 @@ std::string Application::getHelpDir()
|
||||
int Application::checkLinkDepth(int depth, bool no_throw) {
|
||||
if(_objCount<0) {
|
||||
_objCount = 0;
|
||||
for(auto &v : DocMap)
|
||||
for(auto &v : DocMap)
|
||||
_objCount += v.second->countObjects();
|
||||
}
|
||||
if(depth > _objCount+2) {
|
||||
@@ -1499,6 +1478,23 @@ int Application::_argc;
|
||||
char ** Application::_argv;
|
||||
|
||||
|
||||
void Application::cleanupUnits()
|
||||
{
|
||||
try {
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Module mod (Py::Module("FreeCAD").getAttr("Units").ptr());
|
||||
|
||||
Py::List attr(mod.dir());
|
||||
for (Py::List::iterator it = attr.begin(); it != attr.end(); ++it) {
|
||||
mod.delAttr(Py::String(*it));
|
||||
}
|
||||
}
|
||||
catch (Py::Exception& e) {
|
||||
Base::PyGILStateLocker lock;
|
||||
e.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::destruct(void)
|
||||
{
|
||||
// saving system parameter
|
||||
@@ -1529,6 +1525,11 @@ void Application::destruct(void)
|
||||
_pcSysParamMngr = 0;
|
||||
_pcUserParamMngr = 0;
|
||||
|
||||
#ifdef FC_DEBUG
|
||||
// Do this only in debug mode for memory leak checkers
|
||||
cleanupUnits();
|
||||
#endif
|
||||
|
||||
// not initialized or double destruct!
|
||||
assert(_pcSingleton);
|
||||
delete _pcSingleton;
|
||||
@@ -1704,7 +1705,7 @@ void Application::init(int argc, char ** argv)
|
||||
std::signal(SIGSEGV,segmentation_fault_handler);
|
||||
std::signal(SIGABRT,segmentation_fault_handler);
|
||||
std::set_terminate(unhandled_exception_handler);
|
||||
std::set_unexpected(unexpection_error_handler);
|
||||
::set_unexpected(unexpection_error_handler);
|
||||
#elif defined(FC_OS_LINUX)
|
||||
std::signal(SIGSEGV,segmentation_fault_handler);
|
||||
#endif
|
||||
@@ -1713,10 +1714,6 @@ void Application::init(int argc, char ** argv)
|
||||
#endif
|
||||
initTypes();
|
||||
|
||||
#if (BOOST_FILESYSTEM_VERSION == 2)
|
||||
boost::filesystem::path::default_name_check(boost::filesystem::no_check);
|
||||
#endif
|
||||
|
||||
initConfig(argc,argv);
|
||||
initApplication();
|
||||
}
|
||||
@@ -1968,10 +1965,8 @@ void Application::initConfig(int argc, char ** argv)
|
||||
# endif
|
||||
|
||||
// init python
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyImport_AppendInittab ("FreeCAD", init_freecad_module);
|
||||
PyImport_AppendInittab ("__FreeCADBase__", init_freecad_base_module);
|
||||
#endif
|
||||
const char* pythonpath = Interpreter().init(argc,argv);
|
||||
if (pythonpath)
|
||||
mConfig["PythonSearchPath"] = pythonpath;
|
||||
@@ -2127,7 +2122,7 @@ void Application::initApplication(void)
|
||||
catch (const Base::Exception& e) {
|
||||
e.ReportException();
|
||||
}
|
||||
|
||||
|
||||
// seed randomizer
|
||||
srand(time(0));
|
||||
}
|
||||
|
||||
+11
-9
@@ -24,7 +24,7 @@
|
||||
#ifndef APP_APPLICATION_H
|
||||
#define APP_APPLICATION_H
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
@@ -72,7 +72,7 @@ class AppExport Application
|
||||
public:
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// exported functions goes here +++++++++++++++++++++++++++++++++++++++
|
||||
// exported functions go here +++++++++++++++++++++++++++++++++++++++++
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/** @name methods for document handling */
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
*
|
||||
* This function will also open any external referenced files.
|
||||
*/
|
||||
std::vector<Document*> openDocuments(const std::vector<std::string> &filenames,
|
||||
std::vector<Document*> openDocuments(const std::vector<std::string> &filenames,
|
||||
const std::vector<std::string> *paths=0,
|
||||
const std::vector<std::string> *labels=0,
|
||||
std::vector<std::string> *errs=0,
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
/// Indicate the application is closing all document
|
||||
bool isClosingAll() const;
|
||||
//@}
|
||||
|
||||
|
||||
/** @name Application-wide trandaction setting */
|
||||
//@{
|
||||
/** Setup a pending application-wide active transaction
|
||||
@@ -263,9 +263,9 @@ public:
|
||||
/// signal on about changing the editor mode of a property
|
||||
boost::signals2::signal<void (const App::Document&, const App::Property&)> signalChangePropertyEditor;
|
||||
//@}
|
||||
|
||||
|
||||
/** @name Signals of extension changes
|
||||
* These signals are emitted on dynamic extension addition. Dynamic extensions are the ones added by python (c++ ones are part
|
||||
* These signals are emitted on dynamic extension addition. Dynamic extensions are the ones added by python (c++ ones are part
|
||||
* of the class definition, hence not dynamic)
|
||||
* The extension in question is provided as parameter.
|
||||
*/
|
||||
@@ -382,7 +382,7 @@ public:
|
||||
|
||||
/** @name Link handling */
|
||||
//@{
|
||||
|
||||
|
||||
/** Check for link recursion depth
|
||||
*
|
||||
* @param depth: current depth
|
||||
@@ -458,6 +458,8 @@ private:
|
||||
/// Destructor
|
||||
virtual ~Application();
|
||||
|
||||
static void cleanupUnits();
|
||||
|
||||
/** @name member for parameter */
|
||||
//@{
|
||||
static ParameterManager *_pcSysParamMngr;
|
||||
@@ -513,7 +515,7 @@ private:
|
||||
static PyObject *sGetActiveTransaction (PyObject *self,PyObject *args);
|
||||
static PyObject *sCloseActiveTransaction(PyObject *self,PyObject *args);
|
||||
static PyObject *sCheckAbort(PyObject *self,PyObject *args);
|
||||
static PyMethodDef Methods[];
|
||||
static PyMethodDef Methods[];
|
||||
|
||||
friend class ApplicationObserver;
|
||||
|
||||
@@ -526,7 +528,7 @@ private:
|
||||
static Application *_pcSingleton;
|
||||
/// argument helper function
|
||||
static void ParseOptions(int argc, char ** argv);
|
||||
/// checks if the environment is allreight
|
||||
/// checks if the environment is alright
|
||||
//static void CheckEnv(void);
|
||||
/// Search for the FreeCAD home path based on argv[0]
|
||||
/*!
|
||||
|
||||
+10
-10
@@ -104,7 +104,7 @@ PyMethodDef Application::Methods[] = {
|
||||
"loadFile(string=filename,[string=module]) -> None\n\n"
|
||||
"Loads an arbitrary file by delegating to the given Python module:\n"
|
||||
"* If no module is given it will be determined by the file extension.\n"
|
||||
"* If more than one module can load a file the first one one will be taken.\n"
|
||||
"* If more than one module can load a file the first one will be taken.\n"
|
||||
"* If no module exists to load the file an exception will be raised."},
|
||||
{"open", reinterpret_cast<PyCFunction>(reinterpret_cast<void (*) (void)>( Application::sOpenDocument )), METH_VARARGS|METH_KEYWORDS,
|
||||
"See openDocument(string)"},
|
||||
@@ -174,9 +174,9 @@ PyMethodDef Application::Methods[] = {
|
||||
"active transaction causes any document changes to open a transaction with\n"
|
||||
"the given name and ID."},
|
||||
{"getActiveTransaction", (PyCFunction) Application::sGetActiveTransaction, METH_VARARGS,
|
||||
"getActiveTransaction() -> (name,id) return the current active transaction name and ID"},
|
||||
"getActiveTransaction() -> (name,id) return the current active transaction name and ID"},
|
||||
{"closeActiveTransaction", (PyCFunction) Application::sCloseActiveTransaction, METH_VARARGS,
|
||||
"closeActiveTransaction(abort=False) -- commit or abort current active transaction"},
|
||||
"closeActiveTransaction(abort=False) -- commit or abort current active transaction"},
|
||||
{"isRestoring", (PyCFunction) Application::sIsRestoring, METH_VARARGS,
|
||||
"isRestoring() -> Bool -- Test if the application is opening some document"},
|
||||
{"checkAbort", (PyCFunction) Application::sCheckAbort, METH_VARARGS,
|
||||
@@ -877,7 +877,7 @@ PyObject *Application::sGetLinksTo(PyObject * /*self*/, PyObject *args)
|
||||
auto links = GetApplication().getLinksTo(obj,options,count);
|
||||
Py::Tuple ret(links.size());
|
||||
int i=0;
|
||||
for(auto o : links)
|
||||
for(auto o : links)
|
||||
ret.setItem(i++,Py::Object(o->getPyObject(),true));
|
||||
return Py::new_reference_to(ret);
|
||||
}PY_CATCH;
|
||||
@@ -893,7 +893,7 @@ PyObject *Application::sGetDependentObjects(PyObject * /*self*/, PyObject *args)
|
||||
std::vector<App::DocumentObject*> objs;
|
||||
if(PySequence_Check(obj)) {
|
||||
Py::Sequence seq(obj);
|
||||
for(size_t i=0;i<seq.size();++i) {
|
||||
for(Py_ssize_t i=0;i<seq.size();++i) {
|
||||
if(!PyObject_TypeCheck(seq[i].ptr(),&DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
|
||||
return 0;
|
||||
@@ -901,7 +901,7 @@ PyObject *Application::sGetDependentObjects(PyObject * /*self*/, PyObject *args)
|
||||
objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
|
||||
}
|
||||
}else if(!PyObject_TypeCheck(obj,&DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Expect first argument to be either a document object or sequence of document objects");
|
||||
return 0;
|
||||
}else
|
||||
@@ -911,7 +911,7 @@ PyObject *Application::sGetDependentObjects(PyObject * /*self*/, PyObject *args)
|
||||
auto ret = App::Document::getDependencyList(objs,options);
|
||||
|
||||
Py::Tuple tuple(ret.size());
|
||||
for(size_t i=0;i<ret.size();++i)
|
||||
for(size_t i=0;i<ret.size();++i)
|
||||
tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
|
||||
return Py::new_reference_to(tuple);
|
||||
} PY_CATCH;
|
||||
@@ -924,7 +924,7 @@ PyObject *Application::sSetActiveTransaction(PyObject * /*self*/, PyObject *args
|
||||
PyObject *persist = Py_False;
|
||||
if (!PyArg_ParseTuple(args, "s|O", &name,&persist))
|
||||
return 0;
|
||||
|
||||
|
||||
PY_TRY {
|
||||
Py::Int ret(GetApplication().setActiveTransaction(name,PyObject_IsTrue(persist)));
|
||||
return Py::new_reference_to(ret);
|
||||
@@ -935,7 +935,7 @@ PyObject *Application::sGetActiveTransaction(PyObject * /*self*/, PyObject *args
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return 0;
|
||||
|
||||
|
||||
PY_TRY {
|
||||
int id = 0;
|
||||
const char *name = GetApplication().getActiveTransaction(&id);
|
||||
@@ -954,7 +954,7 @@ PyObject *Application::sCloseActiveTransaction(PyObject * /*self*/, PyObject *ar
|
||||
int id = 0;
|
||||
if (!PyArg_ParseTuple(args, "|Oi", &abort,&id))
|
||||
return 0;
|
||||
|
||||
|
||||
PY_TRY {
|
||||
GetApplication().closeActiveTransaction(PyObject_IsTrue(abort),id);
|
||||
Py_Return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2019 Zheng, Lei (realthunder) <[email protected]>*
|
||||
* Copyright (c) 2019 Zheng Lei (realthunder) <[email protected]> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -50,7 +50,7 @@ AutoTransaction::AutoTransaction(const char *name, bool tmpName) {
|
||||
// We use negative transaction guard to disable auto transaction from here
|
||||
// and any stack below. This is to support user setting active transaction
|
||||
// before having any existing AutoTransaction on stack, or 'persist'
|
||||
// transaction that can out live AutoTransaction.
|
||||
// transaction that can out live AutoTransaction.
|
||||
if(app._activeTransactionGuard<0)
|
||||
--app._activeTransactionGuard;
|
||||
else if(tid || app._activeTransactionGuard>0)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2019 Zheng, Lei (realthunder) <[email protected]>*
|
||||
* Copyright (c) 2019 Zheng Lei (realthunder) <[email protected]> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -70,10 +70,10 @@ public:
|
||||
*
|
||||
* Once disabled, any empty temporary named transaction is closed. If there
|
||||
* are non-empty or non-temporary named active transaction, it will not be
|
||||
* auto closed.
|
||||
* auto closed.
|
||||
*
|
||||
* This function may be used in, for example, Gui::Document::setEdit() to
|
||||
* allow a transaction live past any command scope.
|
||||
* allow a transaction live past any command scope.
|
||||
*/
|
||||
static void setEnable(bool enable);
|
||||
|
||||
|
||||
+12
-12
@@ -197,7 +197,7 @@ public:
|
||||
ColorField (void);
|
||||
ColorField (const ColorField &rclCF);
|
||||
ColorField (const ColorModel &rclModel, float fMin, float fMax, unsigned short usCt);
|
||||
virtual ~ColorField ();
|
||||
virtual ~ColorField ();
|
||||
|
||||
ColorField& operator = (const ColorField &rclCF);
|
||||
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
void setDirect (unsigned short usInd, Color clCol) { _aclField[usInd] = clCol; }
|
||||
float getMinValue (void) const { return _fMin; }
|
||||
float getMaxValue (void) const { return _fMax; }
|
||||
|
||||
|
||||
Color getColor (unsigned short usIndex) const { return _aclField[usIndex]; }
|
||||
inline Color getColor (float fVal) const;
|
||||
inline unsigned short getColorIndex (float fVal) const;
|
||||
@@ -281,7 +281,7 @@ public:
|
||||
|
||||
ColorGradient& operator = (const ColorGradient &rclCR);
|
||||
|
||||
void set (float fMin, float fMax, unsigned short usCt, TStyle tS, bool bOG);
|
||||
void set (float fMin, float fMax, unsigned short usCt, TStyle tS, bool bOG);
|
||||
void setRange (float fMin, float fMax) { set(fMin, fMax, _usCtColors, _tStyle, _bOutsideGrayed); }
|
||||
void getRange (float &rfMin, float &rfMax) const { rfMin = _fMin; rfMax = _fMax; }
|
||||
unsigned short getCountColors (void) const { return _usCtColors; }
|
||||
@@ -305,9 +305,9 @@ protected:
|
||||
TColorModel _tColorModel;
|
||||
TStyle _tStyle;
|
||||
float _fMin, _fMax;
|
||||
unsigned short _usCtColors;
|
||||
unsigned short _usCtColors;
|
||||
bool _bOutsideGrayed;
|
||||
ColorModel _clTotal, _clTop, _clBottom;
|
||||
ColorModel _clTotal, _clTop, _clBottom;
|
||||
|
||||
void rebuild (void);
|
||||
void setColorModel (void);
|
||||
@@ -330,7 +330,7 @@ public:
|
||||
bool addMax (const std::string &rclName);
|
||||
bool remove (unsigned long ulPos);
|
||||
void removeFirst (void);
|
||||
void removeLast (void);
|
||||
void removeLast (void);
|
||||
|
||||
Color getColor (unsigned long ulPos) const;
|
||||
uint32_t getPackedColor (unsigned long ulPos) const;
|
||||
@@ -426,10 +426,10 @@ inline Color ColorGradient::getColor (float fVal) const
|
||||
else
|
||||
return _clColFld2.getColor(fVal);
|
||||
}
|
||||
else
|
||||
else
|
||||
return _clColFld1.getColor(fVal);
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
case FLOW:
|
||||
{
|
||||
@@ -451,10 +451,10 @@ inline unsigned short ColorGradient::getColorIndex (float fVal) const
|
||||
else
|
||||
return (unsigned short)(_clColFld1.getCountColors() + _clColFld2.getColorIndex(fVal));
|
||||
}
|
||||
else
|
||||
else
|
||||
return _clColFld1.getColorIndex(fVal);
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
case FLOW:
|
||||
{
|
||||
@@ -464,7 +464,7 @@ inline unsigned short ColorGradient::getColorIndex (float fVal) const
|
||||
}
|
||||
|
||||
inline const ColorModel& ColorGradient::getColorModel (void) const
|
||||
{
|
||||
{
|
||||
if ( _tStyle == ZERO_BASED )
|
||||
{
|
||||
if ( _fMax <= 0.0f )
|
||||
@@ -482,4 +482,4 @@ inline const ColorModel& ColorGradient::getColorModel (void) const
|
||||
|
||||
} // namespace App
|
||||
|
||||
#endif // APP_COLORMODEL_H
|
||||
#endif // APP_COLORMODEL_H
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
|
||||
public:
|
||||
struct Line {uint32_t I1; uint32_t I2;};
|
||||
struct Facet {uint32_t I1; uint32_t I2; uint32_t I3;};
|
||||
@@ -109,11 +109,11 @@ public:
|
||||
* using the setTransform() method.
|
||||
*/
|
||||
void setPlacement(const Base::Placement& rclPlacement);
|
||||
/** Return the current transformation as placement using
|
||||
/** Return the current transformation as placement using
|
||||
* getTransform().
|
||||
*/
|
||||
Base::Placement getPlacement() const;
|
||||
/** Override the current transformation with the new one.
|
||||
/** Override the current transformation with the new one.
|
||||
* This method has to be handled by the child classes.
|
||||
* the actual placement and matrix is not part of this class.
|
||||
*/
|
||||
@@ -201,7 +201,7 @@ protected:
|
||||
/// from local to inside
|
||||
inline Base::Vector3f transformToInside(const Base::Vector3d& vec) const
|
||||
{
|
||||
Base::Matrix4D tmpM(getTransform());
|
||||
Base::Matrix4D tmpM(getTransform());
|
||||
tmpM.inverse();
|
||||
Base::Vector3d tmp = tmpM * vec;
|
||||
return Base::Vector3f((float)tmp.x,(float)tmp.y,(float)tmp.z);
|
||||
|
||||
@@ -141,5 +141,5 @@ PyObject *ComplexGeoDataPy::getCustomAttributes(const char* /*attr*/) const
|
||||
|
||||
int ComplexGeoDataPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+49
-43
@@ -26,7 +26,7 @@
|
||||
\ingroup APP
|
||||
\brief The Base class of the FreeCAD Document
|
||||
|
||||
This is (besides the App::Application class) the most important class in FreeCAD.
|
||||
This (besides the App::Application class) is the most important class in FreeCAD.
|
||||
It contains all the data of the opened, saved, or newly created FreeCAD Document.
|
||||
The App::Document manages the Undo and Redo mechanism and the linking of documents.
|
||||
|
||||
@@ -70,7 +70,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees.
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost_graph_adjacency_list.hpp>
|
||||
#include <boost/graph/subgraph.hpp>
|
||||
#include <boost/graph/graphviz.hpp>
|
||||
#include <boost/graph/strong_components.hpp>
|
||||
@@ -189,7 +189,7 @@ struct DocumentP
|
||||
std::map<DocumentObject*,Vertex> VertexObjectList;
|
||||
std::map<Vertex,DocumentObject*> vertexMap;
|
||||
#endif //USE_OLD_DAG
|
||||
std::multimap<const App::DocumentObject*,
|
||||
std::multimap<const App::DocumentObject*,
|
||||
std::unique_ptr<App::DocumentObjectExecReturn> > _RecomputeLog;
|
||||
|
||||
DocumentP() {
|
||||
@@ -199,7 +199,7 @@ struct DocumentP
|
||||
// Set some random offset to reduce likelihood of ID collision when
|
||||
// copying shape from other document. It is probably better to randomize
|
||||
// on each object ID.
|
||||
lastObjectId = _RDIST(_RGEN);
|
||||
lastObjectId = _RDIST(_RGEN);
|
||||
activeObject = 0;
|
||||
activeUndoTransaction = 0;
|
||||
iTransactionMode = 0;
|
||||
@@ -1047,7 +1047,7 @@ bool Document::redo(int id)
|
||||
|
||||
void Document::addOrRemovePropertyOfObject(TransactionalObject* obj, Property *prop, bool add)
|
||||
{
|
||||
if (!prop || !obj || !obj->isAttachedToDocument())
|
||||
if (!prop || !obj || !obj->isAttachedToDocument())
|
||||
return;
|
||||
if(d->iUndoMode && !isPerformingTransaction() && !d->activeUndoTransaction) {
|
||||
if(!testStatus(Restoring) || testStatus(Importing)) {
|
||||
@@ -1128,9 +1128,9 @@ int Document::_openTransaction(const char* name, int id)
|
||||
|
||||
auto &app = GetApplication();
|
||||
auto activeDoc = app.getActiveDocument();
|
||||
if(activeDoc &&
|
||||
activeDoc!=this &&
|
||||
!activeDoc->hasPendingTransaction())
|
||||
if(activeDoc &&
|
||||
activeDoc!=this &&
|
||||
!activeDoc->hasPendingTransaction())
|
||||
{
|
||||
std::string aname("-> ");
|
||||
aname += d->activeUndoTransaction->Name;
|
||||
@@ -1165,11 +1165,11 @@ void Document::_checkTransaction(DocumentObject* pcDelObj, const Property *What,
|
||||
if(What && What->testStatus(Property::NoModify))
|
||||
ignore = true;
|
||||
if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
|
||||
if(What)
|
||||
FC_LOG((ignore?"ignore":"auto") << " transaction ("
|
||||
<< line << ") '" << What->getFullName());
|
||||
if(What)
|
||||
FC_LOG((ignore?"ignore":"auto") << " transaction ("
|
||||
<< line << ") '" << What->getFullName());
|
||||
else
|
||||
FC_LOG((ignore?"ignore":"auto") <<" transaction ("
|
||||
FC_LOG((ignore?"ignore":"auto") <<" transaction ("
|
||||
<< line << ") '" << name << "' in " << getName());
|
||||
}
|
||||
if(!ignore)
|
||||
@@ -1254,7 +1254,7 @@ void Document::abortTransaction() {
|
||||
FC_WARN("Cannot abort transaction while transacting");
|
||||
return;
|
||||
}
|
||||
if (d->activeUndoTransaction)
|
||||
if (d->activeUndoTransaction)
|
||||
GetApplication().closeActiveTransaction(true,d->activeUndoTransaction->getID());
|
||||
}
|
||||
|
||||
@@ -1620,7 +1620,7 @@ Document::Document(const char *name)
|
||||
|
||||
ADD_PROPERTY_TYPE(License,(license.c_str()),0,Prop_None,"License string of the Item");
|
||||
ADD_PROPERTY_TYPE(LicenseURL,(licenseUrl.c_str()),0,Prop_None,"URL to the license text/contract");
|
||||
ADD_PROPERTY_TYPE(ShowHidden,(false), 0,PropertyType(Prop_None),
|
||||
ADD_PROPERTY_TYPE(ShowHidden,(false), 0,PropertyType(Prop_None),
|
||||
"Whether to show hidden object items in the tree view");
|
||||
|
||||
// this creates and sets 'TransientDir' in onChanged()
|
||||
@@ -1883,7 +1883,7 @@ void Document::writeObjects(const std::vector<App::DocumentObject*>& obj,
|
||||
for(auto o : obj) {
|
||||
const auto &outList = o->getOutList(DocumentObject::OutListNoHidden
|
||||
| DocumentObject::OutListNoXLinked);
|
||||
writer.Stream() << writer.ind()
|
||||
writer.Stream() << writer.ind()
|
||||
<< "<" FC_ELEMENT_OBJECT_DEPS " " FC_ATTR_DEP_OBJ_NAME "=\""
|
||||
<< o->getNameInDocument() << "\" " FC_ATTR_DEP_COUNT "=\"" << outList.size();
|
||||
if(outList.empty()) {
|
||||
@@ -1923,7 +1923,7 @@ void Document::writeObjects(const std::vector<App::DocumentObject*>& obj,
|
||||
if ((*it)->testStatus(ObjectStatus::Error)) {
|
||||
writer.Stream() << "Invalid=\"1\" ";
|
||||
auto desc = getErrorDescription(*it);
|
||||
if(desc)
|
||||
if(desc)
|
||||
writer.Stream() << "Error=\"" << Property::encodeAttribute(desc) << "\" ";
|
||||
}
|
||||
writer.Stream() << "/>" << endl;
|
||||
@@ -1956,9 +1956,9 @@ struct DepInfo {
|
||||
int canLoadPartial = 0;
|
||||
};
|
||||
|
||||
static void _loadDeps(const std::string &name,
|
||||
std::unordered_map<std::string,bool> &objs,
|
||||
const std::unordered_map<std::string,DepInfo> &deps)
|
||||
static void _loadDeps(const std::string &name,
|
||||
std::unordered_map<std::string,bool> &objs,
|
||||
const std::unordered_map<std::string,DepInfo> &deps)
|
||||
{
|
||||
auto it = deps.find(name);
|
||||
if(it == deps.end()) {
|
||||
@@ -2098,7 +2098,7 @@ Document::readObjects(Base::XMLReader& reader)
|
||||
}
|
||||
if (reader.hasAttribute("Invalid")) {
|
||||
obj->setStatus(ObjectStatus::Error, reader.getAttributeAsInteger("Invalid") != 0);
|
||||
if(obj->isError() && reader.hasAttribute("Error"))
|
||||
if(obj->isError() && reader.hasAttribute("Error"))
|
||||
d->addRecomputeLog(reader.getAttribute("Error"),obj);
|
||||
}
|
||||
}
|
||||
@@ -2745,6 +2745,7 @@ void Document::restore (const char *filename,
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("Invalid Document.xml: %s\n", e.what());
|
||||
setStatus(Document::RestoreError, true);
|
||||
}
|
||||
|
||||
d->partialLoadObjects.clear();
|
||||
@@ -2777,7 +2778,7 @@ void Document::afterRestore(bool checkPartial) {
|
||||
setStatus(Document::Restoring, false);
|
||||
}
|
||||
|
||||
bool Document::afterRestore(const std::vector<DocumentObject *> &objArray, bool checkPartial)
|
||||
bool Document::afterRestore(const std::vector<DocumentObject *> &objArray, bool checkPartial)
|
||||
{
|
||||
checkPartial = checkPartial && testStatus(Document::PartialDoc);
|
||||
if(checkPartial && d->touchedObjs.size())
|
||||
@@ -2797,7 +2798,7 @@ bool Document::afterRestore(const std::vector<DocumentObject *> &objArray, bool
|
||||
try {
|
||||
prop->afterRestore();
|
||||
} catch (const Base::Exception& e) {
|
||||
FC_ERR("Failed to restore " << obj->getFullName()
|
||||
FC_ERR("Failed to restore " << obj->getFullName()
|
||||
<< '.' << prop->getName() << ": " << e.what());
|
||||
}
|
||||
}
|
||||
@@ -2864,7 +2865,7 @@ bool Document::afterRestore(const std::vector<DocumentObject *> &objArray, bool
|
||||
if(checkPartial && d->touchedObjs.size()) {
|
||||
// partial document touched, signal full reload
|
||||
return false;
|
||||
} else if(!d->touchedObjs.count(obj))
|
||||
} else if(!d->touchedObjs.count(obj))
|
||||
obj->purgeTouched();
|
||||
|
||||
signalFinishRestoreObject(*obj);
|
||||
@@ -2955,9 +2956,9 @@ int Document::countObjects(void) const
|
||||
return static_cast<int>(d->objectArray.size());
|
||||
}
|
||||
|
||||
void Document::getLinksTo(std::set<DocumentObject*> &links,
|
||||
void Document::getLinksTo(std::set<DocumentObject*> &links,
|
||||
const DocumentObject *obj, int options, int maxCount,
|
||||
const std::vector<DocumentObject*> &objs) const
|
||||
const std::vector<DocumentObject*> &objs) const
|
||||
{
|
||||
std::map<const App::DocumentObject*, std::vector<App::DocumentObject*> > linkMap;
|
||||
|
||||
@@ -2968,7 +2969,7 @@ void Document::getLinksTo(std::set<DocumentObject*> &links,
|
||||
linked = o->getLinkedObject(false);
|
||||
else {
|
||||
auto ext = o->getExtensionByType<LinkBaseExtension>(true);
|
||||
if(ext)
|
||||
if(ext)
|
||||
linked = ext->getTrueLinkedObject(false,0,0,true);
|
||||
else
|
||||
linked = o->getLinkedObject(false);
|
||||
@@ -3052,8 +3053,8 @@ std::vector<App::DocumentObject*> Document::getInList(const DocumentObject* me)
|
||||
// external object.
|
||||
//
|
||||
static void _buildDependencyList(const std::vector<App::DocumentObject*> &objectArray,
|
||||
int options, std::vector<App::DocumentObject*> *depObjs,
|
||||
DependencyList *depList, std::map<DocumentObject*,Vertex> *objectMap,
|
||||
int options, std::vector<App::DocumentObject*> *depObjs,
|
||||
DependencyList *depList, std::map<DocumentObject*,Vertex> *objectMap,
|
||||
bool *touchCheck = 0)
|
||||
{
|
||||
std::map<DocumentObject*, std::vector<DocumentObject*> > outLists;
|
||||
@@ -3132,7 +3133,7 @@ std::vector<App::DocumentObject*> Document::getDependencyList(
|
||||
std::map<int,std::vector<Vertex> > components;
|
||||
boost::strong_components(depList,boost::make_iterator_property_map(
|
||||
c.begin(),boost::get(boost::vertex_index,depList),c[0]));
|
||||
for(size_t i=0;i<c.size();++i)
|
||||
for(size_t i=0;i<c.size();++i)
|
||||
components[c[i]].push_back(i);
|
||||
|
||||
FC_ERR("Dependency cycles: ");
|
||||
@@ -3184,7 +3185,7 @@ std::vector<App::Document*> Document::getDependentDocuments(bool sort) {
|
||||
}
|
||||
|
||||
std::vector<App::Document*> Document::getDependentDocuments(
|
||||
std::vector<App::Document*> pending, bool sort)
|
||||
std::vector<App::Document*> pending, bool sort)
|
||||
{
|
||||
DependencyList depList;
|
||||
std::map<Document*,Vertex> docMap;
|
||||
@@ -3409,7 +3410,7 @@ int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool forc
|
||||
|
||||
#else //ifdef USE_OLD_DAG
|
||||
|
||||
int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool force, bool *hasError, int options)
|
||||
int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool force, bool *hasError, int options)
|
||||
{
|
||||
if (d->undoing || d->rollback) {
|
||||
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
|
||||
@@ -3419,7 +3420,7 @@ int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool forc
|
||||
|
||||
int objectCount = 0;
|
||||
if (testStatus(Document::PartialDoc)) {
|
||||
if(mustExecute())
|
||||
if(mustExecute())
|
||||
FC_WARN("Please reload partial document '" << Label.getValue() << "' for recomputation.");
|
||||
return 0;
|
||||
}
|
||||
@@ -3445,7 +3446,7 @@ int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool forc
|
||||
|
||||
#if 0
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FIXME Comment by Realthunder:
|
||||
// FIXME Comment by Realthunder:
|
||||
// the topologicalSrot() below cannot handle partial recompute, haven't got
|
||||
// time to figure out the code yet, simply use back boost::topological_sort
|
||||
// for now, that is, rely on getDependencyList() to do the sorting. The
|
||||
@@ -3483,7 +3484,7 @@ int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool forc
|
||||
if(canAbort)
|
||||
seq.reset(new Base::SequencerLauncher("Recompute...", topoSortedObjects.size()));
|
||||
FC_LOG("Recompute pass " << passes);
|
||||
for (;idx<topoSortedObjects.size();(seq?seq->next(true):true),++idx) {
|
||||
for (; idx < topoSortedObjects.size(); ++idx) {
|
||||
auto obj = topoSortedObjects[idx];
|
||||
if(!obj->getNameInDocument() || filter.find(obj)!=filter.end())
|
||||
continue;
|
||||
@@ -3514,13 +3515,15 @@ int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool forc
|
||||
for (auto inObjIt : obj->getInList())
|
||||
inObjIt->enforceRecompute();
|
||||
}
|
||||
if (seq)
|
||||
seq->next(true);
|
||||
}
|
||||
// check if all objects are recomputed but still thouched
|
||||
// check if all objects are recomputed but still thouched
|
||||
for (size_t i=0;i<topoSortedObjects.size();++i) {
|
||||
auto obj = topoSortedObjects[i];
|
||||
obj->setStatus(ObjectStatus::Recompute2,false);
|
||||
if(!filter.count(obj) && obj->isTouched()) {
|
||||
if(passes>0)
|
||||
if(passes>0)
|
||||
FC_ERR(obj->getFullName() << " still touched after recompute");
|
||||
else{
|
||||
FC_LOG(obj->getFullName() << " still touched after recompute");
|
||||
@@ -3808,7 +3811,7 @@ bool Document::recomputeFeature(DocumentObject* Feat, bool recursive)
|
||||
return false;
|
||||
}
|
||||
|
||||
DocumentObject * Document::addObject(const char* sType, const char* pObjectName,
|
||||
DocumentObject * Document::addObject(const char* sType, const char* pObjectName,
|
||||
bool isNew, const char* viewType, bool isPartial)
|
||||
{
|
||||
Base::BaseClass* base = static_cast<Base::BaseClass*>(Base::Type::createInstanceByName(sType,true));
|
||||
@@ -4154,6 +4157,11 @@ void Document::removeObject(const char* sName)
|
||||
TipName.setValue("");
|
||||
}
|
||||
|
||||
// remove the ID before possibly deleting the object
|
||||
d->objectIdMap.erase(pos->second->_Id);
|
||||
// Unset the bit to be on the safe side
|
||||
pos->second->setStatus(ObjectStatus::Remove, false);
|
||||
|
||||
// do no transactions if we do a rollback!
|
||||
std::unique_ptr<DocumentObject> tobedestroyed;
|
||||
if (!d->rollback) {
|
||||
@@ -4177,8 +4185,6 @@ void Document::removeObject(const char* sName)
|
||||
}
|
||||
}
|
||||
|
||||
pos->second->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side
|
||||
d->objectIdMap.erase(pos->second->_Id);
|
||||
d->objectMap.erase(pos);
|
||||
}
|
||||
|
||||
@@ -4331,7 +4337,7 @@ std::vector<DocumentObject*> Document::copyObject(
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*>
|
||||
std::vector<App::DocumentObject*>
|
||||
Document::importLinks(const std::vector<App::DocumentObject*> &objArray)
|
||||
{
|
||||
std::set<App::DocumentObject*> links;
|
||||
@@ -4395,7 +4401,7 @@ Document::importLinks(const std::vector<App::DocumentObject*> &objArray)
|
||||
// properties, e.g. a link sub referring to some sub object of an xlink, If
|
||||
// that sub object is imported with a different name, and xlink is changed
|
||||
// before this link sub, it will break.
|
||||
for(auto &v : propMap)
|
||||
for(auto &v : propMap)
|
||||
v.first->Paste(*v.second);
|
||||
|
||||
return objs;
|
||||
@@ -4422,13 +4428,13 @@ DocumentObject* Document::moveObject(DocumentObject* obj, bool recursive)
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> deps;
|
||||
if(recursive)
|
||||
if(recursive)
|
||||
deps = getDependencyList({obj},DepNoXLinked|DepSort);
|
||||
else
|
||||
deps.push_back(obj);
|
||||
|
||||
auto objs = copyObject(deps,false);
|
||||
if(objs.empty())
|
||||
if(objs.empty())
|
||||
return 0;
|
||||
// Some object may delete its children if deleted, so we collect the IDs
|
||||
// or all depending objects for safety reason.
|
||||
|
||||
+10
-9
@@ -37,7 +37,7 @@
|
||||
#include <stack>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
|
||||
namespace Base {
|
||||
class Writer;
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
PartialDoc = 7,
|
||||
AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set
|
||||
TempDoc = 9, // Mark as temporary document without prompt for save
|
||||
RestoreError = 10
|
||||
};
|
||||
|
||||
/** @name Properties */
|
||||
@@ -193,7 +194,7 @@ public:
|
||||
bool saveAs(const char* file);
|
||||
bool saveCopy(const char* file) const;
|
||||
/// Restore the document from the file in Property Path
|
||||
void restore (const char *filename=0,
|
||||
void restore (const char *filename=0,
|
||||
bool delaySignal=false, const std::set<std::string> &objNames={});
|
||||
void afterRestore(bool checkPartial=false);
|
||||
bool afterRestore(const std::vector<App::DocumentObject *> &, bool checkPartial=false);
|
||||
@@ -209,7 +210,7 @@ public:
|
||||
*
|
||||
* @param objs: input list of objects. Only objects belonging to this document will
|
||||
* be checked for external links. And all found external linked object will be imported
|
||||
* to this document. Link type properties of those input objects will be automatically
|
||||
* to this document. Link type properties of those input objects will be automatically
|
||||
* reassigned to the imported objects. Note that the link properties of other objects
|
||||
* in the document but not included in the input list, will not be affected even if they
|
||||
* point to some object beining imported. To import all objects, simply pass in all objects
|
||||
@@ -228,7 +229,7 @@ public:
|
||||
/// Get program version the project file was created with
|
||||
const char* getProgramVersion() const;
|
||||
/** Returned filename
|
||||
*
|
||||
*
|
||||
* For saved document, this will be the content stored in property
|
||||
* 'Filename'. For unsaved temporary file, this will be the content of
|
||||
* property 'TransientDir'.
|
||||
@@ -252,7 +253,7 @@ public:
|
||||
* @param viewType override object's view provider name
|
||||
* @param isPartial indicate if this object is meant to be partially loaded
|
||||
*/
|
||||
DocumentObject *addObject(const char* sType, const char* pObjectName=0,
|
||||
DocumentObject *addObject(const char* sType, const char* pObjectName=0,
|
||||
bool isNew=true, const char *viewType=0, bool isPartial=false);
|
||||
/** Add an array of features of the given types and names.
|
||||
* Unicode names are set through the Label property.
|
||||
@@ -356,7 +357,7 @@ public:
|
||||
//@}
|
||||
|
||||
|
||||
/** @name methods for the UNDO REDO and Transaction handling
|
||||
/** @name methods for the UNDO REDO and Transaction handling
|
||||
*
|
||||
* Introduce a new concept of transaction ID. Each transaction must be
|
||||
* unique inside the document. Multiple transactions from different
|
||||
@@ -447,13 +448,13 @@ public:
|
||||
/// Raise exception on cycles
|
||||
DepNoCycle = 4,
|
||||
};
|
||||
/** Get a complete list of all objects the given objects depend on.
|
||||
/** Get a complete list of all objects the given objects depend on.
|
||||
*
|
||||
* This function is defined as static because it accepts objects from
|
||||
* different documents, and the returned list will contain dependent
|
||||
* objects from all relevant documents
|
||||
*
|
||||
* @param objs: input objects to query for dependency.
|
||||
* @param objs: input objects to query for dependency.
|
||||
* @param options: See DependencyOption
|
||||
*/
|
||||
static std::vector<App::DocumentObject*> getDependencyList(
|
||||
@@ -482,7 +483,7 @@ public:
|
||||
* @param objs: optional objects to search for, if empty, then all objects
|
||||
* of this document are searched.
|
||||
*/
|
||||
void getLinksTo(std::set<DocumentObject*> &links,
|
||||
void getLinksTo(std::set<DocumentObject*> &links,
|
||||
const DocumentObject *obj, int options, int maxCount=0,
|
||||
const std::vector<DocumentObject*> &objs = {}) const;
|
||||
|
||||
|
||||
@@ -108,7 +108,20 @@ App::DocumentObjectExecReturn *DocumentObject::recompute(void)
|
||||
|
||||
// set/unset the execution bit
|
||||
Base::ObjectStatusLocker<ObjectStatus, DocumentObject> exe(App::Recompute, this);
|
||||
return this->execute();
|
||||
|
||||
// mark the object to recompute its extensions
|
||||
this->setStatus(App::RecomputeExtension, true);
|
||||
|
||||
auto ret = this->execute();
|
||||
if (ret == StdReturn) {
|
||||
// most feature classes don't call the execute() method of its base class
|
||||
// so execute the extensions now
|
||||
if (this->testStatus(App::RecomputeExtension)) {
|
||||
ret = executeExtensions();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DocumentObjectExecReturn *DocumentObject::execute(void)
|
||||
@@ -119,6 +132,7 @@ DocumentObjectExecReturn *DocumentObject::execute(void)
|
||||
App::DocumentObjectExecReturn* DocumentObject::executeExtensions()
|
||||
{
|
||||
//execute extensions but stop on error
|
||||
this->setStatus(App::RecomputeExtension, false); // reset the flag
|
||||
auto vector = getExtensionsDerivedFromType<App::DocumentObjectExtension>();
|
||||
for(auto ext : vector) {
|
||||
auto ret = ext->extensionExecute();
|
||||
@@ -668,7 +682,7 @@ bool DocumentObject::removeDynamicProperty(const char* name)
|
||||
}
|
||||
|
||||
for (auto it : removeExpr) {
|
||||
ExpressionEngine.setValue(it, boost::shared_ptr<Expression>());
|
||||
ExpressionEngine.setValue(it, std::shared_ptr<Expression>());
|
||||
}
|
||||
|
||||
return TransactionalObject::removeDynamicProperty(name);
|
||||
@@ -898,7 +912,7 @@ void DocumentObject::Save (Base::Writer &writer) const
|
||||
* @param expr Expression tree
|
||||
*/
|
||||
|
||||
void DocumentObject::setExpression(const ObjectIdentifier &path, boost::shared_ptr<Expression> expr)
|
||||
void DocumentObject::setExpression(const ObjectIdentifier &path, std::shared_ptr<Expression> expr)
|
||||
{
|
||||
ExpressionEngine.setValue(path, expr);
|
||||
}
|
||||
|
||||
+20
-19
@@ -36,7 +36,7 @@
|
||||
|
||||
#include <unordered_map>
|
||||
#include <bitset>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
|
||||
namespace App
|
||||
{
|
||||
@@ -65,6 +65,7 @@ enum ObjectStatus {
|
||||
Expand = 16, // indicate the object's tree item expansion status
|
||||
NoAutoExpand = 17, // disable tree item auto expand on selection for this object
|
||||
PendingTransactionUpdate = 18, // mark that the object expects a call to onUndoRedoFinished() after transaction is finished.
|
||||
RecomputeExtension = 19, // mark the object to recompute its extensions
|
||||
};
|
||||
|
||||
/** Return object for feature execution
|
||||
@@ -183,14 +184,14 @@ public:
|
||||
*/
|
||||
//@{
|
||||
/** Set sub-element visibility
|
||||
*
|
||||
*
|
||||
* For performance reason, \c element must not contain any further
|
||||
* sub-elements, i.e. there should be no '.' inside \c element.
|
||||
*
|
||||
* @return -1 if element visibility is not supported, 0 if element is not
|
||||
* found, 1 if success
|
||||
*/
|
||||
virtual int setElementVisible(const char *element, bool visible);
|
||||
virtual int setElementVisible(const char *element, bool visible);
|
||||
|
||||
/** Get sub-element visibility
|
||||
*
|
||||
@@ -246,7 +247,7 @@ public:
|
||||
* @param inList [in, out]: optional pointer to a vector holding the output
|
||||
* objects, with the furthest linking object ordered last.
|
||||
*/
|
||||
void getInListEx(std::set<App::DocumentObject*> &inSet,
|
||||
void getInListEx(std::set<App::DocumentObject*> &inSet,
|
||||
bool recursive, std::vector<App::DocumentObject*> *inList=0) const;
|
||||
/** Return a set of all objects linking to this object, including possible external parent objects
|
||||
* @param recursive [in]: whether to obtain recursive in list
|
||||
@@ -334,10 +335,10 @@ public:
|
||||
* include the transformation applied by the final object reference in \c
|
||||
* subname. For Part::Feature, the transformation is applied to the
|
||||
* TopoShape inside \c pyObj before returning.
|
||||
*
|
||||
*
|
||||
* @param transform: if false, then it will not apply the object's own
|
||||
* transformation to \c mat, which lets you override the object's placement
|
||||
* (and possibly scale).
|
||||
* (and possibly scale).
|
||||
*
|
||||
* @param depth: depth limitation as hint for cyclic link detection
|
||||
*
|
||||
@@ -345,7 +346,7 @@ public:
|
||||
* then it shall return itself. If subname is invalid, then it shall return
|
||||
* zero.
|
||||
*/
|
||||
virtual DocumentObject *getSubObject(const char *subname, PyObject **pyObj=0,
|
||||
virtual DocumentObject *getSubObject(const char *subname, PyObject **pyObj=0,
|
||||
Base::Matrix4D *mat=0, bool transform=true, int depth=0) const;
|
||||
|
||||
/// Return a list of objects referenced by a given subname including this object
|
||||
@@ -380,13 +381,13 @@ public:
|
||||
std::vector<std::pair<App::DocumentObject*,std::string> > getParents(int depth=0) const;
|
||||
|
||||
/** Return the linked object with optional transformation
|
||||
*
|
||||
*
|
||||
* @param recurse: If false, return the immediate linked object, or else
|
||||
* recursively call this function to return the final linked object.
|
||||
*
|
||||
* @param mat: If non zero, it is used as the current transformation matrix
|
||||
* on input. And output as the accumulated transformation till the final
|
||||
* linked object.
|
||||
* linked object.
|
||||
*
|
||||
* @param transform: if false, then it will not accumulate the object's own
|
||||
* placement into \c mat, which lets you override the object's placement.
|
||||
@@ -394,7 +395,7 @@ public:
|
||||
* @return Return the linked object. This function must return itself if the
|
||||
* it is not a link or the link is invalid.
|
||||
*/
|
||||
virtual DocumentObject *getLinkedObject(bool recurse=true,
|
||||
virtual DocumentObject *getLinkedObject(bool recurse=true,
|
||||
Base::Matrix4D *mat=0, bool transform=false, int depth=0) const;
|
||||
|
||||
/* Return true to cause PropertyView to show linked object's property */
|
||||
@@ -407,7 +408,7 @@ public:
|
||||
*
|
||||
* @param newLabel: input as the new label, which can be modified by object itself
|
||||
*
|
||||
* This function is is called before onBeforeChange()
|
||||
* This function is called before onBeforeChange()
|
||||
*/
|
||||
virtual void onBeforeChangeLabel(std::string &newLabel) {(void)newLabel;}
|
||||
|
||||
@@ -421,7 +422,7 @@ public:
|
||||
|
||||
/* Expression support */
|
||||
|
||||
virtual void setExpression(const ObjectIdentifier & path, boost::shared_ptr<App::Expression> expr);
|
||||
virtual void setExpression(const ObjectIdentifier & path, std::shared_ptr<App::Expression> expr);
|
||||
|
||||
virtual const PropertyExpressionEngine::ExpressionInfo getExpression(const ObjectIdentifier &path) const;
|
||||
|
||||
@@ -441,10 +442,10 @@ public:
|
||||
short attr=0, bool ro=false, bool hidden=false) override;
|
||||
|
||||
/** Resolve the last document object referenced in the subname
|
||||
*
|
||||
*
|
||||
* @param subname: dot separated subname
|
||||
* @param parent: return the direct parent of the object
|
||||
* @param childName: return child name to be passed to is/setElementVisible()
|
||||
* @param childName: return child name to be passed to is/setElementVisible()
|
||||
* @param subElement: return non-object sub-element name if found. The
|
||||
* pointer is guaranteed to be within the buffer pointed to by 'subname'
|
||||
*
|
||||
@@ -452,7 +453,7 @@ public:
|
||||
* @return Returns the last referenced document object in the subname. If no
|
||||
* such object in subname, return pObject.
|
||||
*/
|
||||
App::DocumentObject *resolve(const char *subname, App::DocumentObject **parent=0,
|
||||
App::DocumentObject *resolve(const char *subname, App::DocumentObject **parent=0,
|
||||
std::string *childName=0, const char **subElement=0,
|
||||
PyObject **pyObj=0, Base::Matrix4D *mat=0, bool transform=true, int depth=0) const;
|
||||
|
||||
@@ -500,7 +501,7 @@ public:
|
||||
*
|
||||
* The common parent 'Group' is removed.
|
||||
*/
|
||||
App::DocumentObject *resolveRelativeLink(std::string &subname,
|
||||
App::DocumentObject *resolveRelativeLink(std::string &subname,
|
||||
App::DocumentObject *&link, std::string &linkSub) const;
|
||||
|
||||
/** Called to adjust link properties to avoid cyclic links
|
||||
@@ -533,7 +534,7 @@ public:
|
||||
/** Allow object to redirect a subname path
|
||||
*
|
||||
* @param ss: input as the current subname path from \a topParent leading
|
||||
* just before this object, i.e. ends at the parent of this object. This
|
||||
* just before this object, i.e. ends at the parent of this object. This
|
||||
* function should append its own name to this path, or redirect the
|
||||
* subname to other place.
|
||||
* @param topParent: top parent of this subname path
|
||||
@@ -541,7 +542,7 @@ public:
|
||||
*
|
||||
* This function is called by tree view to generate a subname path when an
|
||||
* item is selected in the tree. Document object can use this function to
|
||||
* redirect the selection to some other objects.
|
||||
* redirect the selection to some other objects.
|
||||
*/
|
||||
virtual bool redirectSubName(std::ostringstream &ss,
|
||||
DocumentObject *topParent, DocumentObject *child) const;
|
||||
@@ -628,7 +629,7 @@ private:
|
||||
|
||||
// unique identifier (among a document) of this object.
|
||||
long _Id;
|
||||
|
||||
|
||||
private:
|
||||
// Back pointer to all the fathers in a DAG of the document
|
||||
// this is used by the document (via friend) to have a effective DAG handling
|
||||
|
||||
@@ -35,7 +35,7 @@ using namespace App;
|
||||
|
||||
EXTENSION_PROPERTY_SOURCE(App::DocumentObjectExtension, App::Extension)
|
||||
|
||||
DocumentObjectExtension::DocumentObjectExtension()
|
||||
DocumentObjectExtension::DocumentObjectExtension()
|
||||
{
|
||||
initExtensionType(App::DocumentObjectExtension::getExtensionClassTypeId());
|
||||
}
|
||||
@@ -46,7 +46,7 @@ DocumentObjectExtension::~DocumentObjectExtension()
|
||||
}
|
||||
|
||||
short int DocumentObjectExtension::extensionMustExecute(void) {
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -64,15 +64,15 @@ void DocumentObjectExtension::onExtendedDocumentRestored() {
|
||||
}
|
||||
|
||||
void DocumentObjectExtension::onExtendedSetupObject() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DocumentObjectExtension::onExtendedUnsetupObject() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
PyObject* DocumentObjectExtension::getExtensionPyObject(void) {
|
||||
|
||||
|
||||
if (ExtensionPythonObject.is(Py::_None())){
|
||||
// ref counter is set to 1
|
||||
ExtensionPythonObject = Py::Object(new DocumentObjectExtensionPy(this),true);
|
||||
@@ -82,17 +82,17 @@ PyObject* DocumentObjectExtension::getExtensionPyObject(void) {
|
||||
|
||||
const DocumentObject* DocumentObjectExtension::getExtendedObject() const {
|
||||
|
||||
assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId()));
|
||||
assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId()));
|
||||
return static_cast<const DocumentObject*>(getExtendedContainer());
|
||||
}
|
||||
|
||||
DocumentObject* DocumentObjectExtension::getExtendedObject() {
|
||||
|
||||
assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId()));
|
||||
assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId()));
|
||||
return static_cast<DocumentObject*>(getExtendedContainer());
|
||||
}
|
||||
|
||||
bool DocumentObjectExtension::extensionGetSubObject(DocumentObject *&,
|
||||
bool DocumentObjectExtension::extensionGetSubObject(DocumentObject *&,
|
||||
const char *, PyObject **, Base::Matrix4D *, bool, int) const
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
#include "DocumentObject.h"
|
||||
|
||||
namespace App {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Extension with special document object calls
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AppExport DocumentObjectExtension : public App::Extension
|
||||
{
|
||||
@@ -47,12 +47,12 @@ public:
|
||||
|
||||
App::DocumentObject* getExtendedObject();
|
||||
const App::DocumentObject* getExtendedObject() const;
|
||||
|
||||
|
||||
//override if execution is necessary
|
||||
virtual short extensionMustExecute(void);
|
||||
virtual App::DocumentObjectExecReturn *extensionExecute(void);
|
||||
|
||||
|
||||
|
||||
|
||||
/// get called after setting the document
|
||||
virtual void onExtendedSettingDocument();
|
||||
/// get called after a document has been fully restored
|
||||
@@ -63,8 +63,8 @@ public:
|
||||
virtual void onExtendedUnsetupObject();
|
||||
|
||||
virtual PyObject* getExtensionPyObject(void) override;
|
||||
|
||||
/// returns the type name of the ViewProviderExtension which is automatically attached
|
||||
|
||||
/// returns the type name of the ViewProviderExtension which is automatically attached
|
||||
/// to the viewprovider object when it is initiated
|
||||
virtual const char* getViewProviderExtensionName(void) const {return "";}
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
*
|
||||
* @return Return turn if handled, the sub object is returned in \c ret
|
||||
*/
|
||||
virtual bool extensionGetSubObject( DocumentObject *&ret, const char *subname,
|
||||
virtual bool extensionGetSubObject( DocumentObject *&ret, const char *subname,
|
||||
PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const;
|
||||
|
||||
/** Get name references of all sub objects
|
||||
|
||||
@@ -34,7 +34,7 @@ using namespace App;
|
||||
PROPERTY_SOURCE(App::DocumentObjectFileIncluded, App::DocumentObject)
|
||||
|
||||
|
||||
DocumentObjectFileIncluded::DocumentObjectFileIncluded()
|
||||
DocumentObjectFileIncluded::DocumentObjectFileIncluded()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(File,(0),"",(App::PropertyType)(Prop_None),"File to include into Project File");
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ public:
|
||||
DocumentObjectFileIncluded(void);
|
||||
virtual ~DocumentObjectFileIncluded();
|
||||
|
||||
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "Gui::ViewProviderDocumentObject";
|
||||
}
|
||||
|
||||
|
||||
/// Properties
|
||||
PropertyFileIncluded File;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ PyObject *DocumentObjectGroup::getPyObject()
|
||||
// Python feature ---------------------------------------------------------
|
||||
|
||||
namespace App {
|
||||
|
||||
|
||||
/// @cond DOXERR
|
||||
PROPERTY_SOURCE_TEMPLATE(App::DocumentObjectGroupPython, App::DocumentObjectGroup)
|
||||
template<> const char* App::DocumentObjectGroupPython::getViewProviderName(void) const {
|
||||
|
||||
@@ -33,21 +33,21 @@
|
||||
|
||||
namespace App
|
||||
{
|
||||
|
||||
|
||||
class AppExport DocumentObjectGroup : public DocumentObject, public GroupExtension {
|
||||
|
||||
|
||||
PROPERTY_HEADER_WITH_EXTENSIONS(App::DocumentObjectGroup);
|
||||
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
DocumentObjectGroup(void);
|
||||
virtual ~DocumentObjectGroup();
|
||||
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const override{
|
||||
return "Gui::ViewProviderDocumentObjectGroup";
|
||||
}
|
||||
|
||||
|
||||
virtual PyObject *getPyObject(void) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -65,6 +65,20 @@
|
||||
<UserDocu>recompute(recursive=False): Recomputes this object</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getStatusString" const="True">
|
||||
<Documentation>
|
||||
<UserDocu>Returns the status of the object as string.
|
||||
If the object is invalid its error description will be returned.
|
||||
If the object is valid but touched then 'Touched' will be returned,
|
||||
'Valid' otherwise.
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="isValid" const="True">
|
||||
<Documentation>
|
||||
<UserDocu>Returns True if the object is valid, False otherwise</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getSubObject" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
|
||||
@@ -329,7 +329,7 @@ PyObject* DocumentObjectPy::setExpression(PyObject * args)
|
||||
App::ObjectIdentifier p(ObjectIdentifier::parse(getDocumentObjectPtr(), path));
|
||||
|
||||
if (Py::Object(expr).isNone())
|
||||
getDocumentObjectPtr()->setExpression(p, boost::shared_ptr<Expression>());
|
||||
getDocumentObjectPtr()->setExpression(p, std::shared_ptr<Expression>());
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
else if (PyUnicode_Check(expr)) {
|
||||
const char * exprStr = PyUnicode_AsUTF8(expr);
|
||||
@@ -337,7 +337,7 @@ PyObject* DocumentObjectPy::setExpression(PyObject * args)
|
||||
else if (PyString_Check(expr)) {
|
||||
const char * exprStr = PyString_AsString(expr);
|
||||
#endif
|
||||
boost::shared_ptr<Expression> shared_expr(Expression::parse(getDocumentObjectPtr(), exprStr));
|
||||
std::shared_ptr<Expression> shared_expr(Expression::parse(getDocumentObjectPtr(), exprStr));
|
||||
if(shared_expr && comment)
|
||||
shared_expr->comment = comment;
|
||||
|
||||
@@ -351,7 +351,7 @@ PyObject* DocumentObjectPy::setExpression(PyObject * args)
|
||||
if (unicode) {
|
||||
std::string exprStr = PyString_AsString(unicode);
|
||||
Py_DECREF(unicode);
|
||||
boost::shared_ptr<Expression> shared_expr(ExpressionParser::parse(getDocumentObjectPtr(), exprStr.c_str()));
|
||||
std::shared_ptr<Expression> shared_expr(ExpressionParser::parse(getDocumentObjectPtr(), exprStr.c_str()));
|
||||
|
||||
if(shared_expr && comment)
|
||||
shared_expr->comment = comment;
|
||||
@@ -375,7 +375,7 @@ PyObject* DocumentObjectPy::evalExpression(PyObject * args)
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
PY_TRY {
|
||||
boost::shared_ptr<Expression> shared_expr(Expression::parse(getDocumentObjectPtr(), expr));
|
||||
std::shared_ptr<Expression> shared_expr(Expression::parse(getDocumentObjectPtr(), expr));
|
||||
if(shared_expr)
|
||||
return Py::new_reference_to(shared_expr->getPyValue());
|
||||
Py_Return;
|
||||
@@ -397,6 +397,34 @@ PyObject* DocumentObjectPy::recompute(PyObject *args)
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* DocumentObjectPy::isValid(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
bool ok = getDocumentObjectPtr()->isValid();
|
||||
return Py_BuildValue("O", (ok ? Py_True : Py_False));
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
throw Py::RuntimeError(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* DocumentObjectPy::getStatusString(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
Py::String text(getDocumentObjectPtr()->getStatusString());
|
||||
return Py::new_reference_to(text);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
throw Py::RuntimeError(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds)
|
||||
{
|
||||
PyObject *obj;
|
||||
|
||||
@@ -24,11 +24,10 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <functional>
|
||||
# include <sstream>
|
||||
#endif
|
||||
|
||||
#include <boost_bind_bind.hpp>
|
||||
|
||||
#include <Base/Tools.h>
|
||||
#include "Application.h"
|
||||
#include "Document.h"
|
||||
@@ -38,7 +37,7 @@
|
||||
#include "GeoFeature.h"
|
||||
|
||||
using namespace App;
|
||||
namespace bp = boost::placeholders;
|
||||
namespace sp = std::placeholders;
|
||||
|
||||
|
||||
DocumentT::DocumentT()
|
||||
@@ -249,7 +248,7 @@ const std::string &DocumentObjectT::getPropertyName() const {
|
||||
std::string DocumentObjectT::getPropertyPython() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "FreeCAD.getDocument('" << document
|
||||
str << "FreeCAD.getDocument('" << document
|
||||
<< "').getObject('" << object
|
||||
<< "')";
|
||||
if(property.size())
|
||||
@@ -364,7 +363,7 @@ std::string SubObjectT::getOldElementName(int *index) const {
|
||||
if(!obj)
|
||||
return std::string();
|
||||
GeoFeature::resolveElement(obj,subname.c_str(),element);
|
||||
if(!index)
|
||||
if(!index)
|
||||
return std::move(element.second);
|
||||
std::size_t pos = element.second.find_first_of("0123456789");
|
||||
if(pos == std::string::npos)
|
||||
@@ -405,8 +404,8 @@ class DocumentWeakPtrT::Private {
|
||||
public:
|
||||
Private(App::Document* doc) : _document(doc) {
|
||||
if (doc) {
|
||||
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(boost::bind
|
||||
(&Private::deletedDocument, this, bp::_1));
|
||||
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(std::bind
|
||||
(&Private::deletedDocument, this, sp::_1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,13 +482,13 @@ public:
|
||||
object = obj;
|
||||
if (obj) {
|
||||
indocument = true;
|
||||
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(boost::bind
|
||||
(&Private::deletedDocument, this, bp::_1));
|
||||
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(std::bind
|
||||
(&Private::deletedDocument, this, sp::_1));
|
||||
App::Document* doc = obj->getDocument();
|
||||
connectDocumentCreatedObject = doc->signalNewObject.connect(boost::bind
|
||||
(&Private::createdObject, this, bp::_1));
|
||||
connectDocumentDeletedObject = doc->signalDeletedObject.connect(boost::bind
|
||||
(&Private::deletedObject, this, bp::_1));
|
||||
connectDocumentCreatedObject = doc->signalNewObject.connect(std::bind
|
||||
(&Private::createdObject, this, sp::_1));
|
||||
connectDocumentDeletedObject = doc->signalDeletedObject.connect(std::bind
|
||||
(&Private::deletedObject, this, sp::_1));
|
||||
}
|
||||
}
|
||||
App::DocumentObject* get() const noexcept {
|
||||
@@ -555,19 +554,19 @@ bool DocumentObjectWeakPtrT::operator!= (const DocumentObjectWeakPtrT& p) const
|
||||
|
||||
DocumentObserver::DocumentObserver() : _document(nullptr)
|
||||
{
|
||||
this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect(boost::bind
|
||||
(&DocumentObserver::slotCreatedDocument, this, bp::_1));
|
||||
this->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(boost::bind
|
||||
(&DocumentObserver::slotDeletedDocument, this, bp::_1));
|
||||
this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect(std::bind
|
||||
(&DocumentObserver::slotCreatedDocument, this, sp::_1));
|
||||
this->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(std::bind
|
||||
(&DocumentObserver::slotDeletedDocument, this, sp::_1));
|
||||
}
|
||||
|
||||
DocumentObserver::DocumentObserver(Document* doc) : _document(nullptr)
|
||||
{
|
||||
// Connect to application and given document
|
||||
this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect(boost::bind
|
||||
(&DocumentObserver::slotCreatedDocument, this, bp::_1));
|
||||
this->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(boost::bind
|
||||
(&DocumentObserver::slotDeletedDocument, this, bp::_1));
|
||||
this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect(std::bind
|
||||
(&DocumentObserver::slotCreatedDocument, this, sp::_1));
|
||||
this->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(std::bind
|
||||
(&DocumentObserver::slotDeletedDocument, this, sp::_1));
|
||||
attachDocument(doc);
|
||||
}
|
||||
|
||||
@@ -590,16 +589,16 @@ void DocumentObserver::attachDocument(Document* doc)
|
||||
detachDocument();
|
||||
_document = doc;
|
||||
|
||||
this->connectDocumentCreatedObject = _document->signalNewObject.connect(boost::bind
|
||||
(&DocumentObserver::slotCreatedObject, this, bp::_1));
|
||||
this->connectDocumentDeletedObject = _document->signalDeletedObject.connect(boost::bind
|
||||
(&DocumentObserver::slotDeletedObject, this, bp::_1));
|
||||
this->connectDocumentChangedObject = _document->signalChangedObject.connect(boost::bind
|
||||
(&DocumentObserver::slotChangedObject, this, bp::_1, bp::_2));
|
||||
this->connectDocumentRecomputedObject = _document->signalRecomputedObject.connect(boost::bind
|
||||
(&DocumentObserver::slotRecomputedObject, this, bp::_1));
|
||||
this->connectDocumentRecomputed = _document->signalRecomputed.connect(boost::bind
|
||||
(&DocumentObserver::slotRecomputedDocument, this, bp::_1));
|
||||
this->connectDocumentCreatedObject = _document->signalNewObject.connect(std::bind
|
||||
(&DocumentObserver::slotCreatedObject, this, sp::_1));
|
||||
this->connectDocumentDeletedObject = _document->signalDeletedObject.connect(std::bind
|
||||
(&DocumentObserver::slotDeletedObject, this, sp::_1));
|
||||
this->connectDocumentChangedObject = _document->signalChangedObject.connect(std::bind
|
||||
(&DocumentObserver::slotChangedObject, this, sp::_1, sp::_2));
|
||||
this->connectDocumentRecomputedObject = _document->signalRecomputedObject.connect(std::bind
|
||||
(&DocumentObserver::slotRecomputedObject, this, sp::_1));
|
||||
this->connectDocumentRecomputed = _document->signalRecomputed.connect(std::bind
|
||||
(&DocumentObserver::slotRecomputedDocument, this, sp::_1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#define APP_DOCUMENTOBSERVER_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <string>
|
||||
|
||||
@@ -111,13 +111,13 @@ private:
|
||||
void slotBeforeAddingDynamicExtension(const App::ExtensionContainer&, std::string extension);
|
||||
/** Called when an object gets a dynamic extension added*/
|
||||
void slotAddedDynamicExtension(const App::ExtensionContainer&, std::string extension);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Py::Object inst;
|
||||
static std::vector<DocumentObserverPython*> _instances;
|
||||
|
||||
typedef struct {
|
||||
typedef struct PythonObject {
|
||||
boost::signals2::scoped_connection slot;
|
||||
Py::Object py;
|
||||
PyObject* ptr() {
|
||||
|
||||
+40
-40
@@ -91,8 +91,8 @@ PyObject* DocumentPy::saveAs(PyObject * args)
|
||||
PyObject* DocumentPy::saveCopy(PyObject * args)
|
||||
{
|
||||
char* fn;
|
||||
if (!PyArg_ParseTuple(args, "s", &fn)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "s", &fn)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
PY_TRY {
|
||||
getDocumentPtr()->saveCopy(fn);
|
||||
@@ -127,8 +127,8 @@ PyObject* DocumentPy::load(PyObject * args)
|
||||
|
||||
PyObject* DocumentPy::restore(PyObject * args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
const char* filename = getDocumentPtr()->FileName.getValue();
|
||||
if (!filename || *filename == '\0') {
|
||||
PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set");
|
||||
@@ -151,8 +151,8 @@ PyObject* DocumentPy::restore(PyObject * args)
|
||||
PyObject* DocumentPy::mergeProject(PyObject * args)
|
||||
{
|
||||
char* filename;
|
||||
if (!PyArg_ParseTuple(args, "s", &filename)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "s", &filename)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
PY_TRY {
|
||||
Base::FileInfo fi(filename);
|
||||
@@ -167,8 +167,8 @@ PyObject* DocumentPy::mergeProject(PyObject * args)
|
||||
PyObject* DocumentPy::exportGraphviz(PyObject * args)
|
||||
{
|
||||
char* fn=0;
|
||||
if (!PyArg_ParseTuple(args, "|s",&fn)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "|s",&fn)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (fn) {
|
||||
Base::FileInfo fi(fn);
|
||||
Base::ofstream str(fi);
|
||||
@@ -194,9 +194,9 @@ PyObject* DocumentPy::addObject(PyObject *args, PyObject *kwd)
|
||||
PyObject* view=0;
|
||||
PyObject *attach=Py_False;
|
||||
static char *kwlist[] = {"type","name","objProxy","viewProxy","attach","viewType",NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args,kwd,"s|sOOOs",
|
||||
if (!PyArg_ParseTupleAndKeywords(args,kwd,"s|sOOOs",
|
||||
kwlist, &sType,&sName,&obj,&view,&attach,&sViewType))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
DocumentObject *pcFtr = 0;
|
||||
|
||||
@@ -300,7 +300,7 @@ PyObject* DocumentPy::copyObject(PyObject *args)
|
||||
bool single = false;
|
||||
if (PySequence_Check(obj)) {
|
||||
Py::Sequence seq(obj);
|
||||
for (size_t i=0;i<seq.size();++i) {
|
||||
for (Py_ssize_t i=0;i<seq.size();++i) {
|
||||
if (!PyObject_TypeCheck(seq[i].ptr(),&DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
|
||||
return 0;
|
||||
@@ -309,7 +309,7 @@ PyObject* DocumentPy::copyObject(PyObject *args)
|
||||
}
|
||||
}
|
||||
else if (!PyObject_TypeCheck(obj,&DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Expect first argument to be either a document object or sequence of document objects");
|
||||
return 0;
|
||||
}
|
||||
@@ -324,7 +324,7 @@ PyObject* DocumentPy::copyObject(PyObject *args)
|
||||
return ret[0]->getPyObject();
|
||||
|
||||
Py::Tuple tuple(ret.size());
|
||||
for (size_t i=0;i<ret.size();++i)
|
||||
for (size_t i=0;i<ret.size();++i)
|
||||
tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
|
||||
return Py::new_reference_to(tuple);
|
||||
} PY_CATCH
|
||||
@@ -339,7 +339,7 @@ PyObject* DocumentPy::importLinks(PyObject *args)
|
||||
std::vector<App::DocumentObject*> objs;
|
||||
if (PySequence_Check(obj)) {
|
||||
Py::Sequence seq(obj);
|
||||
for (size_t i=0;i<seq.size();++i) {
|
||||
for (Py_ssize_t i=0;i<seq.size();++i) {
|
||||
if (!PyObject_TypeCheck(seq[i].ptr(),&DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
|
||||
return 0;
|
||||
@@ -351,14 +351,14 @@ PyObject* DocumentPy::importLinks(PyObject *args)
|
||||
// do nothing here
|
||||
}
|
||||
else if (!PyObject_TypeCheck(obj,&DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Expect first argument to be either a document object or sequence of document objects");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
|
||||
}
|
||||
|
||||
|
||||
if (objs.empty())
|
||||
objs = getDocumentPtr()->getObjects();
|
||||
|
||||
@@ -366,7 +366,7 @@ PyObject* DocumentPy::importLinks(PyObject *args)
|
||||
auto ret = getDocumentPtr()->importLinks(objs);
|
||||
|
||||
Py::Tuple tuple(ret.size());
|
||||
for (size_t i=0;i<ret.size();++i)
|
||||
for (size_t i=0;i<ret.size();++i)
|
||||
tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
|
||||
return Py::new_reference_to(tuple);
|
||||
} PY_CATCH
|
||||
@@ -420,21 +420,21 @@ PyObject* DocumentPy::openTransaction(PyObject *args)
|
||||
}
|
||||
|
||||
getDocumentPtr()->openTransaction(cmd.c_str());
|
||||
Py_Return;
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* DocumentPy::abortTransaction(PyObject * args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
getDocumentPtr()->abortTransaction();
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* DocumentPy::commitTransaction(PyObject * args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
getDocumentPtr()->commitTransaction();
|
||||
Py_Return;
|
||||
}
|
||||
@@ -445,8 +445,8 @@ Py::Boolean DocumentPy::getHasPendingTransaction() const {
|
||||
|
||||
PyObject* DocumentPy::undo(PyObject * args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (getDocumentPtr()->getAvailableUndos())
|
||||
getDocumentPtr()->undo();
|
||||
Py_Return;
|
||||
@@ -454,8 +454,8 @@ PyObject* DocumentPy::undo(PyObject * args)
|
||||
|
||||
PyObject* DocumentPy::redo(PyObject * args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (getDocumentPtr()->getAvailableRedos())
|
||||
getDocumentPtr()->redo();
|
||||
Py_Return;
|
||||
@@ -463,8 +463,8 @@ PyObject* DocumentPy::redo(PyObject * args)
|
||||
|
||||
PyObject* DocumentPy::clearUndos(PyObject * args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
getDocumentPtr()->clearUndos();
|
||||
Py_Return;
|
||||
}
|
||||
@@ -487,7 +487,7 @@ PyObject* DocumentPy::recompute(PyObject * args)
|
||||
}
|
||||
|
||||
Py::Sequence seq(pyobjs);
|
||||
for (size_t i=0;i<seq.size();++i) {
|
||||
for (Py_ssize_t i=0;i<seq.size();++i) {
|
||||
if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
|
||||
return nullptr;
|
||||
@@ -516,9 +516,9 @@ PyObject* DocumentPy::getObject(PyObject *args)
|
||||
{
|
||||
long id = -1;
|
||||
char *sName = 0;
|
||||
if (!PyArg_ParseTuple(args, "s",&sName)) { // convert args: Python->C
|
||||
if (!PyArg_ParseTuple(args, "s",&sName)) { // convert args: Python->C
|
||||
if (!PyArg_ParseTuple(args, "l", &id))
|
||||
return NULL; // NULL triggers exception
|
||||
return NULL; // NULL triggers exception
|
||||
}
|
||||
|
||||
DocumentObject *pcFtr = sName?getDocumentPtr()->getObject(sName):getDocumentPtr()->getObjectByID(id);
|
||||
@@ -531,8 +531,8 @@ PyObject* DocumentPy::getObject(PyObject *args)
|
||||
PyObject* DocumentPy::getObjectsByLabel(PyObject *args)
|
||||
{
|
||||
char *sName;
|
||||
if (!PyArg_ParseTuple(args, "s",&sName)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
if (!PyArg_ParseTuple(args, "s",&sName)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
Py::List list;
|
||||
std::string name = sName;
|
||||
@@ -575,7 +575,7 @@ PyObject* DocumentPy::findObjects(PyObject *args, PyObject *kwds)
|
||||
}
|
||||
|
||||
Py_ssize_t index=0;
|
||||
PyObject* list = PyList_New((Py_ssize_t)res.size());
|
||||
PyObject* list = PyList_New((Py_ssize_t)res.size());
|
||||
for (std::vector<DocumentObject*>::const_iterator It = res.begin();It != res.end();++It, index++)
|
||||
PyList_SetItem(list, index, (*It)->getPyObject());
|
||||
return list;
|
||||
@@ -591,9 +591,9 @@ Py::Object DocumentPy::getActiveObject(void) const
|
||||
|
||||
PyObject* DocumentPy::supportedTypes(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
|
||||
std::vector<Base::Type> ary;
|
||||
Base::Type::getAllDerivedFrom(App::DocumentObject::getClassTypeId(), ary);
|
||||
Py::List res;
|
||||
@@ -602,7 +602,7 @@ PyObject* DocumentPy::supportedTypes(PyObject *args)
|
||||
return Py::new_reference_to(res);
|
||||
}
|
||||
|
||||
Py::List DocumentPy::getObjects(void) const
|
||||
Py::List DocumentPy::getObjects(void) const
|
||||
{
|
||||
std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
|
||||
Py::List res;
|
||||
@@ -733,7 +733,7 @@ PyObject* DocumentPy::getTempFileName(PyObject *args)
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
|
||||
// search for a temp file name in the document transient directory
|
||||
// search for a temp file name in the document transient directory
|
||||
Base::FileInfo fileName(Base::FileInfo::getTempFileName
|
||||
(string.c_str(),getDocumentPtr()->TransientDir.getValue()));
|
||||
// delete the created file, we need only the name...
|
||||
@@ -785,7 +785,7 @@ int DocumentPy::setCustomAttributes(const char* attr, PyObject *)
|
||||
if (obj)
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "'Document' object attribute '" << attr
|
||||
str << "'Document' object attribute '" << attr
|
||||
<< "' must not be set this way" << std::ends;
|
||||
PyErr_SetString(PyExc_RuntimeError, str.str().c_str());
|
||||
return -1;
|
||||
@@ -815,7 +815,7 @@ PyObject* DocumentPy::getLinksTo(PyObject *args)
|
||||
getDocumentPtr()->getLinksTo(links,obj,options,count);
|
||||
Py::Tuple ret(links.size());
|
||||
int i=0;
|
||||
for (auto o : links)
|
||||
for (auto o : links)
|
||||
ret.setItem(i++,Py::Object(o->getPyObject(),true));
|
||||
return Py::new_reference_to(ret);
|
||||
} PY_CATCH
|
||||
|
||||
@@ -85,7 +85,7 @@ std::vector<std::string> DynamicProperty::getDynamicPropertyNames() const
|
||||
std::vector<std::string> names;
|
||||
auto &index = props.get<0>();
|
||||
names.reserve(index.size());
|
||||
for(auto &v : index)
|
||||
for(auto &v : index)
|
||||
names.push_back(v.name);
|
||||
return names;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ const char* DynamicProperty::getPropertyDocumentation(const char *name) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
Property* DynamicProperty::addDynamicProperty(PropertyContainer &pc, const char* type,
|
||||
Property* DynamicProperty::addDynamicProperty(PropertyContainer &pc, const char* type,
|
||||
const char* name, const char* group, const char* doc, short attr, bool ro, bool hidden)
|
||||
{
|
||||
Base::BaseClass* base = static_cast<Base::BaseClass*>(Base::Type::createInstanceByName(type,true));
|
||||
@@ -217,6 +217,8 @@ bool DynamicProperty::removeDynamicProperty(const char* name)
|
||||
GetApplication().signalRemoveDynamicProperty(*prop);
|
||||
Property::destroy(prop);
|
||||
index.erase(it);
|
||||
// memory of myName has been freed
|
||||
prop->myName = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -246,7 +248,7 @@ std::string DynamicProperty::getUniquePropertyName(PropertyContainer &pc, const
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicProperty::save(const Property *prop, Base::Writer &writer) const
|
||||
void DynamicProperty::save(const Property *prop, Base::Writer &writer) const
|
||||
{
|
||||
auto &index = props.get<1>();
|
||||
auto it = index.find(const_cast<Property*>(prop));
|
||||
@@ -259,8 +261,8 @@ void DynamicProperty::save(const Property *prop, Base::Writer &writer) const
|
||||
}
|
||||
}
|
||||
|
||||
Property *DynamicProperty::restore(PropertyContainer &pc,
|
||||
const char *PropName, const char *TypeName, Base::XMLReader &reader)
|
||||
Property *DynamicProperty::restore(PropertyContainer &pc,
|
||||
const char *PropName, const char *TypeName, Base::XMLReader &reader)
|
||||
{
|
||||
if (!reader.hasAttribute("group"))
|
||||
return 0;
|
||||
|
||||
@@ -3258,16 +3258,16 @@ static void initParser(const App::DocumentObject *owner)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<boost::tuple<int, int, std::string> > tokenize(const std::string &str)
|
||||
std::vector<std::tuple<int, int, std::string> > tokenize(const std::string &str)
|
||||
{
|
||||
ExpressionParser::YY_BUFFER_STATE buf = ExpressionParser_scan_string(str.c_str());
|
||||
std::vector<boost::tuple<int, int, std::string> > result;
|
||||
std::vector<std::tuple<int, int, std::string> > result;
|
||||
int token;
|
||||
|
||||
column = 0;
|
||||
try {
|
||||
while ( (token = ExpressionParserlex()) != 0)
|
||||
result.push_back(boost::make_tuple(token, ExpressionParser::last_column, yytext));
|
||||
result.push_back(std::make_tuple(token, ExpressionParser::last_column, yytext));
|
||||
}
|
||||
catch (...) {
|
||||
// Ignore all exceptions
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define EXPRESSION_H
|
||||
|
||||
#include <string>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <tuple>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Unit.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||
* Copyright (c) 2019 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
|
||||
* Copyright (c) 2019 Zheng Lei (realthunder) <realthunder.dev@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -127,8 +127,8 @@ protected:
|
||||
class AppExport ConstantExpression : public NumberExpression {
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
public:
|
||||
ConstantExpression(const App::DocumentObject *_owner = 0,
|
||||
const char *_name = "",
|
||||
ConstantExpression(const App::DocumentObject *_owner = 0,
|
||||
const char *_name = "",
|
||||
const Base::Quantity &_quantity = Base::Quantity());
|
||||
|
||||
std::string getName() const { return name; }
|
||||
@@ -287,7 +287,7 @@ public:
|
||||
LAST,
|
||||
};
|
||||
|
||||
FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE,
|
||||
FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE,
|
||||
std::string &&name = std::string(), std::vector<Expression *> _args = std::vector<Expression*>());
|
||||
|
||||
virtual ~FunctionExpression();
|
||||
@@ -352,10 +352,10 @@ protected:
|
||||
virtual void _updateLabelReference(App::DocumentObject *, const std::string &, const char *) override;
|
||||
virtual bool _updateElementReference(App::DocumentObject *,bool,ExpressionVisitor &) override;
|
||||
virtual bool _relabeledDocument(const std::string &, const std::string &, ExpressionVisitor &) override;
|
||||
virtual bool _renameObjectIdentifier(const std::map<ObjectIdentifier,ObjectIdentifier> &,
|
||||
virtual bool _renameObjectIdentifier(const std::map<ObjectIdentifier,ObjectIdentifier> &,
|
||||
const ObjectIdentifier &, ExpressionVisitor &) override;
|
||||
virtual void _collectReplacement(std::map<ObjectIdentifier,ObjectIdentifier> &,
|
||||
const App::DocumentObject *parent, App::DocumentObject *oldObj,
|
||||
virtual void _collectReplacement(std::map<ObjectIdentifier,ObjectIdentifier> &,
|
||||
const App::DocumentObject *parent, App::DocumentObject *oldObj,
|
||||
App::DocumentObject *newObj) const override;
|
||||
virtual void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override;
|
||||
virtual void _offsetCells(int, int, ExpressionVisitor &) override;
|
||||
@@ -435,7 +435,7 @@ protected:
|
||||
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
|
||||
virtual Py::Object _getPyValue() const override;
|
||||
virtual void _getDeps(ExpressionDeps &) const override;
|
||||
virtual bool _renameObjectIdentifier(const std::map<ObjectIdentifier,ObjectIdentifier> &,
|
||||
virtual bool _renameObjectIdentifier(const std::map<ObjectIdentifier,ObjectIdentifier> &,
|
||||
const ObjectIdentifier &, ExpressionVisitor &) override;
|
||||
virtual void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override;
|
||||
virtual void _offsetCells(int, int, ExpressionVisitor &) override;
|
||||
@@ -451,7 +451,7 @@ AppExport UnitExpression * parseUnit(const App::DocumentObject *owner, const cha
|
||||
AppExport ObjectIdentifier parsePath(const App::DocumentObject *owner, const char* buffer);
|
||||
AppExport bool isTokenAnIndentifier(const std::string & str);
|
||||
AppExport bool isTokenAUnit(const std::string & str);
|
||||
AppExport std::vector<boost::tuple<int, int, std::string> > tokenize(const std::string & str);
|
||||
AppExport std::vector<std::tuple<int, int, std::string> > tokenize(const std::string & str);
|
||||
|
||||
/// Convenient class to mark begin of importing
|
||||
class AppExport ExpressionImporter {
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
%{
|
||||
/* Lexer for the FreeCAD Expression language */
|
||||
/* (c) 2010 Jürgen Riegel LGPL */
|
||||
/* (c) 2015 Eivind Kvedalen LGPL */
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2010 Jürgen Riegel <[email protected]> *
|
||||
* Copyright (c) 2015 Eivind Kvedalen <[email protected]> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/* Lexer for the FreeCAD Expression language */
|
||||
|
||||
/* This disables inclusion of unistd.h, which is not available under Visual C++
|
||||
* on Win32. The C++ scanner uses STL streams instead. */
|
||||
@@ -28,7 +48,7 @@ extern int column;
|
||||
/* the manual says "somewhat more optimized" */
|
||||
%option batch
|
||||
|
||||
%option never-interactive
|
||||
%option never-interactive
|
||||
|
||||
/* no support for include files is planned */
|
||||
%option noyywrap nounput
|
||||
@@ -211,7 +231,7 @@ EXPO [eE][-+]?[0-9]+
|
||||
"yd" COUNTCHARS; yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = yytext; return UNIT; // yard
|
||||
"mi" COUNTCHARS; yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = yytext; return UNIT; // mile
|
||||
|
||||
"mph" COUNTCHARS; yylval.quantity.scaler = Quantity::MilePerHour; yylval.quantity.unitStr = yytext; return UNIT; // mile per hour
|
||||
"mph" COUNTCHARS; yylval.quantity.scaler = Quantity::MilePerHour; yylval.quantity.unitStr = yytext; return UNIT; // mile per hour
|
||||
"sqft" COUNTCHARS; yylval.quantity.scaler = Quantity::SquareFoot; yylval.quantity.unitStr = yytext; return UNIT; // square foot
|
||||
"cft" COUNTCHARS; yylval.quantity.scaler = Quantity::CubicFoot; yylval.quantity.unitStr = yytext; return UNIT; // cubic foot
|
||||
|
||||
@@ -254,6 +274,8 @@ EXPO [eE][-+]?[0-9]+
|
||||
"kV" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloVolt; yylval.quantity.unitStr = yytext; return UNIT; // kilo Volt
|
||||
"mV" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliVolt; yylval.quantity.unitStr = yytext; return UNIT; // milli Volt
|
||||
|
||||
"MS" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaSiemens; yylval.quantity.unitStr = yytext; return UNIT; // mega Siemens
|
||||
"kS" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloSiemens; yylval.quantity.unitStr = yytext; return UNIT; // kilo Siemens
|
||||
"S" COUNTCHARS; yylval.quantity.scaler = Quantity::Siemens; yylval.quantity.unitStr = yytext; return UNIT; // Siemens (A^2*s^3/kg/m^2)
|
||||
"mS" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliSiemens; yylval.quantity.unitStr = yytext; return UNIT; // milli Siemens
|
||||
"uS" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroSiemens; yylval.quantity.unitStr = yytext; return UNIT; // micro Siemens
|
||||
@@ -343,7 +365,7 @@ $[A-Za-z]{1,2}{DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDR
|
||||
std::map<std::string, FunctionExpression::Function>::const_iterator j = registered_functions.find(s);
|
||||
if (j != registered_functions.end())
|
||||
yylval.func.first = j->second;
|
||||
else
|
||||
else
|
||||
{ yylval.func.first = FunctionExpression::NONE; yylval.func.second = std::move(s); }
|
||||
return FUNC;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# Description for bash script
|
||||
flex -olex.ExpressionParser.c < ExpressionParser.l
|
||||
bison -oExpressionParser.tab.c ExpressionParser.y
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
/* Parser for the FreeCAD Units language */
|
||||
/* (c) 2010 Jürgen Riegel LGPL */
|
||||
/* (c) 2015 Eivind Kvedalen LGPL */
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2010 Jürgen Riegel <[email protected]> *
|
||||
* Copyright (c) 2015 Eivind Kvedalen <[email protected]> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/* Parser for the FreeCAD Units language */
|
||||
/* Represents the many different ways we can access our data */
|
||||
|
||||
|
||||
%{
|
||||
|
||||
#define YYSTYPE App::ExpressionParser::semantic_type
|
||||
|
||||
+22
-22
@@ -34,9 +34,9 @@
|
||||
#include <Base/Console.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
#include <ExtensionPy.h>
|
||||
|
||||
|
||||
/* We do not use a standard property macro for type initiation. The reason is that we have the first
|
||||
* PropertyData in the extension chain, there is no parent property data.
|
||||
* PropertyData in the extension chain, there is no parent property data.
|
||||
*/
|
||||
EXTENSION_TYPESYSTEM_SOURCE_P(App::Extension)
|
||||
const App::PropertyData * App::Extension::extensionGetPropertyDataPtr(void){return &propertyData;}
|
||||
@@ -45,15 +45,15 @@ App::PropertyData App::Extension::propertyData;
|
||||
void App::Extension::init(void){
|
||||
|
||||
assert(Extension::classTypeId == Base::Type::badType() && "don't init() twice!");
|
||||
|
||||
/* Set up entry in the type system. */
|
||||
Extension::classTypeId = Base::Type::createType(Base::Type::badType(), "App::Extension",
|
||||
Extension::create);
|
||||
|
||||
/* Set up entry in the type system. */
|
||||
Extension::classTypeId = Base::Type::createType(Base::Type::badType(), "App::Extension",
|
||||
Extension::create);
|
||||
}
|
||||
|
||||
using namespace App;
|
||||
|
||||
Extension::Extension()
|
||||
Extension::Extension()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -82,14 +82,14 @@ void Extension::initExtension(ExtensionContainer* obj) {
|
||||
|
||||
if (m_extensionType.isBad())
|
||||
throw Base::RuntimeError("Extension: Extension type not set");
|
||||
|
||||
|
||||
//all properties are initialised without PropertyContainer father. Now that we know it we can
|
||||
//finally finish the property initialisation
|
||||
std::vector<Property*> list;
|
||||
extensionGetPropertyData().getPropertyList(this, list);
|
||||
for(Property* prop : list)
|
||||
prop->setContainer(obj);
|
||||
|
||||
|
||||
m_base = obj;
|
||||
m_base->registerExtension( m_extensionType, this );
|
||||
}
|
||||
@@ -106,10 +106,10 @@ PyObject* Extension::getExtensionPyObject(void) {
|
||||
}
|
||||
|
||||
std::string Extension::name() const {
|
||||
|
||||
|
||||
if (m_extensionType.isBad())
|
||||
throw Base::RuntimeError("Extension::name: Extension type not set");
|
||||
|
||||
|
||||
std::string temp(m_extensionType.getName());
|
||||
std::string::size_type pos = temp.find_last_of(':');
|
||||
|
||||
@@ -122,48 +122,48 @@ std::string Extension::name() const {
|
||||
|
||||
|
||||
Property* Extension::extensionGetPropertyByName(const char* name) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getPropertyByName(this, name);
|
||||
}
|
||||
|
||||
short int Extension::extensionGetPropertyType(const Property* prop) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getType(this, prop);
|
||||
}
|
||||
|
||||
short int Extension::extensionGetPropertyType(const char* name) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getType(this, name);
|
||||
}
|
||||
|
||||
const char* Extension::extensionGetPropertyName(const Property* prop) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getName(this,prop);
|
||||
}
|
||||
|
||||
const char* Extension::extensionGetPropertyGroup(const Property* prop) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getGroup(this,prop);
|
||||
}
|
||||
|
||||
const char* Extension::extensionGetPropertyGroup(const char* name) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getGroup(this,name);
|
||||
}
|
||||
|
||||
|
||||
const char* Extension::extensionGetPropertyDocumentation(const Property* prop) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getDocumentation(this, prop);
|
||||
}
|
||||
|
||||
const char* Extension::extensionGetPropertyDocumentation(const char* name) const {
|
||||
|
||||
|
||||
return extensionGetPropertyData().getDocumentation(this, name);
|
||||
}
|
||||
|
||||
void Extension::extensionGetPropertyList(std::vector< Property* >& List) const {
|
||||
|
||||
|
||||
extensionGetPropertyData().getPropertyList(this, List);
|
||||
}
|
||||
|
||||
@@ -172,13 +172,13 @@ void Extension::extensionGetPropertyMap(std::map< std::string, Property* >& Map)
|
||||
extensionGetPropertyData().getPropertyMap(this, Map);
|
||||
}
|
||||
|
||||
void Extension::initExtensionSubclass(Base::Type& toInit, const char* ClassName, const char* ParentName,
|
||||
void Extension::initExtensionSubclass(Base::Type& toInit, const char* ClassName, const char* ParentName,
|
||||
Base::Type::instantiationMethod method) {
|
||||
|
||||
// don't init twice!
|
||||
assert(toInit == Base::Type::badType());
|
||||
// get the parent class
|
||||
Base::Type parentType(Base::Type::fromName(ParentName));
|
||||
Base::Type parentType(Base::Type::fromName(ParentName));
|
||||
// forgot init parent!
|
||||
assert(parentType != Base::Type::badType() );
|
||||
|
||||
|
||||
+76
-80
@@ -31,7 +31,7 @@
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
namespace App {
|
||||
|
||||
|
||||
class ExtensionContainer;
|
||||
|
||||
/// define Extension types
|
||||
@@ -53,7 +53,7 @@ public: \
|
||||
static void *create(void);\
|
||||
private: \
|
||||
static Base::Type classTypeId
|
||||
|
||||
|
||||
/// define to implement a subclass of Base::BaseClass
|
||||
#define EXTENSION_TYPESYSTEM_SOURCE_P(_class_) \
|
||||
Base::Type _class_::getExtensionClassTypeId(void) { return _class_::classTypeId; } \
|
||||
@@ -122,105 +122,105 @@ template<> void _class_::init(void){\
|
||||
initExtensionSubclass(_class_::classTypeId, #_class_ , #_parentclass_, &(_class_::create) ); \
|
||||
_class_::propertyData.parentPropertyData = _parentclass_::extensionGetPropertyDataPtr();\
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Base class for all extension that can be added to a DocumentObject
|
||||
*
|
||||
* For general documentation on why extension system exists and how to use it see the ExtensionContainer
|
||||
* documentation. Following is a description howto create custom extensions.
|
||||
*
|
||||
* Extensions are like every other FreeCAD object and based on properties. All information storage
|
||||
* and persistence should be achieved by use of those. Additional any number of methods can be
|
||||
*
|
||||
* For general documentation on why extension system exists and how to use it see the ExtensionContainer
|
||||
* documentation. Following is a description howto create custom extensions.
|
||||
*
|
||||
* Extensions are like every other FreeCAD object and based on properties. All information storage
|
||||
* and persistence should be achieved by use of those. Additional any number of methods can be
|
||||
* added to provide functionality around the properties. There are 3 small difference to normal objects:
|
||||
* 1. They must be derived from Extension class
|
||||
* 2. Properties must be handled with special extension macros
|
||||
* 3. Extensions must be initialised
|
||||
* This works as simple as
|
||||
* This works as simple as
|
||||
* @code
|
||||
* class MyExtension : public Extension {
|
||||
* EXTENSION_PROPERTY_HEADER(MyExtension);
|
||||
* PropertyInt MyProp;
|
||||
* virtual bool overridableMethod(DocumentObject* obj) {};
|
||||
* };
|
||||
*
|
||||
*
|
||||
* EXTENSION_PROPERTY_SOURCE(App::MyExtension, App::Extension)
|
||||
* MyExtension::MyExtension() {
|
||||
*
|
||||
* EXTENSION_ADD_PROPERTY(MyProp, (0)) *
|
||||
*
|
||||
* EXTENSION_ADD_PROPERTY(MyProp, (0)) *
|
||||
* initExtension(MyExtension::getExtensionClassTypeId());
|
||||
* }
|
||||
* typedef ExtensionPythonT<MyExtension> MyExtensionPython;
|
||||
* @endcode
|
||||
*
|
||||
* The special python extension type created above is important, as only those python extensions
|
||||
* can be added to an object from python. It does not work to add the c++ version directly there.
|
||||
*
|
||||
* Note that every method of the extension becomes part of the extended object when added from c++.
|
||||
* @endcode
|
||||
*
|
||||
* The special python extension type created above is important, as only those python extensions
|
||||
* can be added to an object from python. It does not work to add the c++ version directly there.
|
||||
*
|
||||
* Note that every method of the extension becomes part of the extended object when added from c++.
|
||||
* This means one should carefully design the API and make only necessary methods public or protected.
|
||||
* Every internal method should be private.
|
||||
*
|
||||
* The automatic availability of methods in the class does not hold for the python interface, only
|
||||
* for c++ classes. This is like every where else in FreeCAD, there is no automatic creation of python
|
||||
* API from c++ classes. Hence the extension creator must also create a custom python object of its
|
||||
* extension, which works exactly like the normal FreeCAD python object workflow. There is nothing
|
||||
* special at all for extension python objects, the normal xml + imp.cpp approach is used. It must
|
||||
* only be taken care that the objects father is the correct extension base class. Of course also
|
||||
*
|
||||
* The automatic availability of methods in the class does not hold for the python interface, only
|
||||
* for c++ classes. This is like every where else in FreeCAD, there is no automatic creation of python
|
||||
* API from c++ classes. Hence the extension creator must also create a custom python object of its
|
||||
* extension, which works exactly like the normal FreeCAD python object workflow. There is nothing
|
||||
* special at all for extension python objects, the normal xml + imp.cpp approach is used. It must
|
||||
* only be taken care that the objects father is the correct extension base class. Of course also
|
||||
* make sure your extension returns the correct python object in its "getPyObject" call.
|
||||
* Every method you create in the extensions python will be later added to an extended object. This
|
||||
* happens automatically for both, c++ and python extension, if "getPyObject" returns the correct
|
||||
* Every method you create in the extensions python will be later added to an extended object. This
|
||||
* happens automatically for both, c++ and python extension, if "getPyObject" returns the correct
|
||||
* python object. No extra work needs to be done.
|
||||
*
|
||||
* A special case that needs to be handled for extensions is the possibility of overridden methods.
|
||||
* Often it is desired to customise extension behaviour by allowing the user to override methods
|
||||
* provided by the extension. On c++ side this is trivial, such methods are simply marked as "virtual"
|
||||
*
|
||||
* A special case that needs to be handled for extensions is the possibility of overridden methods.
|
||||
* Often it is desired to customise extension behaviour by allowing the user to override methods
|
||||
* provided by the extension. On c++ side this is trivial, such methods are simply marked as "virtual"
|
||||
* and can than be overridden in any derived class. This is more involved for the python interface and
|
||||
* here special care needs to be taken.
|
||||
*
|
||||
* As already seen above one needs to create a special ExtensionPythonT<> object for extension from
|
||||
* python. This is done exactly for the purpose of allowing to have overridable methods. The
|
||||
* ExtensionPythonT wrapper adds a proxy property which holds a PyObject which itself will contain
|
||||
* the implementations for the overridden methods. This design is equal to the ObjectPythonT<> design
|
||||
* of normal document objects.
|
||||
* As this wrapper inherits the c++ extension class it can also override the virtual functions the
|
||||
* user designed to be overridden. What it should do at a call of the virtual method is to check if
|
||||
* this method is implemented in the proxy object and if so call it, and if not call the normal
|
||||
* here special care needs to be taken.
|
||||
*
|
||||
* As already seen above one needs to create a special ExtensionPythonT<> object for extension from
|
||||
* python. This is done exactly for the purpose of allowing to have overridable methods. The
|
||||
* ExtensionPythonT wrapper adds a proxy property which holds a PyObject which itself will contain
|
||||
* the implementations for the overridden methods. This design is equal to the ObjectPythonT<> design
|
||||
* of normal document objects.
|
||||
* As this wrapper inherits the c++ extension class it can also override the virtual functions the
|
||||
* user designed to be overridden. What it should do at a call of the virtual method is to check if
|
||||
* this method is implemented in the proxy object and if so call it, and if not call the normal
|
||||
* c++ version. It is the extensions creators responsibility to implement this check and call behaviour
|
||||
* for every overridable method.
|
||||
* This is done by creating a custom wrapper just like ExtensionPythonT<> and overriding all virtual
|
||||
* This is done by creating a custom wrapper just like ExtensionPythonT<> and overriding all virtual
|
||||
* methods.
|
||||
* @code
|
||||
* template<typename ExtensionT> class MyExtensionPythonT : public ExtensionT {
|
||||
* public:
|
||||
*
|
||||
*
|
||||
* MyExtensionPythonT() {}
|
||||
* virtual ~MyExtensionPythonT() {}
|
||||
*
|
||||
* virtual bool overridableMethod(DocumentObject* obj) override {
|
||||
* Py::Object pyobj = Py::asObject(obj->getPyObject());
|
||||
* EXTENSION_PROXY_ONEARG(allowObject, pyobj);
|
||||
*
|
||||
*
|
||||
* if(result.isNone())
|
||||
* ExtensionT::allowObject(obj);
|
||||
*
|
||||
*
|
||||
* if(result.isBoolean())
|
||||
* return result.isTrue();
|
||||
*
|
||||
*
|
||||
* return false;
|
||||
* };
|
||||
* };
|
||||
* @endcode
|
||||
* @Note As seen in the code there are multiple helper macros to ease the repetitive work of querying
|
||||
* @Note As seen in the code there are multiple helper macros to ease the repetitive work of querying
|
||||
* and calling methods of the proxy object. See the macro documentation for how to use them.
|
||||
*
|
||||
* To ensure that your wrapper is used when a extension is created from python the extension type must
|
||||
*
|
||||
* To ensure that your wrapper is used when a extension is created from python the extension type must
|
||||
* be exposed as follows:
|
||||
* @code
|
||||
* typedef ExtensionPythonT<MyExtensionPythonT<MyExtension>> MyExtensionPython;
|
||||
* @endcode
|
||||
*
|
||||
* This boilerplate is absolutely necessary to allow overridable methods in python and it is the
|
||||
*
|
||||
* This boilerplate is absolutely necessary to allow overridable methods in python and it is the
|
||||
* extension creator's responsibility to ensure full implementation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AppExport Extension
|
||||
{
|
||||
@@ -235,18 +235,18 @@ public:
|
||||
virtual ~Extension();
|
||||
|
||||
virtual void initExtension(App::ExtensionContainer* obj);
|
||||
|
||||
|
||||
App::ExtensionContainer* getExtendedContainer() {return m_base;}
|
||||
const App::ExtensionContainer* getExtendedContainer() const {return m_base;}
|
||||
|
||||
|
||||
//get extension name without namespace
|
||||
std::string name() const;
|
||||
|
||||
|
||||
bool isPythonExtension() {return m_isPythonExtension;}
|
||||
|
||||
|
||||
virtual PyObject* getExtensionPyObject(void);
|
||||
|
||||
|
||||
|
||||
|
||||
/** @name Access properties */
|
||||
//@{
|
||||
/// find a property by its name
|
||||
@@ -271,36 +271,36 @@ public:
|
||||
/// get the Group of a named Property
|
||||
virtual const char* extensionGetPropertyDocumentation(const char *name) const;
|
||||
//@}
|
||||
|
||||
|
||||
/** @name Persistence */
|
||||
//@{
|
||||
virtual void extensionSave(Base::Writer&) const {}
|
||||
virtual void extensionRestore(Base::XMLReader&) {}
|
||||
//@}
|
||||
|
||||
|
||||
/** @name TypeHandling */
|
||||
//@{
|
||||
bool extensionIsDerivedFrom(const Base::Type type) const {return getExtensionTypeId().isDerivedFrom(type);}
|
||||
protected:
|
||||
static void initExtensionSubclass(Base::Type &toInit,const char* ClassName, const char *ParentName,
|
||||
static void initExtensionSubclass(Base::Type &toInit,const char* ClassName, const char *ParentName,
|
||||
Base::Type::instantiationMethod method=0);
|
||||
//@}
|
||||
|
||||
virtual void extensionOnChanged(const Property* p) {(void)(p);}
|
||||
|
||||
|
||||
friend class App::ExtensionContainer;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void initExtensionType(Base::Type type);
|
||||
bool m_isPythonExtension = false;
|
||||
Py::Object ExtensionPythonObject;
|
||||
|
||||
|
||||
private:
|
||||
Base::Type m_extensionType;
|
||||
App::ExtensionContainer* m_base = nullptr;
|
||||
};
|
||||
|
||||
// Property define
|
||||
// Property define
|
||||
#define _EXTENSION_ADD_PROPERTY(_name, _prop_, _defaultval_) \
|
||||
do { \
|
||||
this->_prop_.setValue _defaultval_;\
|
||||
@@ -319,7 +319,7 @@ private:
|
||||
|
||||
#define EXTENSION_ADD_PROPERTY_TYPE(_prop_, _defaultval_, _group_,_type_,_Docu_) \
|
||||
_EXTENSION_ADD_PROPERTY_TYPE(#_prop_, _prop_, _defaultval_, _group_,_type_,_Docu_)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generic Python extension class which allows every extension derived
|
||||
@@ -332,17 +332,13 @@ class ExtensionPythonT : public ExtensionT
|
||||
|
||||
public:
|
||||
typedef ExtensionT Inherited;
|
||||
|
||||
|
||||
ExtensionPythonT() {
|
||||
ExtensionT::m_isPythonExtension = true;
|
||||
ExtensionT::initExtensionType(ExtensionPythonT::getExtensionClassTypeId());
|
||||
|
||||
EXTENSION_ADD_PROPERTY(ExtensionProxy,(Py::Object()));
|
||||
}
|
||||
virtual ~ExtensionPythonT() {
|
||||
}
|
||||
|
||||
PropertyPythonObject ExtensionProxy;
|
||||
};
|
||||
|
||||
typedef ExtensionPythonT<App::Extension> ExtensionPython;
|
||||
@@ -352,22 +348,22 @@ typedef ExtensionPythonT<App::Extension> ExtensionPython;
|
||||
Base::PyGILStateLocker lock;\
|
||||
Py::Object result;\
|
||||
try {\
|
||||
Property* proxy = this->extensionGetPropertyByName("ExtensionProxy");\
|
||||
Property* proxy = this->getExtendedContainer()->getPropertyByName("Proxy");\
|
||||
if (proxy && proxy->getTypeId() == PropertyPythonObject::getClassTypeId()) {\
|
||||
Py::Object feature = static_cast<PropertyPythonObject*>(proxy)->getValue();\
|
||||
if (feature.hasAttr(std::string("function"))) {\
|
||||
if (feature.hasAttr("__object__")) {\
|
||||
Py::Callable method(feature.getAttr(std::string("function")));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define EXTENSION_PROXY_SECOND(function)\
|
||||
result = method.apply(args);\
|
||||
}\
|
||||
else {\
|
||||
Py::Callable method(feature.getAttr(std::string("function")));
|
||||
|
||||
|
||||
#define EXTENSION_PROXY_THIRD()\
|
||||
result = method.apply(args);\
|
||||
}\
|
||||
@@ -378,7 +374,7 @@ typedef ExtensionPythonT<App::Extension> ExtensionPython;
|
||||
Base::PyException e;\
|
||||
e.ReportException();\
|
||||
}
|
||||
|
||||
|
||||
#define EXTENSION_PROXY_NOARG(function)\
|
||||
EXTENSION_PROXY_FIRST(function) \
|
||||
Py::Tuple args;\
|
||||
@@ -401,13 +397,13 @@ typedef ExtensionPythonT<App::Extension> ExtensionPython;
|
||||
virtual void function() override {\
|
||||
EXTENSION_PROXY_NOARGS(function)\
|
||||
};
|
||||
|
||||
|
||||
#define EXTENSION_PYTHON_OVERRIDE_OBJECT_NOARGS(function)\
|
||||
virtual PyObject* function() override {\
|
||||
EXTENSION_PROXY_NOARGS(function)\
|
||||
return res.ptr();\
|
||||
};
|
||||
|
||||
|
||||
} //App
|
||||
|
||||
#endif // APP_EXTENSION_H
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace App {
|
||||
* special macros.
|
||||
* 2. The extensions need to be initialised in the constructor
|
||||
*
|
||||
* Here a working example:
|
||||
* Here is a working example:
|
||||
* @code
|
||||
* class AppExport Part : public App::DocumentObject, public App::FirstExtension, public App::SecondExtension {
|
||||
* PROPERTY_HEADER_WITH_EXTENSIONS(App::Part);
|
||||
@@ -195,7 +195,7 @@ private:
|
||||
#define PROPERTY_HEADER_WITH_EXTENSIONS(_class_) \
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(_class)
|
||||
|
||||
/// We make sur that the PropertyData of the container is not connected to the one of the extension
|
||||
/// We make sure that the PropertyData of the container is not connected to the one of the extension
|
||||
#define PROPERTY_SOURCE_WITH_EXTENSIONS(_class_, _parentclass_) \
|
||||
PROPERTY_SOURCE(_class_, _parentclass_)
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
</Documentation>
|
||||
<Methode Name="addExtension">
|
||||
<Documentation>
|
||||
<UserDocu>Adds an extension to the object. Requires the string identifier as well as the python object
|
||||
used to check for overridden functions (most likely self)</UserDocu>
|
||||
<UserDocu>Adds an extension to the object. Requires the string identifier for the python extension as argument</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasExtension" Const="true">
|
||||
|
||||
@@ -198,10 +198,16 @@ PyObject* ExtensionContainerPy::hasExtension(PyObject *args) {
|
||||
PyObject* ExtensionContainerPy::addExtension(PyObject *args) {
|
||||
|
||||
char *typeId;
|
||||
PyObject* proxy;
|
||||
if (!PyArg_ParseTuple(args, "sO", &typeId, &proxy))
|
||||
PyObject* proxy = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "s|O", &typeId, &proxy))
|
||||
return NULL;
|
||||
|
||||
if (proxy) {
|
||||
PyErr_SetString(PyExc_DeprecationWarning, "Second argument is deprecated. It is ignored and will be removed in future versions. "
|
||||
"The default Python feature proxy is used for extension method overrides.");
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
//get the extension type asked for
|
||||
Base::Type extension = Base::Type::fromName(typeId);
|
||||
if (extension.isBad() || !extension.isDerivedFrom(App::Extension::getExtensionClassTypeId())) {
|
||||
@@ -223,16 +229,7 @@ PyObject* ExtensionContainerPy::addExtension(PyObject *args) {
|
||||
GetApplication().signalBeforeAddingDynamicExtension(*getExtensionContainerPtr(), typeId);
|
||||
ext->initExtension(getExtensionContainerPtr());
|
||||
|
||||
//set the proxy to allow python overrides
|
||||
App::Property* pp = ext->extensionGetPropertyByName("ExtensionProxy");
|
||||
if (!pp) {
|
||||
std::stringstream str;
|
||||
str << "Accessing the proxy property failed!" << std::ends;
|
||||
throw Py::Exception(Base::BaseExceptionFreeCADError,str.str());
|
||||
}
|
||||
static_cast<PropertyPythonObject*>(pp)->setPyObject(proxy);
|
||||
|
||||
// The PyTypeObject is shared by all instances of this type and therefore
|
||||
// The PyTypeObject is shared by all instances of this type and therefore
|
||||
// we have to add new methods only once.
|
||||
PyObject* obj = ext->getExtensionPyObject();
|
||||
PyMethodDef* meth = reinterpret_cast<PyMethodDef*>(obj->ob_type->tp_methods);
|
||||
|
||||
@@ -38,13 +38,18 @@
|
||||
|
||||
using namespace App;
|
||||
|
||||
FeaturePythonImp::FeaturePythonImp(App::DocumentObject* o)
|
||||
FeaturePythonImp::FeaturePythonImp(App::DocumentObject* o)
|
||||
: object(o), has__object__(false)
|
||||
{
|
||||
}
|
||||
|
||||
FeaturePythonImp::~FeaturePythonImp()
|
||||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
#undef FC_PY_ELEMENT
|
||||
#define FC_PY_ELEMENT(_name) py_##_name = Py::None();
|
||||
|
||||
FC_PY_FEATURE_PYTHON
|
||||
}
|
||||
|
||||
void FeaturePythonImp::init(PyObject *pyobj) {
|
||||
@@ -223,7 +228,7 @@ void FeaturePythonImp::onDocumentRestored()
|
||||
}
|
||||
}
|
||||
|
||||
bool FeaturePythonImp::getSubObject(DocumentObject *&ret, const char *subname,
|
||||
bool FeaturePythonImp::getSubObject(DocumentObject *&ret, const char *subname,
|
||||
PyObject **pyObj, Base::Matrix4D *_mat, bool transform, int depth) const
|
||||
{
|
||||
FC_PY_CALL_CHECK(getSubObject);
|
||||
@@ -251,13 +256,13 @@ bool FeaturePythonImp::getSubObject(DocumentObject *&ret, const char *subname,
|
||||
throw Py::TypeError("getSubObject expects return type of tuple");
|
||||
Py::Sequence seq(res);
|
||||
if(seq.length() < 2 ||
|
||||
(!seq.getItem(0).isNone() &&
|
||||
(!seq.getItem(0).isNone() &&
|
||||
!PyObject_TypeCheck(seq.getItem(0).ptr(),&DocumentObjectPy::Type)) ||
|
||||
!PyObject_TypeCheck(seq.getItem(1).ptr(),&Base::MatrixPy::Type))
|
||||
{
|
||||
throw Py::TypeError("getSubObject expects return type of (obj,matrix,pyobj)");
|
||||
}
|
||||
if(_mat)
|
||||
if(_mat)
|
||||
*_mat = *static_cast<Base::MatrixPy*>(seq.getItem(1).ptr())->getMatrixPtr();
|
||||
if(pyObj) {
|
||||
if(seq.length()>2)
|
||||
@@ -296,7 +301,7 @@ bool FeaturePythonImp::getSubObjects(std::vector<std::string> &ret, int reason)
|
||||
if(!res.isSequence())
|
||||
throw Py::TypeError("getSubObjects expects return type of tuple");
|
||||
Py::Sequence seq(res);
|
||||
for(size_t i=0;i<seq.length();++i) {
|
||||
for(Py_ssize_t i=0;i<seq.length();++i) {
|
||||
Py::Object name(seq[i].ptr());
|
||||
if(!name.isString())
|
||||
throw Py::TypeError("getSubObjects expects string in returned sequence");
|
||||
@@ -315,7 +320,7 @@ bool FeaturePythonImp::getSubObjects(std::vector<std::string> &ret, int reason)
|
||||
}
|
||||
}
|
||||
|
||||
bool FeaturePythonImp::getLinkedObject(DocumentObject *&ret, bool recurse,
|
||||
bool FeaturePythonImp::getLinkedObject(DocumentObject *&ret, bool recurse,
|
||||
Base::Matrix4D *_mat, bool transform, int depth) const
|
||||
{
|
||||
FC_PY_CALL_CHECK(getLinkedObject);
|
||||
@@ -339,13 +344,13 @@ bool FeaturePythonImp::getLinkedObject(DocumentObject *&ret, bool recurse,
|
||||
throw Py::TypeError("getLinkedObject expects return type of (object,matrix)");
|
||||
Py::Sequence seq(res);
|
||||
if(seq.length() != 2 ||
|
||||
(!seq.getItem(0).isNone() &&
|
||||
(!seq.getItem(0).isNone() &&
|
||||
!PyObject_TypeCheck(seq.getItem(0).ptr(),&DocumentObjectPy::Type)) ||
|
||||
!PyObject_TypeCheck(seq.getItem(1).ptr(),&Base::MatrixPy::Type))
|
||||
{
|
||||
throw Py::TypeError("getLinkedObject expects return type of (object,matrix)");
|
||||
}
|
||||
if(_mat)
|
||||
if(_mat)
|
||||
*_mat = *static_cast<Base::MatrixPy*>(seq.getItem(1).ptr())->getMatrixPtr();
|
||||
if(seq.getItem(0).isNone())
|
||||
ret = object;
|
||||
@@ -520,7 +525,7 @@ int FeaturePythonImp::canLoadPartial() const {
|
||||
FeaturePythonImp::ValueT
|
||||
FeaturePythonImp::redirectSubName(std::ostringstream &ss,
|
||||
App::DocumentObject *topParent,
|
||||
App::DocumentObject *child) const
|
||||
App::DocumentObject *child) const
|
||||
{
|
||||
_FC_PY_CALL_CHECK(redirectSubName,return(NotImplemented));
|
||||
Base::PyGILStateLocker lock;
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
#define PYTHON_TYPE_DEF(_class_, _subclass_) \
|
||||
@@ -144,6 +146,8 @@ private:
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // APP_FEATUREPYTHONPYIMP_H
|
||||
|
||||
+12
-11
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <stdexcept>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -77,7 +78,7 @@ FeatureTest::FeatureTest()
|
||||
|
||||
ADD_PROPERTY(IntegerList,(4711) );
|
||||
ADD_PROPERTY(FloatList ,(47.11f) );
|
||||
|
||||
|
||||
ADD_PROPERTY(Link ,(0));
|
||||
ADD_PROPERTY(LinkSub ,(0));
|
||||
ADD_PROPERTY(LinkList ,(0));
|
||||
@@ -87,7 +88,7 @@ FeatureTest::FeatureTest()
|
||||
ADD_PROPERTY(VectorList,(3.0,2.0,1.0));
|
||||
ADD_PROPERTY(Matrix ,(Base::Matrix4D(1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0)));
|
||||
ADD_PROPERTY(Placement ,(Base::Placement()));
|
||||
|
||||
|
||||
// properties for recompute testing
|
||||
static const char* group = "Feature Test";
|
||||
ADD_PROPERTY_TYPE(Source1 ,(0),group,Prop_None,"Source for testing links");
|
||||
@@ -96,7 +97,7 @@ FeatureTest::FeatureTest()
|
||||
ADD_PROPERTY_TYPE(ExecResult ,("empty"),group,Prop_None,"Result of the execution");
|
||||
ADD_PROPERTY_TYPE(ExceptionType ,(0),group,Prop_None,"The type of exception the execution method throws");
|
||||
ADD_PROPERTY_TYPE(ExecCount ,(0),group,Prop_None,"Number of executions");
|
||||
|
||||
|
||||
// properties with types
|
||||
ADD_PROPERTY_TYPE(TypeHidden ,(4711),group,Prop_Hidden,"An example property which has the type 'Hidden'" );
|
||||
ADD_PROPERTY_TYPE(TypeReadOnly,(4711),group,Prop_ReadOnly ,"An example property which has the type 'ReadOnly'" );
|
||||
@@ -104,8 +105,8 @@ FeatureTest::FeatureTest()
|
||||
ADD_PROPERTY_TYPE(TypeTransient,(4711),group,Prop_Transient ,"An example property which has the type 'Transient'" );
|
||||
ADD_PROPERTY_TYPE(TypeNoRecompute,(4711),group,Prop_NoRecompute,"An example property which has the type 'NoRecompute'");
|
||||
ADD_PROPERTY_TYPE(TypeAll ,(4711),group,(App::PropertyType) (Prop_Output|Prop_ReadOnly |Prop_Hidden ),
|
||||
"An example property which has the types 'Output', 'ReadOnly' and 'Hidden'");
|
||||
|
||||
"An example property which has the types 'Output', 'ReadOnly', and 'Hidden'");
|
||||
|
||||
ADD_PROPERTY(QuantityLength,(1.0));
|
||||
QuantityLength.setUnit(Base::Unit::Length);
|
||||
ADD_PROPERTY(QuantityOther,(5.0));
|
||||
@@ -164,14 +165,14 @@ doc.recompute()
|
||||
switch(ExceptionType.getValue())
|
||||
{
|
||||
case 0: break;
|
||||
case 1: throw "Test Exception";
|
||||
case 1: throw std::runtime_error("Test Exception");
|
||||
case 2: throw Base::RuntimeError("FeatureTestException::execute(): Testexception");
|
||||
#if 0 // only allow these error types on purpose
|
||||
case 3: *i=0;printf("%i",*i);break; // seg-fault
|
||||
case 4: t = nullptr; break; // seg-fault
|
||||
case 5: j=0; printf("%i",1/j); break; // int division by zero
|
||||
case 6: f=0.0; printf("%f",1/f); break; // float division by zero
|
||||
case 7: s = malloc(3600000000ul); free(s); break; // out-of-memory
|
||||
case 3: *i=0;printf("%i",*i);break; // seg-fault
|
||||
case 4: t = nullptr; break; // seg-fault
|
||||
case 5: j=0; printf("%i",1/j); break; // int division by zero
|
||||
case 6: f=0.0; printf("%f",1/f); break; // float division by zero
|
||||
case 7: s = malloc(3600000000ul); free(s); break; // out-of-memory
|
||||
#else
|
||||
default: (void)i; (void)j; (void)f; (void)s; (void)t; break;
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
App::PropertyEnumeration Enum;
|
||||
App::PropertyIntegerConstraint ConstraintInt;
|
||||
App::PropertyFloatConstraint ConstraintFloat;
|
||||
|
||||
|
||||
// Standard Properties (PrppertyStandard.h)
|
||||
App::PropertyIntegerList IntegerList;
|
||||
App::PropertyFloatList FloatList;
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
App::PropertyString ExecResult;
|
||||
App::PropertyInteger ExceptionType;
|
||||
App::PropertyInteger ExecCount;
|
||||
|
||||
|
||||
App::PropertyInteger TypeHidden;
|
||||
App::PropertyInteger TypeReadOnly;
|
||||
App::PropertyInteger TypeOutput;
|
||||
|
||||
+67
-54
@@ -1,12 +1,5 @@
|
||||
# FreeCAD init module
|
||||
# (c) 2001 Jürgen Riegel
|
||||
#
|
||||
# Gathering all the information to start FreeCAD
|
||||
# This is the second one of three init scripts, the third one
|
||||
# runs when the gui is up
|
||||
|
||||
#***************************************************************************
|
||||
#* Copyright (c) 2002 Jürgen Riegel <[email protected]> *
|
||||
#* Copyright (c) 2001,2002 Jürgen Riegel <[email protected]> *
|
||||
#* *
|
||||
#* This file is part of the FreeCAD CAx development system. *
|
||||
#* *
|
||||
@@ -28,6 +21,11 @@
|
||||
#* *
|
||||
#***************************************************************************/
|
||||
|
||||
# FreeCAD init module
|
||||
#
|
||||
# Gathering all the information to start FreeCAD.
|
||||
# This is the second of of three init scripts.
|
||||
# The third one runs when the gui is up,
|
||||
|
||||
# imports the one and only
|
||||
import FreeCAD
|
||||
@@ -36,14 +34,49 @@ def removeFromPath(module_name):
|
||||
"""removes the module from the sys.path. The entry point for imports
|
||||
will therefore always be FreeCAD.
|
||||
eg.: from FreeCAD.Module.submodule import function"""
|
||||
import sys, os
|
||||
import sys
|
||||
paths = sys.path
|
||||
for path in paths:
|
||||
if module_name in path:
|
||||
sys.path.remove(path)
|
||||
return
|
||||
else:
|
||||
Wrn(module_name + " not found in sys.path\n")
|
||||
Wrn(module_name + " not found in sys.path\n")
|
||||
|
||||
def setupSearchPaths(PathExtension):
|
||||
# DLL resolution in Python 3.8 on Windows has changed
|
||||
import sys
|
||||
if sys.platform == 'win32' and hasattr(os, "add_dll_directory"):
|
||||
if "FREECAD_LIBPACK_BIN" in os.environ:
|
||||
os.add_dll_directory(os.environ["FREECAD_LIBPACK_BIN"])
|
||||
for path in PathExtension:
|
||||
os.add_dll_directory(path)
|
||||
|
||||
PathEnvironment = PathExtension.pop(0) + os.pathsep
|
||||
for path in PathExtension:
|
||||
try:
|
||||
PathEnvironment += path + os.pathsep
|
||||
except UnicodeDecodeError:
|
||||
Wrn('Filter invalid module path: u{}\n'.format(repr(path)))
|
||||
|
||||
# new paths must be prepended to avoid to load a wrong version of a library
|
||||
try:
|
||||
os.environ["PATH"] = PathEnvironment + os.environ["PATH"]
|
||||
except UnicodeDecodeError:
|
||||
# See #0002238. FIXME: check again once ported to Python 3.x
|
||||
Log('UnicodeDecodeError was raised when concatenating unicode string with PATH. Try to remove non-ascii paths...\n')
|
||||
path = os.environ["PATH"].split(os.pathsep)
|
||||
cleanpath=[]
|
||||
for i in path:
|
||||
if test_ascii(i):
|
||||
cleanpath.append(i)
|
||||
os.environ["PATH"] = PathEnvironment + os.pathsep.join(cleanpath)
|
||||
Log('done\n')
|
||||
except UnicodeEncodeError:
|
||||
Log('UnicodeEncodeError was raised when concatenating unicode string with PATH. Try to replace non-ascii chars...\n')
|
||||
os.environ["PATH"] = PathEnvironment.encode(errors='replace') + os.environ["PATH"]
|
||||
Log('done\n')
|
||||
except KeyError:
|
||||
os.environ["PATH"] = PathEnvironment
|
||||
|
||||
FreeCAD._importFromFreeCAD = removeFromPath
|
||||
|
||||
@@ -125,8 +158,8 @@ def InitApplications():
|
||||
# from FreeCAD.Module import package
|
||||
FreeCAD.__path__ = [ModDir] + libpaths + [HomeMod]
|
||||
|
||||
# also add these directories to the sys.path to
|
||||
# not change the old behaviour. once we have moved to
|
||||
# also add these directories to the sys.path to
|
||||
# not change the old behaviour. once we have moved to
|
||||
# proper python modules this can eventuelly be removed.
|
||||
sys.path = [ModDir] + libpaths + [ExtDir] + sys.path
|
||||
|
||||
@@ -138,9 +171,12 @@ def InitApplications():
|
||||
if (os.path.exists(InstallFile)):
|
||||
try:
|
||||
# XXX: This looks scary securitywise...
|
||||
|
||||
with open(InstallFile) as f:
|
||||
exec(f.read())
|
||||
if sys.version_info.major < 3:
|
||||
with open(InstallFile) as f:
|
||||
exec(f.read())
|
||||
else:
|
||||
with open(file=InstallFile, encoding="utf-8") as f:
|
||||
exec(f.read())
|
||||
except Exception as inst:
|
||||
Log('Init: Initializing ' + Dir + '... failed\n')
|
||||
Log('-'*100+'\n')
|
||||
@@ -185,32 +221,7 @@ def InitApplications():
|
||||
Log("Using "+ModDir+" as module path!\n")
|
||||
# In certain cases the PathExtension list can contain invalid strings. We concatenate them to a single string
|
||||
# but check that the output is a valid string
|
||||
PathEnvironment = PathExtension.pop(0) + os.pathsep
|
||||
for path in PathExtension:
|
||||
try:
|
||||
PathEnvironment += path + os.pathsep
|
||||
except UnicodeDecodeError:
|
||||
Wrn('Filter invalid module path: u{}\n'.format(repr(path)))
|
||||
|
||||
# new paths must be prepended to avoid to load a wrong version of a library
|
||||
try:
|
||||
os.environ["PATH"] = PathEnvironment + os.environ["PATH"]
|
||||
except UnicodeDecodeError:
|
||||
# See #0002238. FIXME: check again once ported to Python 3.x
|
||||
Log('UnicodeDecodeError was raised when concatenating unicode string with PATH. Try to remove non-ascii paths...\n')
|
||||
path = os.environ["PATH"].split(os.pathsep)
|
||||
cleanpath=[]
|
||||
for i in path:
|
||||
if test_ascii(i):
|
||||
cleanpath.append(i)
|
||||
os.environ["PATH"] = PathEnvironment + os.pathsep.join(cleanpath)
|
||||
Log('done\n')
|
||||
except UnicodeEncodeError:
|
||||
Log('UnicodeEncodeError was raised when concatenating unicode string with PATH. Try to replace non-ascii chars...\n')
|
||||
os.environ["PATH"] = PathEnvironment.encode(errors='replace') + os.environ["PATH"]
|
||||
Log('done\n')
|
||||
except KeyError:
|
||||
os.environ["PATH"] = PathEnvironment
|
||||
setupSearchPaths(PathExtension)
|
||||
path = os.environ["PATH"].split(os.pathsep)
|
||||
Log("System path after init:\n")
|
||||
for i in path:
|
||||
@@ -241,7 +252,7 @@ App.__unit_test__ = []
|
||||
Log ('Init: starting App::FreeCADInit.py\n')
|
||||
|
||||
try:
|
||||
import sys,os,traceback,io,inspect
|
||||
import sys,os,traceback,inspect
|
||||
from datetime import datetime
|
||||
except ImportError:
|
||||
FreeCAD.Console.PrintError("\n\nSeems the python standard libs are not installed, bailing out!\n\n")
|
||||
@@ -255,7 +266,7 @@ if sys.version_info.major < 3:
|
||||
|
||||
class FCADLogger(object):
|
||||
'''Convenient class for tagged logging.
|
||||
|
||||
|
||||
Example usage:
|
||||
>>> logger = FreeCAD.Logger('MyModule')
|
||||
>>> logger.info('log test {}',1)
|
||||
@@ -620,7 +631,6 @@ FreeCAD.Logger = FCADLogger
|
||||
|
||||
# init every application by importing Init.py
|
||||
try:
|
||||
import traceback
|
||||
InitApplications()
|
||||
except Exception as e:
|
||||
Err('Error in InitApplications ' + str(e) + '\n')
|
||||
@@ -721,6 +731,8 @@ App.Units.Volt = App.Units.Quantity('V')
|
||||
App.Units.MilliVolt = App.Units.Quantity('mV')
|
||||
App.Units.KiloVolt = App.Units.Quantity('kV')
|
||||
|
||||
App.Units.MegaSiemens = App.Units.Quantity('MS')
|
||||
App.Units.KiloSiemens = App.Units.Quantity('kS')
|
||||
App.Units.Siemens = App.Units.Quantity('S')
|
||||
App.Units.MilliSiemens = App.Units.Quantity('mS')
|
||||
App.Units.MicroSiemens = App.Units.Quantity('uS')
|
||||
@@ -774,7 +786,7 @@ App.Units.AngularSecond = App.Units.Quantity().AngularSecond
|
||||
App.Units.Length = App.Units.Unit(1)
|
||||
App.Units.Area = App.Units.Unit(2)
|
||||
App.Units.Volume = App.Units.Unit(3)
|
||||
App.Units.Mass = App.Units.Unit(0,1)
|
||||
App.Units.Mass = App.Units.Unit(0,1)
|
||||
# (length, weight, time, current, temperature, amount of substance, luminous intensity, angle)
|
||||
|
||||
# Angle
|
||||
@@ -783,13 +795,13 @@ App.Units.AngleOfFriction = App.Units.Unit(0,0,0,0,0,0,0,1)
|
||||
|
||||
App.Units.Density = App.Units.Unit(-3,1)
|
||||
|
||||
App.Units.TimeSpan = App.Units.Unit(0,0,1)
|
||||
App.Units.TimeSpan = App.Units.Unit(0,0,1)
|
||||
App.Units.Frequency = App.Units.Unit(0,0,-1)
|
||||
App.Units.Velocity = App.Units.Unit(1,0,-1)
|
||||
App.Units.Acceleration = App.Units.Unit(1,0,-2)
|
||||
App.Units.Temperature = App.Units.Unit(0,0,0,0,1)
|
||||
App.Units.Velocity = App.Units.Unit(1,0,-1)
|
||||
App.Units.Acceleration = App.Units.Unit(1,0,-2)
|
||||
App.Units.Temperature = App.Units.Unit(0,0,0,0,1)
|
||||
|
||||
App.Units.ElectricCurrent = App.Units.Unit(0,0,0,1)
|
||||
App.Units.ElectricCurrent = App.Units.Unit(0,0,0,1)
|
||||
App.Units.ElectricPotential = App.Units.Unit(2,1,-3,-1)
|
||||
App.Units.ElectricCharge = App.Units.Unit(0,0,1,1)
|
||||
App.Units.MagneticFluxDensity = App.Units.Unit(0,1,-2,-1)
|
||||
@@ -797,6 +809,7 @@ App.Units.ElectricalCapacitance = App.Units.Unit(-2,-1,4,2)
|
||||
App.Units.ElectricalInductance = App.Units.Unit(2,1,-2,-2)
|
||||
App.Units.ElectricalConductance = App.Units.Unit(-2,-1,3,2)
|
||||
App.Units.ElectricalResistance = App.Units.Unit(2,1,-3,-2)
|
||||
App.Units.ElectricalConductivity = App.Units.Unit(-3,-1,3,2)
|
||||
App.Units.AmountOfSubstance = App.Units.Unit(0,0,0,0,0,1)
|
||||
App.Units.LuminousIntensity = App.Units.Unit(0,0,0,0,0,0,1)
|
||||
|
||||
@@ -809,9 +822,9 @@ App.Units.UltimateTensileStrength = App.Units.Unit(-1,1,-2)
|
||||
App.Units.YieldStrength = App.Units.Unit(-1,1,-2)
|
||||
App.Units.YoungsModulus = App.Units.Unit(-1,1,-2)
|
||||
|
||||
App.Units.Force = App.Units.Unit(1,1,-2)
|
||||
App.Units.Work = App.Units.Unit(2,1,-2)
|
||||
App.Units.Power = App.Units.Unit(2,1,-3)
|
||||
App.Units.Force = App.Units.Unit(1,1,-2)
|
||||
App.Units.Work = App.Units.Unit(2,1,-2)
|
||||
App.Units.Power = App.Units.Unit(2,1,-3)
|
||||
|
||||
App.Units.SpecificEnergy = App.Units.Unit(2,0,-2)
|
||||
App.Units.ThermalConductivity = App.Units.Unit(1,1,-3,0,-1)
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
# FreeCAD test module
|
||||
# (c) 2002 Jürgen Riegel
|
||||
#
|
||||
# Testing the function of the base system and run
|
||||
# (if existing) the test function of the modules
|
||||
#
|
||||
|
||||
#***************************************************************************
|
||||
#* Copyright (c) 2002 Jürgen Riegel <[email protected]> *
|
||||
#* *
|
||||
@@ -28,6 +21,12 @@
|
||||
#* *
|
||||
#***************************************************************************/
|
||||
|
||||
# FreeCAD test module
|
||||
#
|
||||
# Testing the function of the base system and run
|
||||
# (if existing) the test function of the modules
|
||||
|
||||
|
||||
|
||||
Log ("FreeCAD test running...\n\n")
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef APP_GROUPEXTENSION_H
|
||||
#define APP_GROUPEXTENSION_H
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
#include "FeaturePython.h"
|
||||
#include "DocumentObject.h"
|
||||
#include "PropertyLinks.h"
|
||||
|
||||
+56
-48
@@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
|
||||
* Copyright (c) 2017 Zheng Lei (realthunder) <realthunder.dev@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "Link.h"
|
||||
#include "LinkBaseExtensionPy.h"
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
#include "ComplexGeoData.h"
|
||||
#include "ComplexGeoDataPy.h"
|
||||
|
||||
@@ -55,9 +56,9 @@ LinkBaseExtension::LinkBaseExtension(void)
|
||||
:myOwner(0),enableLabelCache(false),hasOldSubElement(false)
|
||||
{
|
||||
initExtensionType(LinkBaseExtension::getExtensionClassTypeId());
|
||||
EXTENSION_ADD_PROPERTY_TYPE(_LinkTouched, (false), " Link",
|
||||
EXTENSION_ADD_PROPERTY_TYPE(_LinkTouched, (false), " Link",
|
||||
PropertyType(Prop_Hidden|Prop_NoPersist),0);
|
||||
EXTENSION_ADD_PROPERTY_TYPE(_ChildCache, (), " Link",
|
||||
EXTENSION_ADD_PROPERTY_TYPE(_ChildCache, (), " Link",
|
||||
PropertyType(Prop_Hidden|Prop_NoPersist|Prop_ReadOnly),0);
|
||||
_ChildCache.setScope(LinkScope::Global);
|
||||
props.resize(PropMax,0);
|
||||
@@ -87,7 +88,7 @@ const LinkBaseExtension::PropInfoMap &LinkBaseExtension::getPropertyInfoMap() co
|
||||
static PropInfoMap PropsMap;
|
||||
if(PropsMap.empty()) {
|
||||
const auto &infos = getPropertyInfo();
|
||||
for(const auto &info : infos)
|
||||
for(const auto &info : infos)
|
||||
PropsMap[info.name] = info;
|
||||
}
|
||||
return PropsMap;
|
||||
@@ -116,12 +117,12 @@ void LinkBaseExtension::setProperty(int idx, Property *prop) {
|
||||
props[idx]->setStatus(Property::LockDynamic,false);
|
||||
props[idx] = 0;
|
||||
}
|
||||
if(!prop)
|
||||
if(!prop)
|
||||
return;
|
||||
if(!prop->isDerivedFrom(infos[idx].type)) {
|
||||
std::ostringstream str;
|
||||
str << "App::LinkBaseExtension: expected property type '" <<
|
||||
infos[idx].type.getName() << "', instead of '" <<
|
||||
str << "App::LinkBaseExtension: expected property type '" <<
|
||||
infos[idx].type.getName() << "', instead of '" <<
|
||||
prop->getClassTypeId().getName() << "'";
|
||||
LINK_THROW(Base::TypeError,str.str().c_str());
|
||||
}
|
||||
@@ -166,13 +167,13 @@ void LinkBaseExtension::setProperty(int idx, Property *prop) {
|
||||
|
||||
if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_TRACE)) {
|
||||
const char *propName;
|
||||
if(!prop)
|
||||
if(!prop)
|
||||
propName = "<null>";
|
||||
else if(prop->getContainer())
|
||||
propName = prop->getName();
|
||||
else
|
||||
else
|
||||
propName = extensionGetPropertyName(prop);
|
||||
if(!propName)
|
||||
if(!propName)
|
||||
propName = "?";
|
||||
FC_TRACE("set property " << infos[idx].name << ": " << propName);
|
||||
}
|
||||
@@ -303,7 +304,7 @@ int LinkBaseExtension::_getElementCountValue() const {
|
||||
}
|
||||
|
||||
bool LinkBaseExtension::extensionHasChildElement() const {
|
||||
if(_getElementListValue().size()
|
||||
if(_getElementListValue().size()
|
||||
|| (_getElementCountValue() && _getShowElementValue()))
|
||||
return true;
|
||||
DocumentObject *linked = getTrueLinkedObject(false);
|
||||
@@ -318,7 +319,7 @@ int LinkBaseExtension::extensionSetElementVisible(const char *element, bool visi
|
||||
int index = _getShowElementValue()?getElementIndex(element):getArrayIndex(element);
|
||||
if(index>=0) {
|
||||
auto propElementVis = getVisibilityListProperty();
|
||||
if(!propElementVis || !element || !element[0])
|
||||
if(!propElementVis || !element || !element[0])
|
||||
return -1;
|
||||
if(propElementVis->getSize()<=index) {
|
||||
if(visible) return 1;
|
||||
@@ -381,7 +382,7 @@ DocumentObject *LinkBaseExtension::getLink(int depth) const{
|
||||
}
|
||||
|
||||
int LinkBaseExtension::getArrayIndex(const char *subname, const char **psubname) {
|
||||
if(!subname || Data::ComplexGeoData::isMappedElement(subname))
|
||||
if(!subname || Data::ComplexGeoData::isMappedElement(subname))
|
||||
return -1;
|
||||
const char *dot = strchr(subname,'.');
|
||||
if(!dot) dot= subname+strlen(subname);
|
||||
@@ -401,7 +402,7 @@ int LinkBaseExtension::getArrayIndex(const char *subname, const char **psubname)
|
||||
}
|
||||
|
||||
int LinkBaseExtension::getElementIndex(const char *subname, const char **psubname) const {
|
||||
if(!subname || Data::ComplexGeoData::isMappedElement(subname))
|
||||
if(!subname || Data::ComplexGeoData::isMappedElement(subname))
|
||||
return -1;
|
||||
int idx = -1;
|
||||
const char *dot = strchr(subname,'.');
|
||||
@@ -414,7 +415,7 @@ int LinkBaseExtension::getElementIndex(const char *subname, const char **psubnam
|
||||
if(_getElementCountProperty()) {
|
||||
if(idx>=_getElementCountValue())
|
||||
return -1;
|
||||
}else if(idx>=(int)_getElementListValue().size())
|
||||
}else if(idx>=(int)_getElementListValue().size())
|
||||
return -1;
|
||||
}else if(!_getShowElementValue() && _getElementCountValue()) {
|
||||
// If elements are collapsed, we check first for LinkElement naming
|
||||
@@ -579,8 +580,8 @@ bool LinkBaseExtension::extensionGetSubObjects(std::vector<std::string> &ret, in
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname,
|
||||
PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const
|
||||
bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname,
|
||||
PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const
|
||||
{
|
||||
ret = 0;
|
||||
auto obj = getContainer();
|
||||
@@ -605,8 +606,8 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char *
|
||||
_mat = *mat;
|
||||
}
|
||||
|
||||
if(pyObj && !_getElementCountValue()
|
||||
&& _getElementListValue().empty() && mySubElements.size()<=1)
|
||||
if(pyObj && !_getElementCountValue()
|
||||
&& _getElementListValue().empty() && mySubElements.size()<=1)
|
||||
{
|
||||
// Scale will be included here
|
||||
if(getScaleProperty() || getScaleVectorProperty()) {
|
||||
@@ -659,7 +660,7 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char *
|
||||
}
|
||||
|
||||
auto linked = getTrueLinkedObject(false,mat,depth);
|
||||
if(!linked || linked==obj)
|
||||
if(!linked || linked==obj)
|
||||
return true;
|
||||
|
||||
Base::Matrix4D matNext;
|
||||
@@ -692,13 +693,13 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char *
|
||||
return true;
|
||||
}
|
||||
|
||||
void LinkBaseExtension::checkGeoElementMap(const App::DocumentObject *obj,
|
||||
void LinkBaseExtension::checkGeoElementMap(const App::DocumentObject *obj,
|
||||
const App::DocumentObject *linked, PyObject **pyObj, const char *postfix) const
|
||||
{
|
||||
if(!pyObj || !*pyObj || (!postfix && obj->getDocument()==linked->getDocument()) ||
|
||||
!PyObject_TypeCheck(*pyObj, &Data::ComplexGeoDataPy::Type))
|
||||
return;
|
||||
|
||||
|
||||
// auto geoData = static_cast<Data::ComplexGeoDataPy*>(*pyObj)->getComplexGeoDataPtr();
|
||||
// geoData->reTagElementMap(obj->getID(),obj->getDocument()->Hasher,postfix);
|
||||
}
|
||||
@@ -708,14 +709,14 @@ void LinkBaseExtension::onExtendedUnsetupObject() {
|
||||
return;
|
||||
auto objs = getElementListValue();
|
||||
getElementListProperty()->setValue();
|
||||
for(auto obj : objs)
|
||||
for(auto obj : objs)
|
||||
detachElement(obj);
|
||||
}
|
||||
|
||||
DocumentObject *LinkBaseExtension::getTrueLinkedObject(
|
||||
bool recurse, Base::Matrix4D *mat, int depth, bool noElement) const
|
||||
{
|
||||
if(noElement && extensionIsDerivedFrom(LinkElement::getExtensionClassTypeId())
|
||||
if(noElement && extensionIsDerivedFrom(LinkElement::getExtensionClassTypeId())
|
||||
&& !static_cast<const LinkElement*>(this)->canDelete())
|
||||
{
|
||||
return 0;
|
||||
@@ -736,10 +737,10 @@ DocumentObject *LinkBaseExtension::getTrueLinkedObject(
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LinkBaseExtension::extensionGetLinkedObject(DocumentObject *&ret,
|
||||
bool LinkBaseExtension::extensionGetLinkedObject(DocumentObject *&ret,
|
||||
bool recurse, Base::Matrix4D *mat, bool transform, int depth) const
|
||||
{
|
||||
if(mat)
|
||||
if(mat)
|
||||
*mat *= getTransform(transform);
|
||||
ret = 0;
|
||||
if(!_getElementCountValue())
|
||||
@@ -822,7 +823,7 @@ void LinkBaseExtension::updateGroup() {
|
||||
auto group = ext->getExtendedObject();
|
||||
auto &conn = plainGroupConns[group];
|
||||
if(!conn.connected()) {
|
||||
FC_LOG("new group connection " << getExtendedObject()->getFullName()
|
||||
FC_LOG("new group connection " << getExtendedObject()->getFullName()
|
||||
<< " -> " << group->getFullName());
|
||||
conn = group->signalChanged.connect(
|
||||
boost::bind(&LinkBaseExtension::slotChangedPlainGroup,this,bp::_1,bp::_2));
|
||||
@@ -836,7 +837,7 @@ void LinkBaseExtension::updateGroup() {
|
||||
groupSet.insert(child);
|
||||
auto &conn = plainGroupConns[child];
|
||||
if(!conn.connected()) {
|
||||
FC_LOG("new group connection " << getExtendedObject()->getFullName()
|
||||
FC_LOG("new group connection " << getExtendedObject()->getFullName()
|
||||
<< " -> " << child->getFullName());
|
||||
conn = child->signalChanged.connect(
|
||||
boost::bind(&LinkBaseExtension::slotChangedPlainGroup,this,bp::_1,bp::_2));
|
||||
@@ -885,7 +886,7 @@ void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop
|
||||
}
|
||||
}
|
||||
}else if(prop == _getShowElementProperty()) {
|
||||
if(_getShowElementValue())
|
||||
if(_getShowElementValue())
|
||||
update(parent,_getElementCountProperty());
|
||||
else {
|
||||
auto objs = getElementListValue();
|
||||
@@ -1001,7 +1002,7 @@ void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop
|
||||
obj->Scale.setValue(1);
|
||||
objs.push_back(obj);
|
||||
}
|
||||
if(getPlacementListProperty())
|
||||
if(getPlacementListProperty())
|
||||
getPlacementListProperty()->setSize(0);
|
||||
if(getScaleListProperty())
|
||||
getScaleListProperty()->setSize(0);
|
||||
@@ -1074,9 +1075,9 @@ void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop
|
||||
}
|
||||
}
|
||||
syncElementList();
|
||||
if(_getShowElementValue()
|
||||
&& _getElementCountProperty()
|
||||
&& getElementListProperty()
|
||||
if(_getShowElementValue()
|
||||
&& _getElementCountProperty()
|
||||
&& getElementListProperty()
|
||||
&& getElementCountValue()!=getElementListProperty()->getSize())
|
||||
{
|
||||
getElementCountProperty()->setValue(
|
||||
@@ -1121,8 +1122,8 @@ void LinkBaseExtension::cacheChildLabel(int enable) const {
|
||||
}
|
||||
|
||||
bool LinkBaseExtension::linkTransform() const {
|
||||
if(!getLinkTransformProperty() &&
|
||||
!getLinkPlacementProperty() &&
|
||||
if(!getLinkTransformProperty() &&
|
||||
!getLinkPlacementProperty() &&
|
||||
!getPlacementProperty())
|
||||
return true;
|
||||
return getLinkTransformValue();
|
||||
@@ -1138,7 +1139,7 @@ void LinkBaseExtension::syncElementList() {
|
||||
auto elements = getElementListValue();
|
||||
for(size_t i=0;i<elements.size();++i) {
|
||||
auto element = freecad_dynamic_cast<LinkElement>(elements[i]);
|
||||
if(!element || (element->myOwner && element->myOwner!=ownerID))
|
||||
if(!element || (element->myOwner && element->myOwner!=ownerID))
|
||||
continue;
|
||||
|
||||
element->myOwner = ownerID;
|
||||
@@ -1175,12 +1176,12 @@ void LinkBaseExtension::onExtendedDocumentRestored() {
|
||||
// SubElements was stored as a PropertyStringList. It is now migrated to be
|
||||
// stored inside PropertyXLink.
|
||||
auto xlink = freecad_dynamic_cast<PropertyXLink>(getLinkedObjectProperty());
|
||||
if(!xlink)
|
||||
if(!xlink)
|
||||
FC_ERR("Failed to restore SubElements for " << parent->getFullName());
|
||||
else if(!xlink->getValue())
|
||||
FC_ERR("Discard SubElements of " << parent->getFullName() << " due to null link");
|
||||
else if(xlink->getSubValues().size() > 1)
|
||||
FC_ERR("Failed to restore SubElements for " << parent->getFullName()
|
||||
FC_ERR("Failed to restore SubElements for " << parent->getFullName()
|
||||
<< " due to conflict subnames");
|
||||
else if(xlink->getSubValues().empty()) {
|
||||
auto subs = xlink->getSubValues();
|
||||
@@ -1227,8 +1228,8 @@ void LinkBaseExtension::_handleChangedPropertyName(
|
||||
}
|
||||
}
|
||||
|
||||
void LinkBaseExtension::setLink(int index, DocumentObject *obj,
|
||||
const char *subname, const std::vector<std::string> &subElements)
|
||||
void LinkBaseExtension::setLink(int index, DocumentObject *obj,
|
||||
const char *subname, const std::vector<std::string> &subElements)
|
||||
{
|
||||
auto parent = getContainer();
|
||||
if(!parent)
|
||||
@@ -1316,7 +1317,7 @@ void LinkBaseExtension::setLink(int index, DocumentObject *obj,
|
||||
|
||||
auto objs = getElementListValue();
|
||||
getElementListProperty()->setValue();
|
||||
for(auto obj : objs)
|
||||
for(auto obj : objs)
|
||||
detachElement(obj);
|
||||
return;
|
||||
}
|
||||
@@ -1421,14 +1422,21 @@ static bool isExcludedProperties(const char *name) {
|
||||
}
|
||||
|
||||
Property *LinkBaseExtension::extensionGetPropertyByName(const char* name) const {
|
||||
auto prop = inherited::extensionGetPropertyByName(name);
|
||||
if(prop || isExcludedProperties(name))
|
||||
return prop;
|
||||
if (checkingProperty)
|
||||
return inherited::extensionGetPropertyByName(name);
|
||||
Base::StateLocker guard(checkingProperty);
|
||||
if(isExcludedProperties(name))
|
||||
return nullptr;
|
||||
auto owner = getContainer();
|
||||
if(owner && owner->canLinkProperties()) {
|
||||
auto linked = getTrueLinkedObject(true);
|
||||
if(linked)
|
||||
return linked->getPropertyByName(name);
|
||||
if (owner) {
|
||||
App::Property *prop = owner->getPropertyByName(name);
|
||||
if(prop)
|
||||
return prop;
|
||||
if(owner->canLinkProperties()) {
|
||||
auto linked = getTrueLinkedObject(true);
|
||||
if(linked)
|
||||
return linked->getPropertyByName(name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+17
-15
@@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
|
||||
* Copyright (c) 2017 Zheng Lei (realthunder) <realthunder.dev@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -24,7 +24,7 @@
|
||||
#define APP_LINK_H
|
||||
|
||||
#include <unordered_set>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
#include <boost/preprocessor/facilities/expand.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
@@ -54,7 +54,7 @@
|
||||
namespace App
|
||||
{
|
||||
|
||||
class AppExport LinkBaseExtension : public App::DocumentObjectExtension
|
||||
class AppExport LinkBaseExtension : public App::DocumentObjectExtension
|
||||
{
|
||||
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::LinkExtension);
|
||||
typedef App::DocumentObjectExtension inherited;
|
||||
@@ -239,7 +239,7 @@ public:
|
||||
|
||||
bool linkTransform() const;
|
||||
|
||||
const char *getSubName() const {
|
||||
const char *getSubName() const {
|
||||
parseSubName();
|
||||
return mySubName.size()?mySubName.c_str():0;
|
||||
}
|
||||
@@ -249,12 +249,12 @@ public:
|
||||
return mySubElements;
|
||||
}
|
||||
|
||||
bool extensionGetSubObject(DocumentObject *&ret, const char *subname,
|
||||
bool extensionGetSubObject(DocumentObject *&ret, const char *subname,
|
||||
PyObject **pyObj=0, Base::Matrix4D *mat=0, bool transform=false, int depth=0) const override;
|
||||
|
||||
bool extensionGetSubObjects(std::vector<std::string>&ret, int reason) const override;
|
||||
|
||||
bool extensionGetLinkedObject(DocumentObject *&ret,
|
||||
bool extensionGetLinkedObject(DocumentObject *&ret,
|
||||
bool recurse, Base::Matrix4D *mat, bool transform, int depth) const override;
|
||||
|
||||
virtual App::DocumentObjectExecReturn *extensionExecute(void) override;
|
||||
@@ -293,13 +293,13 @@ public:
|
||||
void cacheChildLabel(int enable=-1) const;
|
||||
|
||||
protected:
|
||||
void _handleChangedPropertyName(Base::XMLReader &reader,
|
||||
void _handleChangedPropertyName(Base::XMLReader &reader,
|
||||
const char * TypeName, const char *PropName);
|
||||
void parseSubName() const;
|
||||
void update(App::DocumentObject *parent, const Property *prop);
|
||||
void syncElementList();
|
||||
void detachElement(App::DocumentObject *obj);
|
||||
void checkGeoElementMap(const App::DocumentObject *obj,
|
||||
void checkGeoElementMap(const App::DocumentObject *obj,
|
||||
const App::DocumentObject *linked, PyObject **pyObj, const char *postfix) const;
|
||||
void updateGroup();
|
||||
void slotChangedPlainGroup(const App::DocumentObject &, const App::Property &);
|
||||
@@ -310,7 +310,7 @@ protected:
|
||||
mutable std::vector<std::string> mySubElements;
|
||||
mutable std::string mySubName;
|
||||
|
||||
std::unordered_map<const App::DocumentObject*,
|
||||
std::unordered_map<const App::DocumentObject*,
|
||||
boost::signals2::scoped_connection> plainGroupConns;
|
||||
|
||||
long myOwner;
|
||||
@@ -319,6 +319,8 @@ protected:
|
||||
mutable bool enableLabelCache;
|
||||
|
||||
bool hasOldSubElement;
|
||||
|
||||
mutable bool checkingProperty = false;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -336,10 +338,10 @@ public:
|
||||
LinkExtension();
|
||||
virtual ~LinkExtension();
|
||||
|
||||
/** \name Helpers for defining extended parameter
|
||||
/** \name Helpers for defining extended parameter
|
||||
*
|
||||
* extended parameter definition
|
||||
* (Name, Type, Property_Type, Default, Document, Property_Name,
|
||||
* extended parameter definition
|
||||
* (Name, Type, Property_Type, Default, Document, Property_Name,
|
||||
* Derived_Property_Type, App_Property_Type, Group)
|
||||
*
|
||||
* This helper simply reuses Name as Property_Name, Property_Type as
|
||||
@@ -422,7 +424,7 @@ public:
|
||||
|
||||
#define LINK_PROP_DEFINE(_1,_2,_param) LINK_ETYPE(_param) LINK_ENAME(_param);
|
||||
#define LINK_PROPS_DEFINE(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_DEFINE,_,_seq)
|
||||
|
||||
|
||||
// defines the actual properties
|
||||
LINK_PROPS_DEFINE(LINK_PARAMS_EXT)
|
||||
|
||||
@@ -467,7 +469,7 @@ public:
|
||||
inherited::onDocumentRestored();
|
||||
}
|
||||
|
||||
void handleChangedPropertyName(Base::XMLReader &reader,
|
||||
void handleChangedPropertyName(Base::XMLReader &reader,
|
||||
const char * TypeName, const char *PropName) override
|
||||
{
|
||||
_handleChangedPropertyName(reader,TypeName,PropName);
|
||||
@@ -508,7 +510,7 @@ public:
|
||||
|
||||
bool canDelete() const;
|
||||
|
||||
void handleChangedPropertyName(Base::XMLReader &reader,
|
||||
void handleChangedPropertyName(Base::XMLReader &reader,
|
||||
const char * TypeName, const char *PropName) override
|
||||
{
|
||||
_handleChangedPropertyName(reader,TypeName,PropName);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
|
||||
* Copyright (c) 2017 Zheng Lei (realthunder) <realthunder.dev@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -43,8 +43,8 @@ std::string LinkBaseExtensionPy::representation(void) const
|
||||
typedef std::map<std::string, std::pair<int,Property*> > PropTmpMap;
|
||||
typedef std::map<std::string, Property*> PropMap;
|
||||
|
||||
static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap &infoMap,
|
||||
const PropMap &propMap, PyObject *key, PyObject *value)
|
||||
static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap &infoMap,
|
||||
const PropMap &propMap, PyObject *key, PyObject *value)
|
||||
{
|
||||
std::ostringstream str;
|
||||
|
||||
@@ -69,7 +69,7 @@ static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap
|
||||
}
|
||||
|
||||
const char *valStr = 0;
|
||||
if(key == value)
|
||||
if(key == value)
|
||||
valStr = keyStr;
|
||||
else if (value!=Py_None) {
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
@@ -86,7 +86,7 @@ static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap
|
||||
valStr = PyUnicode_AsUTF8(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
App::Property *prop = 0;
|
||||
auto &info = it->second;
|
||||
if(valStr) {
|
||||
@@ -98,8 +98,8 @@ static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap
|
||||
}
|
||||
prop = pIt->second;
|
||||
if(!prop->isDerivedFrom(info.type)) {
|
||||
str << "expect property '" << keyStr << "(" << valStr
|
||||
<< ") to be derived from '" << info.type.getName()
|
||||
str << "expect property '" << keyStr << "(" << valStr
|
||||
<< ") to be derived from '" << info.type.getName()
|
||||
<< "', instead of '" << prop->getTypeId().getName() << "'";
|
||||
PyErr_SetString(PyExc_TypeError, str.str().c_str());
|
||||
}
|
||||
@@ -132,7 +132,7 @@ PyObject* LinkBaseExtensionPy::configLinkProperty(PyObject *args, PyObject *keyw
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for(auto &v : props)
|
||||
for(auto &v : props)
|
||||
ext->setProperty(v.second.first,v.second.second);
|
||||
Py_Return;
|
||||
}
|
||||
@@ -182,7 +182,7 @@ PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject *args)
|
||||
Py::Tuple ret(infos.size());
|
||||
int i=0;
|
||||
for(const auto &info : infos) {
|
||||
ret.setItem(i++,Py::TupleN(Py::String(info.name),
|
||||
ret.setItem(i++,Py::TupleN(Py::String(info.name),
|
||||
Py::String(info.type.getName()),Py::String(info.doc)));
|
||||
}
|
||||
return Py::new_reference_to(ret);
|
||||
@@ -258,7 +258,7 @@ PyObject* LinkBaseExtensionPy::setLink(PyObject *_args)
|
||||
}else if(PySequence_Check(pcObj)) {
|
||||
ext->setLink(-1,0);
|
||||
Py::Sequence seq(pcObj);
|
||||
for(size_t i=0;i<seq.size();++i)
|
||||
for(Py_ssize_t i=0;i<seq.size();++i)
|
||||
parseLink(ext,i,seq[i].ptr());
|
||||
}else
|
||||
parseLink(ext,-1,_args);
|
||||
|
||||
@@ -34,7 +34,7 @@ using namespace App;
|
||||
PROPERTY_SOURCE(App::MaterialObject, App::DocumentObject)
|
||||
|
||||
|
||||
MaterialObject::MaterialObject()
|
||||
MaterialObject::MaterialObject()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(Material,(),"Material",Prop_None,"Material key/value map");
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ using namespace App;
|
||||
PROPERTY_SOURCE(App::MeasureDistance, App::DocumentObject)
|
||||
|
||||
|
||||
MeasureDistance::MeasureDistance()
|
||||
MeasureDistance::MeasureDistance()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(P1,(Base::Vector3d()),"Measurement",Prop_None,"First point of measurement");
|
||||
ADD_PROPERTY_TYPE(P2,(Base::Vector3d()),"Measurement",Prop_None,"Second point of measurement");
|
||||
|
||||
@@ -68,7 +68,7 @@ protected:
|
||||
// It is not safe to change potential object name reference at this level.
|
||||
// For example, a LinkSub with sub element name Face1 may also be some
|
||||
// object's name that may potentially be mapped. In addition, with the
|
||||
// introduction of full quanlified SubName reference, the Sub value inside
|
||||
// introduction of full qualified SubName reference, the Sub value inside
|
||||
// LinkSub may require customized mapping. So we move the mapping logic to
|
||||
// various link property's Restore() function.
|
||||
#if 0
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef APP_MERGEDOCUMENTS_H
|
||||
#define APP_MERGEDOCUMENTS_H
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
#include <Base/Persistence.h>
|
||||
|
||||
namespace zipios {
|
||||
|
||||
@@ -1153,7 +1153,7 @@ std::vector<std::string> ObjectIdentifier::getStringList() const
|
||||
|
||||
ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier &other) const
|
||||
{
|
||||
ObjectIdentifier result(owner);
|
||||
ObjectIdentifier result(other.getOwner());
|
||||
ResolveResults thisresult(*this);
|
||||
ResolveResults otherresult(other);
|
||||
|
||||
|
||||
+17
-17
@@ -82,11 +82,11 @@ public:
|
||||
|
||||
// Constructor
|
||||
String(const std::string & s = "", bool _isRealString = false, bool _forceIdentifier = false)
|
||||
: str(s), isString(_isRealString), forceIdentifier(_forceIdentifier)
|
||||
: str(s), isString(_isRealString), forceIdentifier(_forceIdentifier)
|
||||
{ }
|
||||
|
||||
String(std::string &&s, bool _isRealString = false, bool _forceIdentifier = false)
|
||||
: str(std::move(s)), isString(_isRealString), forceIdentifier(_forceIdentifier)
|
||||
: str(std::move(s)), isString(_isRealString), forceIdentifier(_forceIdentifier)
|
||||
{ }
|
||||
|
||||
FC_DEFAULT_CTORS(String) {
|
||||
@@ -125,7 +125,7 @@ public:
|
||||
|
||||
bool operator>(const String & other) const { return str > other.str; }
|
||||
|
||||
void checkImport(const App::DocumentObject *owner,
|
||||
void checkImport(const App::DocumentObject *owner,
|
||||
const App::DocumentObject *obj=0, String *objName=0);
|
||||
private:
|
||||
|
||||
@@ -164,9 +164,9 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Component(const String &_name = String(), typeEnum _type=SIMPLE,
|
||||
Component(const String &_name = String(), typeEnum _type=SIMPLE,
|
||||
int begin=INT_MAX, int end=INT_MAX, int step=1);
|
||||
Component(String &&_name, typeEnum _type=SIMPLE,
|
||||
Component(String &&_name, typeEnum _type=SIMPLE,
|
||||
int begin=INT_MAX, int end=INT_MAX, int step=1);
|
||||
|
||||
static Component SimpleComponent(const char * _component);
|
||||
@@ -224,16 +224,16 @@ public:
|
||||
|
||||
};
|
||||
|
||||
static Component SimpleComponent(const char * _component)
|
||||
static Component SimpleComponent(const char * _component)
|
||||
{return Component::SimpleComponent(_component);}
|
||||
|
||||
static Component SimpleComponent(const String & _component)
|
||||
static Component SimpleComponent(const String & _component)
|
||||
{return Component::SimpleComponent(_component);}
|
||||
|
||||
static Component SimpleComponent(String &&_component)
|
||||
static Component SimpleComponent(String &&_component)
|
||||
{return Component::SimpleComponent(std::move(_component));}
|
||||
|
||||
static Component ArrayComponent(int _index)
|
||||
static Component ArrayComponent(int _index)
|
||||
{return Component::ArrayComponent(_index); }
|
||||
|
||||
static Component RangeComponent(int _begin, int _end = INT_MAX, int _step=1)
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
static Component MapComponent(String &&_key)
|
||||
{return Component::MapComponent(_key);}
|
||||
|
||||
ObjectIdentifier(const App::PropertyContainer * _owner = 0,
|
||||
ObjectIdentifier(const App::PropertyContainer * _owner = 0,
|
||||
const std::string & property = std::string(), int index=INT_MAX);
|
||||
|
||||
ObjectIdentifier(const App::PropertyContainer * _owner, bool localProperty);
|
||||
@@ -272,13 +272,13 @@ public:
|
||||
App::DocumentObject *getOwner() const { return owner; }
|
||||
|
||||
// Components
|
||||
void addComponent(const Component &c) {
|
||||
void addComponent(const Component &c) {
|
||||
components.push_back(c);
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
// Components
|
||||
void addComponent(Component &&c) {
|
||||
void addComponent(Component &&c) {
|
||||
components.push_back(std::move(c));
|
||||
_cache.clear();
|
||||
}
|
||||
@@ -320,10 +320,10 @@ public:
|
||||
|
||||
String getDocumentName() const;
|
||||
|
||||
void setDocumentObjectName(String &&name, bool force = false,
|
||||
void setDocumentObjectName(String &&name, bool force = false,
|
||||
String &&subname = String(), bool checkImport=false);
|
||||
|
||||
void setDocumentObjectName(const App::DocumentObject *obj, bool force = false,
|
||||
void setDocumentObjectName(const App::DocumentObject *obj, bool force = false,
|
||||
String &&subname = String(), bool checkImport=false);
|
||||
|
||||
bool hasDocumentObjectName(bool forced=false) const;
|
||||
@@ -347,7 +347,7 @@ public:
|
||||
App::Document *getDocument(String name = String(), bool *ambiguous=0) const;
|
||||
|
||||
App::DocumentObject *getDocumentObject() const;
|
||||
|
||||
|
||||
std::vector<std::string> getStringList() const;
|
||||
|
||||
App::ObjectIdentifier relativeTo(const App::ObjectIdentifier & other) const;
|
||||
@@ -417,7 +417,7 @@ protected:
|
||||
|
||||
friend struct ResolveResults;
|
||||
|
||||
App::Property *resolveProperty(const App::DocumentObject *obj,
|
||||
App::Property *resolveProperty(const App::DocumentObject *obj,
|
||||
const char *propertyName, App::DocumentObject *&sobj,int &ptype) const;
|
||||
|
||||
void getSubPathStr(std::ostream &ss, const ResolveResults &result, bool toPython=false) const;
|
||||
@@ -462,7 +462,7 @@ Py::Object AppExport pyObjectFromAny(const App::any &value);
|
||||
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
struct hash<App::ObjectIdentifier> {
|
||||
typedef App::ObjectIdentifier argument_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2015 Stefan Tr�ger <stefantroeger@gmx.net> *
|
||||
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
|
||||
* Copyright (c) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
|
||||
@@ -27,12 +27,15 @@
|
||||
#endif
|
||||
|
||||
#include <Base/Exception.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <App/Document.h>
|
||||
#include "Origin.h"
|
||||
|
||||
#include "GeoFeature.h"
|
||||
|
||||
FC_LOG_LEVEL_INIT("App", true, true)
|
||||
|
||||
using namespace App;
|
||||
|
||||
EXTENSION_PROPERTY_SOURCE(App::OriginGroupExtension, App::GeoFeatureGroupExtension)
|
||||
@@ -67,12 +70,12 @@ App::Origin *OriginGroupExtension::getOrigin () const {
|
||||
}
|
||||
|
||||
bool OriginGroupExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname,
|
||||
PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const
|
||||
PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const
|
||||
{
|
||||
App::DocumentObject *originObj = Origin.getValue ();
|
||||
const char *dot;
|
||||
if(originObj && originObj->getNameInDocument() &&
|
||||
subname && (dot=strchr(subname,'.')))
|
||||
if(originObj && originObj->getNameInDocument() &&
|
||||
subname && (dot=strchr(subname,'.')))
|
||||
{
|
||||
bool found;
|
||||
if(subname[0] == '$')
|
||||
@@ -80,7 +83,7 @@ bool OriginGroupExtension::extensionGetSubObject(DocumentObject *&ret, const cha
|
||||
else
|
||||
found = std::string(subname,dot)==originObj->getNameInDocument();
|
||||
if(found) {
|
||||
if(mat && transform)
|
||||
if(mat && transform)
|
||||
*mat *= const_cast<OriginGroupExtension*>(this)->placement().getValue().toMatrix();
|
||||
ret = originObj->getSubObject(dot+1,pyObj,mat,true,depth+1);
|
||||
return true;
|
||||
@@ -93,9 +96,9 @@ App::DocumentObject *OriginGroupExtension::getGroupOfObject (const DocumentObjec
|
||||
|
||||
if(!obj)
|
||||
return nullptr;
|
||||
|
||||
|
||||
bool isOriginFeature = obj->isDerivedFrom(App::OriginFeature::getClassTypeId());
|
||||
|
||||
|
||||
auto list = obj->getInList();
|
||||
for (auto o : list) {
|
||||
if(o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId()))
|
||||
@@ -160,8 +163,12 @@ void OriginGroupExtension::extensionOnChanged(const Property* p) {
|
||||
&& owner->getDocument()->testStatus(Document::Importing)) {
|
||||
for (auto o : origin->getInList()) {
|
||||
if(o != owner && o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) {
|
||||
Origin.setValue(nullptr);
|
||||
throw Base::RuntimeError("Origin can only be in a single OriginGroup");
|
||||
// Temporarily reset 'Restoring' status to allow document to auto label new objects
|
||||
Base::ObjectStatusLocker<Document::Status, Document> guard(
|
||||
Document::Restoring, owner->getDocument(), false);
|
||||
Origin.setValue(owner->getDocument()->addObject("App::Origin", "Origin"));
|
||||
FC_WARN("Reset origin in " << owner->getFullName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,13 +185,13 @@ void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
|
||||
obj->getPropertyList(list);
|
||||
for(App::Property* prop : list) {
|
||||
if(prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId())) {
|
||||
|
||||
|
||||
auto p = static_cast<App::PropertyLink*>(prop);
|
||||
if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
|
||||
continue;
|
||||
|
||||
|
||||
p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()));
|
||||
}
|
||||
}
|
||||
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
|
||||
auto p = static_cast<App::PropertyLinkList*>(prop);
|
||||
auto vec = p->getValues();
|
||||
@@ -205,7 +212,7 @@ void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
|
||||
auto p = static_cast<App::PropertyLinkSub*>(prop);
|
||||
if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
|
||||
continue;
|
||||
|
||||
|
||||
std::vector<std::string> subValues = p->getSubValues();
|
||||
p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()), subValues);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class Origin;
|
||||
class AppExport OriginGroupExtension : public App::GeoFeatureGroupExtension
|
||||
{
|
||||
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::OriginGroupExtension);
|
||||
|
||||
|
||||
public:
|
||||
OriginGroupExtension ();
|
||||
virtual ~OriginGroupExtension ();
|
||||
@@ -48,22 +48,22 @@ public:
|
||||
return "Gui::ViewProviderOriginGroup";
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the origin group which contains this object.
|
||||
* In case this object is not part of any geoFeatureGroup 0 is returned.
|
||||
* In case this object is not part of any geoFeatureGroup, 0 is returned.
|
||||
* @param obj the object to search for
|
||||
*/
|
||||
static DocumentObject* getGroupOfObject (const DocumentObject* obj);
|
||||
|
||||
/// Returns true on changing OriginFeature set
|
||||
virtual short extensionMustExecute () override;
|
||||
|
||||
|
||||
/// Origin linked to the group
|
||||
PropertyLink Origin;
|
||||
|
||||
//changes all links of obj to a origin to point to this groupes origin
|
||||
|
||||
// changes all links of obj to a origin to point to this groups origin
|
||||
void relinkToOrigin(App::DocumentObject* obj);
|
||||
|
||||
|
||||
virtual std::vector<DocumentObject*> addObjects(std::vector<DocumentObject*> obj) override;
|
||||
virtual bool hasObject(const DocumentObject* obj, bool recursive = false) const override;
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ PyObject *OriginGroupExtensionPy::getCustomAttributes(const char* /*attr*/) cons
|
||||
|
||||
int OriginGroupExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+27
-8
@@ -67,19 +67,38 @@ Part::~Part(void)
|
||||
{
|
||||
}
|
||||
|
||||
App::Part *Part::getPartOfObject (const DocumentObject* obj) {
|
||||
|
||||
//as a Part is a geofeaturegroup it must directly link to all objects it contains, even
|
||||
//if they are in additional groups etc.
|
||||
auto list = obj->getInList();
|
||||
for (auto obj : list) {
|
||||
if(obj->isDerivedFrom(App::Part::getClassTypeId()))
|
||||
return static_cast<App::Part*>(obj);
|
||||
static App::Part *_getPartOfObject(const DocumentObject *obj,
|
||||
std::set<const DocumentObject*> *objset)
|
||||
{
|
||||
// as a Part is a geofeaturegroup it must directly link to all
|
||||
// objects it contains, even if they are in additional groups etc.
|
||||
// But we still must call 'hasObject()' to exclude link brought in by
|
||||
// expressions.
|
||||
for (auto inObj : obj->getInList()) {
|
||||
if (objset && !objset->insert(inObj).second)
|
||||
continue;
|
||||
auto group = inObj->getExtensionByType<GeoFeatureGroupExtension>(true);
|
||||
if(group && group->hasObject(obj)) {
|
||||
if(inObj->isDerivedFrom(App::Part::getClassTypeId()))
|
||||
return static_cast<App::Part*>(inObj);
|
||||
else if (objset)
|
||||
return _getPartOfObject(inObj, objset);
|
||||
// Only one parent geofeature group per object, so break
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
App::Part *Part::getPartOfObject (const DocumentObject* obj, bool recursive) {
|
||||
if (!recursive)
|
||||
return _getPartOfObject(obj, nullptr);
|
||||
std::set<const DocumentObject *> objset;
|
||||
objset.insert(obj);
|
||||
return _getPartOfObject(obj, &objset);
|
||||
}
|
||||
|
||||
|
||||
PyObject *Part::getPyObject()
|
||||
{
|
||||
|
||||
+4
-3
@@ -44,7 +44,7 @@ public:
|
||||
PropertyString Type;
|
||||
|
||||
/** @name base properties of all Assembly Items
|
||||
* This properties corospond mostly to the meta information
|
||||
* These properties correspond mostly to the meta information
|
||||
* in the App::Document class
|
||||
*/
|
||||
//@{
|
||||
@@ -86,10 +86,11 @@ public:
|
||||
|
||||
/**
|
||||
* Returns the part which contains this object.
|
||||
* In case this object is not belongs to any Part 0 is returned.
|
||||
* In case this object does not belong to any Part, 0 is returned.
|
||||
* @param obj the object to search for
|
||||
* @param recursive: whether to recursively find any grand parent Part container
|
||||
*/
|
||||
static App::Part* getPartOfObject (const DocumentObject* obj);
|
||||
static App::Part* getPartOfObject (const DocumentObject* obj, bool recursive=true);
|
||||
|
||||
virtual PyObject *getPyObject(void) override;
|
||||
};
|
||||
|
||||
@@ -49,7 +49,6 @@ PyObject *PartPy::getCustomAttributes(const char* /*attr*/) const
|
||||
|
||||
int PartPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ namespace App
|
||||
|
||||
/** Base class of all geometric document objects.
|
||||
*/
|
||||
class AppExport Path
|
||||
class AppExport Path
|
||||
{
|
||||
protected:
|
||||
std::vector<Base::Persistence *> _PathVector;
|
||||
|
||||
+4
-6
@@ -21,14 +21,12 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef _AppPlacement_h_
|
||||
#define _AppPlacement_h_
|
||||
|
||||
#include <Base/Placement.h>
|
||||
|
||||
#include "FeaturePython.h"
|
||||
#include "FeaturePython.h"
|
||||
#include "GeoFeature.h"
|
||||
#include "PropertyGeo.h"
|
||||
|
||||
@@ -59,7 +57,7 @@ public:
|
||||
/// Constructor
|
||||
Placement(void);
|
||||
virtual ~Placement();
|
||||
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "Gui::ViewProviderPlacement";
|
||||
@@ -67,7 +65,7 @@ public:
|
||||
|
||||
|
||||
};
|
||||
typedef App::FeaturePythonT<App::Placement> PlacementPython;
|
||||
typedef App::FeaturePythonT<App::Placement> PlacementPython;
|
||||
|
||||
|
||||
|
||||
@@ -76,4 +74,4 @@ typedef App::FeaturePythonT<App::Placement> PlacementPython;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
@@ -61,14 +63,13 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
// STL
|
||||
// STL
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
#include <bitset>
|
||||
#include <exception>
|
||||
@@ -76,15 +77,16 @@
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
|
||||
// Boost
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost_graph_adjacency_list.hpp>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
//namespace po = boost::program_options;
|
||||
|
||||
@@ -228,7 +228,7 @@ void Property::verifyPath(const ObjectIdentifier &p) const
|
||||
p.verify(*this);
|
||||
}
|
||||
|
||||
Property *Property::Copy(void) const
|
||||
Property *Property::Copy(void) const
|
||||
{
|
||||
// have to be reimplemented by a subclass!
|
||||
assert(0);
|
||||
@@ -242,7 +242,7 @@ void Property::Paste(const Property& /*from*/)
|
||||
}
|
||||
|
||||
void Property::setStatusValue(unsigned long status) {
|
||||
static const unsigned long mask =
|
||||
static const unsigned long mask =
|
||||
(1<<PropDynamic)
|
||||
|(1<<PropNoRecompute)
|
||||
|(1<<PropReadOnly)
|
||||
@@ -287,13 +287,13 @@ void PropertyListsBase::_setPyObject(PyObject *value) {
|
||||
const auto &item = *it;
|
||||
PyObject *key = item.first.ptr();
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if(!PyInt_Check(key))
|
||||
if(!PyInt_Check(key))
|
||||
#else
|
||||
if(!PyLong_Check(key))
|
||||
#endif
|
||||
throw Base::TypeError("expect key type to be integer");
|
||||
long idx = PyLong_AsLong(key);
|
||||
if(idx<-1 || idx>listSize)
|
||||
if(idx<-1 || idx>listSize)
|
||||
throw Base::ValueError("index out of bound");
|
||||
if(idx==-1 || idx==listSize) {
|
||||
idx = listSize;
|
||||
|
||||
+18
-18
@@ -43,7 +43,7 @@ class PropertyContainer;
|
||||
class DocumentObject;
|
||||
class Extension;
|
||||
|
||||
enum PropertyType
|
||||
enum PropertyType
|
||||
{
|
||||
Prop_None = 0, /*!< No special property type */
|
||||
Prop_ReadOnly = 1, /*!< Property is read-only in the editor */
|
||||
@@ -67,16 +67,16 @@ struct AppExport PropertyData
|
||||
:Name(name),Group(group),Docu(doc),Offset(offset),Type(type)
|
||||
{}
|
||||
};
|
||||
|
||||
//purpose of this struct is to be constructible from all acceptable container types and to
|
||||
//be able to return the offset to a property from the accepted containers. This allows to use
|
||||
//one function implementation for multiple container types without losing all type safety by
|
||||
|
||||
//purpose of this struct is to be constructible from all acceptable container types and to
|
||||
//be able to return the offset to a property from the accepted containers. This allows to use
|
||||
//one function implementation for multiple container types without losing all type safety by
|
||||
//accepting void*
|
||||
struct OffsetBase
|
||||
{
|
||||
OffsetBase(const App::PropertyContainer* container) : m_container(container) {}
|
||||
OffsetBase(const App::Extension* container) : m_container(container) {}
|
||||
|
||||
|
||||
short int getOffsetTo(const App::Property* prop) const {
|
||||
auto *pt = (const char*)prop;
|
||||
auto *base = (const char *)m_container;
|
||||
@@ -85,7 +85,7 @@ struct AppExport PropertyData
|
||||
return (short) (pt-base);
|
||||
};
|
||||
char* getOffset() const {return (char*) m_container;}
|
||||
|
||||
|
||||
private:
|
||||
const void* m_container;
|
||||
};
|
||||
@@ -115,10 +115,10 @@ struct AppExport PropertyData
|
||||
const PropertyData* parentPropertyData;
|
||||
|
||||
void addProperty(OffsetBase offsetBase,const char* PropName, Property *Prop, const char* PropertyGroup= 0, PropertyType = Prop_None, const char* PropertyDocu= 0 );
|
||||
|
||||
|
||||
const PropertySpec *findProperty(OffsetBase offsetBase,const char* PropName) const;
|
||||
const PropertySpec *findProperty(OffsetBase offsetBase,const Property* prop) const;
|
||||
|
||||
|
||||
const char* getName (OffsetBase offsetBase,const Property* prop) const;
|
||||
short getType (OffsetBase offsetBase,const Property* prop) const;
|
||||
short getType (OffsetBase offsetBase,const char* name) const;
|
||||
@@ -227,15 +227,15 @@ public:
|
||||
friend class DynamicProperty;
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/// get called by the container when a property has changed
|
||||
virtual void onChanged(const Property* /*prop*/){}
|
||||
/// get called before the value is changed
|
||||
virtual void onBeforeChange(const Property* /*prop*/){}
|
||||
|
||||
//void hasChanged(Property* prop);
|
||||
static const PropertyData * getPropertyDataPtr(void);
|
||||
virtual const PropertyData& getPropertyData(void) const;
|
||||
static const PropertyData * getPropertyDataPtr(void);
|
||||
virtual const PropertyData& getPropertyData(void) const;
|
||||
|
||||
virtual void handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName);
|
||||
virtual void handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop);
|
||||
@@ -248,12 +248,12 @@ private:
|
||||
protected:
|
||||
DynamicProperty dynamicProps;
|
||||
|
||||
private:
|
||||
private:
|
||||
std::string _propertyPrefix;
|
||||
static PropertyData propertyData;
|
||||
static PropertyData propertyData;
|
||||
};
|
||||
|
||||
/// Property define
|
||||
/// Property define
|
||||
#define _ADD_PROPERTY(_name,_prop_, _defaultval_) \
|
||||
do { \
|
||||
this->_prop_.setValue _defaultval_;\
|
||||
@@ -281,7 +281,7 @@ protected: \
|
||||
static const App::PropertyData * getPropertyDataPtr(void); \
|
||||
virtual const App::PropertyData &getPropertyData(void) const; \
|
||||
private: \
|
||||
static App::PropertyData propertyData
|
||||
static App::PropertyData propertyData
|
||||
|
||||
/// Like PROPERTY_HEADER, but with overridden methods declared as such
|
||||
#define PROPERTY_HEADER_WITH_OVERRIDE(_class_) \
|
||||
@@ -290,8 +290,8 @@ protected: \
|
||||
static const App::PropertyData * getPropertyDataPtr(void); \
|
||||
virtual const App::PropertyData &getPropertyData(void) const override; \
|
||||
private: \
|
||||
static App::PropertyData propertyData
|
||||
///
|
||||
static App::PropertyData propertyData
|
||||
///
|
||||
#define PROPERTY_SOURCE(_class_, _parentclass_) \
|
||||
TYPESYSTEM_SOURCE_P(_class_)\
|
||||
const App::PropertyData * _class_::getPropertyDataPtr(void){return &propertyData;} \
|
||||
|
||||
@@ -97,6 +97,11 @@ text names of the status.
|
||||
<UserDocu>Return the documentation string of the property of this class.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getEnumerationsOfProperty">
|
||||
<Documentation>
|
||||
<UserDocu>Return all enumeration strings of the property of this class or None if not a PropertyEnumeration.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="dumpPropertyContent" Keyword="true" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Dumps the content of the property, both the XML representation as well as the additional datafiles
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2007 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
@@ -295,7 +294,7 @@ PyObject* PropertyContainerPy::getPropertyStatus(PyObject *args)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
if(!found)
|
||||
ret.append(Py::Int((long)i));
|
||||
}
|
||||
}
|
||||
@@ -359,6 +358,33 @@ PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args)
|
||||
return Py::new_reference_to(Py::String(""));
|
||||
}
|
||||
|
||||
PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args)
|
||||
{
|
||||
char *pstr;
|
||||
if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
|
||||
if (!prop) {
|
||||
PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PropertyEnumeration *enumProp = dynamic_cast<PropertyEnumeration*>(prop);
|
||||
if (!enumProp) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
std::vector<std::string> enumerations = enumProp->getEnumVector();
|
||||
|
||||
Py::List ret;
|
||||
for (std::vector<std::string>::const_iterator it = enumerations.begin(); it != enumerations.end(); ++it) {
|
||||
ret.append(Py::String(*it));
|
||||
}
|
||||
return Py::new_reference_to(ret);
|
||||
}
|
||||
|
||||
Py::List PropertyContainerPy::getPropertiesList(void) const
|
||||
{
|
||||
Py::List ret;
|
||||
@@ -396,7 +422,7 @@ PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwd
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_IOError, "Unable parse content into binary representation");
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//build the byte array with correct size
|
||||
@@ -493,23 +519,15 @@ PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const
|
||||
// get the properties to the C++ PropertyContainer class
|
||||
std::map<std::string,App::Property*> Map;
|
||||
getPropertyContainerPtr()->getPropertyMap(Map);
|
||||
PyObject *dict = PyDict_New();
|
||||
if (dict) {
|
||||
for ( std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it )
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyDict_SetItem(dict, PyUnicode_FromString(it->first.c_str()), PyUnicode_FromString(""));
|
||||
#else
|
||||
PyDict_SetItem(dict, PyString_FromString(it->first.c_str()), PyString_FromString(""));
|
||||
#endif
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(dict);
|
||||
dict = NULL;
|
||||
}
|
||||
|
||||
Py::Dict dict;
|
||||
for (std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it) {
|
||||
dict.setItem(it->first, Py::String(""));
|
||||
}
|
||||
return dict;
|
||||
} else if(Base::streq(attr,"Shape")
|
||||
&& getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId()))
|
||||
{
|
||||
return Py::new_reference_to(dict);
|
||||
}
|
||||
///FIXME: For v0.20: Do not use stuff from Part module here!
|
||||
else if(Base::streq(attr,"Shape") && getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
|
||||
// Special treatment of Shape property
|
||||
static PyObject *_getShape = 0;
|
||||
if(!_getShape) {
|
||||
@@ -527,7 +545,7 @@ PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0,Py::Object(const_cast<PropertyContainerPy*>(this)));
|
||||
auto res = PyObject_CallObject(_getShape, args.ptr());
|
||||
if(!res)
|
||||
if(!res)
|
||||
PyErr_Clear();
|
||||
else {
|
||||
Py::Object pyres(res,true);
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <CXX/Objects.hxx>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
|
||||
using namespace App;
|
||||
@@ -111,7 +110,7 @@ Property *PropertyExpressionEngine::Copy() const
|
||||
PropertyExpressionEngine * engine = new PropertyExpressionEngine();
|
||||
|
||||
for (ExpressionMap::const_iterator it = expressions.begin(); it != expressions.end(); ++it)
|
||||
engine->expressions[it->first] = ExpressionInfo(boost::shared_ptr<Expression>(it->second.expression->copy()));
|
||||
engine->expressions[it->first] = ExpressionInfo(std::shared_ptr<Expression>(it->second.expression->copy()));
|
||||
|
||||
engine->validator = validator;
|
||||
|
||||
@@ -154,7 +153,7 @@ void PropertyExpressionEngine::Paste(const Property &from)
|
||||
expressions.clear();
|
||||
for(auto &e : fromee.expressions) {
|
||||
expressions[e.first] = ExpressionInfo(
|
||||
boost::shared_ptr<Expression>(e.second.expression->copy()));
|
||||
std::shared_ptr<Expression>(e.second.expression->copy()));
|
||||
expressionChanged(e.first);
|
||||
}
|
||||
validator = fromee.validator;
|
||||
@@ -219,7 +218,7 @@ void PropertyExpressionEngine::Restore(Base::XMLReader &reader)
|
||||
*/
|
||||
|
||||
void PropertyExpressionEngine::buildGraphStructures(const ObjectIdentifier & path,
|
||||
const boost::shared_ptr<Expression> expression,
|
||||
const std::shared_ptr<Expression> expression,
|
||||
boost::unordered_map<ObjectIdentifier, int> & nodes,
|
||||
boost::unordered_map<int, ObjectIdentifier> & revNodes,
|
||||
std::vector<Edge> & edges) const
|
||||
@@ -305,7 +304,7 @@ void PropertyExpressionEngine::afterRestore()
|
||||
|
||||
for(auto &info : *restoredExpressions) {
|
||||
ObjectIdentifier path = ObjectIdentifier::parse(docObj, info.path);
|
||||
boost::shared_ptr<Expression> expression(Expression::parse(docObj, info.expr.c_str()));
|
||||
std::shared_ptr<Expression> expression(Expression::parse(docObj, info.expr.c_str()));
|
||||
if(expression)
|
||||
expression->comment = std::move(info.comment);
|
||||
setValue(path, expression);
|
||||
@@ -352,7 +351,7 @@ const boost::any PropertyExpressionEngine::getPathValue(const App::ObjectIdentif
|
||||
* @param comment Optional comment.
|
||||
*/
|
||||
|
||||
void PropertyExpressionEngine::setValue(const ObjectIdentifier & path, boost::shared_ptr<Expression> expr)
|
||||
void PropertyExpressionEngine::setValue(const ObjectIdentifier & path, std::shared_ptr<Expression> expr)
|
||||
{
|
||||
ObjectIdentifier usePath(canonicalPath(path));
|
||||
const Property * prop = usePath.getProperty();
|
||||
@@ -624,7 +623,7 @@ bool PropertyExpressionEngine::depsAreTouched() const
|
||||
* @return Empty string on success, error message on failure.
|
||||
*/
|
||||
|
||||
std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier &path, boost::shared_ptr<const Expression> expr) const
|
||||
std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier &path, std::shared_ptr<const Expression> expr) const
|
||||
{
|
||||
std::string error;
|
||||
ObjectIdentifier usePath(canonicalPath(path));
|
||||
@@ -654,7 +653,7 @@ std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier
|
||||
ExpressionMap newExpressions = expressions;
|
||||
|
||||
// Add expression in question
|
||||
boost::shared_ptr<Expression> exprClone(expr->copy());
|
||||
std::shared_ptr<Expression> exprClone(expr->copy());
|
||||
newExpressions[usePath].expression = exprClone;
|
||||
|
||||
// Build graph; an exception will be thrown if it is not a DAG
|
||||
@@ -820,9 +819,9 @@ Property *PropertyExpressionEngine::CopyOnImportExternal(
|
||||
std::unique_ptr<PropertyExpressionEngine> engine;
|
||||
for(auto it=expressions.begin();it!=expressions.end();++it) {
|
||||
#ifdef BOOST_NO_CXX11_SMART_PTR
|
||||
boost::shared_ptr<Expression> expr(it->second.expression->importSubNames(nameMap).release());
|
||||
std::shared_ptr<Expression> expr(it->second.expression->importSubNames(nameMap).release());
|
||||
#else
|
||||
boost::shared_ptr<Expression> expr(it->second.expression->importSubNames(nameMap));
|
||||
std::shared_ptr<Expression> expr(it->second.expression->importSubNames(nameMap));
|
||||
#endif
|
||||
if(!expr && !engine)
|
||||
continue;
|
||||
@@ -830,7 +829,7 @@ Property *PropertyExpressionEngine::CopyOnImportExternal(
|
||||
engine.reset(new PropertyExpressionEngine);
|
||||
for(auto it2=expressions.begin();it2!=it;++it2) {
|
||||
engine->expressions[it2->first] = ExpressionInfo(
|
||||
boost::shared_ptr<Expression>(it2->second.expression->copy()));
|
||||
std::shared_ptr<Expression>(it2->second.expression->copy()));
|
||||
}
|
||||
}else if(!expr)
|
||||
expr = it->second.expression;
|
||||
@@ -848,9 +847,9 @@ Property *PropertyExpressionEngine::CopyOnLabelChange(App::DocumentObject *obj,
|
||||
std::unique_ptr<PropertyExpressionEngine> engine;
|
||||
for(auto it=expressions.begin();it!=expressions.end();++it) {
|
||||
#ifdef BOOST_NO_CXX11_SMART_PTR
|
||||
boost::shared_ptr<Expression> expr(it->second.expression->updateLabelReference(obj,ref,newLabel).release());
|
||||
std::shared_ptr<Expression> expr(it->second.expression->updateLabelReference(obj,ref,newLabel).release());
|
||||
#else
|
||||
boost::shared_ptr<Expression> expr(it->second.expression->updateLabelReference(obj,ref,newLabel));
|
||||
std::shared_ptr<Expression> expr(it->second.expression->updateLabelReference(obj,ref,newLabel));
|
||||
#endif
|
||||
if(!expr && !engine)
|
||||
continue;
|
||||
@@ -858,7 +857,7 @@ Property *PropertyExpressionEngine::CopyOnLabelChange(App::DocumentObject *obj,
|
||||
engine.reset(new PropertyExpressionEngine);
|
||||
for(auto it2=expressions.begin();it2!=it;++it2) {
|
||||
engine->expressions[it2->first] = ExpressionInfo(
|
||||
boost::shared_ptr<Expression>(it2->second.expression->copy()));
|
||||
std::shared_ptr<Expression>(it2->second.expression->copy()));
|
||||
}
|
||||
}else if(!expr)
|
||||
expr = it->second.expression;
|
||||
@@ -876,10 +875,10 @@ Property *PropertyExpressionEngine::CopyOnLinkReplace(const App::DocumentObject
|
||||
std::unique_ptr<PropertyExpressionEngine> engine;
|
||||
for(auto it=expressions.begin();it!=expressions.end();++it) {
|
||||
#ifdef BOOST_NO_CXX11_SMART_PTR
|
||||
boost::shared_ptr<Expression> expr(
|
||||
std::shared_ptr<Expression> expr(
|
||||
it->second.expression->replaceObject(parent,oldObj,newObj).release());
|
||||
#else
|
||||
boost::shared_ptr<Expression> expr(
|
||||
std::shared_ptr<Expression> expr(
|
||||
it->second.expression->replaceObject(parent,oldObj,newObj));
|
||||
#endif
|
||||
if(!expr && !engine)
|
||||
@@ -888,7 +887,7 @@ Property *PropertyExpressionEngine::CopyOnLinkReplace(const App::DocumentObject
|
||||
engine.reset(new PropertyExpressionEngine);
|
||||
for(auto it2=expressions.begin();it2!=it;++it2) {
|
||||
engine->expressions[it2->first] = ExpressionInfo(
|
||||
boost::shared_ptr<Expression>(it2->second.expression->copy()));
|
||||
std::shared_ptr<Expression>(it2->second.expression->copy()));
|
||||
}
|
||||
}else if(!expr)
|
||||
expr = it->second.expression;
|
||||
@@ -915,7 +914,7 @@ void PropertyExpressionEngine::setExpressions(
|
||||
AtomicPropertyChange signaller(*this);
|
||||
#ifdef BOOST_NO_CXX11_SMART_PTR
|
||||
for(auto &v : exprs)
|
||||
setValue(v.first,boost::shared_ptr<Expression>(v.second.release()));
|
||||
setValue(v.first,std::shared_ptr<Expression>(v.second.release()));
|
||||
#else
|
||||
for(auto &v : exprs)
|
||||
setValue(v.first,std::move(v.second));
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
|
||||
#include <boost/unordered/unordered_map.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
#include <boost_graph_adjacency_list.hpp>
|
||||
#include <boost/graph/topological_sort.hpp>
|
||||
#include <App/PropertyLinks.h>
|
||||
#include <App/Expression.h>
|
||||
@@ -77,16 +77,16 @@ public:
|
||||
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent,
|
||||
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override;
|
||||
|
||||
typedef boost::function<std::string (const App::ObjectIdentifier & path, boost::shared_ptr<const App::Expression> expr)> ValidatorFunc;
|
||||
typedef boost::function<std::string (const App::ObjectIdentifier & path, std::shared_ptr<const App::Expression> expr)> ValidatorFunc;
|
||||
|
||||
/**
|
||||
* @brief The ExpressionInfo struct encapsulates an expression and a comment.
|
||||
*/
|
||||
|
||||
struct ExpressionInfo {
|
||||
boost::shared_ptr<App::Expression> expression; /**< The actual expression tree */
|
||||
std::shared_ptr<App::Expression> expression; /**< The actual expression tree */
|
||||
|
||||
ExpressionInfo(boost::shared_ptr<App::Expression> expression = boost::shared_ptr<App::Expression>()) {
|
||||
ExpressionInfo(std::shared_ptr<App::Expression> expression = std::shared_ptr<App::Expression>()) {
|
||||
this->expression = expression;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
|
||||
void Restore(Base::XMLReader &reader) override;
|
||||
|
||||
void setValue(const App::ObjectIdentifier &path, boost::shared_ptr<App::Expression> expr);
|
||||
void setValue(const App::ObjectIdentifier &path, std::shared_ptr<App::Expression> expr);
|
||||
|
||||
const boost::any getPathValue(const App::ObjectIdentifier & path) const override;
|
||||
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
/* Expression validator */
|
||||
void setValidator(ValidatorFunc f) { validator = f; }
|
||||
|
||||
std::string validateExpression(const App::ObjectIdentifier & path, boost::shared_ptr<const App::Expression> expr) const;
|
||||
std::string validateExpression(const App::ObjectIdentifier & path, std::shared_ptr<const App::Expression> expr) const;
|
||||
|
||||
void renameExpressions(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> &paths);
|
||||
|
||||
@@ -179,7 +179,7 @@ private:
|
||||
std::vector<App::ObjectIdentifier> computeEvaluationOrder(ExecuteOption option);
|
||||
|
||||
void buildGraphStructures(const App::ObjectIdentifier &path,
|
||||
const boost::shared_ptr<Expression> expression, boost::unordered_map<App::ObjectIdentifier, int> &nodes,
|
||||
const std::shared_ptr<Expression> expression, boost::unordered_map<App::ObjectIdentifier, int> &nodes,
|
||||
boost::unordered_map<int, App::ObjectIdentifier> &revNodes, std::vector<Edge> &edges) const;
|
||||
|
||||
void buildGraph(const ExpressionMap &exprs,
|
||||
|
||||
@@ -225,11 +225,11 @@ bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &re
|
||||
|
||||
std::string p = path.getSubPathStr();
|
||||
if (p == ".x") {
|
||||
res = new QuantityPy(new Quantity(getValue().x,unit));
|
||||
res = Py::asObject(new QuantityPy(new Quantity(getValue().x,unit)));
|
||||
} else if(p == ".y") {
|
||||
res = new QuantityPy(new Quantity(getValue().y,unit));
|
||||
res = Py::asObject(new QuantityPy(new Quantity(getValue().y,unit)));
|
||||
} else if(p == ".z") {
|
||||
res = new QuantityPy(new Quantity(getValue().z,unit));
|
||||
res = Py::asObject(new QuantityPy(new Quantity(getValue().z,unit)));
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
@@ -678,13 +678,13 @@ bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object
|
||||
if (p == ".Rotation.Angle") {
|
||||
Base::Vector3d axis; double angle;
|
||||
_cPos.getRotation().getValue(axis,angle);
|
||||
res = new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle));
|
||||
res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle)));
|
||||
} else if (p == ".Base.x") {
|
||||
res = new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length));
|
||||
res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length)));
|
||||
} else if (p == ".Base.y") {
|
||||
res = new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length));
|
||||
res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length)));
|
||||
} else if (p == ".Base.z") {
|
||||
res = new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length));
|
||||
res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length)));
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
|
||||
+176
-167
File diff suppressed because it is too large
Load Diff
+62
-62
@@ -25,7 +25,7 @@
|
||||
#define APP_PROPERTYLINKS_H
|
||||
|
||||
// Std. configurations
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost_signals2.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@@ -52,7 +52,7 @@ class PropertyXLink;
|
||||
/**
|
||||
* @brief Defines different scopes for which a link can be valid
|
||||
* The scopes defined in this enum describe the different possibilities of where a link can point to.
|
||||
* Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in none.
|
||||
* Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in none.
|
||||
* Child: links are valid within the same or any sub GeoFeatureGroup
|
||||
* Global: all possible links are valid
|
||||
* Hidden: links are not included in dependency calculation
|
||||
@@ -67,34 +67,34 @@ enum class LinkScope {
|
||||
/**
|
||||
* @brief Enables scope handling for links
|
||||
* This class is a base for all link properties and enables them to handle scopes of the linked objects.
|
||||
* The possible scopes are defined by LinkScope enum class. The default value is Local.
|
||||
* The possible scopes are defined by LinkScope enum class. The default value is Local.
|
||||
* The scope of a property is not saved in the document. It is a value that needs to be fixed when
|
||||
* the object holding the property is loaded. That is possible with two methods:
|
||||
* the object holding the property is loaded. That is possible with two methods:
|
||||
* 1. Set the scope value in the constructor of the link property
|
||||
* 2. Use setScope to change the scope in the constructor of the link property
|
||||
*
|
||||
* The second option is only available in c++, not in python, as setscope is not exposed. It would
|
||||
*
|
||||
* The second option is only available in c++, not in python, as setscope is not exposed. It would
|
||||
* not make sense to expose it there, as restoring python objects does not call the constructor again.
|
||||
* Hence in python the only way to create a LinkProperty with different scope than local is to use a
|
||||
* specialized property for that. In c++ existing properties can simply be changed via setScope in the
|
||||
* objects constructor.
|
||||
* Hence in python the only way to create a LinkProperty with different scope than local is to use a
|
||||
* specialized property for that. In c++ existing properties can simply be changed via setScope in the
|
||||
* objects constructor.
|
||||
*/
|
||||
class AppExport ScopedLink {
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Set the links scope
|
||||
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and
|
||||
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and
|
||||
* all Childs or to all objects within the Glocal scope.
|
||||
*/
|
||||
void setScope(LinkScope scope) {_pcScope = scope;};
|
||||
void setScope(LinkScope scope) {_pcScope = scope;};
|
||||
/**
|
||||
* @brief Get the links scope
|
||||
* Retrieve what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and
|
||||
* Retrieve what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and
|
||||
* all Childs or to all objects within the Glocal scope.
|
||||
*/
|
||||
LinkScope getScope() {return _pcScope;};
|
||||
|
||||
|
||||
protected:
|
||||
LinkScope _pcScope = LinkScope::Local;
|
||||
};
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
* @sa _updateElementReference()
|
||||
*/
|
||||
virtual void updateElementReference(App::DocumentObject *feature,
|
||||
bool reverse=false, bool notify=false)
|
||||
bool reverse=false, bool notify=false)
|
||||
{
|
||||
(void)feature;
|
||||
(void)reverse;
|
||||
@@ -178,9 +178,9 @@ public:
|
||||
* this LinkScope. If false, then return only if the LinkScope
|
||||
* is not hidden.
|
||||
* @param sub: if given, then return subname references.
|
||||
* @param newStyle: whether to return new or old style subname reference
|
||||
* @param newStyle: whether to return new or old style subname reference
|
||||
*/
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const = 0;
|
||||
|
||||
/** Called to reset this link property
|
||||
@@ -203,8 +203,8 @@ public:
|
||||
*/
|
||||
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) = 0;
|
||||
|
||||
/** Return a copy of the property if the link replacement affects this property
|
||||
*
|
||||
/** Return a copy of the property if the link replacement affects this property
|
||||
*
|
||||
* @param owner: the parent object whose link property is to be replace.
|
||||
* Note that The parent may not be the container of this
|
||||
* property. Link sub property can use this opportunity to
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent,
|
||||
App::DocumentObject *oldObj, App::DocumentObject *newObj) const = 0;
|
||||
|
||||
/** Return a copy of the property if any changes caused by importing external linked object
|
||||
/** Return a copy of the property if any changes caused by importing external linked object
|
||||
*
|
||||
* @param nameMap: a map from the original external object name to the
|
||||
* imported new object name
|
||||
@@ -241,7 +241,7 @@ public:
|
||||
* @return Returns a copy of the property if its link reference is affected.
|
||||
* The copy will later be assgiend to this property by calling its Paste().
|
||||
*/
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
const std::string &ref, const char *newLabel) const
|
||||
{
|
||||
(void)obj;
|
||||
@@ -266,8 +266,8 @@ public:
|
||||
}
|
||||
|
||||
/// Helper function to return a map of linked object and its subname references
|
||||
void getLinkedElements(std::map<App::DocumentObject*, std::vector<std::string> > &elements,
|
||||
bool newStyle=true, bool all=true) const
|
||||
void getLinkedElements(std::map<App::DocumentObject*, std::vector<std::string> > &elements,
|
||||
bool newStyle=true, bool all=true) const
|
||||
{
|
||||
std::vector<App::DocumentObject*> ret;
|
||||
std::vector<std::string> subs;
|
||||
@@ -279,8 +279,8 @@ public:
|
||||
}
|
||||
|
||||
/// Helper function to return a map of linked object and its subname references
|
||||
std::map<App::DocumentObject*, std::vector<std::string> >
|
||||
linkedElements(bool newStyle=true, bool all=true) const
|
||||
std::map<App::DocumentObject*, std::vector<std::string> >
|
||||
linkedElements(bool newStyle=true, bool all=true) const
|
||||
{
|
||||
std::map<App::DocumentObject*, std::vector<std::string> > ret;
|
||||
getLinkedElements(ret,newStyle,all);
|
||||
@@ -320,8 +320,8 @@ public:
|
||||
* and correct any link sub reference.
|
||||
*/
|
||||
static std::pair<App::DocumentObject*,std::string> tryReplaceLink(
|
||||
const App::PropertyContainer *owner, App::DocumentObject *obj,
|
||||
const App::DocumentObject *parent, App::DocumentObject *oldObj,
|
||||
const App::PropertyContainer *owner, App::DocumentObject *obj,
|
||||
const App::DocumentObject *parent, App::DocumentObject *oldObj,
|
||||
App::DocumentObject *newObj, const char *sub=0);
|
||||
|
||||
/** Helper function to check and replace a link with multiple subname references
|
||||
@@ -340,9 +340,9 @@ public:
|
||||
*/
|
||||
static std::pair<App::DocumentObject*, std::vector<std::string> >
|
||||
tryReplaceLinkSubs( const App::PropertyContainer *owner,
|
||||
App::DocumentObject *obj,
|
||||
const App::DocumentObject *parent,
|
||||
App::DocumentObject *oldObj,
|
||||
App::DocumentObject *obj,
|
||||
const App::DocumentObject *parent,
|
||||
App::DocumentObject *oldObj,
|
||||
App::DocumentObject *newObj,
|
||||
const std::vector<std::string> &subs);
|
||||
|
||||
@@ -367,11 +367,11 @@ public:
|
||||
* geometry element reference change due to geometry model changes.
|
||||
*/
|
||||
bool _updateElementReference(App::DocumentObject *feature,
|
||||
App::DocumentObject *obj, std::string &sub, ShadowSub &shadow,
|
||||
App::DocumentObject *obj, std::string &sub, ShadowSub &shadow,
|
||||
bool reverse, bool notify=false);
|
||||
|
||||
/** Helper function to register geometry element reference
|
||||
*
|
||||
*
|
||||
* @param obj: the linked object
|
||||
* @param sub: the subname reference
|
||||
* @param shadow: a pair of new and old style element references to be updated.
|
||||
@@ -406,9 +406,9 @@ public:
|
||||
* the API CopyOnImportExternal(). This function helps to rewrite subname
|
||||
* reference to point to the correct sub objects that are imported.
|
||||
*/
|
||||
static std::string tryImportSubName(const App::DocumentObject *obj, const char *sub,
|
||||
const App::Document *doc, const std::map<std::string,std::string> &nameMap);
|
||||
|
||||
static std::string tryImportSubName(const App::DocumentObject *obj, const char *sub,
|
||||
const App::Document *doc, const std::map<std::string,std::string> &nameMap);
|
||||
|
||||
/** Helper function for link import operation
|
||||
*
|
||||
* @param doc: owner document of the imported objects
|
||||
@@ -446,7 +446,7 @@ public:
|
||||
* restoreLabelReference() can be used together to restore the reference
|
||||
* during import.
|
||||
*/
|
||||
static const char *exportSubName(std::string &output,
|
||||
static const char *exportSubName(std::string &output,
|
||||
const App::DocumentObject *obj, const char *subname, bool first_obj=false);
|
||||
|
||||
/** Helper function to import a subname reference
|
||||
@@ -504,7 +504,7 @@ public:
|
||||
*
|
||||
* @param obj: the object that owns the label
|
||||
* @param newLabel: the new label
|
||||
*
|
||||
*
|
||||
* @return return a map from the affected property to a copy of it with
|
||||
* updated subname references
|
||||
*/
|
||||
@@ -562,11 +562,11 @@ private:
|
||||
};
|
||||
|
||||
/** The general Link Property
|
||||
* Main Purpose of this property is to Link Objects and Features in a document. Like all links this
|
||||
* property is scope aware, meaning it does define which objects are allowed to be linked depending
|
||||
* Main Purpose of this property is to Link Objects and Features in a document. Like all links this
|
||||
* property is scope aware, meaning it does define which objects are allowed to be linked depending
|
||||
* of the GeoFeatureGroup where it is in. Default is Local.
|
||||
*
|
||||
* @note Links that are invalid in respect to the scope of this property is set to are not rejected.
|
||||
*
|
||||
* @note Links that are invalid in respect to the scope of this property is set to are not rejected.
|
||||
* They are only detected to be invalid and prevent the feature from recomputing.
|
||||
*/
|
||||
class AppExport PropertyLink : public PropertyLinkBase
|
||||
@@ -622,7 +622,7 @@ public:
|
||||
virtual const char* getEditorName(void) const override
|
||||
{ return "Gui::PropertyEditor::PropertyLinkItem"; }
|
||||
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override;
|
||||
|
||||
virtual void breakLink(App::DocumentObject *obj, bool clear) override;
|
||||
@@ -672,7 +672,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class AppExport PropertyLinkList :
|
||||
class AppExport PropertyLinkList :
|
||||
public PropertyListsT<DocumentObject*,std::vector<DocumentObject*>, PropertyLinkListBase>
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
@@ -712,7 +712,7 @@ public:
|
||||
virtual const char* getEditorName(void) const override
|
||||
{ return "Gui::PropertyEditor::PropertyLinkListItem"; }
|
||||
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override;
|
||||
|
||||
virtual void breakLink(App::DocumentObject *obj, bool clear) override;
|
||||
@@ -765,7 +765,7 @@ public:
|
||||
/** the Link Property with sub elements
|
||||
* This property links an object and a defined sequence of
|
||||
* sub elements. These subelements (like Edges of a Shape)
|
||||
* are stored as names, which can be resolved by the
|
||||
* are stored as names, which can be resolved by the
|
||||
* ComplexGeoDataType interface to concrete sub objects.
|
||||
*/
|
||||
class AppExport PropertyLinkSub : public PropertyLinkBase
|
||||
@@ -799,7 +799,7 @@ public:
|
||||
*/
|
||||
App::DocumentObject * getValue(void) const;
|
||||
|
||||
/// return the list of sub elements
|
||||
/// return the list of sub elements
|
||||
const std::vector<std::string>& getSubValues(void) const;
|
||||
|
||||
/// return the list of sub elements with mapped names
|
||||
@@ -809,7 +809,7 @@ public:
|
||||
|
||||
std::vector<std::string> getSubValues(bool newStyle) const;
|
||||
|
||||
/// return the list of sub elements starts with a special string
|
||||
/// return the list of sub elements starts with a special string
|
||||
std::vector<std::string> getSubValuesStartsWith(const char*, bool newStyle=false) const;
|
||||
|
||||
/** Returns the link type checked
|
||||
@@ -835,10 +835,10 @@ public:
|
||||
virtual const char* getEditorName(void) const override
|
||||
{ return "Gui::PropertyEditor::PropertyLinkItem"; }
|
||||
|
||||
/// Return a copy of the property if any changes caused by importing external object
|
||||
/// Return a copy of the property if any changes caused by importing external object
|
||||
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override;
|
||||
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
const std::string &ref, const char *newLabel) const override;
|
||||
|
||||
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent,
|
||||
@@ -853,7 +853,7 @@ public:
|
||||
|
||||
virtual bool referenceChanged() const override;
|
||||
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override;
|
||||
|
||||
virtual void breakLink(App::DocumentObject *obj, bool clear) override;
|
||||
@@ -980,10 +980,10 @@ public:
|
||||
virtual const char* getEditorName(void) const override
|
||||
{ return "Gui::PropertyEditor::PropertyLinkListItem"; }
|
||||
|
||||
/// Return a copy of the property if any changes caused by importing external object
|
||||
/// Return a copy of the property if any changes caused by importing external object
|
||||
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override;
|
||||
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
const std::string &ref, const char *newLabel) const override;
|
||||
|
||||
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent,
|
||||
@@ -996,7 +996,7 @@ public:
|
||||
|
||||
virtual bool referenceChanged() const override;
|
||||
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override;
|
||||
|
||||
virtual void breakLink(App::DocumentObject *obj, bool clear) override;
|
||||
@@ -1065,7 +1065,7 @@ public:
|
||||
void setValue(App::DocumentObject *,std::vector<std::string> &&SubList,
|
||||
std::vector<ShadowSub> &&ShadowSubList = {});
|
||||
|
||||
void setValue(App::DocumentObject *,const std::vector<std::string> &SubList,
|
||||
void setValue(App::DocumentObject *,const std::vector<std::string> &SubList,
|
||||
std::vector<ShadowSub > &&ShadowSubList={});
|
||||
|
||||
void setSubValues(std::vector<std::string> &&SubList,
|
||||
@@ -1073,7 +1073,7 @@ public:
|
||||
|
||||
const char *getSubName(bool newStyle=true) const;
|
||||
void setSubName(const char *subname);
|
||||
|
||||
|
||||
bool hasSubName() const {return !_SubList.empty();}
|
||||
|
||||
App::Document *getDocument() const;
|
||||
@@ -1088,10 +1088,10 @@ public:
|
||||
virtual Property *Copy(void) const override;
|
||||
virtual void Paste(const Property &from) override;
|
||||
|
||||
/// Return a copy of the property if any changes caused by importing external object
|
||||
/// Return a copy of the property if any changes caused by importing external object
|
||||
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override;
|
||||
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
const std::string &ref, const char *newLabel) const override;
|
||||
|
||||
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent,
|
||||
@@ -1114,7 +1114,7 @@ public:
|
||||
|
||||
virtual bool referenceChanged() const override;
|
||||
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override;
|
||||
|
||||
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) override;
|
||||
@@ -1260,7 +1260,7 @@ public:
|
||||
|
||||
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override;
|
||||
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
|
||||
const std::string &ref, const char *newLabel) const override;
|
||||
|
||||
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent,
|
||||
@@ -1273,7 +1273,7 @@ public:
|
||||
|
||||
virtual bool referenceChanged() const override;
|
||||
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override;
|
||||
|
||||
virtual void breakLink(App::DocumentObject *obj, bool clear) override;
|
||||
@@ -1327,9 +1327,9 @@ public:
|
||||
virtual void Save (Base::Writer &writer) const override;
|
||||
virtual void Restore(Base::XMLReader &reader) override;
|
||||
virtual void breakLink(App::DocumentObject *obj, bool clear) override;
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override;
|
||||
|
||||
|
||||
bool isLinkedToDocument(const App::Document &doc) const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -100,18 +100,18 @@ PyObject *PropertyInteger::getPyObject(void)
|
||||
}
|
||||
|
||||
void PropertyInteger::setPyObject(PyObject *value)
|
||||
{
|
||||
{
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyInt_Check(value)) {
|
||||
aboutToSetValue();
|
||||
_lValue = PyInt_AsLong(value);
|
||||
#else
|
||||
#else
|
||||
if (PyLong_Check(value)) {
|
||||
aboutToSetValue();
|
||||
_lValue = PyLong_AsLong(value);
|
||||
#endif
|
||||
hasSetValue();
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be int, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
@@ -623,6 +623,29 @@ const PropertyIntegerConstraint::Constraints* PropertyIntegerConstraint::getCon
|
||||
return _ConstStruct;
|
||||
}
|
||||
|
||||
long PropertyIntegerConstraint::getMinimum() const
|
||||
{
|
||||
if (_ConstStruct)
|
||||
return _ConstStruct->LowerBound;
|
||||
// return the min of int, not long
|
||||
return std::numeric_limits<int>::min();
|
||||
}
|
||||
|
||||
long PropertyIntegerConstraint::getMaximum() const
|
||||
{
|
||||
if (_ConstStruct)
|
||||
return _ConstStruct->UpperBound;
|
||||
// return the max of int, not long
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
|
||||
long PropertyIntegerConstraint::getStepSize() const
|
||||
{
|
||||
if (_ConstStruct)
|
||||
return _ConstStruct->StepSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PropertyIntegerConstraint::setPyObject(PyObject *value)
|
||||
{
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
@@ -744,7 +767,7 @@ long PropertyIntegerList::getPyValue(PyObject *item) const {
|
||||
if (PyInt_Check(item))
|
||||
return PyInt_AsLong(item);
|
||||
#else
|
||||
if (PyLong_Check(item))
|
||||
if (PyLong_Check(item))
|
||||
return PyLong_AsLong(item);
|
||||
#endif
|
||||
std::string error = std::string("type in list must be int, not ");
|
||||
@@ -768,13 +791,13 @@ void PropertyIntegerList::Restore(Base::XMLReader &reader)
|
||||
reader.readElement("IntegerList");
|
||||
// get the value of my Attribute
|
||||
int count = reader.getAttributeAsInteger("count");
|
||||
|
||||
|
||||
std::vector<long> values(count);
|
||||
for(int i = 0; i < count; i++) {
|
||||
reader.readElement("I");
|
||||
values[i] = reader.getAttributeAsInteger("v");
|
||||
}
|
||||
|
||||
|
||||
reader.readEndElement("IntegerList");
|
||||
|
||||
//assignment
|
||||
@@ -854,9 +877,9 @@ PyObject *PropertyIntegerSet::getPyObject(void)
|
||||
}
|
||||
|
||||
void PropertyIntegerSet::setPyObject(PyObject *value)
|
||||
{
|
||||
{
|
||||
if (PySequence_Check(value)) {
|
||||
|
||||
|
||||
Py_ssize_t nSize = PySequence_Length(value);
|
||||
std::set<long> values;
|
||||
|
||||
@@ -912,13 +935,13 @@ void PropertyIntegerSet::Restore(Base::XMLReader &reader)
|
||||
reader.readElement("IntegerSet");
|
||||
// get the value of my Attribute
|
||||
int count = reader.getAttributeAsInteger("count");
|
||||
|
||||
|
||||
std::set<long> values;
|
||||
for(int i = 0; i < count; i++) {
|
||||
reader.readElement("I");
|
||||
values.insert(reader.getAttributeAsInteger("v"));
|
||||
}
|
||||
|
||||
|
||||
reader.readEndElement("IntegerSet");
|
||||
|
||||
//assignment
|
||||
@@ -1102,8 +1125,29 @@ const PropertyFloatConstraint::Constraints* PropertyFloatConstraint::getConstra
|
||||
return _ConstStruct;
|
||||
}
|
||||
|
||||
double PropertyFloatConstraint::getMinimum() const
|
||||
{
|
||||
if (_ConstStruct)
|
||||
return _ConstStruct->LowerBound;
|
||||
return std::numeric_limits<double>::min();
|
||||
}
|
||||
|
||||
double PropertyFloatConstraint::getMaximum() const
|
||||
{
|
||||
if (_ConstStruct)
|
||||
return _ConstStruct->UpperBound;
|
||||
return std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
double PropertyFloatConstraint::getStepSize() const
|
||||
{
|
||||
if (_ConstStruct)
|
||||
return _ConstStruct->StepSize;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
void PropertyFloatConstraint::setPyObject(PyObject *value)
|
||||
{
|
||||
{
|
||||
if (PyFloat_Check(value)) {
|
||||
double temp = PyFloat_AsDouble(value);
|
||||
if (_ConstStruct) {
|
||||
@@ -1112,7 +1156,7 @@ void PropertyFloatConstraint::setPyObject(PyObject *value)
|
||||
else if (temp < _ConstStruct->LowerBound)
|
||||
temp = _ConstStruct->LowerBound;
|
||||
}
|
||||
|
||||
|
||||
aboutToSetValue();
|
||||
_dValue = temp;
|
||||
hasSetValue();
|
||||
@@ -1130,7 +1174,7 @@ void PropertyFloatConstraint::setPyObject(PyObject *value)
|
||||
else if (temp < _ConstStruct->LowerBound)
|
||||
temp = _ConstStruct->LowerBound;
|
||||
}
|
||||
|
||||
|
||||
aboutToSetValue();
|
||||
_dValue = temp;
|
||||
hasSetValue();
|
||||
@@ -1261,7 +1305,7 @@ void PropertyFloatList::Save (Base::Writer &writer) const
|
||||
writer.Stream() << writer.ind() <<"</FloatList>" << endl ;
|
||||
}
|
||||
else {
|
||||
writer.Stream() << writer.ind() << "<FloatList file=\"" <<
|
||||
writer.Stream() << writer.ind() << "<FloatList file=\"" <<
|
||||
(getSize()?writer.addFile(getName(), this):"") << "\"/>" << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -1366,8 +1410,8 @@ void PropertyString::setValue(const char* newLabel)
|
||||
|
||||
if(obj && obj->getNameInDocument() && this==&obj->Label &&
|
||||
(!obj->getDocument()->testStatus(App::Document::Restoring)||
|
||||
obj->getDocument()->testStatus(App::Document::Importing)) &&
|
||||
!obj->getDocument()->isPerformingTransaction())
|
||||
obj->getDocument()->testStatus(App::Document::Importing)) &&
|
||||
!obj->getDocument()->isPerformingTransaction())
|
||||
{
|
||||
// allow object to control label change
|
||||
|
||||
@@ -1420,7 +1464,7 @@ void PropertyString::setValue(const char* newLabel)
|
||||
break;
|
||||
}
|
||||
if(*c == 0 && std::find(objectLabels.begin(), objectLabels.end(),
|
||||
obj->getNameInDocument())==objectLabels.end())
|
||||
obj->getNameInDocument())==objectLabels.end())
|
||||
{
|
||||
label = obj->getNameInDocument();
|
||||
changed = true;
|
||||
@@ -1441,7 +1485,7 @@ void PropertyString::setValue(const char* newLabel)
|
||||
// importing (which also counts as restoring), it is possible the
|
||||
// new object changes its label. However, we cannot update label
|
||||
// references here, because object restoring is not based on
|
||||
// dependency order. It can only be done in afterRestore().
|
||||
// dependency order. It can only be done in afterRestore().
|
||||
//
|
||||
// See PropertyLinkBase::restoreLabelReference() for more details.
|
||||
propChanges = PropertyLinkBase::updateLabelReferences(obj,newLabel);
|
||||
@@ -1514,7 +1558,7 @@ void PropertyString::Save (Base::Writer &writer) const
|
||||
auto obj = dynamic_cast<DocumentObject*>(getContainer());
|
||||
writer.Stream() << writer.ind() << "<String ";
|
||||
bool exported = false;
|
||||
if(obj && obj->getNameInDocument() &&
|
||||
if(obj && obj->getNameInDocument() &&
|
||||
obj->isExporting() && &obj->Label==this)
|
||||
{
|
||||
if(obj->allowDuplicateLabel())
|
||||
@@ -1809,7 +1853,7 @@ std::string PropertyStringList::getPyValue(PyObject *item) const
|
||||
unsigned int PropertyStringList::getMemSize (void) const
|
||||
{
|
||||
size_t size=0;
|
||||
for(int i = 0;i<getSize(); i++)
|
||||
for(int i = 0;i<getSize(); i++)
|
||||
size += _lValueList[i].size();
|
||||
return static_cast<unsigned int>(size);
|
||||
}
|
||||
@@ -1838,7 +1882,7 @@ void PropertyStringList::Restore(Base::XMLReader &reader)
|
||||
reader.readElement("String");
|
||||
values[i] = reader.getAttribute("value");
|
||||
}
|
||||
|
||||
|
||||
reader.readEndElement("StringList");
|
||||
|
||||
// assignment
|
||||
@@ -1899,7 +1943,7 @@ void PropertyMap::setValues(const std::map<std::string,std::string>& map)
|
||||
|
||||
|
||||
|
||||
const std::string& PropertyMap::operator[] (const std::string& key) const
|
||||
const std::string& PropertyMap::operator[] (const std::string& key) const
|
||||
{
|
||||
static std::string empty;
|
||||
std::map<std::string,std::string>::const_iterator it = _lValueList.find(key);
|
||||
@@ -1907,7 +1951,7 @@ const std::string& PropertyMap::operator[] (const std::string& key) const
|
||||
return it->second;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PyObject *PropertyMap::getPyObject(void)
|
||||
@@ -1921,6 +1965,7 @@ PyObject *PropertyMap::getPyObject(void)
|
||||
throw Base::UnicodeError("UTF8 conversion failure at PropertyMap::getPyObject()");
|
||||
}
|
||||
PyDict_SetItemString(dict,it->first.c_str(),item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
|
||||
return dict;
|
||||
@@ -1979,7 +2024,7 @@ void PropertyMap::setPyObject(PyObject *value)
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setValues(values);
|
||||
}
|
||||
else {
|
||||
@@ -2024,7 +2069,7 @@ void PropertyMap::Restore(Base::XMLReader &reader)
|
||||
reader.readElement("Item");
|
||||
values[reader.getAttribute("key")] = reader.getAttribute("value");
|
||||
}
|
||||
|
||||
|
||||
reader.readEndElement("Map");
|
||||
|
||||
// assignment
|
||||
@@ -2325,7 +2370,7 @@ void PropertyColor::setValue(float r, float g, float b, float a)
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
const Color& PropertyColor::getValue(void) const
|
||||
const Color& PropertyColor::getValue(void) const
|
||||
{
|
||||
return _cCol;
|
||||
}
|
||||
@@ -2404,7 +2449,7 @@ void PropertyColor::setPyObject(PyObject *value)
|
||||
|
||||
void PropertyColor::Save (Base::Writer &writer) const
|
||||
{
|
||||
writer.Stream() << writer.ind() << "<PropertyColor value=\""
|
||||
writer.Stream() << writer.ind() << "<PropertyColor value=\""
|
||||
<< _cCol.getPackedValue() <<"\"/>" << endl;
|
||||
}
|
||||
|
||||
@@ -2484,7 +2529,7 @@ Color PropertyColorList::getPyValue(PyObject *item) const {
|
||||
void PropertyColorList::Save (Base::Writer &writer) const
|
||||
{
|
||||
if (!writer.isForceXML()) {
|
||||
writer.Stream() << writer.ind() << "<ColorList file=\"" <<
|
||||
writer.Stream() << writer.ind() << "<ColorList file=\"" <<
|
||||
(getSize()?writer.addFile(getName(), this):"") << "\"/>" << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -2567,7 +2612,7 @@ void PropertyMaterial::setValue(const Material &mat)
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
const Material& PropertyMaterial::getValue(void) const
|
||||
const Material& PropertyMaterial::getValue(void) const
|
||||
{
|
||||
return _cMat;
|
||||
}
|
||||
@@ -2633,13 +2678,14 @@ void PropertyMaterial::setPyObject(PyObject *value)
|
||||
|
||||
void PropertyMaterial::Save (Base::Writer &writer) const
|
||||
{
|
||||
writer.Stream() << writer.ind() << "<PropertyMaterial ambientColor=\""
|
||||
<< _cMat.ambientColor.getPackedValue()
|
||||
<< "\" diffuseColor=\"" << _cMat.diffuseColor.getPackedValue()
|
||||
writer.Stream() << writer.ind() << "<PropertyMaterial ambientColor=\""
|
||||
<< _cMat.ambientColor.getPackedValue()
|
||||
<< "\" diffuseColor=\"" << _cMat.diffuseColor.getPackedValue()
|
||||
<< "\" specularColor=\"" << _cMat.specularColor.getPackedValue()
|
||||
<< "\" emissiveColor=\"" << _cMat.emissiveColor.getPackedValue()
|
||||
<< "\" shininess=\"" << _cMat.shininess << "\" transparency=\""
|
||||
<< _cMat.transparency << "\"/>" << endl;
|
||||
<< "\" shininess=\"" << _cMat.shininess
|
||||
<< "\" transparency=\"" << _cMat.transparency
|
||||
<< "\"/>" << endl;
|
||||
}
|
||||
|
||||
void PropertyMaterial::Restore(Base::XMLReader &reader)
|
||||
@@ -2724,7 +2770,7 @@ Material PropertyMaterialList::getPyValue(PyObject *value) const {
|
||||
void PropertyMaterialList::Save(Base::Writer &writer) const
|
||||
{
|
||||
if (!writer.isForceXML()) {
|
||||
writer.Stream() << writer.ind() << "<MaterialList file=\"" <<
|
||||
writer.Stream() << writer.ind() << "<MaterialList file=\"" <<
|
||||
(getSize()?writer.addFile(getName(), this):"") << "\"/>" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user