Merge branch 'master' into addThemeSupport

This commit is contained in:
Chris Hennes
2021-09-24 07:51:04 -05:00
committed by GitHub
1543 changed files with 219178 additions and 76082 deletions
+263 -2
View File
@@ -1,11 +1,33 @@
# Contents
<a name="contents"></a>
- [Building FreeCAD on Mac OS 10.15.x -- Catalina](#build-freecad-macos-catalina)
- [Directions](#directions)
- [Install Xcode Command line tools](#install-xcode-cli-tools)
- [Install Conda](#install-conda)
- [Run the shell script](#run-the-shell-script)
- [Building FreeCAD on macOS using homebrew packages with & without formual file](#homebrew-build-fc-on-macos)
- [Requirements](#homebrew-requirements)
- [Install required FreeCAD dependencies](#homebrew-install-required-deps)
- [Limitations of using freecad formula file](#homebrew-limits-of-formula-file)
- [Directions, Installing FreeCAD using brew packages without formula file](#homebrew-install-no-form-file)
- [Expanded Directions](#homebrew-expanded-directions)
- [Boost v1.75 fix](#homebrew-boost-175-fix)
- [Errors, Issues, & Possible Solutions](#errors-issues-solutions)
<!-- SEE: https://stackoverflow.com/a/7335259/708807 for explanation of using `name` attribute for in page linking within a MD doc -->
# Building FreeCAD on Mac OS 10.15.x -- Catalina #
<a name="build-freecad-macos-catalina"></a>
General notes on how the tooling works:
This setup uses [conda](https://docs.conda.io) for dependency management.
Conda is able to pull the deps from a repository called conda-forge and
setup an isolated build environment. Not quite as isolated as docker, but
it is a good option for Mac and its what the FreeCAD CI system uses.
it is a good option for Mac and is what the FreeCAD CI system uses.
Once the dependencies are installed into a conda environment, then the
build uses the standard `cmake` configuration process to configure the build
@@ -15,18 +37,26 @@ that architecture.
All of this, and some sanity checks, are in a unified shell script. See below.
# Directions #
# Directions
<a name="directions"></a>
## Install XCode Command line tools ##
<a name="install-xcode-cli-tools"></a>
Run `xcode-select --install` and click through.
## Install Conda ##
<a name="install-conda"></a>
Refer to [MiniConda Docs](https://docs.conda.io/en/latest/miniconda.html).
## Run the shell script ##
<a name="run-the-shell-script"></a>
Run the `./build_unix_dev_conda.sh` and go get coffee. Builds take
an hour+ on a 2012 Retina MacBook.
@@ -36,3 +66,234 @@ Output binaries will be in the `./build/bin/FreeCAD` *and*
You can code/build/test using the cmake configuration folder `./build` in
the standard way *from within the freecad_dev conda environment*.
---
# Building FreeCAD on macOS using homebrew with & without a formula file
<a name="homebrew-build-fc-on-macos"></a>
> The below procedure provides an alternative way to install FreeCAD from the git source on macOS without having to use conda, but rather relies on [**mac homebrew**][lnk1] to manage dependencies.
## Requirements
<a name="homebrew-requirements"></a>
- macOS, running High Sierra _10.13_ or later
- homebrew installed and working
- All required dependencies to build FreeCAD installed using `brew install`
There is an official [**homebrew tap**][lnk2] that provides a list of formulas along with FreeCAD to setup all the dependencies to build FreeCAD from source on macOS, and also provides prebuilt bottles to install FreeCAD from a package rather than building from source.
> 💡 The below steps will build a FreeCAD binary that will launch FreeCAD from a command line interface, and will **NOT** build the **FreeCAD.app** bundle, ie. a double clickable app icon that can be launched from a Finder window.
### Install required FreeCAD dependencies
<a name="homebrew-install-required-deps"></a>
- Setup homebrew to use the official [**freecad-homebrew**][lnk2] tap.
```shell
brew tap FreeCAD/freecad
```
- Install FreeCAD dependencies provided by the tap
```shell
brew install --only-dependencies freecad
```
> The above step will install FreeCAD dependencies provided by the tap, and if a _bottle_ is provided by the tap homebrew will install the bottled version of the dep rather than building from source, unless the `install` command explicitly uses a _flag_ to build from source.
After all the dependencies have been installed, it should be possible to install FreeCAD from the provided bottle.
```shell
brew install freecad/freecad/freecad
```
> As of writing this, there are bottles provided for macOS Catalina and Big Sur
> > If running a different version of macOS then building FreeCAD from source will be required.
To explicitly build FreeCAD from source using the formula file provided by the tap
```shell
brew install freecad/freecad/freecad --build-from-source --HEAD --verbose
```
The above command will grab the latest git source of FreeCAD and output the build process to the terminal.
> NOTE: On a MacBookPro 2013 late model it takes ~60 minutes to build FreeCAD from source.
After the _make_ and _make install_ process completes it should be possible to launch FreeCAD from any directory using a terminal with the below commands,
```shell
FreeCAD
FreeCADCmd
```
- `FreeCAD` will launch a GUI version of FreeCAD
- `FreeCADCmd` will launch **only** a command line version of FreeCAD
## Limitations of using the FreeCAD formula file
<a name="homebrew-limits-of-formula-file"></a>
If FreeCAD is installed via the bottle then one will have to wait for a new bottle to be generated to install a later version of FreeCAD. However, if FreeCAD is built from source, then FreeCAD will have all the updates up to the time the build process was started.
If any of the dependencies FreeCAD relies on is updated FreeCAD will likely require a rebuild. Mac homebrew does provide a feature to pin packages at specific versions to prevent them from updating, and also allows setting of an environment variable to prevent homebrew from automatically checking for updates (which can slow things down). All that said, FreeCAD can be built using all the dependencies provided by Mac homebrew, but not using the formula file: instead cloning the source to an arbitrary path on a local filesystem. This provides a couple of advantages:
- If `brew cleanup` is run and FreeCAD was installed using the above-provided command, all source tarballs or bottles that were _checked out_ or downloaded during the install process will be deleted from the system. If a reinstall or upgrade is later required then homebrew will have to refetch the bottles, or reclone the git source again.
- Mac homebrew provides a method, _install flag_, for keeping the source regardless if the build succeeds or fails. The options are limited, however, and performing a standard `git clone` outside of homebrew is **much** preferred.
- Cloning the FreeCAD source allows passing **any** cmake flags not provided by the formula file
- Allowing the use of other build systems such as _ninja_
- Allowing the use of alternate compilers, e.g. _ccache_
- Pulling in subsequent updates are quicker because the `git clone` of the FreeCAD source will remain on the local filesystem even if a `brew cleanup` is run
- Subsequent recompiles should not take 60 minutes if using a caching strategy such as _ccache_.
## Directions, Installing FreeCAD using brew packages without a formula file
<a name="homebrew-install-no-form-file"></a>
> ⚠️ The below directions assume macOS High Sierra or later is being used, homebrew is setup properly, and all dependencies were installed successfully.
**TL;DR**
- Clone the FreeCAD source, pass cmake args/flags within source dir, run make, and make install, then profit 💰
### Expanded Directions
<a name="homebrew-expanded-directions"></a>
- Clone the FreeCAD source from GitHub
```shell
git clone https://github.com/freecad/freecad
cd ./freecad
git fetch
```
> The above _fetch_ cmd will take some time to fetch the commit history for the repo, but if a shallow clone is performed then FreeCAD will not show to correct build number in the About dialog [**learn more**][lnk3].
Advanced users may alter the process below to build in a different location, use a different compiler, etc. but these instructions represent a procedure that works successfully for this author.
Set the path / environment variables for specifying the compilers to use
```
export CC="/usr/local/opt/llvm/bin/clang"
export CXX="/usr/local/opt/llvm/bin/clang++"
```
- Linking the brew-provided install of python 3 will be required in order for cmake to find the proper python and python libraries.
```shell
brew link [email protected]
```
#### Boost v1.75 fix
<a name="homebrew-boost-175-fix"></a>
- Due to recent changes in boost v1.75, building FreeCAD will fail with the below linking error message (for a more exhaustive error message, [**learn more**][lnk4])
To work around the linking issue until the [**PR**][lnk5] is merged install boost will the patches applied within the PR.
```shell
ld: library not found for -licudata
```
```shell
git checkout -b mybuild
cmake \
-DCMAKE_C_FLAGS_RELEASE=-DNDEBUG \
-DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG \
-DCMAKE_INSTALL_PREFIX=/opt/beta/freecad \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_FIND_FRAMEWORK=LAST
-DCMAKE_VERBOSE_MAKEFILE=ON \
-Wno-dev \
-DCMAKE_OSX_SYSROOT=/Library/Developer/CommandLineTools/SDKs/macOSX10.14.sdk \
-std=c++14 \
-DCMAKE_CXX_STANDARD=14 \
-DBUILD_ENABLE_CXX_STD:STRING=C++14 \
-Wno-deprecated-declarations \
-DUSE_PYTHON3=1 -DPYTHON_EXECUTABLE=/usr/local/bin/python3 \
-DBUILD_FEM_NETGEN=1 \
-DBUILD_FEM=1 \
-DBUILD_TECHDRAW=0 \
-DFREECAD_USE_EXTERNAL_KDL=ON \
-DFREECAD_CREATE_MAC_APP=OFF
-DCMAKE_PREFIX_PATH="/usr/local/opt/qt/lib/cmake;/usr/local/opt/nglib/Contents/Resources;/usr/local/opt/[email protected]/lib/cmake;/usr/local;" .
```
After the configuration completes run the below commands to start the build & install process
```shell
make
make install
```
> 💡 Author's note: The above cmake build flags are the ones I've had good luck with, but that's not to say other ones can be added or removed. And for reasons unknown to me the above build process takes ~ twice along than using `brew install --build-from-source`
If everything goes well FreeCAD should be able to launch from a terminal
## Errors and Issues + possible solutions
<a name="errors-issues-solutions"></a>
Some common pitfalls are listed in this section.
---
<details>
<summary><strong>error:</strong> no member named </summary>
```shell
[ 18%] Building CXX object src/Gui/CMakeFiles/FreeCADGui.dir/DlgProjectInformationImp.cpp.o
cd /opt/code/github/public/forks/freecad/build/src/Gui && /usr/local/bin/ccache /usr/local/opt/llvm/bin/clang++ -DBOOST_ALL_NO_LIB -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PP_VARIADICS=1 -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_REGEX_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_THREAD_DYN_LINK -DBUILD_ADDONMGR -DCMAKE_BUILD_TYPE=\"Release\" -DFreeCADGui_EXPORTS -DGL_SILENCE_DEPRECATION -DHAVE_CONFIG_H -DHAVE_FREEIMAGE -DHAVE_PYSIDE2 -DHAVE_RAPIDJSON -DHAVE_SHIBOKEN2 -DHAVE_TBB -DNDEBUG -DOCC_CONVERT_SIGNALS -DPYSIDE_QML_SUPPORT=1 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB -DQT_UITOOLS_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_OCC64 -I/opt/code/github/public/forks/freecad/build -I/opt/code/github/public/forks/freecad/build/src -I/opt/code/github/public/forks/freecad/src -I/opt/code/github/public/forks/freecad/src/Gui -I/opt/code/github/public/forks/freecad/src/Gui/Quarter -I/opt/code/github/public/forks/freecad/build/src/Gui -I/opt/code/github/public/forks/freecad/src/Gui/.. -I/opt/code/github/public/forks/freecad/build/src/Gui/.. -I/opt/code/github/public/forks/freecad/build/src/Gui/Language -I/opt/code/github/public/forks/freecad/build/src/Gui/propertyeditor -I/opt/code/github/public/forks/freecad/build/src/Gui/TaskView -I/opt/code/github/public/forks/freecad/build/src/Gui/Quarter -I/opt/code/github/public/forks/freecad/build/src/Gui/DAGView -I/usr/local/include/eigen3 -I/usr/local/include/PySide2/QtCore -I/usr/local/include/PySide2/QtGui -I/usr/local/include/PySide2/QtWidgets -isystem /usr/local/include -isystem /usr/local/Frameworks/Python.framework/Versions/3.9/include/python3.9 -iframework /usr/local/opt/qt/lib -isystem /usr/local/opt/qt/lib/QtCore.framework/Headers -isystem /usr/local/opt/qt/./mkspecs/macx-clang -isystem /usr/local/opt/qt/lib/QtWidgets.framework/Headers -isystem /usr/local/opt/qt/lib/QtGui.framework/Headers -isystem /Library/Developer/CommandLineTools/SDKs/macOSX10.14.sdk/System/Library/Frameworks/OpenGL.framework/Headers -isystem /usr/local/opt/qt/lib/QtOpenGL.framework/Headers -isystem /usr/local/opt/qt/lib/QtPrintSupport.framework/Headers -isystem /usr/local/opt/qt/lib/QtSvg.framework/Headers -isystem /usr/local/opt/qt/lib/QtNetwork.framework/Headers -isystem /usr/local/opt/qt/include -isystem /usr/local/opt/qt/include/QtUiTools -isystem /usr/local/include/shiboken2 -isystem /usr/local/include/PySide2 -isystem /usr/local/opt/qt/lib/QtXml.framework/Headers -Wall -Wextra -Wpedantic -Wno-write-strings -Wno-undefined-var-template -DNDEBUG -isysroot /Library/Developer/CommandLineTools/SDKs/macOSX10.14.sdk -fPIC -I/usr/local/Cellar/open-mpi/4.0.5/include -fPIC -std=gnu++14 -o CMakeFiles/FreeCADGui.dir/DlgProjectInformationImp.cpp.o -c /opt/code/github/public/forks/freecad/src/Gui/DlgProjectInformationImp.cpp
/opt/code/github/public/forks/freecad/src/Gui/DlgProjectInformationImp.cpp:56:9: error: no member named 'lineEditProgramVersion' in 'Gui::Dialog::Ui_DlgProjectInformation'
ui->lineEditProgramVersion->setText(QString::fromUtf8(doc->getProgramVersion()));
~~ ^
1 error generated.
make[2]: *** [src/Gui/CMakeFiles/FreeCADGui.dir/DlgProjectInformationImp.cpp.o] Error 1
make[1]: *** [src/Gui/CMakeFiles/FreeCADGui.dir/all] Error 2
make: *** [all] Error 2
```
</details>
FreeCAD may fail to build if creating a build directory within the _src_ directory and running `cmake ..` within the newly created _build_ directory. As it currently stands, `cmake` needs run within the _src_ directory or the this error message will likely appear during the build process.
---
<details>
<summary> ⚠️ <strong>warning:</strong> specified path differs in case from file name on disk</summary>
```
/opt/code/github/public/forks/FreeCAD/src/Gui/moc_DlgParameterFind.cpp:10:10: warning: non-portable path to file '"../../../FreeCAD/src/Gui/DlgParameterFind.h"'; specified path differs in case from file name on disk [-Wnonportable-include-path]
#include "../../../freecad/src/Gui/DlgParameterFind.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"../../../FreeCAD/src/Gui/DlgParameterFind.h"
1 warning generated.
```
</details>
On macOS most filesystems are case **insensitive**, whereas most GNU+Linux distros use _case sensitive_ file systems. So if FreeCAD source is cloned within a `FreeCAD` directory the build process on macOS may look for a `freecad` that is _case sensitive_ however the file system isn't case sensitive, thus the compiler will provide the above warning message.
One way to resolve such error message is to rename `FreeCAD` to `freecad`
```shell
mv FreeCAD freecadd;
mv freecadd freecad;
```
---
<!-- links -->
[lnk1]: <http://brew.sh>
[lnk2]: <https://github.com/FreeCAD/homebrew-freecad>
[lnk3]: <https://forum.freecadweb.org/viewtopic.php?f=4&t=51981#p446796>
[lnk4]: <https://gist.github.com/ipatch/6116824ab1f2a99b526cb07e43317b91#gistcomment-3577066>
[lnk5]: <https://github.com/Homebrew/homebrew-core/pull/67615>
+2 -2
View File
@@ -9,7 +9,7 @@
SET( COIN3D_FOUND "NO" )
IF (WIN32)
IF (CYGWIN)
IF (CYGWIN OR MINGW)
FIND_PATH(COIN3D_INCLUDE_DIRS Inventor/So.h
${CMAKE_INCLUDE_PATH}
@@ -24,7 +24,7 @@ IF (WIN32)
/usr/local/lib
)
ELSE (CYGWIN)
ELSE (CYGWIN OR MINGW)
FIND_PATH(COIN3D_INCLUDE_DIRS Inventor/So.h
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\SIM\\Coin3D\\2;Installation Path]/include"
@@ -130,7 +130,7 @@ macro(InitializeFreeCADBuildOptions)
option(BUILD_PART "Build the FreeCAD part module" ON)
option(BUILD_PART_DESIGN "Build the FreeCAD part design module" ON)
option(BUILD_PATH "Build the FreeCAD path module" ON)
option(BUILD_PLOT "Build the FreeCAD plot module" OFF)
option(BUILD_PLOT "Build the FreeCAD plot module" ON)
option(BUILD_POINTS "Build the FreeCAD points module" ON)
option(BUILD_RAYTRACING "Build the FreeCAD ray tracing module" ON)
option(BUILD_REVERSEENGINEERING "Build the FreeCAD reverse engineering module" ON)
@@ -62,17 +62,25 @@ macro(SetGlobalCompilerAndLinkerSettings)
endif(MSVC)
if(MINGW)
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=12477
# Actually '-Wno-inline-dllimport' should work to suppress warnings of the form:
# inline function 'foo' is declared as dllimport: attribute ignored
# But it doesn't work with MinGW gcc 4.5.0 while using '-Wno-attributes' seems to
# do the trick.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthreads -Wno-attributes")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthreads -Wno-attributes")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mthreads -Wl,--export-all-symbols")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mthreads -Wl,--export-all-symbols")
# http://stackoverflow.com/questions/8375310/warning-auto-importing-has-been-activated-without-enable-auto-import-specifie
# set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++")
link_libraries(-lgdi32)
if(CMAKE_COMPILER_IS_CLANGXX)
# clang for MSYS doesn't support -mthreads
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-attributes")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--export-all-symbols")
#set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--export-all-symbols")
else()
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=12477
# Actually '-Wno-inline-dllimport' should work to suppress warnings of the form:
# inline function 'foo' is declared as dllimport: attribute ignored
# But it doesn't work with MinGW gcc 4.5.0 while using '-Wno-attributes' seems to
# do the trick.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-attributes")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--export-all-symbols")
#set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--export-all-symbols")
# http://stackoverflow.com/questions/8375310/warning-auto-importing-has-been-activated-without-enable-auto-import-specifie
# set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++")
link_libraries(-lgdi32)
endif()
endif(MINGW)
endmacro(SetGlobalCompilerAndLinkerSettings)
+18 -7
View File
@@ -27,13 +27,24 @@ macro(SetupSalomeSMESH)
# check which modules are available
if(UNIX OR WIN32)
find_package(VTK COMPONENTS vtkCommonCore REQUIRED NO_MODULE)
list(APPEND VTK_COMPONENTS vtkIOMPIParallel vtkParallelMPI vtkhdf5 vtkFiltersParallelDIY2 vtkRenderingCore vtkInteractionStyle vtkRenderingFreeType vtkRenderingOpenGL2)
foreach(_module ${VTK_COMPONENTS})
list (FIND VTK_MODULES_ENABLED ${_module} _index)
if (${_index} GREATER -1)
list(APPEND AVAILABLE_VTK_COMPONENTS ${_module})
endif()
endforeach()
if(${VTK_MAJOR_VERSION} LESS 9)
list(APPEND VTK_COMPONENTS vtkIOMPIParallel vtkParallelMPI vtkhdf5 vtkFiltersParallelDIY2 vtkRenderingCore vtkInteractionStyle vtkRenderingFreeType vtkRenderingOpenGL2)
foreach(_module ${VTK_COMPONENTS})
list (FIND VTK_MODULES_ENABLED ${_module} _index)
if(${_index} GREATER -1)
list(APPEND AVAILABLE_VTK_COMPONENTS ${_module})
endif()
endforeach()
else()
set(VTK_COMPONENTS "CommonCore;CommonDataModel;FiltersVerdict;IOXML;FiltersCore;FiltersGeneral;IOLegacy;FiltersExtraction;FiltersSources;FiltersGeometry")
list(APPEND VTK_COMPONENTS "IOMPIParallel;ParallelMPI;hdf5;FiltersParallelDIY2;RenderingCore;InteractionStyle;RenderingFreeType;RenderingOpenGL2")
foreach(_module ${VTK_COMPONENTS})
list (FIND VTK_AVAILABLE_COMPONENTS ${_module} _index)
if(${_index} GREATER -1)
list(APPEND AVAILABLE_VTK_COMPONENTS ${_module})
endif()
endforeach()
endif()
endif()
# don't check VERSION 6 as this would exclude VERSION 7
+43
View File
@@ -0,0 +1,43 @@
# gitlab CI config file
# this image is on dockerhub. Dockerfile is here: https://gitlab.com/PrzemoF/FreeCAD/-/blob/gitlab-v1/ci/Dockerfile
image: freecadci/runner
stages: # List of stages for jobs, and their order of execution
- build
- test
before_script:
- apt-get update -yqq
# CCache Config
- mkdir -p ccache
- export CCACHE_BASEDIR=${PWD}
- export CCACHE_DIR=${PWD}/ccache
cache:
paths:
- ccache/
build-job: # This job runs in the build stage, which runs first.
stage: build
script:
- echo "Compiling the code..."
- mkdir build
- cd build
- ccache cmake ../
- ccache cmake --build ./ -j$(nproc)
- echo "Compile complete."
artifacts:
paths:
- build/
test-job: # This job runs in the test stage.
stage: test # It only starts when the job in the build stage completes successfully.
script:
- echo "Running unit tests... "
- cd build/bin/
# Testing currently doesn't work due to problems with libraries ot being visible by the binary.
- ./FreeCADCmd -t 0
+118
View File
@@ -0,0 +1,118 @@
FROM ubuntu:20.04
MAINTAINER Przemo Firszt
# This is the docker image definition used to build FreeCAD. It's currently accessible on:
# https://hub.docker.com/repository/docker/freecadci/runner
# on under name freecadci/runner when using docker
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y
RUN apt-get update -y && apt-get install -y gnupg2
RUN echo "deb http://ppa.launchpad.net/freecad-maintainers/freecad-daily/ubuntu focal main" >> /etc/apt/sources.list.d/freecad-daily.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 83193AA3B52FF6FCF10A1BBF005EAE8119BB5BCA
RUN apt-get update -y
# those 3 are for debugging purposes only. Not required to build FreeCAD
RUN apt-get install -y \
vim \
nano \
bash
# Main set of FreeCAD dependencies. To be verified.
RUN apt-get install -y \
ccache \
cmake \
debhelper \
dh-exec \
dh-python \
doxygen \
git \
graphviz \
libboost-date-time-dev \
libboost-dev \
libboost-filesystem-dev \
libboost-filesystem1.71-dev \
libboost-graph-dev \
libboost-iostreams-dev \
libboost-program-options-dev \
libboost-program-options1.71-dev \
libboost-python1.71-dev \
libboost-regex-dev \
libboost-regex1.71-dev \
libboost-serialization-dev \
libboost-system1.71-dev \
libboost-thread-dev \
libboost-thread1.71-dev \
libboost1.71-dev \
libcoin-dev \
libdouble-conversion-dev \
libeigen3-dev \
libglew-dev \
libgts-bin \
libgts-dev \
libkdtree++-dev \
liblz4-dev \
libmedc-dev \
libmetis-dev \
libnglib-dev \
libocct-data-exchange-dev \
libocct-ocaf-dev \
libocct-visualization-dev \
libopencv-dev \
libproj-dev \
libpyside2-dev \
libqt5opengl5 \
libqt5opengl5-dev \
libqt5svg5-dev \
libqt5webkit5 \
libqt5webkit5-dev \
libqt5x11extras5-dev \
libqt5xmlpatterns5-dev \
libshiboken2-dev \
libspnav-dev \
libvtk7-dev \
libvtk7.1p \
libvtk7.1p-qt \
libx11-dev \
libxerces-c-dev \
libzipios++-dev \
lsb-release \
nastran \
netgen \
netgen-headers \
occt-draw \
pybind11-dev \
pyqt5-dev-tools \
pyside2-tools \
python3-dev \
python3-matplotlib \
python3-pivy \
python3-ply \
python3-pyqt5 \
python3-pyside2.* \
python3-pyside2.qtcore \
python3-pyside2.qtgui \
python3-pyside2.qtsvg \
python3-pyside2.qtuitools \
python3-pyside2.qtwidgets \
python3-pyside2.qtxml \
python3-requests \
python3-yaml \
qt5-default \
qt5-qmake \
qtbase5-dev \
qttools5-dev \
qtwebengine5-dev \
swig
RUN apt-get update -y --fix-missing
# Clean
RUN apt-get clean \
&& rm /var/lib/apt/lists/* \
/usr/share/doc/* \
/usr/share/locale/* \
/usr/share/man/* \
/usr/share/info/* -fR
-1
View File
@@ -35,7 +35,6 @@ cmake -G "Ninja" ^
-D SMESH_INCLUDE_DIR:FILEPATH=%LIBRARY_PREFIX%/include/smesh ^
-D FREECAD_USE_EXTERNAL_SMESH:BOOL=ON ^
-D BUILD_FLAT_MESH:BOOL=ON ^
-D BUILD_PLOT:BOOL=OFF ^
-D OCCT_CMAKE_FALLBACK:BOOL=ON ^
-D PYTHON_EXECUTABLE:FILEPATH=%PREFIX%/python ^
-D BUILD_DYNAMIC_LINK_PYTHON:BOOL=ON ^
-1
View File
@@ -62,7 +62,6 @@ cmake \
-D BUILD_WITH_CONDA:BOOL=ON \
-D PYTHON_EXECUTABLE:FILEPATH=$PREFIX/bin/python \
-D BUILD_FEM_NETGEN:BOOL=ON \
-D BUILD_PLOT:BOOL=OFF \
-D OCCT_CMAKE_FALLBACK:BOOL=OFF \
-D FREECAD_USE_QT_DIALOG:BOOL=ON \
-D BUILD_DYNAMIC_LINK_PYTHON:BOOL=OFF \
Binary file not shown.
+4 -2
View File
@@ -31,8 +31,8 @@
Name: %{name}
Epoch: 1
Version: 0.19
Release: pre_{{{ git_commit_no }}}%{?dist}
Version: 0.20
Release: pre_{{{git_commit_no}}}%{?dist}
Summary: A general purpose 3D CAD modeler
Group: Applications/Engineering
@@ -50,7 +50,9 @@ BuildRequires: git
# Development Libraries
BuildRequires: Coin4-devel
%if 0%{?fedora} < 35
BuildRequires: Inventor-devel
%endif
BuildRequires: opencascade-devel
BuildRequires: boost-devel
BuildRequires: boost-python3-devel
+1 -1
View File
@@ -1,4 +1,4 @@
function git_commit_no {
commits=$(curl -s 'https://api.github.com/repos/FreeCAD/FreeCAD/compare/120ca87015...master' | grep "ahead_by" | sed -s 's/ //g' | sed -s 's/"ahead_by"://' | sed -s 's/,//')
echo $((commits + 1))
echo -n $((commits + 1))
}
+2 -2
View File
@@ -54,8 +54,8 @@ namespace KDTree
inline _Base_iterator(_Base_const_ptr const __N = NULL)
: _M_node(__N) {}
inline _Base_iterator(_Base_iterator const& __THAT)
: _M_node(__THAT._M_node) {}
//inline _Base_iterator(_Base_iterator const& __THAT)
// : _M_node(__THAT._M_node) {}
inline void
_M_increment()
+1 -1
View File
@@ -243,7 +243,7 @@ TARGET_LINK_LIBRARIES(DriverSTL ${SMESH_LIBS} Driver SMDS ${Boost_LIBRARIES})
SET_BIN_DIR(DriverSTL DriverSTL)
if(WIN32)
set_target_properties(DriverSTL PROPERTIES COMPILE_FLAGS "-DMESHDRIVERSTL_EXPORTS -DBASICS_EXPORT -DSMESHUtils_EXPORTS -DBASICS_EXPORTS")
set_target_properties(DriverSTL PROPERTIES COMPILE_FLAGS "-DMESHDRIVERSTL_EXPORTS -DSMESHUtils_EXPORTS -DBASICS_EXPORTS")
endif(WIN32)
+1 -1
View File
@@ -34,7 +34,7 @@
#else
// avoid name collision with std::byte in C++17
#define NOCRYPT
#define NOGDI
#define NOGDI NOGDI
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib,"winmm.lib")
+3 -3
View File
@@ -126,14 +126,14 @@ public:
void destroy(X* obj)
{
long adrobj = (long) (obj);
intptr_t adrobj = (intptr_t) (obj);
for (size_t i = 0; i < _chunkList.size(); i++)
{
X* chunk = _chunkList[i];
long adrmin = (long) (chunk);
intptr_t adrmin = (intptr_t) (chunk);
if (adrobj < adrmin)
continue;
long adrmax = (long) (chunk + _chunkSize);
intptr_t adrmax = (intptr_t) (chunk + _chunkSize);
if (adrobj >= adrmax)
continue;
int rank = (adrobj - adrmin) / sizeof(X);
+1 -1
View File
@@ -36,7 +36,7 @@ class SMDS_EXPORT SMDS_SpacePosition:public SMDS_Position
public:
SMDS_SpacePosition(double x=0, double y=0, double z=0);
virtual inline SMDS_TypeOfPosition GetTypeOfPosition() const;
virtual SMDS_TypeOfPosition GetTypeOfPosition() const;
static SMDS_PositionPtr originSpacePosition();
private:
static SMDS_SpacePosition* _originPosition;
+2 -2
View File
@@ -50,7 +50,7 @@ typedef void (*PVF)();
class SMESH_EXPORT Unexpect { //save / retrieve unexpected exceptions treatment
PVF old;
public :
#ifndef WNT
#ifndef _MSC_VER
// std::set_unexpected has been removed in C++17
Unexpect( PVF f )
{ /*old = std::set_unexpected(f);*/old = f; }
@@ -66,7 +66,7 @@ class SMESH_EXPORT Terminate {//save / retrieve terminate function
PVF old;
public :
#ifndef WNT
#ifndef _MSC_VER
Terminate( PVF f )
{ old = std::set_terminate(f); }
~Terminate() { std::set_terminate(old); }
+1 -1
View File
@@ -46,7 +46,7 @@
#include <list>
#ifdef WIN32
#ifdef _MSC_VER
#pragma warning(disable:4251) // Warning DLL Interface ...
#pragma warning(disable:4290) // Warning Exception ...
#endif
+2 -2
View File
@@ -38,7 +38,7 @@ typedef void (*PVF)();
class UTILS_EXPORT Unexpect { //save / retrieve unexpected exceptions treatment
PVF old;
public :
#ifndef WIN32
#ifndef _MSC_VER
// std::set_unexpected has been removed in C++17
Unexpect( PVF f )
{ /*old = std::set_unexpected(f);*/old = f; }
@@ -54,7 +54,7 @@ class UTILS_EXPORT Terminate {//save / retrieve terminate function
PVF old;
public :
#ifndef WIN32
#ifndef _MSC_VER
Terminate( PVF f )
{ old = std::set_terminate(f); }
~Terminate() { std::set_terminate(old); }
@@ -23,8 +23,10 @@
#include "DriverSTL_W_SMDS_Mesh.h"
#ifdef WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#endif
#include <Basics_Utils.hxx>
+2 -1
View File
@@ -141,7 +141,8 @@ void SMESH_File::close()
_pos = _end = 0;
_size = -1;
}
else if ( _file >= 0 )
//else if ( _file >= 0 )
else if ( _file != 0 )
{
#ifdef WIN32
if(_file != INVALID_HANDLE_VALUE) {
@@ -102,11 +102,11 @@ namespace HERE = StdMeshers_ProjectionUtils;
namespace {
static SMESHDS_Mesh* theMeshDS[2] = { 0, 0 }; // used for debug only
inline long shapeIndex(const TopoDS_Shape& S)
inline intptr_t shapeIndex(const TopoDS_Shape& S)
{
if ( theMeshDS[0] && theMeshDS[1] )
return max(theMeshDS[0]->ShapeToIndex(S), theMeshDS[1]->ShapeToIndex(S) );
return long(S.TShape().operator->());
return intptr_t(S.TShape().operator->());
}
//================================================================================
+11 -5
View File
@@ -66,6 +66,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees.
# include <climits>
# include <bitset>
# include <random>
# include <boost/filesystem.hpp>
#endif
#include <boost/algorithm/string.hpp>
@@ -142,6 +143,8 @@ using namespace zipios;
# define FC_LOGFEATUREUPDATE
#endif
namespace fs = boost::filesystem;
// typedef boost::property<boost::vertex_root_t, DocumentObject* > VertexProperty;
typedef boost::adjacency_list <
boost::vecS, // class OutEdgeListS : a Sequence or an AssociativeContainer
@@ -2398,8 +2401,8 @@ private:
Base::FileInfo tmp(sourcename);
if (tmp.renameFile(targetname.c_str()) == false) {
Base::Console().Warning("Cannot rename file from '%s' to '%s'\n",
sourcename.c_str(), targetname.c_str());
throw Base::FileException(
"Cannot rename tmp save file to project file", targetname);
}
}
void applyTimeStamp(const std::string& sourcename, const std::string& targetname) {
@@ -2531,9 +2534,8 @@ private:
Base::FileInfo tmp(sourcename);
if (tmp.renameFile(targetname.c_str()) == false) {
Base::Console().Error("Save interrupted: Cannot rename file from '%s' to '%s'\n",
sourcename.c_str(), targetname.c_str());
//throw Base::FileException("Save interrupted: Cannot rename temporary file to project file", tmp);
throw Base::FileException(
"Save interrupted: Cannot rename temporary file to project file", tmp);
}
if (numberOfFiles <= 0) {
@@ -2610,6 +2612,10 @@ bool Document::saveToFile(const char* filename) const
fn += uuid;
}
Base::FileInfo tmp(fn);
// In case some folders in the path do not exist
fs::path parent = fs::path(filename).parent_path();
if (!parent.empty() && !parent.filename_is_dot() && !parent.filename_is_dot_dot())
fs::create_directories(parent);
// open extra scope to close ZipWriter properly
{
+1 -1
View File
@@ -55,7 +55,7 @@
<UserDocu>Register an expression for a property</UserDocu>
</Documentation>
</Methode>
<Methode Name="evalExpression">
<Methode Name="evalExpression" Class="true">
<Documentation>
<UserDocu>Evaluate an expression</UserDocu>
</Documentation>
+21 -5
View File
@@ -346,15 +346,31 @@ PyObject* DocumentObjectPy::setExpression(PyObject * args)
Py_Return;
}
PyObject* DocumentObjectPy::evalExpression(PyObject * args)
PyObject* DocumentObjectPy::evalExpression(PyObject *self, PyObject * args)
{
const char *expr;
if (!PyArg_ParseTuple(args, "s", &expr)) // convert args: Python->C
return NULL; // NULL triggers exception
if (!PyArg_ParseTuple(args, "s", &expr))
return nullptr;
// HINT:
// The standard behaviour of Python for class methods is to always pass the class
// object as first argument.
// For FreeCAD-specific types the behaviour is a bit different:
// When calling this method for an instance then this is passed as first argument
// and otherwise the class object is passed.
// This behaviour is achieved by the function _getattr() that passed 'this' to
// PyCFunction_New().
//
// evalExpression() is a class method and thus 'self' can either be an instance of
// DocumentObjectPy or a type object.
App::DocumentObject* obj = nullptr;
if (self && PyObject_TypeCheck(self, &DocumentObjectPy::Type)) {
obj = static_cast<DocumentObjectPy*>(self)->getDocumentObjectPtr();
}
PY_TRY {
std::shared_ptr<Expression> shared_expr(Expression::parse(getDocumentObjectPtr(), expr));
if(shared_expr)
std::shared_ptr<Expression> shared_expr(Expression::parse(obj, expr));
if (shared_expr)
return Py::new_reference_to(shared_expr->getPyValue());
Py_Return;
} PY_CATCH
+3 -3
View File
@@ -484,11 +484,11 @@ App::any pyObjectToAny(Py::Object value, bool check) {
if (PyLong_Check(pyvalue))
return App::any(PyLong_AsLong(pyvalue));
else if (PyUnicode_Check(pyvalue)) {
const char* value = PyUnicode_AsUTF8(pyvalue);
if (!value) {
const char* utf8value = PyUnicode_AsUTF8(pyvalue);
if (!utf8value) {
FC_THROWM(Base::ValueError, "Invalid unicode string");
}
return App::any(std::string(value));
return App::any(std::string(utf8value));
}
else {
return App::any(pyObjectWrap(pyvalue));
+2 -2
View File
@@ -1322,8 +1322,8 @@ void LinkBaseExtension::setLink(int index, DocumentObject *obj,
auto objs = getElementListValue();
getElementListProperty()->setValue();
for(auto obj : objs)
detachElement(obj);
for(auto thisObj : objs)
detachElement(thisObj);
return;
}
+3 -3
View File
@@ -1490,14 +1490,14 @@ void ObjectIdentifier::String::checkImport(const App::DocumentObject *owner,
else {
str.resize(str.size()-1);
auto mapped = reader->getName(str.c_str());
auto obj = owner->getDocument()->getObject(mapped);
if (!obj) {
auto objForMapped = owner->getDocument()->getObject(mapped);
if (!objForMapped) {
FC_ERR("Cannot find object " << str);
}
else {
isString = true;
forceIdentifier = false;
str = obj->Label.getValue();
str = objForMapped->Label.getValue();
}
}
}
+3 -3
View File
@@ -2729,9 +2729,9 @@ public:
// potentially unchanged. So we just touch at most one.
std::set<Document*> docs;
for(auto link : links) {
auto doc = static_cast<DocumentObject*>(link->getContainer())->getDocument();
auto ret = docs.insert(doc);
if(ret.second && !doc->isTouched())
auto linkdoc = static_cast<DocumentObject*>(link->getContainer())->getDocument();
auto ret = docs.insert(linkdoc);
if(ret.second && !linkdoc->isTouched())
link->touch();
}
}
+12
View File
@@ -324,6 +324,18 @@ PropertyPressure::PropertyPressure()
setUnit(Base::Unit::Pressure);
}
//**************************************************************************
//**************************************************************************
// PropertyStiffness
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TYPESYSTEM_SOURCE(App::PropertyStiffness, App::PropertyQuantity)
PropertyStiffness::PropertyStiffness()
{
setUnit(Base::Unit::Stiffness);
}
//**************************************************************************
//**************************************************************************
// PropertyForce
+12
View File
@@ -227,6 +227,18 @@ public:
virtual ~PropertyPressure(){}
};
/** Stiffness property
* This is a property for representing stiffness. It is basically a float
* property. On the Gui it has a quantity like m/s^2.
*/
class AppExport PropertyStiffness: public PropertyQuantity
{
TYPESYSTEM_HEADER();
public:
PropertyStiffness(void);
virtual ~PropertyStiffness(){}
};
/** Force property
* This is a property for representing acceleration. It is basically a float
* property. On the Gui it has a quantity like m/s^2.
+3
View File
@@ -24,6 +24,9 @@
#define RANGE_H
#include <string>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace App {
-1
View File
@@ -63,7 +63,6 @@ void * _class_::create(void){\
/// define to implement a subclass of Base::BaseClass
#define TYPESYSTEM_SOURCE_TEMPLATE_P(_class_) \
template<> Base::Type _class_::classTypeId = Base::Type::badType(); \
template<> Base::Type _class_::getClassTypeId(void) { return _class_::classTypeId; } \
template<> Base::Type _class_::getTypeId(void) const { return _class_::classTypeId; } \
template<> void * _class_::create(void){\
+3
View File
@@ -29,6 +29,9 @@
#include <sstream>
#include <vector>
#include "Vector3D.h"
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base
{
+3
View File
@@ -26,6 +26,9 @@
#include <QObject>
#include <QEventLoop>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base {
/**
+12 -7
View File
@@ -248,17 +248,13 @@ const char* XMLAttributeError::what() const throw()
FileException::FileException(const char * sMessage, const char * sFileName)
: Exception( sMessage ),file(sFileName)
{
if (sFileName) {
_sErrMsgAndFileName = _sErrMsg + ": ";
_sErrMsgAndFileName += sFileName;
}
setFileName(sFileName);
}
FileException::FileException(const char * sMessage, const FileInfo& File)
: Exception( sMessage ),file(File)
{
_sErrMsgAndFileName = _sErrMsg + ": ";
_sErrMsgAndFileName += File.fileName();
setFileName(File.fileName().c_str());
}
FileException::FileException()
@@ -274,6 +270,15 @@ FileException::FileException(const FileException &inst)
{
}
void FileException::setFileName(const char * sFileName) {
file.setFile(sFileName);
_sErrMsgAndFileName = _sErrMsg;
if (sFileName) {
_sErrMsgAndFileName += ": ";
_sErrMsgAndFileName += sFileName;
}
}
std::string FileException::getFileName() const
{
return file.fileName();
@@ -324,7 +329,7 @@ void FileException::setPyObject( PyObject * pydict)
Py::Dict edict(pydict);
if (edict.hasKey("filename"))
file.setFile(static_cast<std::string>(Py::String(edict.getItem("filename"))));
setFileName(Py::String(edict.getItem("filename")).as_std_string("utf-8").c_str());
}
}
+1
View File
@@ -262,6 +262,7 @@ protected:
// necessary for what() legacy behaviour as it returns a buffer that
// can not be of a temporary object to be destroyed at end of what()
std::string _sErrMsgAndFileName;
void setFileName(const char * sFileName=0);
};
/**
+7 -5
View File
@@ -25,11 +25,13 @@
#ifndef BASE_FACTORY_H
#define BASE_FACTORY_H
#include<typeinfo>
#include<string>
#include<map>
#include<list>
#include"../FCConfig.h"
#include <typeinfo>
#include <string>
#include <map>
#include <list>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base
+3
View File
@@ -27,6 +27,9 @@
// Std. configurations
#include <string>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base
{
+3
View File
@@ -30,6 +30,9 @@
#include <string>
#include <map>
#include <typeinfo>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
class QAtomicInt;
+3
View File
@@ -32,6 +32,9 @@
#include <xercesc/util/XercesVersion.hpp>
#include <xercesc/sax/InputSource.hpp>
#include <QTextCodec>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
XERCES_CPP_NAMESPACE_BEGIN
+4 -1
View File
@@ -25,12 +25,15 @@
#define BASE_MATRIX_H
#include <cassert>
#include <cfloat>
#include <cmath>
#include <cstdio>
#include <string>
#include "Vector3D.h"
#include <float.h>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base {
+21 -17
View File
@@ -22,30 +22,34 @@
#ifndef BASE_MEMDEBUG_H
#define BASE_MEMDEBUG_H
#ifndef FC_GLOBAL_H
#include <crtdbg.h>
#include <FCGlobal.h>
#endif
namespace Base
{
// Std. configurations
#if defined(_MSC_VER)
class BaseExport MemCheck
{
public:
MemCheck();
~MemCheck();
void setNextCheckpoint();
static bool checkMemory();
static bool dumpLeaks();
static bool isValidHeapPointer(const void*);
private:
_CrtMemState s1, s2, s3;
};
#if defined(_MSC_VER)
class BaseExport MemCheck
{
public:
MemCheck();
~MemCheck();
void setNextCheckpoint();
static bool checkMemory();
static bool dumpLeaks();
static bool isValidHeapPointer(const void*);
private:
_CrtMemState s1, s2, s3;
};
#endif
} //namespace Base
#endif // BASE_MEMDEBUG_H
+3
View File
@@ -73,6 +73,9 @@ extern "C" { /* a C library, but callable from C++ */
# undef _POSIX_C_SOURCE
#endif // (re-)defined in pyconfig.h
#include <Python.h>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
extern int PP_RELOAD; /* 1=reload py modules when attributes referenced */
extern int PP_DEBUG; /* 1=start debugger when string/function/member run */
+271 -2
View File
@@ -27,6 +27,7 @@
# include <climits>
#endif
#include <boost/algorithm/string/predicate.hpp>
#include "Rotation.h"
#include "Matrix.h"
#include "Base/Exception.h"
@@ -672,13 +673,13 @@ void Rotation::getYawPitchRoll(double& y, double& p, double& r) const
double qd2 = 2.0*(q13-q02);
// handle gimbal lock
if (fabs(qd2-1.0) < DBL_EPSILON) {
if (fabs(qd2-1.0) <= DBL_EPSILON) {
// north pole
y = 0.0;
p = D_PI/2.0;
r = 2.0 * atan2(quat[0],quat[3]);
}
else if (fabs(qd2+1.0) < DBL_EPSILON) {
else if (fabs(qd2+1.0) <= DBL_EPSILON) {
// south pole
y = 0.0;
p = -D_PI/2.0;
@@ -712,3 +713,271 @@ bool Rotation::isNull() const
this->quat[2] == 0.0 &&
this->quat[3] == 0.0);
}
//=======================================================================
// The following code is borrowed from OCCT gp/gp_Quaternion.cxx
namespace { // anonymous namespace
//=======================================================================
//function : translateEulerSequence
//purpose :
// Code supporting conversion between quaternion and generalized
// Euler angles (sequence of three rotations) is based on
// algorithm by Ken Shoemake, published in Graphics Gems IV, p. 222-22
// http://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/EulerAngles.c
//=======================================================================
struct EulerSequence_Parameters
{
int i; // first rotation axis
int j; // next axis of rotation
int k; // third axis
bool isOdd; // true if order of two first rotation axes is odd permutation, e.g. XZ
bool isTwoAxes; // true if third rotation is about the same axis as first
bool isExtrinsic; // true if rotations are made around fixed axes
EulerSequence_Parameters (int theAx1,
bool theisOdd,
bool theisTwoAxes,
bool theisExtrinsic)
: i(theAx1),
j(1 + (theAx1 + (theisOdd ? 1 : 0)) % 3),
k(1 + (theAx1 + (theisOdd ? 0 : 1)) % 3),
isOdd(theisOdd),
isTwoAxes(theisTwoAxes),
isExtrinsic(theisExtrinsic)
{}
};
EulerSequence_Parameters translateEulerSequence (const Rotation::EulerSequence theSeq)
{
typedef EulerSequence_Parameters Params;
const bool F = false;
const bool T = true;
switch (theSeq)
{
case Rotation::Extrinsic_XYZ: return Params (1, F, F, T);
case Rotation::Extrinsic_XZY: return Params (1, T, F, T);
case Rotation::Extrinsic_YZX: return Params (2, F, F, T);
case Rotation::Extrinsic_YXZ: return Params (2, T, F, T);
case Rotation::Extrinsic_ZXY: return Params (3, F, F, T);
case Rotation::Extrinsic_ZYX: return Params (3, T, F, T);
// Conversion of intrinsic angles is made by the same code as for extrinsic,
// using equivalence rule: intrinsic rotation is equivalent to extrinsic
// rotation by the same angles but with inverted order of elemental rotations.
// Swapping of angles (Alpha <-> Gamma) is done inside conversion procedure;
// sequence of axes is inverted by setting appropriate parameters here.
// Note that proper Euler angles (last block below) are symmetric for sequence of axes.
case Rotation::Intrinsic_XYZ: return Params (3, T, F, F);
case Rotation::Intrinsic_XZY: return Params (2, F, F, F);
case Rotation::Intrinsic_YZX: return Params (1, T, F, F);
case Rotation::Intrinsic_YXZ: return Params (3, F, F, F);
case Rotation::Intrinsic_ZXY: return Params (2, T, F, F);
case Rotation::Intrinsic_ZYX: return Params (1, F, F, F);
case Rotation::Extrinsic_XYX: return Params (1, F, T, T);
case Rotation::Extrinsic_XZX: return Params (1, T, T, T);
case Rotation::Extrinsic_YZY: return Params (2, F, T, T);
case Rotation::Extrinsic_YXY: return Params (2, T, T, T);
case Rotation::Extrinsic_ZXZ: return Params (3, F, T, T);
case Rotation::Extrinsic_ZYZ: return Params (3, T, T, T);
case Rotation::Intrinsic_XYX: return Params (1, F, T, F);
case Rotation::Intrinsic_XZX: return Params (1, T, T, F);
case Rotation::Intrinsic_YZY: return Params (2, F, T, F);
case Rotation::Intrinsic_YXY: return Params (2, T, T, F);
case Rotation::Intrinsic_ZXZ: return Params (3, F, T, F);
case Rotation::Intrinsic_ZYZ: return Params (3, T, T, F);
default:
case Rotation::EulerAngles : return Params (3, F, T, F); // = Intrinsic_ZXZ
case Rotation::YawPitchRoll: return Params (1, F, F, F); // = Intrinsic_ZYX
};
}
class Mat : public Base::Matrix4D
{
public:
double operator()(int i, int j) const {
return this->operator[](i-1)[j-1];
}
double & operator()(int i, int j) {
return this->operator[](i-1)[j-1];
}
};
const char *EulerSequenceNames[] = {
//! Classic Euler angles, alias to Intrinsic_ZXZ
"Euler",
//! Yaw Pitch Roll (or nautical) angles, alias to Intrinsic_ZYX
"YawPitchRoll",
// Tait-Bryan angles (using three different axes)
"XYZ",
"XZY",
"YZX",
"YXZ",
"ZXY",
"ZYX",
"IXYZ",
"IXZY",
"IYZX",
"IYXZ",
"IZXY",
"IZYX",
// Proper Euler angles (using two different axes, first and third the same)
"XYX",
"XZX",
"YZY",
"YXY",
"ZYZ",
"ZXZ",
"IXYX",
"IXZX",
"IYZY",
"IYXY",
"IZXZ",
"IZYZ",
};
} // anonymous namespace
const char * Rotation::eulerSequenceName(EulerSequence seq)
{
if (seq == Invalid || seq >= EulerSequenceLast)
return 0;
return EulerSequenceNames[seq-1];
}
Rotation::EulerSequence Rotation::eulerSequenceFromName(const char *name)
{
if (name) {
for (unsigned i=0; i<sizeof(EulerSequenceNames)/sizeof(EulerSequenceNames[0]); ++i) {
if (boost::iequals(name, EulerSequenceNames[i]))
return (EulerSequence)(i+1);
}
}
return Invalid;
}
void Rotation::setEulerAngles(EulerSequence theOrder,
double theAlpha,
double theBeta,
double theGamma)
{
if (theOrder == Invalid || theOrder >= EulerSequenceLast)
throw Base::ValueError("invalid euler sequence");
EulerSequence_Parameters o = translateEulerSequence (theOrder);
theAlpha *= D_PI/180.0;
theBeta *= D_PI/180.0;
theGamma *= D_PI/180.0;
double a = theAlpha, b = theBeta, c = theGamma;
if ( ! o.isExtrinsic )
std::swap(a, c);
if ( o.isOdd )
b = -b;
double ti = 0.5 * a;
double tj = 0.5 * b;
double th = 0.5 * c;
double ci = cos (ti);
double cj = cos (tj);
double ch = cos (th);
double si = sin (ti);
double sj = sin (tj);
double sh = sin (th);
double cc = ci * ch;
double cs = ci * sh;
double sc = si * ch;
double ss = si * sh;
double values[4]; // w, x, y, z
if ( o.isTwoAxes )
{
values[o.i] = cj * (cs + sc);
values[o.j] = sj * (cc + ss);
values[o.k] = sj * (cs - sc);
values[0] = cj * (cc - ss);
}
else
{
values[o.i] = cj * sc - sj * cs;
values[o.j] = cj * ss + sj * cc;
values[o.k] = cj * cs - sj * sc;
values[0] = cj * cc + sj * ss;
}
if ( o.isOdd )
values[o.j] = -values[o.j];
quat[0] = values[1];
quat[1] = values[2];
quat[2] = values[3];
quat[3] = values[0];
}
void Rotation::getEulerAngles(EulerSequence theOrder,
double& theAlpha,
double& theBeta,
double& theGamma) const
{
Mat M;
getValue(M);
EulerSequence_Parameters o = translateEulerSequence (theOrder);
if ( o.isTwoAxes )
{
double sy = sqrt (M(o.i, o.j) * M(o.i, o.j) + M(o.i, o.k) * M(o.i, o.k));
if (sy > 16 * DBL_EPSILON)
{
theAlpha = atan2 (M(o.i, o.j), M(o.i, o.k));
theGamma = atan2 (M(o.j, o.i), -M(o.k, o.i));
}
else
{
theAlpha = atan2 (-M(o.j, o.k), M(o.j, o.j));
theGamma = 0.;
}
theBeta = atan2 (sy, M(o.i, o.i));
}
else
{
double cy = sqrt (M(o.i, o.i) * M(o.i, o.i) + M(o.j, o.i) * M(o.j, o.i));
if (cy > 16 * DBL_EPSILON)
{
theAlpha = atan2 (M(o.k, o.j), M(o.k, o.k));
theGamma = atan2 (M(o.j, o.i), M(o.i, o.i));
}
else
{
theAlpha = atan2 (-M(o.j, o.k), M(o.j, o.j));
theGamma = 0.;
}
theBeta = atan2 (-M(o.k, o.i), cy);
}
if ( o.isOdd )
{
theAlpha = -theAlpha;
theBeta = -theBeta;
theGamma = -theGamma;
}
if ( ! o.isExtrinsic )
{
double aFirst = theAlpha;
theAlpha = theGamma;
theGamma = aFirst;
}
theAlpha *= 180.0/D_PI;
theBeta *= 180.0/D_PI;
theGamma *= 180.0/D_PI;
}
+50
View File
@@ -25,6 +25,9 @@
#define BASE_ROTATION_H
#include "Vector3D.h"
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base {
@@ -63,6 +66,53 @@ public:
void setYawPitchRoll(double y, double p, double r);
/// Euler angles in yaw,pitch,roll notation
void getYawPitchRoll(double& y, double& p, double& r) const;
enum EulerSequence
{
Invalid,
//! Classic Euler angles, alias to Intrinsic_ZXZ
EulerAngles,
//! Yaw Pitch Roll (or nautical) angles, alias to Intrinsic_ZYX
YawPitchRoll,
// Tait-Bryan angles (using three different axes)
Extrinsic_XYZ,
Extrinsic_XZY,
Extrinsic_YZX,
Extrinsic_YXZ,
Extrinsic_ZXY,
Extrinsic_ZYX,
Intrinsic_XYZ,
Intrinsic_XZY,
Intrinsic_YZX,
Intrinsic_YXZ,
Intrinsic_ZXY,
Intrinsic_ZYX,
// Proper Euler angles (using two different axes, first and third the same)
Extrinsic_XYX,
Extrinsic_XZX,
Extrinsic_YZY,
Extrinsic_YXY,
Extrinsic_ZYZ,
Extrinsic_ZXZ,
Intrinsic_XYX,
Intrinsic_XZX,
Intrinsic_YZY,
Intrinsic_YXY,
Intrinsic_ZXZ,
Intrinsic_ZYZ,
EulerSequenceLast,
};
static const char *eulerSequenceName(EulerSequence seq);
static EulerSequence eulerSequenceFromName(const char *name);
void getEulerAngles(EulerSequence seq, double &alpha, double &beta, double &gamma) const;
void setEulerAngles(EulerSequence seq, double alpha, double beta, double gamma);
bool isIdentity() const;
bool isNull() const;
//@}
+12 -1
View File
@@ -24,6 +24,8 @@
-- a Vector (axis) and a float (angle)
-- two Vectors (rotation from/to vector)
-- three floats (Euler angles) as yaw-pitch-roll in XY'Z'' convention
-- one string and three floats (Euler angles) as euler rotation
of a given type. Call toEulerSequence() for supported sequence types.
-- four floats (Quaternion) where the quaternion is specified as:
q=xi+yj+zk+w, i.e. the last parameter is the real part
-- three vectors that define rotated axes directions + an optional
@@ -84,12 +86,21 @@
<Methode Name="toEuler" Const="true">
<Documentation>
<UserDocu>
toEuler(Vector) -> list
toEuler() -> list
Get the Euler angles of this rotation
as yaw-pitch-roll in XY'Z'' convention
</UserDocu>
</Documentation>
</Methode>
<Methode Name="toEulerAngles" Const="true">
<Documentation>
<UserDocu>
toEulerAngles(seq='') -> list
Get the Euler angles in a given sequence for this rotation.
Call this function without arguments to output all possible values of 'seq'.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="toMatrix" Const="true">
<Documentation>
<UserDocu>
+37
View File
@@ -102,6 +102,17 @@ int RotationPy::PyInit(PyObject* args, PyObject* /*kwd*/)
return 0;
}
PyErr_Clear();
const char *seq;
double a, b, c;
if (PyArg_ParseTuple(args, "sddd", &seq, &a, &b, &c)) {
PY_TRY {
getRotationPtr()->setEulerAngles(
Rotation::eulerSequenceFromName(seq), a, b, c);
return 0;
} _PY_CATCH(return -1)
}
double a11 = 1.0, a12 = 0.0, a13 = 0.0, a14 = 0.0;
double a21 = 0.0, a22 = 1.0, a23 = 0.0, a24 = 0.0;
double a31 = 0.0, a32 = 0.0, a33 = 1.0, a34 = 0.0;
@@ -282,6 +293,32 @@ PyObject* RotationPy::toEuler(PyObject * args)
return Py::new_reference_to(tuple);
}
PyObject* RotationPy::toEulerAngles(PyObject * args)
{
const char *seq = nullptr;
if (!PyArg_ParseTuple(args, "|s", &seq))
return NULL;
if (!seq) {
Py::List res;
for (int i=1; i<Rotation::EulerSequenceLast; ++i)
res.append(Py::String(Rotation::eulerSequenceName((Rotation::EulerSequence)i)));
return Py::new_reference_to(res);
}
PY_TRY {
double A,B,C;
this->getRotationPtr()->getEulerAngles(
Rotation::eulerSequenceFromName(seq),A,B,C);
Py::Tuple tuple(3);
tuple.setItem(0, Py::Float(A));
tuple.setItem(1, Py::Float(B));
tuple.setItem(2, Py::Float(C));
return Py::new_reference_to(tuple);
} PY_CATCH
}
PyObject* RotationPy::toMatrix(PyObject * args)
{
if (!PyArg_ParseTuple(args, ""))
+8
View File
@@ -41,7 +41,11 @@ namespace Base {
// members
static std::vector<SequencerBase*> _instances; /**< A vector of all created instances */
static SequencerLauncher* _topLauncher; /**< The outermost launcher */
#if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
static QRecursiveMutex mutex; /**< A mutex-locker for the launcher */
#else
static QMutex mutex; /**< A mutex-locker for the launcher */
#endif
/** Sets a global sequencer object.
* Access to the last registered object is performed by @see Sequencer().
*/
@@ -67,7 +71,11 @@ namespace Base {
*/
std::vector<SequencerBase*> SequencerP::_instances;
SequencerLauncher* SequencerP::_topLauncher = 0;
#if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
QRecursiveMutex SequencerP::mutex;
#else
QMutex SequencerP::mutex(QMutex::Recursive);
#endif
}
SequencerBase& SequencerBase::Instance ()
+4 -1
View File
@@ -36,7 +36,10 @@
// so we need not to check the version (because we only support _MSC_VER >= 1100)!
#pragma once
#include <windows.h>
#include <Windows.h>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
// special defines for VC5/6 (if no actual PSDK is installed):
#if _MSC_VER < 1300
+2 -2
View File
@@ -26,7 +26,7 @@
#ifndef _PreComp_
# include <sstream>
# include <QDateTime>
# if defined(FC_OS_LINUX)
# if defined(FC_OS_LINUX) || defined(__MINGW32__)
# include <sys/time.h>
# endif
#endif
@@ -60,7 +60,7 @@ TimeInfo::~TimeInfo()
void TimeInfo::setCurrent(void)
{
#if defined (FC_OS_BSD) || defined(FC_OS_LINUX)
#if defined (FC_OS_BSD) || defined(FC_OS_LINUX) || defined(__MINGW32__)
struct timeval t;
gettimeofday(&t, NULL);
timebuffer.time = t.tv_sec;
+3
View File
@@ -24,6 +24,9 @@
#ifndef BASE_TOOLS_H
#define BASE_TOOLS_H
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
#include <functional>
#include <algorithm>
#include <cmath>
+4 -1
View File
@@ -28,11 +28,14 @@
#include <algorithm>
#include <cmath>
#include <cfloat>
#include <stdio.h>
#include <cstdio>
#include <list>
#include <vector>
#include "Vector3D.h"
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base {
+3
View File
@@ -26,6 +26,9 @@
#include <CXX/Extensions.hxx>
#include <CXX/Objects.hxx>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base {
+3
View File
@@ -30,6 +30,9 @@
#include <map>
#include <set>
#include <vector>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base
{
+8
View File
@@ -187,6 +187,10 @@ QString UnitsSchemaImperialDecimal::schemaTranslate(const Base::Quantity& quant,
unitString = QString::fromLatin1("psi");
factor = 6.894744825494;
}
else if (unit == Unit::Stiffness) {
unitString = QString::fromLatin1("lbf/in");
factor = 4.448222/0.0254;
}
else if (unit == Unit::Velocity) {
unitString = QString::fromLatin1("in/min");
factor = 25.4 / 60;
@@ -360,6 +364,10 @@ QString UnitsSchemaImperialCivil::schemaTranslate(const Base::Quantity& quant, d
unitString = QString::fromLatin1("psi");
factor = 6.894744825494;
}
else if (unit == Unit::Stiffness) {
unitString = QString::fromLatin1("lbf/in");
factor = 4.448222/0.0254;
}
else if (unit == Unit::Velocity) {
unitString = QString::fromLatin1("mph");
factor = 447.04; //1mm/sec => mph
+3
View File
@@ -27,6 +27,9 @@
// Std. configurations
#include <string>
#ifndef FC_GLOBAL_H
#include <FCGlobal.h>
#endif
namespace Base
{
+1 -1
View File
@@ -55,7 +55,7 @@
namespace Py
{
typedef Py_ssize_t sequence_index_type; // type of an index into a sequence
Py_ssize_t numeric_limits_max();
PYCXX_EXPORT Py_ssize_t numeric_limits_max();
// Forward declarations
class Object;
+7 -4
View File
@@ -3,16 +3,18 @@ EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c
OUTPUT_VARIABLE python_libs OUTPUT_STRIP_TRAILING_WHITESPACE )
SET(PYTHON_MAIN_DIR ${python_libs})
set(NAMESPACE_INIT "${CMAKE_BINARY_DIR}/Ext/freecad/__init__.py")
set(NAMESPACE_DIR "${CMAKE_BINARY_DIR}/Ext/freecad")
set(NAMESPACE_INIT "${NAMESPACE_DIR}/__init__.py")
if (WIN32)
get_filename_component(FREECAD_LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}"
get_filename_component(FREECAD_LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}"
REALPATH BASE_DIR "${CMAKE_INSTALL_PREFIX}")
set( ${CMAKE_INSTALL_BINDIR})
set( ${CMAKE_INSTALL_BINDIR})
else()
set(FREECAD_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
set(FREECAD_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
endif()
configure_file(__init__.py.template ${NAMESPACE_INIT})
configure_file(UiTools.py ${NAMESPACE_DIR}/UiTools.py)
if (INSTALL_TO_SITEPACKAGES)
SET(SITE_PACKAGE_DIR ${PYTHON_MAIN_DIR}/freecad)
@@ -23,6 +25,7 @@ endif()
INSTALL(
FILES
${NAMESPACE_INIT}
UiTools.py
DESTINATION
${SITE_PACKAGE_DIR}
)
+21
View File
@@ -0,0 +1,21 @@
# (c) 2021 Werner Mayer LGPL
from PySide2 import QtUiTools
from PySide2 import QtCore
import FreeCADGui as Gui
class QUiLoader(QtUiTools.QUiLoader):
"""
This is an extension of Qt's QUiLoader to also create custom widgets
"""
def __init__(self, arg = None):
super(QUiLoader, self).__init__(arg)
self.ui = Gui.PySideUic
def createWidget(self, className, parent = None, name = ""):
widget = self.ui.createCustomWidget(className, parent, name)
if not widget:
widget = super(QUiLoader, self).createWidget(className, parent, name)
return widget
+1 -33
View File
@@ -304,39 +304,7 @@ typedef unsigned __int64 uint64_t;
//**************************************************************************
// Windows import export DLL defines
#if defined (FC_OS_WIN32) || defined(FC_OS_CYGWIN)
# ifdef FCApp
# define AppExport __declspec(dllexport)
# define DataExport __declspec(dllexport)
# else
# define AppExport __declspec(dllimport)
# define DataExport __declspec(dllimport)
# endif
# ifdef FCBase
# define BaseExport __declspec(dllexport)
# else
# define BaseExport __declspec(dllimport)
# endif
# ifdef FCGui
# define GuiExport __declspec(dllexport)
# else
# define GuiExport __declspec(dllimport)
# endif
#else
# ifndef BaseExport
# define BaseExport
# endif
# ifndef GuiExport
# define GuiExport
# endif
# ifndef AppExport
# define AppExport
# endif
# ifndef DataExport
# define DataExport
# endif
#endif
#include <FCGlobal.h>
//**************************************************************************
// here get the warnings of too long specifiers disabled (needed for VC6)
+62
View File
@@ -0,0 +1,62 @@
/***************************************************************************
* Copyright (c) 2019 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 *
* *
***************************************************************************/
/** \file FCGlobal.h
* \brief Include export or import macros.
*/
#ifndef FC_GLOBAL_H
#define FC_GLOBAL_H
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(__CYGWIN__)
# define FREECAD_DECL_EXPORT __declspec(dllexport)
# define FREECAD_DECL_IMPORT __declspec(dllimport)
#else
# define FREECAD_DECL_EXPORT
# define FREECAD_DECL_IMPORT
#endif
// FreeCADBase
#ifdef FreeCADBase_EXPORTS
# define BaseExport FREECAD_DECL_EXPORT
#else
# define BaseExport FREECAD_DECL_IMPORT
#endif
// FreeCADApp
#ifdef FreeCADApp_EXPORTS
# define AppExport FREECAD_DECL_EXPORT
# define DataExport FREECAD_DECL_EXPORT
#else
# define AppExport FREECAD_DECL_IMPORT
# define DataExport FREECAD_DECL_IMPORT
#endif
// FreeCADGui
#ifdef FreeCADGui_EXPORTS
# define GuiExport FREECAD_DECL_EXPORT
#else
# define GuiExport FREECAD_DECL_IMPORT
#endif
#endif //FC_GLOBAL_H
+18 -17
View File
@@ -64,35 +64,36 @@
<ButtonMap DeviceName="SpacePilot Pro">
<Mapping>
<Map Description="Menu" KeyCode="0" DownTime="short" Command=""/>
<Map Description="Fit" KeyCode="1" DownTime="short" Command=""/>
<Map Description="Fit" KeyCode="1" DownTime="short" Command="Std_ViewFitAll"/>
<Map Description="Top" KeyCode="2" DownTime="short" Command="Std_ViewTop"/>
<Map Description="Bottom" KeyCode="2" DownTime="long" Command="Std_ViewBottom"/>
<Map Description="Left" KeyCode="3" DownTime="long" Command="Std_ViewLeft"/>
<Map Description="Right" KeyCode="4" DownTime="short" Command="Std_ViewRight"/>
<Map Description="Left" KeyCode="4" DownTime="long" Command="Std_ViewLeft"/>
<Map Description="Front" KeyCode="5" DownTime="short" Command="Std_ViewFront"/>
<Map Description="Rear" KeyCode="5" DownTime="long" Command="Std_ViewRear"/>
<Map Description="Clockwise" KeyCode="8" DownTime="short" Command=""/>
<Map Description="AntiClockwise" KeyCode="8" DownTime="long" Command=""/>
<Map Description="ISO1" KeyCode="10" DownTime="short" Command="Std_OrthographicCamera"/>
<Map Description="ISO2" KeyCode="10" DownTime="long" Command=""/>
<Map Description="Bottom" KeyCode="6" DownTime="long" Command="Std_ViewBottom"/>
<Map Description="Rear" KeyCode="7" DownTime="long" Command="Std_ViewRear"/>
<Map Description="Clockwise" KeyCode="8" DownTime="short" Command="Std_ViewRotateRight"/>
<Map Description="AntiClockwise" KeyCode="9" DownTime="long" Command="Std_ViewRotateLeft"/>
<Map Description="ISO1" KeyCode="10" DownTime="short" Command="Std_ViewIsometric"/>
<Map Description="ISO2" KeyCode="11" DownTime="long" Command="Std_ViewDimetric"/>
<Map Description="1" KeyCode="12" DownTime="short" Command=""/>
<Map Description="6" KeyCode="12" DownTime="long" Command=""/>
<Map Description="2" KeyCode="13" DownTime="short" Command=""/>
<Map Description="7" KeyCode="13" DownTime="long" Command=""/>
<Map Description="3" KeyCode="14" DownTime="short" Command=""/>
<Map Description="8" KeyCode="14" DownTime="long" Command=""/>
<Map Description="4" KeyCode="15" DownTime="short" Command=""/>
<Map Description="9" KeyCode="15" DownTime="long" Command=""/>
<Map Description="5" KeyCode="16" DownTime="short" Command=""/>
<Map Description="10" KeyCode="16" DownTime="long" Command=""/>
<Map Description="6" KeyCode="17" DownTime="long" Command=""/>
<Map Description="7" KeyCode="18" DownTime="long" Command=""/>
<Map Description="8" KeyCode="19" DownTime="long" Command=""/>
<Map Description="9" KeyCode="20" DownTime="long" Command=""/>
<Map Description="10" KeyCode="21" DownTime="long" Command=""/>
<Map Description="ESC" KeyCode="22" DownTime="short" Command=""/>
<Map Description="ALT" KeyCode="23" DownTime="short" Command=""/>
<Map Description="SHIFT" KeyCode="24" DownTime="short" Command=""/>
<Map Description="CTRL" KeyCode="25" DownTime="short" Command=""/>
<Map Description="ROTZ" KeyCode="26" DownTime="short" Command=""/>
<Map Description="AXIS" KeyCode="27" DownTime="short" Command=""/>
<Map Description="FIT" KeyCode="28" DownTime="short" Command=""/>
<Map Description="PlusMinus" KeyCode="30" DownTime="short" Command=""/>
<Map Description="Rotation" KeyCode="26" DownTime="short" Command=""/>
<Map Description="PanAndZoom" KeyCode="27" DownTime="short" Command=""/>
<Map Description="Dominant" KeyCode="28" DownTime="short" Command=""/>
<Map Description="Plus" KeyCode="29" DownTime="short" Command=""/>
<Map Description="Minus" KeyCode="30" DownTime="short" Command=""/>
</Mapping>
</ButtonMap>
+3 -3
View File
@@ -227,7 +227,7 @@ void Action::setMenuRole(QAction::MenuRole menuRole)
* to the command object.
*/
ActionGroup::ActionGroup ( Command* pcCmd,QObject * parent)
: Action(pcCmd, parent), _group(0), _dropDown(false),_external(false),_toggle(false)
: Action(pcCmd, parent), _group(0), _dropDown(false),_external(false),_toggle(false),_isMode(false)
{
_group = new QActionGroup(this);
connect(_group, SIGNAL(triggered(QAction*)), this, SLOT(onActivated (QAction*)));
@@ -336,7 +336,7 @@ void ActionGroup::setCheckedAction(int i)
QAction* a = _group->actions()[i];
a->setChecked(true);
this->setIcon(a->icon());
this->setToolTip(a->toolTip());
if (!this->_isMode) this->setToolTip(a->toolTip());
this->setProperty("defaultAction", QVariant(i));
}
@@ -378,7 +378,7 @@ void ActionGroup::onActivated (QAction* a)
}
#endif
this->setIcon(a->icon());
this->setToolTip(a->toolTip());
if (!this->_isMode) this->setToolTip(a->toolTip());
this->setProperty("defaultAction", QVariant(index));
_pcCmd->invoke(index, Command::TriggerChildAction);
}
+2
View File
@@ -107,6 +107,7 @@ public:
void setExclusive (bool);
bool isExclusive() const;
void setVisible (bool);
void setIsMode(bool b) { _isMode = b; }
void setDropDownMenu(bool b) { _dropDown = b; }
QAction* addAction(QAction*);
@@ -126,6 +127,7 @@ protected:
bool _dropDown;
bool _external;
bool _toggle;
bool _isMode;
};
// --------------------------------------------------------------------
+45
View File
@@ -70,6 +70,7 @@
#include "DocumentPy.h"
#include "View.h"
#include "View3DPy.h"
#include "UiLoader.h"
#include "WidgetFactory.h"
#include "Command.h"
#include "Macro.h"
@@ -1250,6 +1251,50 @@ void Application::tryClose(QCloseEvent * e)
}
}
int Application::getUserEditMode(const std::string &mode) const
{
if (mode.empty()) {
return userEditMode;
}
for (auto const &uem : userEditModes) {
if (uem.second == mode) {
return uem.first;
}
}
return -1;
}
std::string Application::getUserEditModeName(int mode) const
{
if (mode == -1) {
return userEditModes.at(userEditMode);
}
if (userEditModes.find(mode) != userEditModes.end()) {
return userEditModes.at(mode);
}
return "";
}
bool Application::setUserEditMode(int mode)
{
if (userEditModes.find(mode) != userEditModes.end() && userEditMode != mode) {
userEditMode = mode;
this->signalUserEditModeChanged(userEditMode);
return true;
}
return false;
}
bool Application::setUserEditMode(const std::string &mode)
{
for (auto const &uem : userEditModes) {
if (uem.second == mode) {
return setUserEditMode(uem.first);
}
}
return false;
}
/**
* Activate the matching workbench to the registered workbench handler with name \a name.
* The handler must be an instance of a class written in Python.
+29
View File
@@ -27,6 +27,7 @@
#include <QPixmap>
#include <string>
#include <vector>
#include <map>
#define putpix()
@@ -134,6 +135,8 @@ public:
boost::signals2::signal<void (const Gui::ViewProviderDocumentObject&)> signalInEdit;
/// signal on leaving edit mode
boost::signals2::signal<void (const Gui::ViewProviderDocumentObject&)> signalResetEdit;
/// signal on changing user edit mode
boost::signals2::signal<void (int)> signalUserEditModeChanged;
//@}
/** @name methods for Document handling */
@@ -230,6 +233,28 @@ public:
static void runApplication(void);
void tryClose( QCloseEvent * e );
//@}
/** @name User edit mode */
//@{
protected:
// the below std::map is a translation of 'EditMode' enum in ViewProvider.h
// to add a new edit mode, it should first be added there
// this is only used for GUI user interaction (menu, toolbar, Python API)
const std::map <int, std::string> userEditModes {
{0, QT_TRANSLATE_NOOP("EditMode", "Default")},
{1, QT_TRANSLATE_NOOP("EditMode", "Transform")},
{2, QT_TRANSLATE_NOOP("EditMode", "Cutting")},
{3, QT_TRANSLATE_NOOP("EditMode", "Color")}
};
int userEditMode = userEditModes.begin()->first;
public:
std::map <int, std::string> listUserEditModes() const { return userEditModes; }
int getUserEditMode(const std::string &mode = "") const;
std::string getUserEditModeName(int mode = -1) const;
bool setUserEditMode(int mode);
bool setUserEditMode(const std::string &mode);
//@}
public:
//---------------------------------------------------------------------
@@ -296,6 +321,10 @@ public:
static PyObject* sAddDocObserver (PyObject *self,PyObject *args);
static PyObject* sRemoveDocObserver (PyObject *self,PyObject *args);
static PyObject* sListUserEditModes (PyObject *self,PyObject *args);
static PyObject* sGetUserEditMode (PyObject *self,PyObject *args);
static PyObject* sSetUserEditMode (PyObject *self,PyObject *args);
static PyMethodDef Methods[];
+39
View File
@@ -52,6 +52,7 @@
#include "SplitView3DInventor.h"
#include "ViewProvider.h"
#include "WaitCursor.h"
#include "PythonWrapper.h"
#include "WidgetFactory.h"
#include "Workbench.h"
#include "WorkbenchManager.h"
@@ -205,6 +206,18 @@ PyMethodDef Application::Methods[] = {
{"removeDocumentObserver", (PyCFunction) Application::sRemoveDocObserver, METH_VARARGS,
"removeDocumentObserver() -> None\n\n"
"Remove an added document observer."},
{"listUserEditModes", (PyCFunction) Application::sListUserEditModes, METH_VARARGS,
"listUserEditModes() -> list\n\n"
"List available user edit modes"},
{"getUserEditMode", (PyCFunction) Application::sGetUserEditMode, METH_VARARGS,
"getUserEditMode() -> string\n\n"
"Get current user edit mode"},
{"setUserEditMode", (PyCFunction) Application::sSetUserEditMode, METH_VARARGS,
"setUserEditMode(string=mode) -> Bool\n\n"
"Set user edit mode to 'mode', returns True if exists, false otherwise"},
{"reload", (PyCFunction) Application::sReload, METH_VARARGS,
"reload(name) -> doc\n\n"
@@ -1485,3 +1498,29 @@ PyObject* Application::sCoinRemoveAllChildren(PyObject * /*self*/, PyObject *arg
}PY_CATCH;
}
PyObject* Application::sListUserEditModes(PyObject * /*self*/, PyObject *args)
{
Py::List ret;
if (!PyArg_ParseTuple(args, ""))
return NULL;
for (auto const &uem : Instance->listUserEditModes()) {
ret.append(Py::String(uem.second));
}
return Py::new_reference_to(ret);
}
PyObject* Application::sGetUserEditMode(PyObject * /*self*/, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
return Py::new_reference_to(Py::String(Instance->getUserEditModeName()));
}
PyObject* Application::sSetUserEditMode(PyObject * /*self*/, PyObject *args)
{
char *mode = "";
if (!PyArg_ParseTuple(args, "s", &mode))
return NULL;
bool ok = Instance->setUserEditMode(std::string(mode));
return Py::new_reference_to(Py::Boolean(ok));
}
+4
View File
@@ -1038,6 +1038,8 @@ SET(Widget_CPP_SRCS
QuantitySpinBox.cpp
SpinBox.cpp
Splashscreen.cpp
PythonWrapper.cpp
UiLoader.cpp
WidgetFactory.cpp
Widgets.cpp
Window.cpp
@@ -1054,6 +1056,8 @@ SET(Widget_HPP_SRCS
QuantitySpinBox_p.h
SpinBox.h
Splashscreen.h
PythonWrapper.h
UiLoader.h
WidgetFactory.h
Widgets.h
Window.h
+102 -28
View File
@@ -852,34 +852,24 @@ const char * Command::endCmdHelp(void)
return "</body></html>\n\n";
}
void Command::applyCommandData(const char* context, Action* action)
void Command::recreateTooltip(const char* context, Action* action)
{
action->setText(QCoreApplication::translate(
QString tooltip;
tooltip.append(QString::fromLatin1("<h3>"));
tooltip.append(QCoreApplication::translate(
context, getMenuText()));
// build the tooltip
QString tooltip;
tooltip.append(QString::fromLatin1("<h3>"));
tooltip.append(QCoreApplication::translate(
context, getMenuText()));
tooltip.append(QString::fromLatin1("</h3>"));
QRegularExpression re(QString::fromLatin1("([^&])&([^&])"));
tooltip.replace(re, QString::fromLatin1("\\1\\2"));
tooltip.replace(QString::fromLatin1("&&"), QString::fromLatin1("&"));
tooltip.append(QCoreApplication::translate(
context, getToolTipText()));
tooltip.append(QString::fromLatin1("<br><i>("));
tooltip.append(QCoreApplication::translate(
context, getWhatsThis()));
tooltip.append(QString::fromLatin1(")</i> "));
action->setToolTip(tooltip);
action->setWhatsThis(QCoreApplication::translate(
tooltip.append(QString::fromLatin1("</h3>"));
QRegularExpression re(QString::fromLatin1("([^&])&([^&])"));
tooltip.replace(re, QString::fromLatin1("\\1\\2"));
tooltip.replace(QString::fromLatin1("&&"), QString::fromLatin1("&"));
tooltip.append(QCoreApplication::translate(
context, getToolTipText()));
tooltip.append(QString::fromLatin1("<br><i>("));
tooltip.append(QCoreApplication::translate(
context, getWhatsThis()));
if (sStatusTip)
action->setStatusTip(QCoreApplication::translate(
context, getStatusTip()));
else
action->setStatusTip(QCoreApplication::translate(
context, getToolTipText()));
tooltip.append(QString::fromLatin1(")</i> "));
action->setToolTip(tooltip);
QString accel = action->shortcut().toString(QKeySequence::NativeText);
if (!accel.isEmpty()) {
// show shortcut inside tooltip
@@ -892,6 +882,22 @@ void Command::applyCommandData(const char* context, Action* action)
.arg(accel, action->statusTip());
action->setStatusTip(stip);
}
if (sStatusTip)
action->setStatusTip(QCoreApplication::translate(
context, getStatusTip()));
else
action->setStatusTip(QCoreApplication::translate(
context, getToolTipText()));
}
void Command::applyCommandData(const char* context, Action* action)
{
action->setText(QCoreApplication::translate(
context, getMenuText()));
recreateTooltip(context, action);
action->setWhatsThis(QCoreApplication::translate(
context, getWhatsThis()));
}
const char* Command::keySequenceToAccel(int sk) const
@@ -952,16 +958,24 @@ void Command::adjustCameraPosition()
}
}
void Command::printConflictingAccelerators() const
{
auto cmd = Application::Instance->commandManager().checkAcceleratorForConflicts(sAccel, this);
if (cmd)
Base::Console().Warning("Accelerator conflict between %s (%s) and %s (%s)\n", sName, sAccel, cmd->sName, cmd->sAccel);
}
Action * Command::createAction(void)
{
Action *pcAction;
pcAction = new Action(this,getMainWindow());
#ifdef FC_DEBUG
printConflictingAccelerators();
#endif
pcAction->setShortcut(QString::fromLatin1(sAccel));
applyCommandData(this->className(), pcAction);
if (sPixmap)
pcAction->setIcon(Gui::BitmapFactory().iconFromTheme(sPixmap));
return pcAction;
}
@@ -1056,7 +1070,7 @@ void GroupCommand::setup(Action *pcAction) {
const char *statustip = cmd->getStatusTip();
if (!statustip || '\0' == *statustip)
statustip = tooltip;
pcAction->setToolTip(QCoreApplication::translate(context,tooltip));
recreateTooltip(context, pcAction);
pcAction->setStatusTip(QCoreApplication::translate(context,statustip));
}
}
@@ -1125,6 +1139,9 @@ Action * MacroCommand::createAction(void)
pcAction->setWhatsThis(QString::fromUtf8(sWhatsThis));
if (sPixmap)
pcAction->setIcon(Gui::BitmapFactory().pixmap(sPixmap));
#ifdef FC_DEBUG
printConflictingAccelerators();
#endif
pcAction->setShortcut(QString::fromLatin1(sAccel));
QString accel = pcAction->shortcut().toString(QKeySequence::NativeText);
@@ -1327,6 +1344,9 @@ Action * PythonCommand::createAction(void)
Action *pcAction;
pcAction = new Action(this, qtAction, getMainWindow());
#ifdef FC_DEBUG
printConflictingAccelerators();
#endif
pcAction->setShortcut(QString::fromLatin1(getAccel()));
applyCommandData(this->getName(), pcAction);
if (strcmp(getResource("Pixmap"),"") != 0)
@@ -1839,3 +1859,57 @@ void CommandManager::updateCommands(const char* sContext, int mode)
}
}
}
const Command* Gui::CommandManager::checkAcceleratorForConflicts(const char* accel, const Command* ignore) const
{
if (!accel || accel[0] == '\0')
return nullptr;
QString newCombo = QString::fromLatin1(accel);
if (newCombo.isEmpty())
return nullptr;
auto newSequence = QKeySequence::fromString(newCombo);
if (newSequence.count() == 0)
return nullptr;
// Does this command shortcut conflict with other commands already defined?
auto commands = Application::Instance->commandManager().getAllCommands();
for (const auto& cmd : commands) {
if (cmd == ignore)
continue;
auto existingAccel = cmd->getAccel();
if (!existingAccel || existingAccel[0] == '\0')
continue;
// Three possible conflict scenarios:
// 1) Exactly the same combo as another command
// 2) The new command is a one-char combo that overrides an existing two-char combo
// 3) The old command is a one-char combo that overrides the new command
QString existingCombo = QString::fromLatin1(existingAccel);
if (existingCombo.isEmpty())
continue;
auto existingSequence = QKeySequence::fromString(existingCombo);
if (existingSequence.count() == 0)
continue;
// Exact match
if (existingSequence == newSequence)
return cmd;
// If it's not exact, then see if one of the sequences is a partial match for
// the beginning of the other sequence
auto numCharsToCheck = std::min(existingSequence.count(), newSequence.count());
bool firstNMatch = true;
for (int i = 0; i < numCharsToCheck; ++i) {
if (newSequence[i] != existingSequence[i]) {
firstNMatch = false;
break;
}
}
if (firstNMatch)
return cmd;
}
return nullptr;
}
+15 -3
View File
@@ -31,6 +31,7 @@
#include <vector>
#include <Base/Type.h>
#include <Gui/Application.h>
/** @defgroup CommandMacros Helper macros for running commands through Python interpreter */
//@{
@@ -179,8 +180,8 @@
auto __obj = _obj;\
if(__obj && __obj->getNameInDocument()) {\
Gui::Command::doCommand(Gui::Command::Gui,\
"Gui.ActiveDocument.setEdit(App.getDocument('%s').getObject('%s'))",\
__obj->getDocument()->getName(), __obj->getNameInDocument());\
"Gui.ActiveDocument.setEdit(App.getDocument('%s').getObject('%s'), %i)",\
__obj->getDocument()->getName(), __obj->getNameInDocument(), Gui::Application::Instance->getUserEditMode());\
}\
}while(0)
@@ -330,6 +331,7 @@ protected:
/// Applies the menu text, tool and status tip to the passed action object
void applyCommandData(const char* context, Action* );
const char* keySequenceToAccel(int) const;
void printConflictingAccelerators() const;
//@}
public:
@@ -343,6 +345,8 @@ public:
void testActive(void);
/// Enables or disables the command
void setEnabled(bool);
/// (Re)Create the text for the tooltip (for example, when the shortcut is changed)
void recreateTooltip(const char* context, Action*);
/// Command trigger source
enum TriggerSource {
/// No external trigger, e.g. invoked through Python
@@ -450,7 +454,7 @@ public:
*
* @sa Command::_doCommand()
*/
#ifdef FC_OS_WIN32
#ifdef _MSC_VER
#define doCommand(_type,...) _doCommand(__FILE__,__LINE__,_type,##__VA_ARGS__)
#else
#define doCommand(...) _doCommand(__FILE__,__LINE__,__VA_ARGS__)
@@ -870,6 +874,14 @@ public:
void addCommandMode(const char* sContext, const char* sName);
void updateCommands(const char* sContext, int mode);
/**
* Returns a pointer to a conflicting command, or nullptr if there is no conflict.
* In the case of multiple conflicts, only the first is returned.
* \param accel The accelerator to check
* \param ignore (optional) A command to ignore matches with
*/
const Command* checkAcceleratorForConflicts(const char* accel, const Command *ignore = nullptr) const;
private:
/// Destroys all commands in the manager and empties the list.
void clearCommands();
+1 -1
View File
@@ -1574,7 +1574,7 @@ void StdCmdPlacement::activated(int iMsg)
bool StdCmdPlacement::isActive(void)
{
return (Gui::Control().activeDialog()==0);
return Gui::Selection().countObjectsOfType(App::GeoFeature::getClassTypeId()) == 1;
}
//===========================================================================
+1 -1
View File
@@ -31,7 +31,7 @@
#include "MainWindow.h"
#include "Selection.h"
#include "Window.h"
#include "WidgetFactory.h"
#include "PythonWrapper.h"
// inclusion of the generated files (generated out of AreaPy.xml)
#include "CommandPy.h"
+97
View File
@@ -29,6 +29,7 @@
# include <QWhatsThis>
# include <QDesktopServices>
# include <QUrl>
# include <boost_bind_bind.hpp>
#endif
#include <boost/scoped_ptr.hpp>
@@ -63,6 +64,7 @@
using Base::Console;
using Base::Sequencer;
using namespace Gui;
namespace bp = boost::placeholders;
//===========================================================================
@@ -813,6 +815,100 @@ void StdCmdUnitsCalculator::activated(int iMsg)
dlg->show();
}
//===========================================================================
// StdCmdUserEditMode
//===========================================================================
class StdCmdUserEditMode : public Gui::Command
{
public:
StdCmdUserEditMode();
virtual ~StdCmdUserEditMode(){}
virtual void languageChange();
virtual const char* className() const {return "StdCmdUserEditMode";}
void updateIcon(int mode);
protected:
virtual void activated(int iMsg);
virtual bool isActive(void);
virtual Gui::Action * createAction(void);
};
StdCmdUserEditMode::StdCmdUserEditMode()
: Command("Std_UserEditMode")
{
sGroup = QT_TR_NOOP("Edit mode");
sMenuText = QT_TR_NOOP("Edit mode");
sToolTipText = QT_TR_NOOP("Defines behavior when editing an object from tree");
sStatusTip = QT_TR_NOOP("Defines behavior when editing an object from tree");
sWhatsThis = "Std_UserEditMode";
sPixmap = "EditModeDefault";
eType = ForEdit;
this->getGuiApplication()->signalUserEditModeChanged.connect(boost::bind(&StdCmdUserEditMode::updateIcon, this, bp::_1));
}
Gui::Action * StdCmdUserEditMode::createAction(void)
{
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
pcAction->setDropDownMenu(true);
pcAction->setIsMode(true);
applyCommandData(this->className(), pcAction);
for (auto const &uem : Gui::Application::Instance->listUserEditModes()) {
QAction* act = pcAction->addAction(QString());
auto modeName = QString::fromStdString(uem.second);
act->setCheckable(true);
act->setIcon(BitmapFactory().iconFromTheme(qPrintable(QString::fromLatin1("EditMode")+modeName)));
act->setObjectName(QString::fromLatin1("Std_EditMode")+modeName);
act->setWhatsThis(QString::fromLatin1(getWhatsThis()));
if (uem.first == 0) {
pcAction->setIcon(act->icon());
act->setChecked(true);
}
}
_pcAction = pcAction;
languageChange();
return pcAction;
}
void StdCmdUserEditMode::languageChange()
{
Command::languageChange();
if (!_pcAction)
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
for (int i = 0 ; i < a.count() ; i++) {
auto modeName = QString::fromStdString(Gui::Application::Instance->getUserEditModeName(i));
a[i]->setText(QCoreApplication::translate(
"EditMode", qPrintable(modeName)));
a[i]->setToolTip(QCoreApplication::translate(
"EditMode", qPrintable(modeName+QString::fromLatin1(" mode"))));
}
}
void StdCmdUserEditMode::updateIcon(int mode)
{
Gui::ActionGroup *actionGroup = dynamic_cast<Gui::ActionGroup *>(_pcAction);
if (!actionGroup)
return;
actionGroup->setCheckedAction(mode);
}
void StdCmdUserEditMode::activated(int iMsg)
{
Gui::Application::Instance->setUserEditMode(iMsg);
}
bool StdCmdUserEditMode::isActive(void)
{
return true;
}
namespace Gui {
void CreateStdCommands(void)
@@ -842,6 +938,7 @@ void CreateStdCommands(void)
rcCmdMgr.addCommand(new StdCmdPythonWebsite());
rcCmdMgr.addCommand(new StdCmdTextDocument());
rcCmdMgr.addCommand(new StdCmdUnitsCalculator());
rcCmdMgr.addCommand(new StdCmdUserEditMode());
//rcCmdMgr.addCommand(new StdCmdMeasurementSimple());
//rcCmdMgr.addCommand(new StdCmdDownloadOnlineHelp());
//rcCmdMgr.addCommand(new StdCmdDescription());
+223 -13
View File
@@ -61,6 +61,7 @@
#include "SoFCBoundingBox.h"
#include "SoFCUnifiedSelection.h"
#include "SoAxisCrossKit.h"
#include "SoQTQuarterAdaptor.h"
#include "View3DInventor.h"
#include "View3DInventorViewer.h"
#include "ViewParams.h"
@@ -655,6 +656,7 @@ Gui::Action * StdCmdDrawStyle::createAction(void)
{
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
pcAction->setDropDownMenu(true);
pcAction->setIsMode(true);
applyCommandData(this->className(), pcAction);
QAction* a0 = pcAction->addAction(QString());
@@ -2544,10 +2546,137 @@ bool StdViewZoomOut::isActive(void)
{
return (qobject_cast<View3DInventor*>(getMainWindow()->activeWindow()));
}
class SelectionCallbackHandler {
private:
static std::unique_ptr<SelectionCallbackHandler> currentSelectionHandler;
QCursor* prevSelectionCursor;
typedef void (*FnCb)(void * userdata, SoEventCallback * node);
FnCb fnCb;
void* userData;
bool prevSelectionEn;
public:
// Creates a selection handler used to implement the common behaviour of BoxZoom, BoxSelection and BoxElementSelection.
// Takes the viewer, a selection mode, a cursor, a function pointer to be called on success and a void pointer for user data to be passed to the given function.
// The selection handler class stores all necessary previous states, registers a event callback and starts the selection in the given mode.
// If there is still a selection handler active, this call will generate a message and returns.
static void Create(View3DInventorViewer* viewer, View3DInventorViewer::SelectionMode selectionMode, const QCursor& cursor, FnCb doFunction= NULL, void* ud=NULL)
{
if (currentSelectionHandler)
{
Base::Console().Message("SelectionCallbackHandler: A selection handler already active.");
return;
}
currentSelectionHandler = std::unique_ptr<SelectionCallbackHandler>(new SelectionCallbackHandler());
if (viewer)
{
currentSelectionHandler->userData = ud;
currentSelectionHandler->fnCb = doFunction;
currentSelectionHandler->prevSelectionCursor = new QCursor(viewer->cursor());
viewer->setEditingCursor(cursor);
viewer->addEventCallback(SoEvent::getClassTypeId(),
SelectionCallbackHandler::selectionCallback, currentSelectionHandler.get());
currentSelectionHandler->prevSelectionEn = viewer->isSelectionEnabled();
viewer->setSelectionEnabled(false);
viewer->startSelection(selectionMode);
}
};
void* getUserData() { return userData; };
// Implements the event handler. In the normal case the provided function is called.
// Also supports aborting the selection mode by pressing (releasing) the Escape key.
static void selectionCallback(void * ud, SoEventCallback * n)
{
SelectionCallbackHandler* selectionHandler = reinterpret_cast<SelectionCallbackHandler*>(ud);
Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
const SoEvent* ev = n->getEvent();
if (ev->isOfType(SoKeyboardEvent::getClassTypeId())) {
n->setHandled();
n->getAction()->setHandled();
const SoKeyboardEvent * ke = static_cast<const SoKeyboardEvent*>(ev);
const SbBool press = ke->getState() == SoButtonEvent::DOWN ? true : false;
if (ke->getKey() == SoKeyboardEvent::ESCAPE) {
if (!press) {
view->abortSelection();
restoreState(selectionHandler, view);
}
}
}
else if (ev->isOfType(SoMouseButtonEvent::getClassTypeId())) {
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent*>(ev);
// Mark all incoming mouse button events as handled, especially, to deactivate the selection node
n->getAction()->setHandled();
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::UP)
{
if (selectionHandler && selectionHandler->fnCb) selectionHandler->fnCb(selectionHandler->getUserData(), n);
restoreState(selectionHandler, view);
}
// No other mouse events available from Coin3D to implement right mouse up abort
}
}
static void restoreState(SelectionCallbackHandler * selectionHandler, View3DInventorViewer* view)
{
if(selectionHandler) selectionHandler->fnCb = NULL;
view->setEditingCursor(*selectionHandler->prevSelectionCursor);
view->removeEventCallback(SoEvent::getClassTypeId(), SelectionCallbackHandler::selectionCallback, selectionHandler);
view->setSelectionEnabled(selectionHandler->prevSelectionEn);
Application::Instance->commandManager().testActive();
currentSelectionHandler = NULL;
}
};
std::unique_ptr<SelectionCallbackHandler> SelectionCallbackHandler::currentSelectionHandler = std::unique_ptr<SelectionCallbackHandler>();
//===========================================================================
// Std_ViewBoxZoom
//===========================================================================
/* XPM */
static const char * cursor_box_zoom[] = {
"32 32 3 1",
" c None",
". c #FFFFFF",
"@ c #FF0000",
" . ",
" . ",
" . ",
" . ",
" . ",
" ",
"..... ..... ",
" ",
" . @@@@@@@ ",
" . @@@@@@@@@@@ ",
" . @@ @@ ",
" . @@. . . . . .@@ ",
" . @ @ ",
" @@ . . @@ ",
" @@ @@ ",
" @@ . . @@ ",
" @@ @@ ",
" @@ . . @@ ",
" @@ @@ ",
" @@ . . @@ ",
" @ @ ",
" @@. . . . . .@@@ ",
" @@ @@@@ ",
" @@@@@@@@@@@@ @@ ",
" @@@@@@@ @@ @@ ",
" @@ @@ ",
" @@ @@ ",
" @@ @@ ",
" @@ @@ ",
" @@@@ ",
" @@ ",
" " };
DEF_3DV_CMD(StdViewBoxZoom)
StdViewBoxZoom::StdViewBoxZoom()
@@ -2569,8 +2698,9 @@ void StdViewBoxZoom::activated(int iMsg)
View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow());
if ( view ) {
View3DInventorViewer* viewer = view->getViewer();
if (!viewer->isSelecting())
viewer->startSelection(View3DInventorViewer::BoxZoom);
if (!viewer->isSelecting()) {
SelectionCallbackHandler::Create(viewer, View3DInventorViewer::BoxZoom, QCursor(QPixmap(cursor_box_zoom), 7, 7));
}
}
}
@@ -2579,6 +2709,46 @@ void StdViewBoxZoom::activated(int iMsg)
//===========================================================================
DEF_3DV_CMD(StdBoxSelection)
/* XPM */
static const char * cursor_box_select[] = {
"32 32 4 1",
" c None",
". c #FFFFFF",
"+ c #FF0000",
"@ c #000000",
" . ",
" . ",
" . ",
" . ",
" . ",
" ",
"..... ..... ",
" ",
" . ",
" . ",
" . + +++ +++ +++ ",
" . +@@ ",
" . +@.@@@ ",
" @...@@@ ",
" @......@@ ",
" @........@@@ + ",
" @..........@@ + ",
" + @............@ + ",
" + @........@@@ ",
" + @.......@ ",
" @........@ ",
" @........@ + ",
" @...@.....@ + ",
" + @..@ @.....@ + ",
" + @.@ @.....@ ",
" + @.@ @.....@ ",
" @ @.....@ ",
" @...@ ",
" @.@ + ",
" @ + ",
" +++ +++ +++ + ",
" " };
StdBoxSelection::StdBoxSelection()
: Command("Std_BoxSelection")
{
@@ -2717,18 +2887,18 @@ static std::vector<std::string> getBoxSelection(
return ret;
}
static void selectionCallback(void * ud, SoEventCallback * cb)
static void doSelect(void* ud, SoEventCallback * cb)
{
bool selectElement = ud?true:false;
Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(cb->getUserData());
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback, ud);
SoNode* root = view->getSceneGraph();
bool selectElement = ud ? true : false;
Gui::View3DInventorViewer* viewer = reinterpret_cast<Gui::View3DInventorViewer*>(cb->getUserData());
SoNode* root = viewer->getSceneGraph();
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(true);
SelectionMode selectionMode = CENTER;
std::vector<SbVec2f> picked = view->getGLPolygon();
SoCamera* cam = view->getSoRenderManager()->getCamera();
std::vector<SbVec2f> picked = viewer->getGLPolygon();
SoCamera* cam = viewer->getSoRenderManager()->getCamera();
SbViewVolume vv = cam->getViewVolume();
Gui::ViewVolumeProjection proj(vv);
Base::Polygon2d polygon;
@@ -2788,8 +2958,7 @@ void StdBoxSelection::activated(int iMsg)
SoKeyboardEvent ev;
viewer->navigationStyle()->processEvent(&ev);
}
viewer->startSelection(View3DInventorViewer::Rubberband);
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback);
SelectionCallbackHandler::Create(viewer, View3DInventorViewer::Rubberband, QCursor(QPixmap(cursor_box_select), 7, 7), doSelect, NULL);
SoNode* root = viewer->getSceneGraph();
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(false);
}
@@ -2799,6 +2968,48 @@ void StdBoxSelection::activated(int iMsg)
//===========================================================================
// Std_BoxElementSelection
//===========================================================================
/* XPM */
static char * cursor_box_element_select[] = {
"32 32 6 1",
" c None",
". c #FFFFFF",
"+ c #00FF1B",
"@ c #19A428",
"# c #FF0000",
"$ c #000000",
" . ",
" . ",
" . ",
" . ",
" . ",
" ",
"..... ..... ",
" ++++++++++++ ",
" .+@@@@@@@@@@+ ",
" .+@@@@@@@@@@+ ",
" .+@@#@@@@###+ ### ### ",
" .+@@#$$@@@@@+ ",
" .+@@#$.$$$@@+ ",
" +@@@@$...$$$ ",
" +@@@@$......$$ ",
" +@@@@$........$$$ # ",
" +@@@@@$..........$$ # ",
" +@@#@@$............$ # ",
" +++#+++$........$$$ ",
" # $.......$ ",
" $........$ ",
" $........$ # ",
" $...$.....$ # ",
" # $..$ $.....$ # ",
" # $.$ $.....$ ",
" # $.$ $.....$ ",
" $ $.....$ ",
" $...$ ",
" $.$ # ",
" $ # ",
" ### ### ### # ",
" " };
DEF_3DV_CMD(StdBoxElementSelection)
StdBoxElementSelection::StdBoxElementSelection()
@@ -2828,8 +3039,7 @@ void StdBoxElementSelection::activated(int iMsg)
SoKeyboardEvent ev;
viewer->navigationStyle()->processEvent(&ev);
}
viewer->startSelection(View3DInventorViewer::Rubberband);
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback, this);
SelectionCallbackHandler::Create(viewer, View3DInventorViewer::Rubberband, QCursor(QPixmap(cursor_box_element_select), 7, 7), doSelect, this);
SoNode* root = viewer->getSceneGraph();
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(false);
}
+7 -1
View File
@@ -182,7 +182,7 @@
<string>Revert to last calculated value (as constant)</string>
</property>
<property name="autoDefault">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="default">
<bool>false</bool>
@@ -194,6 +194,12 @@
<property name="text">
<string>Ok</string>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
+9 -29
View File
@@ -234,35 +234,8 @@ void DlgCustomKeyboardImp::setShortcutOfCurrentAction(const QString& accelText)
ui->editShortcut->clear();
}
// update the tool tip
QString toolTip = QCoreApplication::translate(cmd->className(),
cmd->getToolTipText());
if (!nativeText.isEmpty()) {
if (!toolTip.isEmpty()) {
QString tip = QString::fromLatin1("%1 (%2)")
.arg(toolTip, nativeText);
action->setToolTip(tip);
}
}
else {
action->setToolTip(toolTip);
}
// update the status tip
QString statusTip = QCoreApplication::translate(cmd->className(),
cmd->getStatusTip());
if (statusTip.isEmpty())
statusTip = toolTip;
if (!nativeText.isEmpty()) {
if (!statusTip.isEmpty()) {
QString tip = QString::fromLatin1("(%1)\t%2")
.arg(nativeText, statusTip);
action->setStatusTip(tip);
}
}
else {
action->setStatusTip(statusTip);
}
// update the tool tip (and status tip)
cmd->recreateTooltip(cmd->className(), action);
// The shortcuts for macros are store in a different location,
// also override the command's shortcut directly
@@ -313,6 +286,9 @@ void DlgCustomKeyboardImp::on_buttonReset_clicked()
ui->accelLineEditShortcut->setText((txt.isEmpty() ? tr("none") : txt));
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("Shortcut");
hGrp->RemoveASCII(name.constData());
// update the tool tip (and status tip)
cmd->recreateTooltip(cmd->className(), cmd->getAction());
}
ui->buttonReset->setEnabled( false );
@@ -327,6 +303,10 @@ void DlgCustomKeyboardImp::on_buttonResetAll_clicked()
if ((*it)->getAction()) {
(*it)->getAction()->setShortcut(QKeySequence(QString::fromLatin1((*it)->getAccel()))
.toString(QKeySequence::NativeText));
// update the tool tip (and status tip)
(*it)->recreateTooltip((*it)->className(), (*it)->getAction());
}
}
+62 -2
View File
@@ -350,8 +350,16 @@ void DlgMacroExecuteImp::on_editButton_clicked()
void DlgMacroExecuteImp::on_createButton_clicked()
{
// query file name
bool replaceSpaces = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->GetBool("ReplaceSpaces", true);
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->SetBool("ReplaceSpaces", replaceSpaces); //create parameter
QString fn = QInputDialog::getText(this, tr("Macro file"), tr("Enter a file name, please:"),
QLineEdit::Normal, QString(), nullptr, Qt::MSWindowsFixedSizeDialogHint);
if(replaceSpaces){
fn = fn.replace(QString::fromStdString(" "),QString::fromStdString("_"));
}
if (!fn.isEmpty())
{
QString suffix = QFileInfo(fn).suffix().toLower();
@@ -674,6 +682,9 @@ void DlgMacroExecuteImp::on_renameButton_clicked()
if (!item)
return;
bool replaceSpaces = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->GetBool("ReplaceSpaces", true);
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->SetBool("ReplaceSpaces", replaceSpaces); //create parameter
QString oldName = item->text(0);
QFileInfo oldfi(dir, oldName);
QFile oldfile(oldfi.absoluteFilePath());
@@ -681,6 +692,11 @@ void DlgMacroExecuteImp::on_renameButton_clicked()
// query new name
QString fn = QInputDialog::getText(this, tr("Renaming Macro File"),
tr("Enter new name:"), QLineEdit::Normal, oldName, nullptr, Qt::MSWindowsFixedSizeDialogHint);
if(replaceSpaces){
fn = fn.replace(QString::fromStdString(" "),QString::fromStdString("_"));
}
if (!fn.isEmpty() && fn != oldName) {
QString suffix = QFileInfo(fn).suffix().toLower();
if (suffix != QLatin1String("fcmacro") && suffix != QLatin1String("py"))
@@ -714,6 +730,24 @@ void DlgMacroExecuteImp::on_duplicateButton_clicked()
QDir dir;
QTreeWidgetItem* item = 0;
//When duplicating a macro we can either begin trying to find a unique name with @001 or begin with the current @NNN if applicable
bool from001 = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->GetBool("DuplicateFrom001", false);
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->SetBool("DuplicateFrom001", from001); //create parameter
//A user may wish to add a note to end of the filename when duplicating
//example: [email protected]_bug_in_dialog.FCMacro
//and then when duplicating to have the extra note removed so the suggested new name is:
//[email protected] instead of [email protected]_bug_in_dialog.FCMacro since the new duplicate will be given a new note
bool ignoreExtra = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->GetBool("DuplicateIgnoreExtraNote", false);
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->SetBool("DuplicateIgnoreExtraNote", ignoreExtra); //create parameter
//when creating a note it will be convenient to convert spaces to underscores if the user desires this behavior
bool replaceSpaces = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->GetBool("ReplaceSpaces", true);
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")->SetBool("ReplaceSpaces", replaceSpaces); //create parameter
int index = ui->tabMacroWidget->currentIndex();
if (index == 0) { //user-specific
item = ui->userMacroListBox->currentItem();
@@ -728,15 +762,19 @@ void DlgMacroExecuteImp::on_duplicateButton_clicked()
QFileInfo oldfi(dir, oldName);
QFile oldfile(oldfi.absoluteFilePath());
QString completeSuffix = oldfi.completeSuffix(); //everything after the first "."
QString extraNote = completeSuffix.left(completeSuffix.size()-oldfi.suffix().size());
QString baseName = oldfi.baseName(); //everything before first "."
QString neutralSymbol = QString::fromStdString("@");
QString last3 = baseName.right(3);
bool ok = true; //was conversion to int successful?
int nLast3 = last3.toInt(&ok);
last3 = QString::fromStdString("001"); //increment beginning with 001 no matter what
last3 = QString::fromStdString("001"); //increment beginning with 001 unless from001 = false
if (ok ){
//last3 were all digits, so we strip them from the base name
if (baseName.size()>3){ //if <= 3 leave be (e.g. 2.py becomes [email protected])
if(!from001){
last3 = baseName.right(3); //use these instead of 001
}
baseName = baseName.left(baseName.size()-3); //strip digits
if (baseName.endsWith(neutralSymbol)){
baseName = baseName.left(baseName.size()-1); //trim the "@", will be added back later
@@ -745,13 +783,28 @@ void DlgMacroExecuteImp::on_duplicateButton_clicked()
}
//at this point baseName = the base name without any digits, e.g. "MyMacro"
//neutralSymbol = "@"
//last3 is a string representing 3 digits, always "001" at this time
//last3 is a string representing 3 digits, always "001"
//unless from001 = false, in which case we begin with previous numbers
//completeSuffix = FCMacro or py or FCMacro.py or else suffix will become FCMacro below
//if ignoreExtra any extra notes added between @NN. and .FCMacro will be ignored
//when suggesting a new filename
if(ignoreExtra && !extraNote.isEmpty()){
nLast3++;
last3 = QString::number(nLast3);
while (last3.size()<3){
last3.prepend(QString::fromStdString("0")); //pad 0's if needed
}
}
QString oldNameDigitized = baseName+neutralSymbol+last3+QString::fromStdString(".")+completeSuffix;
QFileInfo fi(dir, oldNameDigitized);
// increment until we find available name with smallest digits
// test from "001" through "999", then give up and let user enter name of choice
while (fi.exists()) {
nLast3 = last3.toInt()+1;
if (nLast3 >=1000){ //avoid infinite loop, 999 files will have to be enough
@@ -765,10 +818,17 @@ void DlgMacroExecuteImp::on_duplicateButton_clicked()
fi = QFileInfo(dir,oldNameDigitized);
}
if(ignoreExtra && !extraNote.isEmpty()){
oldNameDigitized = oldNameDigitized.remove(extraNote);
}
// give user a chance to pick a different name from digitized name suggested
QString fn = QInputDialog::getText(this, tr("Duplicate Macro"),
tr("Enter new name:"), QLineEdit::Normal, oldNameDigitized,
nullptr, Qt::MSWindowsFixedSizeDialogHint);
if (replaceSpaces){
fn = fn.replace(QString::fromStdString(" "),QString::fromStdString("_"));
}
if (!fn.isEmpty() && fn != oldName) {
QString suffix = QFileInfo(fn).suffix().toLower();
if (suffix != QLatin1String("fcmacro") && suffix != QLatin1String("py")){
+26
View File
@@ -22,6 +22,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QTreeWidget>
# include <QPushButton>
#endif
#include <Base/Console.h>
@@ -43,6 +44,12 @@ DlgObjectSelection::DlgObjectSelection(
const std::vector<App::DocumentObject*> &objs, QWidget* parent, Qt::WindowFlags fl)
: QDialog(parent, fl), ui(new Ui_DlgObjectSelection)
{
/**
* make a copy of the originally selected objects
* so we can return them if the user clicks useOriginalsBtn
*/
this->originalSelections = objs;
ui->setupUi(this);
// make sure to show a horizontal scrollbar if needed
@@ -97,6 +104,14 @@ DlgObjectSelection::DlgObjectSelection(
v.second.inList[obj] = &it->second;
}
}
/**
* create useOriginalsBtn and add to the button box
* tried adding to .ui file, but could never get the
* formatting exactly the way I wanted it. -- <TheMarkster>
*/
useOriginalsBtn = new QPushButton(tr("&Use Original Selections"));
useOriginalsBtn->setToolTip(tr("Ignore dependencies and proceed with objects\noriginally selected prior to opening this dialog"));
ui->buttonBox->addButton(useOriginalsBtn,QDialogButtonBox::ActionRole);
connect(ui->treeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)),
this, SLOT(onItemExpanded(QTreeWidgetItem*)));
@@ -110,6 +125,7 @@ DlgObjectSelection::DlgObjectSelection(
this, SLOT(onDepSelectionChanged()));
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(useOriginalsBtn, SIGNAL(clicked()), this, SLOT(onUseOriginalsBtnClicked()));
}
/**
@@ -293,6 +309,11 @@ void DlgObjectSelection::onItemChanged(QTreeWidgetItem * item, int column) {
}
std::vector<App::DocumentObject*> DlgObjectSelection::getSelections() const {
if (returnOriginals){
return originalSelections;
}
std::vector<App::DocumentObject*> res;
for(auto &v : objMap) {
if(v.second.checkState != Qt::Unchecked)
@@ -356,6 +377,11 @@ void DlgObjectSelection::onDepSelectionChanged() {
ui->treeWidget->scrollToItem(scroll);
}
void DlgObjectSelection::onUseOriginalsBtnClicked(){
returnOriginals = true;
QDialog::accept();
}
void DlgObjectSelection::accept() {
QDialog::accept();
}
+4
View File
@@ -45,10 +45,14 @@ private Q_SLOTS:
void onItemChanged(QTreeWidgetItem * item, int);
void onItemSelectionChanged();
void onDepSelectionChanged();
void onUseOriginalsBtnClicked();
private:
QTreeWidgetItem *createItem(App::DocumentObject *obj, QTreeWidgetItem *parent);
App::DocumentObject *objFromItem(QTreeWidgetItem *item);
QPushButton *useOriginalsBtn;
std::vector<App::DocumentObject*> originalSelections;
bool returnOriginals = false;
private:
struct Info {
+1
View File
@@ -26,6 +26,7 @@
#include <QDialog>
#include <memory>
#include <FCGlobal.h>
class QAbstractButton;
class QListWidgetItem;
+1 -1
View File
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Unloaded Workbenches</string>
<string>Available Workbenches</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
+2 -2
View File
@@ -91,7 +91,7 @@ void DlgSettingsNavigation::saveSettings()
ui->checkBoxInvertZoom->onSave();
ui->checkBoxDisableTilt->onSave();
ui->spinBoxZoomStep->onSave();
ui->CheckBox_UseAutoRotation->onSave();
ui->checkBoxUseAutoRotation->onSave();
ui->qspinNewDocScale->onSave();
ui->prefStepByTurn->onSave();
ui->naviCubeToNearest->onSave();
@@ -117,7 +117,7 @@ void DlgSettingsNavigation::loadSettings()
ui->checkBoxInvertZoom->onRestore();
ui->checkBoxDisableTilt->onRestore();
ui->spinBoxZoomStep->onRestore();
ui->CheckBox_UseAutoRotation->onRestore();
ui->checkBoxUseAutoRotation->onRestore();
ui->qspinNewDocScale->onRestore();
ui->prefStepByTurn->onRestore();
ui->naviCubeToNearest->onRestore();
+1 -1
View File
@@ -404,7 +404,7 @@ The value is the diameter of the sphere to fit on the screen.</string>
</widget>
</item>
<item row="5" column="0">
<widget class="Gui::PrefCheckBox" name="CheckBox_UseAutoRotation">
<widget class="Gui::PrefCheckBox" name="checkBoxUseAutoRotation">
<property name="enabled">
<bool>true</bool>
</property>
+4 -4
View File
@@ -58,10 +58,10 @@ void DlgSettingsSelection::saveSettings()
void DlgSettingsSelection::loadSettings()
{
auto handle = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/TreeView");
ui->checkBoxAutoSwitch->setChecked(handle->GetBool("SyncView"));
ui->checkBoxAutoExpand->setChecked(handle->GetBool("SyncSelection"));
ui->checkBoxPreselect->setChecked(handle->GetBool("PreSelection"));
ui->checkBoxRecord->setChecked(handle->GetBool("RecordSelection"));
ui->checkBoxAutoSwitch->setChecked(handle->GetBool("SyncView", true));
ui->checkBoxAutoExpand->setChecked(handle->GetBool("SyncSelection", true));
ui->checkBoxPreselect->setChecked(handle->GetBool("PreSelection", true));
ui->checkBoxRecord->setChecked(handle->GetBool("RecordSelection", true));
ui->checkBoxSelectionCheckBoxes->setChecked(handle->GetBool("CheckBoxesSelection"));
}
+65 -4
View File
@@ -1158,9 +1158,29 @@ bool Document::save(void)
if(gdoc) gdoc->setModified(false);
}
}
catch (const Base::FileException& e) {
int ret = QMessageBox::question(
getMainWindow(),
QObject::tr("Could not save document"),
QObject::tr("There was an issue trying to save the file. "
"This may be because some of the parent folders do not exist, "
"or you do not have sufficient permissions, "
"or for other reasons. Error details:\n\n\"%1\"\n\n"
"Would you like to save the file with a different name?")
.arg(QString::fromLatin1(e.what())),
QMessageBox::Yes, QMessageBox::No);
if (ret == QMessageBox::No) {
// TODO: Understand what exactly is supposed to be returned here
getMainWindow()->showMessage(QObject::tr("Saving aborted"), 2000);
return false;
} else if (ret == QMessageBox::Yes) {
return saveAs();
}
}
catch (const Base::Exception& e) {
QMessageBox::critical(getMainWindow(), QObject::tr("Saving document failed"),
QString::fromLatin1(e.what()));
return false;
}
return true;
}
@@ -1196,6 +1216,25 @@ bool Document::saveAs(void)
setModified(false);
getMainWindow()->appendRecentFile(fi.filePath());
}
catch (const Base::FileException& e) {
int ret = QMessageBox::question(
getMainWindow(),
QObject::tr("Could not save document"),
QObject::tr("There was an issue trying to save the file. "
"This may be because some of the parent folders do not exist, "
"or you do not have sufficient permissions, "
"or for other reasons. Error details:\n\n\"%1\"\n\n"
"Would you like to save the file with a different name?")
.arg(QString::fromLatin1(e.what())),
QMessageBox::Yes, QMessageBox::No);
if (ret == QMessageBox::No) {
// TODO: Understand what exactly is supposed to be returned here
getMainWindow()->showMessage(QObject::tr("Saving aborted"), 2000);
return false;
} else if (ret == QMessageBox::Yes) {
return saveAs();
}
}
catch (const Base::Exception& e) {
QMessageBox::critical(getMainWindow(), QObject::tr("Saving document failed"),
QString::fromLatin1(e.what()));
@@ -1942,11 +1981,33 @@ bool Document::canClose (bool checkModify, bool checkLink)
bool ok = true;
if (checkModify && isModified() && !getDocument()->testStatus(App::Document::PartialDoc)) {
int res = getMainWindow()->confirmSave(getDocument()->Label.getValue(),getActiveView());
if(res>0)
const char *docName = getDocument()->Label.getValue();
int res = getMainWindow()->confirmSave(docName, getActiveView());
switch (res)
{
case MainWindow::ConfirmSaveResult::Cancel:
ok = false;
break;
case MainWindow::ConfirmSaveResult::SaveAll:
case MainWindow::ConfirmSaveResult::Save:
ok = save();
else
ok = res<0;
if (!ok) {
int ret = QMessageBox::question(
getActiveView(),
QObject::tr("Document not saved"),
QObject::tr("The document%1 could not be saved. Do you want to cancel closing it?")
.arg(docName?(QString::fromUtf8(" ")+QString::fromUtf8(docName)):QString()),
QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Discard);
if (ret == QMessageBox::Discard)
ok = true;
}
break;
case MainWindow::ConfirmSaveResult::DiscardAll:
case MainWindow::ConfirmSaveResult::Discard:
ok = true;
break;
}
}
if (ok) {
+1 -1
View File
@@ -165,7 +165,7 @@ private:
/**
* @brief The ViewProviderWeakPtrT class
*/
class AppExport ViewProviderWeakPtrT
class GuiExport ViewProviderWeakPtrT
{
public:
ViewProviderWeakPtrT(ViewProviderDocumentObject*);
+1 -1
View File
@@ -25,7 +25,7 @@
#endif
#include "ExpressionBindingPy.h"
#include "ExpressionBinding.h"
#include "WidgetFactory.h"
#include "PythonWrapper.h"
#include "QuantitySpinBox.h"
#include "InputField.h"
#include <App/DocumentObjectPy.h>
+243
View File
@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2816"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="ImageWorkbench.svg">
<defs
id="defs2818">
<linearGradient
inkscape:collect="always"
id="linearGradient3825">
<stop
style="stop-color:#4e9a06;stop-opacity:1;"
offset="0"
id="stop3827" />
<stop
style="stop-color:#8ae234;stop-opacity:1"
offset="1"
id="stop3829" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3817">
<stop
style="stop-color:#a40000;stop-opacity:1"
offset="0"
id="stop3819" />
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="1"
id="stop3821" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3809">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3811" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3813" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3767">
<stop
style="stop-color:#c17d11;stop-opacity:1"
offset="0"
id="stop3769" />
<stop
style="stop-color:#e9b96e;stop-opacity:1"
offset="1"
id="stop3771" />
</linearGradient>
<linearGradient
id="linearGradient3691">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3693" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop3695" />
</linearGradient>
<linearGradient
id="linearGradient3614">
<stop
style="stop-color:#ff9100;stop-opacity:1;"
offset="0"
id="stop3616" />
<stop
style="stop-color:#ffcb00;stop-opacity:1;"
offset="1"
id="stop3618" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2824" />
<inkscape:perspective
id="perspective2834"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3691"
id="linearGradient3697"
x1="31.066811"
y1="17.542589"
x2="26.010498"
y2="24.832104"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-0.37824909,-2.8753906)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3767"
id="linearGradient3773"
x1="38"
y1="56"
x2="23"
y2="11"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3767-7"
id="linearGradient3773-1"
x1="38"
y1="56"
x2="23"
y2="11"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient3767-7">
<stop
style="stop-color:#8f5902;stop-opacity:1"
offset="0"
id="stop3769-4" />
<stop
style="stop-color:#e9b96e;stop-opacity:1"
offset="1"
id="stop3771-0" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3809"
id="linearGradient3815"
x1="49"
y1="40"
x2="43"
y2="29"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3817"
id="linearGradient3823"
x1="42"
y1="52"
x2="36"
y2="35"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3825"
id="linearGradient3831"
x1="31"
y1="48"
x2="27"
y2="36"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11"
inkscape:cx="27.819741"
inkscape:cy="25.25348"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="837"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-bbox="true"
inkscape:snap-nodes="false">
<inkscape:grid
type="xygrid"
id="grid2997"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2821">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="fill:url(#linearGradient3773);fill-opacity:1;stroke:#271903;stroke-width:1.99999988000000010;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 14.371999,5.0538129 C 7.8696489,5.9472735 2.7428728,13.491844 3.0099824,21.942056 3.3492104,32.673779 20.653513,54.224555 31.609802,56.533609 42.566089,58.84266 54.497373,52.194832 58.294307,45.024826 62.091243,37.85482 62.551014,24.106355 55.352159,18.710901 48.153305,13.315446 38.635294,17.388528 32.133777,16.028924 25.63226,14.669318 20.874348,4.1603522 14.371999,5.0538129 z m 3.992937,13.5953611 c 3.445997,0.07124 6.845415,3.444682 6.784747,7.009598 -0.992516,10.288311 -15.4911171,1.008006 -10.128426,-5.868502 1.028684,-0.826923 2.195014,-1.16484 3.343679,-1.141096 z"
id="path2840"
sodipodi:nodetypes="cszzzzzcccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient3831);stroke:#4e9a06;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="m 26.484363,35.972858 c -3.430345,1.49337 -1.427147,5.521391 -0.995166,8.148201 0.07684,2.825426 3.049863,6.651994 6.009348,4.612197 2.725914,-2.617267 2.01049,-6.876427 0.925458,-10.088285 -0.847269,-2.556979 -3.463456,-3.681919 -5.93964,-2.672113 z"
id="path3644" />
<path
style="fill:url(#linearGradient3823);stroke:#a40000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="m 35.483904,38.801286 c -0.614014,3.657403 -0.588904,7.644227 1.24659,10.969758 0.526463,0.878063 1.097031,1.827625 2.013469,2.339827 1.295182,0.687126 3.044551,0.542866 4.059789,-0.573318 1.649455,-1.632946 2.102305,-4.363465 1.071235,-6.439563 -0.760845,-1.232935 -2.036005,-2.003223 -3.125803,-2.914563 -1.34932,-1.039951 -2.730874,-2.328706 -2.998644,-4.099852 -0.174498,-1.08408 0.399099,-2.293989 -0.293445,-3.274314 -0.410772,-0.711168 -1.462137,-1.306295 -2.192922,-0.701898 -0.73315,0.818306 -0.346058,2.017311 -0.155827,2.971112 0.141329,0.57038 0.30568,1.13773 0.375558,1.722811 z"
id="path3654" />
<path
style="fill:url(#linearGradient3815);stroke:#204a87;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="m 35.998163,30.058875 c 2.8139,0.725202 5.667849,2.68437 6.055182,5.780259 -0.324522,2.843364 2.643122,3.395323 4.816063,3.564547 2.43744,-0.225527 2.724431,4.475957 5.109502,2.908887 2.027846,-2.172623 1.204782,-5.559781 -0.180215,-7.835537 -1.508283,-2.056753 -2.407321,-5.463248 -5.708611,-4.057709 -3.157474,0.569068 -5.221518,-3.684217 -8.46863,-2.397408 -0.898837,0.220429 -2.117867,0.917831 -1.623291,2.036961 z"
id="path3666" />
<path
style="fill:none;stroke:#e9b96e;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 14.405905,7.322401 C 9.0792655,7.2380432 4.7606057,14.838626 5.0092939,22.638821 5.3251269,32.545027 22.617848,52.165325 31.818531,54.478577 41.019214,56.791829 52.673104,51.291734 56.480909,43.945994 60.288714,36.600254 60.898595,25.363909 54.196212,20.38349 47.49383,15.403069 39.359507,19.344659 32.033643,17.998728 24.707779,16.652797 19.732544,7.4067588 14.405905,7.322401 z m 5.092228,9.44841 c 4.847544,0.483596 9.008898,6.329545 7.120365,11.580851 -5.455979,9.65761 -19.8224908,-1.801536 -12.933308,-10.109696 0.989881,-0.827597 4.100672,-1.910909 5.812943,-1.471155 z"
id="path2840-9"
sodipodi:nodetypes="zszzzzzcccc"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

+496
View File
@@ -0,0 +1,496 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
id="svg23883"
sodipodi:version="0.32"
inkscape:version="0.43+devel"
version="1.0"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
sodipodi:docname="edit-cut.svg"
inkscape:export-filename="/home/garrett/edit-cut.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs23885">
<linearGradient
inkscape:collect="always"
id="linearGradient2269">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop2271" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop2273" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2259">
<stop
style="stop-color:#9a0c00;stop-opacity:1;"
offset="0"
id="stop2261" />
<stop
style="stop-color:#9a0c00;stop-opacity:0;"
offset="1"
id="stop2263" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2251">
<stop
style="stop-color:#df2a2a;stop-opacity:1;"
offset="0"
id="stop2253" />
<stop
style="stop-color:#df2a2a;stop-opacity:0;"
offset="1"
id="stop2255" />
</linearGradient>
<linearGradient
id="linearGradient2229">
<stop
style="stop-color:#e2e2e2;stop-opacity:1;"
offset="0"
id="stop2231" />
<stop
style="stop-color:#d8d8d8;stop-opacity:1;"
offset="1"
id="stop2233" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.000000,0.000000,0.000000,1.010300,1.007969e-18,-0.159801)"
r="7.2848282"
cy="23.333008"
cx="165.06104"
id="radialGradient16850">
<stop
id="stop16852"
style="stop-color:#EF3535"
offset="0" />
<stop
id="stop16854"
style="stop-color:#a40000;stop-opacity:0"
offset="1" />
</radialGradient>
<linearGradient
id="XMLID_897_"
gradientUnits="userSpaceOnUse"
x1="292.97168"
y1="4.7592773"
x2="296.93979"
y2="10.711433">
<stop
offset="0"
style="stop-color:#EEEEEC"
id="stop45093" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:1;"
id="stop45095" />
</linearGradient>
<linearGradient
id="path3230_2_"
gradientUnits="userSpaceOnUse"
x1="1668.7646"
y1="185.30176"
x2="1679.5989"
y2="175.78883"
gradientTransform="matrix(1.213800,0.000000,0.282500,-1.671200,46.72625,447.9442)">
<stop
offset="0"
style="stop-color:#FFFFFF"
id="stop4977" />
<stop
offset="1"
style="stop-color:#CFCFCF"
id="stop4979" />
</linearGradient>
<linearGradient
id="path3311_1_"
gradientUnits="userSpaceOnUse"
x1="1420.5474"
y1="-50.919434"
x2="1420.6542"
y2="-79.574341"
gradientTransform="matrix(2.051000,0.000000,0.167200,-0.989000,-799.2049,221.0724)">
<stop
offset="0"
style="stop-color:#C4A000"
id="stop4970" />
<stop
offset="1"
style="stop-color:#957A00"
id="stop4972" />
</linearGradient>
<radialGradient
id="XMLID_52_"
cx="165.06104"
cy="23.333008"
r="7.2848282"
gradientTransform="matrix(1.000000,0.000000,0.000000,1.010300,1.007969e-18,-0.159801)"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#EF3535"
id="stop812" />
<stop
id="stop2239"
style="stop-color:#c91a1a;stop-opacity:1;"
offset="0" />
<stop
offset="1"
style="stop-color:#ff4c4c;stop-opacity:1;"
id="stop814" />
</radialGradient>
<linearGradient
id="XMLID_45_"
gradientUnits="userSpaceOnUse"
x1="68.175293"
y1="21.424805"
x2="74.587158"
y2="27.836672">
<stop
offset="0"
style="stop-color:#BABDB6"
id="stop695" />
<stop
offset="1"
style="stop-color:#EEEEEC"
id="stop697" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#path3230_2_"
id="linearGradient142876"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.213781,0,0.282495,-1.671173,-1712.251,391.532)"
x1="1668.7646"
y1="185.30176"
x2="1679.5989"
y2="175.78883" />
<linearGradient
inkscape:collect="always"
xlink:href="#path3230_2_"
id="linearGradient142884"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.213781,0.000000,0.282495,-1.671173,-1385.251,394.5320)"
x1="1668.7646"
y1="185.30176"
x2="1679.5989"
y2="175.78883" />
<linearGradient
inkscape:collect="always"
xlink:href="#path3311_1_"
id="linearGradient142892"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.050967,0.000000,0.167197,-0.988984,-2231.169,167.6639)"
x1="1420.5474"
y1="-50.919434"
x2="1420.6542"
y2="-79.574341" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_45_"
id="linearGradient16739"
x1="22.225399"
y1="23.843431"
x2="24.190449"
y2="22.860907"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient16769"
x1="294.59497"
y1="12.187603"
x2="297.18515"
y2="13.3396"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient16894"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.624438,0.000000,0.000000,3.624438,-1053.179,-16.84720)"
x1="296.76199"
y1="12.012225"
x2="297.79822"
y2="10.946587" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient16946"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.637893,0.000000,0.000000,3.470375,-1056.116,-16.00724)"
x1="296.48611"
y1="15.506916"
x2="296.52905"
y2="9.8769522" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_897_"
id="linearGradient16968"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-4.127761,0.000000,0.000000,4.136601,1244.465,-11.90495)"
x1="292.97168"
y1="4.7592773"
x2="296.93979"
y2="10.711433" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_897_"
id="linearGradient16974"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(4.053427,0.000000,0.000000,4.136601,-1175.535,-11.90495)"
x1="292.97168"
y1="4.7592773"
x2="296.93979"
y2="10.711433" />
<linearGradient
inkscape:collect="always"
xlink:href="#radialGradient16850"
id="linearGradient17028"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.161878,0.000000,0.000000,0.992497,-5.112111,6.400522e-2)"
x1="39.619942"
y1="44.540932"
x2="-3.532515"
y2="-11.889042" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient17034"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.161878,0.000000,0.000000,0.992497,-2.666967,6.400522e-2)"
x1="13.82536"
y1="40.068752"
x2="7.6700611"
y2="2.3262277" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient17037"
gradientUnits="userSpaceOnUse"
x1="7.184845"
y1="31.056622"
x2="25.152235"
y2="50.774887"
gradientTransform="matrix(1.161878,0.000000,0.000000,0.992497,-2.430779,0.265761)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2229"
id="linearGradient2235"
x1="20.288025"
y1="6.4603648"
x2="24.32597"
y2="23.942537"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2229"
id="linearGradient2237"
x1="20.288025"
y1="6.4603648"
x2="24.32597"
y2="23.942537"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="radialGradient2241"
cx="34.376091"
cy="37.50008"
fx="34.376091"
fy="37.50008"
r="8.3887873"
gradientTransform="matrix(1.000000,0.000000,0.000000,1.060381,0.000000,-2.299514)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2251"
id="linearGradient2257"
x1="298.47852"
y1="13.599585"
x2="298.86948"
y2="13.802949"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2259"
id="linearGradient2265"
x1="298.47852"
y1="13.599585"
x2="298.86948"
y2="13.802949"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2269"
id="radialGradient2275"
cx="25.1875"
cy="41.625"
fx="25.1875"
fy="41.625"
r="18.0625"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.325260,2.029626e-16,28.08607)"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="0.13333333"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313708"
inkscape:cx="32.034218"
inkscape:cy="23.0589"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
gridempspacing="4"
gridtolerance="0.5px"
inkscape:window-width="1011"
inkscape:window-height="1110"
inkscape:window-x="378"
inkscape:window-y="0"
stroke="#a40000"
inkscape:showpageshadow="false" />
<metadata
id="metadata23888">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Edit Cut</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Garrett Le Sage</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>edit</rdf:li>
<rdf:li>cut</rdf:li>
<rdf:li>clipboard</rdf:li>
</rdf:Bag>
</dc:subject>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.0/" />
<dc:contributor>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:prohibits
rdf:resource="http://web.resource.org/cc/CommercialUse" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="fill:url(#linearGradient16968);stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 34.174311,1.6249997 C 34.386261,1.6935355 34.59157,1.7696619 34.798294,1.842502 C 35.449709,4.0395037 38.469777,6.2612218 37.321354,8.4491328 C 33.495509,14.82952 29.697021,21.294565 25.899759,27.72527 C 25.154013,27.872172 24.401732,27.952183 23.647995,27.96996 C 22.061603,28.01017 20.433063,27.775465 18.927431,27.23589 C 23.978303,18.684616 29.031301,10.114483 34.174311,1.6249997 z "
id="path16717" />
<path
style="fill:url(#linearGradient2237);fill-opacity:1;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 34.288823,4.25 C 34.057702,4.5574529 33.839208,5.120942 33.602793,5.40625 C 29.555938,12.158979 25.440784,18.900329 21.378976,25.625 C 21.318425,25.878117 20.565047,26.637291 21.366935,26.567963 C 22.478492,26.765843 23.638682,26.918567 24.746762,26.625 C 28.505752,20.407794 32.192639,14.142582 35.943048,7.9231779 C 36.285519,7.5359043 36.352163,6.9979201 35.992403,6.611197 C 35.462387,5.7945892 34.925464,4.9364821 34.382373,4.15625 L 34.311813,4.2269607 L 34.288823,4.25 z "
id="path16719" />
<polygon
style="fill:url(#linearGradient16769);fill-opacity:1;stroke:#9a0c00;stroke-width:0.28144068;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="polygon45129"
points="297.04443,12.300293 296.39941,13.384766 295.13281,14.71875 294.73242,13.672852 295.74658,11.960449 297.04443,12.300293 "
transform="matrix(3.637893,0.000000,0.000000,3.470375,-1056.116,-16.00724)" />
<path
style="fill:url(#linearGradient16946);fill-opacity:1;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 20.40625,26.96875 C 19.183905,27.455468 19.192232,29.003929 18.481272,29.932762 C 18.138949,30.648557 17.537483,31.278989 17.28125,32.03125 C 17.271571,32.546641 17.729203,33.391474 18.3125,32.9375 C 19.697476,31.791172 20.876866,30.398821 21.756725,28.810629 C 21.989088,28.320596 22.552476,27.916466 22.625,27.40625 C 22.086431,26.835441 21.112182,26.873225 20.40625,26.96875 z "
id="polygon16896" />
<path
style="fill:url(#linearGradient16974);stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 12.960099,1.6249997 C 12.751966,1.6935355 12.550355,1.7696619 12.347353,1.842502 C 11.707669,4.0395037 8.7419877,6.2612218 9.8697297,8.4491328 C 13.626677,14.82952 17.35676,21.294565 21.085639,27.72527 C 21.817956,27.872172 22.55669,27.952183 23.296853,27.96996 C 24.854677,28.01017 26.453889,27.775465 27.932407,27.23589 C 22.972493,18.684616 18.010492,10.114483 12.960099,1.6249997 z "
id="polygon45097" />
<path
style="fill:url(#linearGradient2235);fill-opacity:1;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 12.719667,4.25 C 12.336632,5.3766793 11.270006,6.2059645 11.004855,7.40625 C 14.713376,13.800362 18.475798,20.175378 22.181757,26.5625 C 23.380123,26.820799 24.610198,26.655657 25.795112,26.40625 C 25.606339,25.665807 25.056911,25.075319 24.765129,24.3767 C 20.870526,17.806174 16.941429,11.242872 13.087127,4.65625 C 13.072466,4.5046403 12.870425,4.1721152 12.719667,4.25 z "
id="path16635" />
<path
sodipodi:type="arc"
style="opacity:1;color:#000000;fill:url(#linearGradient16739);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path16731"
sodipodi:cx="23.207924"
sodipodi:cy="23.843431"
sodipodi:rx="0.98252523"
sodipodi:ry="0.98252523"
d="M 24.190449 23.843431 A 0.98252523 0.98252523 0 1 1 22.225399,23.843431 A 0.98252523 0.98252523 0 1 1 24.190449 23.843431 z"
transform="matrix(0.979893,0.000000,0.000000,1.000000,0.311384,0.174043)" />
<path
sodipodi:type="arc"
style="opacity:0.26704544;color:#000000;fill:url(#radialGradient2275);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path2267"
sodipodi:cx="25.1875"
sodipodi:cy="41.625"
sodipodi:rx="18.0625"
sodipodi:ry="5.875"
d="M 43.25 41.625 A 18.0625 5.875 0 1 1 7.125,41.625 A 18.0625 5.875 0 1 1 43.25 41.625 z"
transform="matrix(1.256055,0.000000,0.000000,0.819149,-7.199394,9.090421)" />
<path
id="path45138"
style="fill:url(#linearGradient17037);fill-opacity:1;stroke:#a40000;stroke-opacity:1"
d="M 17.700393,30.286934 C 20.935404,32.013583 21.196229,36.899851 18.278338,41.201286 C 15.360479,45.50525 10.373849,47.596472 7.1373807,45.877418 C 3.9008825,44.150767 3.6415462,39.267032 6.5594356,34.965597 C 9.4758075,30.664166 14.463925,28.572944 17.700393,30.286934 z M 15.845268,33.029079 C 14.408745,32.26545 11.33781,33.569599 9.3789266,36.463107 C 7.4160164,39.356612 7.5560293,42.376624 8.991202,43.137951 C 10.426348,43.906181 13.499985,42.597432 15.458868,39.703925 C 17.42313,36.81042 17.281765,33.792709 15.845268,33.029079 z " />
<path
style="fill:url(#linearGradient17034);fill-opacity:1;stroke:none;stroke-opacity:1"
d="M 14.3255,30.583289 C 12.400369,30.97051 10.691041,32.037306 9.2785926,33.064531 C 8.5268294,33.759433 8.0350294,34.514452 7.3629449,35.31874 C 5.6546178,37.670805 4.9387067,40.762168 6.2901069,43.388409 C 6.90956,44.841515 8.9327419,45.435852 10.658323,45.067542 C 12.110236,44.819078 13.339639,43.906473 14.470735,43.268641 C 15.391637,42.47786 16.024749,41.642131 16.803626,40.677364 C 18.612986,38.202962 19.595537,34.928687 18.101604,32.165081 C 17.377898,31.022952 15.866963,30.41829 14.3255,30.583289 z M 14.797513,31.54477 C 16.814017,31.795124 18.154487,33.577585 17.92006,35.266634 C 17.940833,37.553573 16.774038,39.710728 15.196909,41.500756 C 13.779705,42.902737 11.848294,44.229027 9.5327534,44.137076 C 8.1738996,44.134209 7.100179,43.224779 6.7169325,42.176618 C 6.1002938,39.644695 6.9116496,36.911389 8.6831288,34.83862 C 10.041367,33.315308 11.877976,31.95152 14.150642,31.596926 C 14.366331,31.581652 14.581522,31.554432 14.797513,31.54477 z "
id="path16771" />
<path
d="M 30.331764,30.286934 C 27.096753,32.013583 26.835929,36.899851 29.75382,41.201286 C 32.671679,45.50525 37.658309,47.596472 40.894777,45.877418 C 44.131276,44.150767 44.390611,39.267032 41.472722,34.965597 C 38.55635,30.664166 33.568233,28.572944 30.331764,30.286934 z M 32.18689,33.029079 C 33.623412,32.26545 36.694348,33.569599 38.653231,36.463107 C 40.616141,39.356612 40.476128,42.376624 39.040956,43.137951 C 37.60581,43.906181 34.532173,42.597432 32.57329,39.703925 C 30.609028,36.81042 30.750393,33.792709 32.18689,33.029079 z "
style="fill:url(#radialGradient2241);fill-opacity:1;stroke:#a40000;stroke-opacity:1"
id="path11967" />
<polygon
style="fill:url(#linearGradient2257);fill-opacity:1;stroke:url(#linearGradient2265);stroke-width:0.27590489;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="polygon45101"
points="296.95605,12.300293 297.6001,13.384766 298.86719,14.71875 299.26807,13.672852 298.25391,11.960449 296.95605,12.300293 "
transform="matrix(3.624438,0.000000,0.000000,3.624438,-1053.179,-16.84720)" />
<path
style="fill:url(#linearGradient16894);fill-opacity:1;stroke:none;stroke-width:0.27590489;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 26.15625,27.9375 C 25.729502,28.136321 25.139436,28.138981 24.8125,28.4375 C 25.76252,29.838889 26.702412,31.352161 27.663379,32.650077 C 28.331933,33.404621 29.019194,34.150303 29.78125,34.8125 C 30.516527,33.421076 29.91641,31.751292 28.96875,30.625 C 28.366215,29.725307 28.138928,28.512038 27.125,28.03125 C 26.820951,27.912839 26.474385,27.853373 26.15625,27.9375 z "
id="polygon16860" />
<path
style="fill:url(#linearGradient17028);fill-opacity:1;stroke:none;stroke-opacity:1"
d="M 32.280087,30.449093 C 30.759703,30.678844 29.385141,31.534748 29.039639,32.837057 C 27.908495,35.232508 28.824763,37.950571 30.319418,40.063908 C 31.421345,41.40911 32.259488,42.993821 33.959001,43.837878 C 35.429654,44.761502 37.300143,45.728452 39.176641,45.138766 C 40.689956,44.705317 41.547313,43.4582 41.856813,42.166912 C 42.461243,39.856882 41.561117,37.490951 40.149846,35.530428 C 39.491173,34.616722 38.816861,33.647222 38.036528,32.835783 C 36.841969,31.932329 35.398614,31.184254 33.947688,30.603431 C 33.41359,30.493019 32.832464,30.37069 32.280087,30.449093 z M 32.715792,31.658699 C 34.473095,31.591923 35.950305,32.398157 37.092162,33.427664 C 38.124459,34.396792 39.113817,35.23287 39.754673,36.426541 C 40.831856,38.24711 41.142534,40.4065 40.594777,42.390073 C 40.066397,43.714585 38.368623,44.362109 36.803657,44.006518 C 34.821776,43.77769 33.586317,42.335503 32.277091,41.198158 C 30.771344,39.766768 29.83647,37.719532 29.76651,35.715783 C 29.780622,34.698114 29.740042,33.53736 30.464653,32.682212 C 30.876926,32.139062 31.84466,31.627886 32.715792,31.658699 z "
id="path16795" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

+396
View File
@@ -0,0 +1,396 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:export-ydpi="90.000000"
inkscape:export-xdpi="90.000000"
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
width="48px"
height="48px"
id="svg11300"
sodipodi:version="0.32"
inkscape:version="0.43+devel"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/categories"
sodipodi:docname="preferences-system.svg">
<defs
id="defs3">
<linearGradient
inkscape:collect="always"
id="linearGradient2250">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2252" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2254" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2265">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop2267" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop2269" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2257">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2259" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2261" />
</linearGradient>
<linearGradient
id="linearGradient3087">
<stop
style="stop-color:#3465a4;stop-opacity:1;"
offset="0"
id="stop3089" />
<stop
id="stop3095"
offset="0"
style="stop-color:#9fbce1;stop-opacity:1;" />
<stop
style="stop-color:#6b95ca;stop-opacity:1;"
offset="0"
id="stop2242" />
<stop
id="stop2244"
offset="0.75"
style="stop-color:#3d6aa5;stop-opacity:1;" />
<stop
style="stop-color:#386eb4;stop-opacity:1;"
offset="1"
id="stop3091" />
</linearGradient>
<linearGradient
id="linearGradient3077">
<stop
style="stop-color:#98a0a9;stop-opacity:1;"
offset="0"
id="stop3079" />
<stop
style="stop-color:#c3d0dd;stop-opacity:1;"
offset="1"
id="stop3081" />
</linearGradient>
<linearGradient
id="linearGradient3061">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3063" />
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="1"
id="stop3065" />
</linearGradient>
<linearGradient
id="linearGradient3049">
<stop
style="stop-color:#b6b6b6;stop-opacity:1;"
offset="0"
id="stop3051" />
<stop
id="stop2262"
offset="0.5"
style="stop-color:#f2f2f2;stop-opacity:1;" />
<stop
style="stop-color:#fafafa;stop-opacity:1;"
offset="0.67612958"
id="stop2264" />
<stop
id="stop2268"
offset="0.84051722"
style="stop-color:#d8d8d8;stop-opacity:1;" />
<stop
id="stop2266"
offset="0.875"
style="stop-color:#f2f2f2;stop-opacity:1;" />
<stop
style="stop-color:#dbdbdb;stop-opacity:1;"
offset="1"
id="stop3053" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3041">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop3043" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop3045" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3041"
id="radialGradient3047"
cx="24.8125"
cy="39.125"
fx="24.8125"
fy="39.125"
r="17.6875"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.374558,7.194333e-15,24.47041)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3049"
id="linearGradient3055"
x1="19.648342"
y1="42.253601"
x2="20.631224"
y2="6.7758031"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.878270,0.000000,0.000000,0.878270,2.536988,4.967681)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3061"
id="linearGradient3067"
x1="50.152931"
y1="-3.6324477"
x2="25.291086"
y2="-4.3002653"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.878270,-1.375944e-15,1.375944e-15,0.878270,5.328299,1.650243)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3077"
id="linearGradient3083"
x1="38.227654"
y1="13.602527"
x2="37.53537"
y2="6.6285896"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.878270,0.000000,0.000000,0.878270,2.847503,5.588712)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3087"
id="linearGradient3093"
x1="9.7503242"
y1="32.28376"
x2="16.915297"
y2="39.443218"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.878270,0.000000,0.000000,0.878270,2.536988,4.967681)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2257"
id="linearGradient2263"
x1="12.004697"
y1="35.688461"
x2="10.650805"
y2="33.194965"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.007254,-2.636526e-2,2.636526e-2,1.007254,1.593411,7.919100e-2)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2265"
id="linearGradient2271"
x1="14.017542"
y1="36.942543"
x2="15.415793"
y2="38.268368"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.878099,-1.732370e-2,1.732370e-2,0.878099,2.163687,4.067899)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2250"
id="linearGradient2256"
x1="31.177404"
y1="19.821514"
x2="40.859177"
y2="9.6568537"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3041"
id="radialGradient2260"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.374558,7.272829e-15,24.47041)"
cx="24.8125"
cy="39.125"
fx="24.8125"
fy="39.125"
r="17.6875" />
</defs>
<sodipodi:namedview
stroke="#204a87"
fill="#3465a4"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="0.25490196"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4"
inkscape:cx="19.425317"
inkscape:cy="26.37487"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:showpageshadow="false"
inkscape:window-width="1034"
inkscape:window-height="1010"
inkscape:window-x="296"
inkscape:window-y="83" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://jimmac.musichall.cz</dc:source>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:title>Preferences System</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>preferences</rdf:li>
<rdf:li>settings</rdf:li>
<rdf:li>control panel</rdf:li>
<rdf:li>tweaks</rdf:li>
<rdf:li>system</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
transform="matrix(0.751118,0.000000,0.000000,0.578703,17.04087,19.36341)"
d="M 42.5 39.125 A 17.6875 6.625 0 1 1 7.125,39.125 A 17.6875 6.625 0 1 1 42.5 39.125 z"
sodipodi:ry="6.625"
sodipodi:rx="17.6875"
sodipodi:cy="39.125"
sodipodi:cx="24.8125"
id="path2258"
style="opacity:0.19886367;color:#000000;fill:url(#radialGradient2260);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
sodipodi:type="arc" />
<path
sodipodi:type="arc"
style="opacity:0.3125;color:#000000;fill:url(#radialGradient3047);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path3039"
sodipodi:cx="24.8125"
sodipodi:cy="39.125"
sodipodi:rx="17.6875"
sodipodi:ry="6.625"
d="M 42.5 39.125 A 17.6875 6.625 0 1 1 7.125,39.125 A 17.6875 6.625 0 1 1 42.5 39.125 z"
transform="matrix(0.836071,0.000000,0.000000,0.685436,-7.959607,15.71781)" />
<path
style="opacity:1;color:#000000;fill:url(#linearGradient3055);fill-opacity:1;fill-rule:nonzero;stroke:#888a85;stroke-width:0.9999997;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 17.906713,21.215676 L 36.899302,40.6474 C 37.667788,41.52567 40.102812,42.204461 41.729787,40.6474 C 43.300913,39.143787 42.937408,37.024536 41.400436,35.487563 L 23.176333,15.946056 C 25.426333,9.696056 20.872444,4.446488 14.997444,5.571488 L 13.73493,6.7242174 L 17.687145,10.456865 L 17.906713,13.750381 L 14.955871,16.443984 L 11.429472,16.05584 L 7.8066086,12.652544 C 7.8066086,12.652544 6.5364873,13.907448 6.5364873,13.907448 C 5.9457238,19.548765 11.844213,24.590676 17.906713,21.215676 z "
id="path2140"
sodipodi:nodetypes="cczcccccccccsc" />
<path
sodipodi:nodetypes="cczccccccccccc"
id="path3057"
d="M 18.117385,19.9401 L 37.320267,39.967712 C 37.915174,40.647605 39.800194,41.173077 41.059681,39.967712 C 42.275934,38.803723 41.994534,37.163152 40.804721,35.973338 L 22.313189,16.352183 C 23.813189,9.852183 20.454401,6.3475455 15.454401,6.4725455 L 15.18427,6.7459223 L 18.787193,9.982189 L 18.917359,14.163983 L 15.303442,17.462466 L 11.061136,17.004257 L 7.8845536,14.012776 L 7.5319165,14.442835 C 7.2194165,20.411585 14.023635,23.1276 18.117385,19.9401 z "
style="opacity:0.42613639;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.99999917;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<rect
style="opacity:0.17045456;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3067);stroke-width:0.9999972;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="rect3059"
width="23.268276"
height="2.0554912"
x="28.185335"
y="-2.6184492"
rx="0.88388073"
ry="0.88388073"
transform="matrix(0.697938,0.716158,-0.716158,0.697938,0.000000,0.000000)" />
<path
style="opacity:1;color:#000000;fill:url(#linearGradient3083);fill-opacity:1;fill-rule:nonzero;stroke:#878f9d;stroke-width:0.9999997;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 22.498794,30.12538 C 23.332335,29.410917 35.782628,16.676871 35.782628,16.676871 L 38.856573,16.457303 L 43.687058,9.7604906 L 39.662731,6.1752987 L 33.405057,11.554705 L 33.405057,14.628651 L 20.670142,27.857593 C 20.066332,28.461403 21.730308,30.784082 22.498794,30.12538 z "
id="path2144"
sodipodi:nodetypes="ccccccccc" />
<path
sodipodi:nodetypes="ccccccccc"
id="path3085"
d="M 22.401987,29.085455 C 23.04876,28.531078 35.426388,15.855648 35.426388,15.855648 L 38.354971,15.607649 L 42.568887,9.945584 L 39.679156,7.3965946 L 34.202578,12.114067 L 34.357836,14.965022 L 21.681731,28.257345 C 21.213213,28.725863 21.805692,29.596565 22.401987,29.085455 z "
style="opacity:0.53977272;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2256);stroke-width:1.00000024;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="color:#000000;fill:url(#linearGradient3093);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.9999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
d="M 8.4653111,43.611561 C 9.7818986,45.07679 13.438996,45.739726 15.060755,42.901647 C 15.767862,41.664211 17.154698,38.198845 23.341883,32.630379 C 24.381029,31.696208 25.481792,29.559241 24.54863,28.406512 L 22.133387,25.991269 C 21.145334,24.893432 18.398973,25.40552 17.272212,26.942145 C 13.913455,31.538339 8.4261393,35.197025 7.1887023,35.638967 C 4.8207828,36.484652 5.0872917,39.975116 6.6538792,41.635454 L 8.4653111,43.611561 z "
id="path2142"
sodipodi:nodetypes="ccccccscc" />
<path
sodipodi:type="arc"
style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#a1a1a1;stroke-width:1.13860166;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path2146"
sodipodi:cx="41.875"
sodipodi:cy="37.5"
sodipodi:rx="1.375"
sodipodi:ry="1.375"
d="M 43.25 37.5 A 1.375 1.375 0 1 1 40.5,37.5 A 1.375 1.375 0 1 1 43.25 37.5 z"
transform="matrix(0.878270,0.000000,0.000000,0.878270,2.427204,5.077464)" />
<path
sodipodi:type="arc"
style="opacity:0.60227272;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path3101"
sodipodi:cx="19.003494"
sodipodi:cy="28.20101"
sodipodi:rx="1.767767"
sodipodi:ry="1.767767"
d="M 20.771261 28.20101 A 1.767767 1.767767 0 1 1 17.235727,28.20101 A 1.767767 1.767767 0 1 1 20.771261 28.20101 z"
transform="matrix(0.570876,0.000000,0.000000,0.570876,9.154848,11.25111)" />
<path
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2263);stroke-width:2.29450917;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 18.678905,29.624807 C 18.678905,29.624807 11.509014,36.92442 8.1502573,38.161857"
id="path3103"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="csccccscc"
id="path2270"
d="M 8.8060013,42.48669 C 10.247267,44.232307 13.405535,44.647919 14.397161,42.116101 C 15.078468,40.376589 17.730783,36.450314 22.594745,32.072748 C 23.411654,31.338363 24.277003,29.658419 23.543411,28.752218 L 21.644704,26.853511 C 20.867961,25.990463 18.708951,26.393033 17.823164,27.601028 C 15.182728,31.214257 9.3398194,35.940582 7.9274145,36.406654 C 5.7406198,37.128264 6.1504221,39.627953 7.3819713,40.933203 L 8.8060013,42.48669 z "
style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.99999946;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;opacity:0.19886364" />
<path
style="opacity:0.27840911;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2271);stroke-width:2.29450917;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 20.824602,31.261024 C 20.824602,31.261024 13.501839,37.878429 11.910849,42.121069"
id="path2247"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

+231
View File
@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewBox="0 0 64 64"
id="svg2"
version="1.1">
<title
id="title930">Std_AxisCross</title>
<defs
id="defs4">
<linearGradient
id="linearGradient926">
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="0"
id="stop922" />
<stop
style="stop-color:#a40000;stop-opacity:1"
offset="1"
id="stop924" />
</linearGradient>
<linearGradient
id="linearGradient918">
<stop
style="stop-color:#8ae234;stop-opacity:1"
offset="0"
id="stop914" />
<stop
style="stop-color:#4e9a06;stop-opacity:1"
offset="1"
id="stop916" />
</linearGradient>
<linearGradient
id="linearGradient910">
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="0"
id="stop906" />
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="1"
id="stop908" />
</linearGradient>
<marker
orient="auto"
refY="0"
refX="0"
id="marker4732"
style="overflow:visible">
<path
id="path4734"
style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:#00ff08;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
</marker>
<marker
orient="auto"
refY="0"
refX="0"
id="Arrow2Lstart"
style="overflow:visible">
<path
id="path4174"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(1.1,0,0,1.1,1.1,0)" />
</marker>
<marker
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible">
<path
id="path4156"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<linearGradient
id="linearGradient4067-6">
<stop
style="stop-color:#888a85;stop-opacity:1;"
offset="0"
id="stop4069-7" />
<stop
style="stop-color:#2e3436;stop-opacity:1;"
offset="1"
id="stop4071-5" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient910"
id="linearGradient912"
x1="16.275192"
y1="999.11859"
x2="20.275194"
y2="1005.3622"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-0.32823259,0.25769489)" />
<linearGradient
xlink:href="#linearGradient918"
id="linearGradient920"
x1="37.791718"
y1="1008.163"
x2="41.744087"
y2="1014.2588"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,0.67970822)" />
<linearGradient
xlink:href="#linearGradient926"
id="linearGradient928"
x1="32.554726"
y1="1037.6899"
x2="38.136963"
y2="1044.7837"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,0.67970822)" />
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Std_AxisCross</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:date>2020/12/20</dc:date>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(0,-988.36216)">
<g
id="g4036-9-5"
transform="matrix(0.42333463,-1.0406928,1.2322046,0.04560555,-18.902112,1031.4247)"
style="fill:#73d216;fill-opacity:1;stroke:#172a04;stroke-width:1.753;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<g
id="g4033-8-3"
transform="matrix(0.70857077,0.64561924,-0.7760537,0.70710678,30.848953,1.7173836)"
style="fill:#73d216;fill-opacity:1;stroke:#172a04;stroke-width:1.75119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<rect
style="fill:#73d216;fill-opacity:1;stroke:#172a04;stroke-width:1.75119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3261-1-56"
width="23"
height="6"
x="-25"
y="-38"
transform="scale(-1)" />
</g>
</g>
<path
style="fill:none;fill-opacity:1;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 17.758513,1025.996 23.516681,-15.1976"
id="path4083-0-29" />
<g
style="fill:#cc0000;fill-opacity:1;stroke:#280000;stroke-width:1.77168;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(-0.09950839,-1.2704661,0.99694669,-0.07808517,-7.0272263,1034.6728)"
id="g4033-8-5">
<rect
transform="matrix(-0.61568026,0.78799608,-0.61567913,-0.78799696,0,0)"
y="-22.253193"
x="11.761694"
height="4.9622731"
width="24.257404"
id="rect3261-1-6"
style="fill:#cc0000;fill-opacity:1;stroke:#280000;stroke-width:1.65466;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<path
style="fill:none;stroke:#ef2929;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 38.136962,1045.4634 17.397878,1027.7269"
id="path4083-0-2" />
<path
id="path872-8"
d="m 44,1049.0419 -8.562552,-14.5923 c -4.048591,1.9848 -5.937899,5.0071 -7.162254,8.3488 z"
style="fill:url(#linearGradient928);fill-opacity:1;stroke:#280000;stroke-width:2.50713;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:url(#linearGradient920);fill-opacity:1;stroke:#172a04;stroke-width:2.50713;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 52.025756,1005.4549 -16.544154,3.5417 c 0.611589,4.4672 2.886818,7.2108 5.674284,9.4235 z"
id="path872-8-1" />
<g
id="g4036-9"
transform="matrix(-0.64428531,-0.92040759,0.70710678,-1.0101525,0.936348,1060.8558)"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:1.753;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<g
id="g4033-8"
transform="matrix(0.53748674,0.48973482,-0.7760537,0.70710678,30.821878,1.6927139)"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:1.75119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<rect
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:1.75119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3261-1"
width="23"
height="6"
x="-25"
y="-38"
transform="scale(-1)" />
</g>
</g>
<path
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 16.157967,1027.8686 V 999.86865"
id="path4083-0" />
<path
style="fill:url(#linearGradient912);fill-opacity:1;stroke:#0b1521;stroke-width:2.50713;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 17.171767,991.6197 -5.5,16.0002 c 4.142481,1.7805 7.666483,1.2466 11,0 z"
id="path872" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.7 KiB

+4
View File
@@ -241,6 +241,10 @@
<file>document-package.svg</file>
<file>Std_Alignment.svg</file>
<file>Std_DuplicateSelection.svg</file>
<file>EditModeDefault.svg</file>
<file>EditModeTransform.svg</file>
<file>EditModeCutting.svg</file>
<file>EditModeColor.svg</file>
</qresource>
<!-- Demonstrating support for an embedded icon theme -->
<!-- See also http://permalink.gmane.org/gmane.comp.lib.qt.general/26374 -->
+126 -12
View File
@@ -276,6 +276,25 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditMode</name>
<message>
<source>Default</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transform</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cutting</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Color</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ExpressionLabel</name>
<message>
@@ -3210,23 +3229,54 @@ You can also use the form: John Doe &lt;[email protected]&gt;</source>
<context>
<name>Gui::Dialog::DlgSettingsLazyLoaded</name>
<message>
<source>Unloaded Workbenches</source>
<source>Workbench Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Load the selected workbenches, adding their preference windows to the preferences dialog.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<source>Autoload?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Selected</source>
<source>Load Now</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available unloaded workbenches&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation, but are not yet loaded:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<source>Available Workbenches</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Gui::Dialog::DlgSettingsLazyLoadedImp</name>
<message>
<source>Workbench</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Autoload</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>If checked</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>will be loaded automatically when FreeCAD starts up</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This is the current startup module, and must be autoloaded. See Preferences/General/Autoload to change.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Loaded</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load now</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -4385,31 +4435,31 @@ The &apos;Status&apos; column shows whether the document could be recovered.</so
<translation type="unfinished"></translation>
</message>
<message>
<source>Around y-axis:</source>
<source>Pitch (around y-axis):</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Around z-axis:</source>
<source>Roll (around x-axis):</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Around x-axis:</source>
<source>Yaw (around z-axis):</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Rotation around the x-axis</source>
<source>Yaw (around z-axis)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Rotation around the y-axis</source>
<source>Pitch (around y-axis)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Rotation around the z-axis</source>
<source>Roll (around the x-axis)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Euler angles (xy&apos;z&apos;&apos;)</source>
<source>Euler angles (zy&apos;x&apos;&apos;)</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -4573,6 +4623,15 @@ The &apos;Status&apos; column shows whether the document could be recovered.</so
<source>Partial</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Use Original Selections</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Ignore dependencies and proceed with objects
originally selected prior to opening this dialog</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Gui::DlgTreeWidget</name>
@@ -5914,6 +5973,18 @@ Do you want to specify another directory?</source>
<source>Vietnamese</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bulgarian</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Greek</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Spanish, Argentina</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Gui::TreeDockWidget</name>
@@ -6860,6 +6931,34 @@ Document: </source>
Physical path: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Could not save document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>There was an issue trying to save the file. This may be because some of the parent folders do not exist, or you do not have sufficient permissions, or for other reasons. Error details:
&quot;%1&quot;
Would you like to save the file with a different name?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Document not saved</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The document%1 could not be saved. Do you want to cancel closing it?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>%1 Document(s) not saved</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Some documents could not be saved. Do you want to cancel closing?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectionFilter</name>
@@ -8632,6 +8731,17 @@ Physical path: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StdCmdUserEditMode</name>
<message>
<source>Edit mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Defines behavior when editing an object from tree</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StdCmdUserInterface</name>
<message>
@@ -9649,6 +9759,10 @@ Do you still want to proceed?</source>
<source>Special Ops</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Axonometric</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>testClass</name>
Binary file not shown.
+39 -8
View File
@@ -3278,20 +3278,51 @@ You can also use the form: John Doe &lt;[email protected]&gt;</translation>
<translation type="unfinished">Unloaded Workbenches</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Load the selected workbenches, adding their preference windows to the preferences dialog.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Load the selected workbenches, adding their preference windows to the preferences dialog.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<source>Workbench Name</source>
<translation type="unfinished">Workbench Name</translation>
</message>
<message>
<source>Load Selected</source>
<translation type="unfinished">Load Selected</translation>
<source>Autoload?</source>
<translation type="unfinished">Autoload?</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available unloaded workbenches&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available unloaded workbenches&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<source>Load Now</source>
<translation type="unfinished">Load Now</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation, but are not yet loaded:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation, but are not yet loaded:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
</context>
<context>
<name>Gui::Dialog::DlgSettingsLazyLoadedImp</name>
<message>
<source>Workbench</source>
<translation>Werkbank</translation>
</message>
<message>
<source>Autoload</source>
<translation type="unfinished">Autoload</translation>
</message>
<message>
<source>If checked</source>
<translation type="unfinished">If checked</translation>
</message>
<message>
<source>will be loaded automatically when FreeCAD starts up</source>
<translation type="unfinished">will be loaded automatically when FreeCAD starts up</translation>
</message>
<message>
<source>This is the current startup module, and must be autoloaded. See Preferences/General/Autoload to change.</source>
<translation type="unfinished">This is the current startup module, and must be autoloaded. See Preferences/General/Autoload to change.</translation>
</message>
<message>
<source>Loaded</source>
<translation type="unfinished">Loaded</translation>
</message>
<message>
<source>Load now</source>
<translation type="unfinished">Load now</translation>
</message>
</context>
<context>
Binary file not shown.
+143 -24
View File
@@ -276,6 +276,25 @@
<translation>إسم الملف</translation>
</message>
</context>
<context>
<name>EditMode</name>
<message>
<source>Default</source>
<translation>الافتراضي</translation>
</message>
<message>
<source>Transform</source>
<translation>تحويل</translation>
</message>
<message>
<source>Cutting</source>
<translation>تقطيع</translation>
</message>
<message>
<source>Color</source>
<translation>لون</translation>
</message>
</context>
<context>
<name>ExpressionLabel</name>
<message>
@@ -3275,24 +3294,55 @@ You can also use the form: John Doe &lt;[email protected]&gt;</translation>
<context>
<name>Gui::Dialog::DlgSettingsLazyLoaded</name>
<message>
<source>Unloaded Workbenches</source>
<translation type="unfinished">Unloaded Workbenches</translation>
<source>Workbench Name</source>
<translation type="unfinished">Workbench Name</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Load the selected workbenches, adding their preference windows to the preferences dialog.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Load the selected workbenches, adding their preference windows to the preferences dialog.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<source>Autoload?</source>
<translation type="unfinished">Autoload?</translation>
</message>
<message>
<source>Load Selected</source>
<translation type="unfinished">Load Selected</translation>
<source>Load Now</source>
<translation type="unfinished">Load Now</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available unloaded workbenches&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available unloaded workbenches&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation, but are not yet loaded:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation, but are not yet loaded:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<source>Available Workbenches</source>
<translation type="unfinished">Available Workbenches</translation>
</message>
</context>
<context>
<name>Gui::Dialog::DlgSettingsLazyLoadedImp</name>
<message>
<source>Workbench</source>
<translation type="unfinished">Workbench</translation>
</message>
<message>
<source>Autoload</source>
<translation type="unfinished">Autoload</translation>
</message>
<message>
<source>If checked</source>
<translation type="unfinished">If checked</translation>
</message>
<message>
<source>will be loaded automatically when FreeCAD starts up</source>
<translation type="unfinished">will be loaded automatically when FreeCAD starts up</translation>
</message>
<message>
<source>This is the current startup module, and must be autoloaded. See Preferences/General/Autoload to change.</source>
<translation type="unfinished">This is the current startup module, and must be autoloaded. See Preferences/General/Autoload to change.</translation>
</message>
<message>
<source>Loaded</source>
<translation type="unfinished">Loaded</translation>
</message>
<message>
<source>Load now</source>
<translation type="unfinished">Load now</translation>
</message>
</context>
<context>
@@ -4461,32 +4511,32 @@ The 'Status' column shows whether the document could be recovered.</source>
<translation type="unfinished">Please select 1, 2, or 3 points before clicking this button. A point may be on a vertex, face, or edge. If on a face or edge the point used will be the point at the mouse position along face or edge. If 1 point is selected it will be used as the center of rotation. If 2 points are selected the midpoint between them will be the center of rotation and a new custom axis will be created, if needed. If 3 points are selected the first point becomes the center of rotation and lies on the vector that is normal to the plane defined by the 3 points. Some distance and angle information is provided in the report view, which can be useful when aligning objects. For your convenience when Shift + click is used the appropriate distance or angle is copied to the clipboard.</translation>
</message>
<message>
<source>Around y-axis:</source>
<translation type="unfinished">Around y-axis:</translation>
<source>Pitch (around y-axis):</source>
<translation type="unfinished">Pitch (around y-axis):</translation>
</message>
<message>
<source>Around z-axis:</source>
<translation type="unfinished">Around z-axis:</translation>
<source>Roll (around x-axis):</source>
<translation type="unfinished">Roll (around x-axis):</translation>
</message>
<message>
<source>Around x-axis:</source>
<translation type="unfinished">Around x-axis:</translation>
<source>Yaw (around z-axis):</source>
<translation type="unfinished">Yaw (around z-axis):</translation>
</message>
<message>
<source>Rotation around the x-axis</source>
<translation type="unfinished">Rotation around the x-axis</translation>
<source>Yaw (around z-axis)</source>
<translation type="unfinished">Yaw (around z-axis)</translation>
</message>
<message>
<source>Rotation around the y-axis</source>
<translation type="unfinished">Rotation around the y-axis</translation>
<source>Pitch (around y-axis)</source>
<translation type="unfinished">Pitch (around y-axis)</translation>
</message>
<message>
<source>Rotation around the z-axis</source>
<translation type="unfinished">Rotation around the z-axis</translation>
<source>Roll (around the x-axis)</source>
<translation type="unfinished">Roll (around the x-axis)</translation>
</message>
<message>
<source>Euler angles (xy'z'')</source>
<translation type="unfinished">Euler angles (xy'z'')</translation>
<source>Euler angles (zy'x'')</source>
<translation type="unfinished">Euler angles (zy'x'')</translation>
</message>
</context>
<context>
@@ -4649,6 +4699,16 @@ The 'Status' column shows whether the document could be recovered.</source>
<source>Partial</source>
<translation type="unfinished">Partial</translation>
</message>
<message>
<source>&amp;Use Original Selections</source>
<translation type="unfinished">&amp;Use Original Selections</translation>
</message>
<message>
<source>Ignore dependencies and proceed with objects
originally selected prior to opening this dialog</source>
<translation type="unfinished">Ignore dependencies and proceed with objects
originally selected prior to opening this dialog</translation>
</message>
</context>
<context>
<name>Gui::DlgTreeWidget</name>
@@ -6002,6 +6062,18 @@ Do you want to specify another directory?</translation>
<source>Vietnamese</source>
<translation type="unfinished">Vietnamese</translation>
</message>
<message>
<source>Bulgarian</source>
<translation type="unfinished">Bulgarian</translation>
</message>
<message>
<source>Greek</source>
<translation>اليونانية</translation>
</message>
<message>
<source>Spanish, Argentina</source>
<translation type="unfinished">Spanish, Argentina</translation>
</message>
</context>
<context>
<name>Gui::TreeDockWidget</name>
@@ -6966,6 +7038,38 @@ Physical path: </source>
Physical path: </translation>
</message>
<message>
<source>Could not save document</source>
<translation type="unfinished">Could not save document</translation>
</message>
<message>
<source>There was an issue trying to save the file. This may be because some of the parent folders do not exist, or you do not have sufficient permissions, or for other reasons. Error details:
"%1"
Would you like to save the file with a different name?</source>
<translation type="unfinished">There was an issue trying to save the file. This may be because some of the parent folders do not exist, or you do not have sufficient permissions, or for other reasons. Error details:
"%1"
Would you like to save the file with a different name?</translation>
</message>
<message>
<source>Document not saved</source>
<translation type="unfinished">Document not saved</translation>
</message>
<message>
<source>The document%1 could not be saved. Do you want to cancel closing it?</source>
<translation type="unfinished">The document%1 could not be saved. Do you want to cancel closing it?</translation>
</message>
<message>
<source>%1 Document(s) not saved</source>
<translation type="unfinished">%1 Document(s) not saved</translation>
</message>
<message>
<source>Some documents could not be saved. Do you want to cancel closing?</source>
<translation type="unfinished">Some documents could not be saved. Do you want to cancel closing?</translation>
</message>
</context>
<context>
<name>SelectionFilter</name>
@@ -8738,6 +8842,17 @@ Physical path: </translation>
<translation type="unfinished">Start the units calculator</translation>
</message>
</context>
<context>
<name>StdCmdUserEditMode</name>
<message>
<source>Edit mode</source>
<translation type="unfinished">Edit mode</translation>
</message>
<message>
<source>Defines behavior when editing an object from tree</source>
<translation type="unfinished">Defines behavior when editing an object from tree</translation>
</message>
</context>
<context>
<name>StdCmdUserInterface</name>
<message>
@@ -9762,6 +9877,10 @@ Do you still want to proceed?</translation>
<source>Special Ops</source>
<translation type="unfinished">Special Ops</translation>
</message>
<message>
<source>Axonometric</source>
<translation type="unfinished">Axonometric</translation>
</message>
</context>
<context>
<name>testClass</name>
Binary file not shown.

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