Merge branch 'refs/heads/master' into jriegel/develop-fem

This commit is contained in:
jriegel 2013-07-08 19:46:54 +02:00
commit 9d05dcc85c
325 changed files with 19291 additions and 6585 deletions

View File

@ -209,30 +209,64 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
#first, look for OpenCASCADE Community Edition (OCE) #first, look for OpenCASCADE Community Edition (OCE)
#if OCE is installed in a nonstandard location, add -DOCE_DIR=/path/to/dir/containing/OCEConfig.cmake #if OCE is installed in a nonstandard location, add -DOCE_DIR=/path/to/dir/containing/OCEConfig.cmake
# when configuring with cmake, i.e. cmake .. -DOCE_DIR=/usr/share/cmake # when configuring with cmake, i.e. cmake .. -DOCE_DIR=/usr/share/cmake
if( NOT DEFINED OCE_DIR ) if(NOT DEFINED OCE_DIR)
if( UNIX ) if(UNIX)
set( OCE_DIR "/usr/local/share/cmake/" ) set(OCE_DIR "/usr/local/share/cmake/")
else() elseif(WIN32)
set( OCE_DIR "c:/OCE-0.4.0/share/cmake" ) set(OCE_DIR "c:/OCE-0.4.0/share/cmake")
endif() endif()
endif() endif()
find_package ( OCE ) find_package (OCE QUIET)
if( ${OCE_FOUND} ) if(${OCE_FOUND})
message("-- OpenCASCADE Community Edition has been found.") message("-- OpenCASCADE Community Edition has been found.")
add_definitions ( -DHAVE_CONFIG_H ) add_definitions (-DHAVE_CONFIG_H)
set( OCC_LIBRARIES "TKFeat;TKFillet;TKMesh;TKernel;TKG2d;TKG3d;TKMath;TKIGES;TKSTL;TKShHealing;TKXSBase;TKBool;TKBO;TKBRep;TKTopAlgo;TKGeomAlgo;TKGeomBase;TKOffset;TKPrim;TKSTEP;TKSTEPBase;TKSTEPAttr;TKHLR" ) #lib list copied from FreeCAD's FindOpenCasCade.cmake #lib list copied from FreeCAD's FindOpenCasCade.cmake
set( OCC_OCAF_LIBRARIES "TKCAF;TKXCAF;TKLCAF;TKXDESTEP;TKXDEIGES;TKMeshVS;TKAdvTools" ) #lib list copied from FreeCAD's FindOpenCasCade.cmake set(OCC_LIBRARIES
set( OCC_INCLUDE_DIR ${OCE_INCLUDE_DIRS} ) TKFillet
set( OCC_FOUND ${OCE_FOUND} ) TKMesh
else() #look for OpenCASCADE TKernel
find_package(OpenCasCade) TKG2d
IF(NOT OCC_FOUND) TKG3d
MESSAGE("Neither OpenCASCADE Community Edition nor OpenCasCade were found: will not build CAD modules!") TKMath
ELSE() TKIGES
MESSAGE("-- OpenCASCADE include directory: ${OCC_INCLUDE_PATH}") TKSTL
MESSAGE("-- OpenCASCADE shared libraries directory: ${OCC_LIB_PATH}") TKShHealing
ENDIF() TKXSBase
endif() TKBool
TKBO
TKBRep
TKTopAlgo
TKGeomAlgo
TKGeomBase
TKOffset
TKPrim
TKSTEP
TKSTEPBase
TKSTEPAttr
TKHLR
TKFeat
)
#lib list copied from FreeCAD's FindOpenCasCade.cmake
set(OCC_OCAF_LIBRARIES
TKCAF
TKXCAF
TKLCAF
TKXDESTEP
TKXDEIGES
TKMeshVS
TKAdvTools
)
set(OCC_INCLUDE_DIR ${OCE_INCLUDE_DIRS})
set(OCC_FOUND ${OCE_FOUND})
else() #look for OpenCASCADE
find_package(OpenCasCade)
if(NOT OCC_FOUND)
message("Neither OpenCASCADE Community Edition nor OpenCasCade were found: will not build CAD modules!")
else()
message("-- OpenCASCADE include directory: ${OCC_INCLUDE_PATH}")
message("-- OpenCASCADE shared libraries directory: ${OCC_LIB_PATH}")
endif()
endif()
# -------------------------------- Salome SMESH -------------------------- # -------------------------------- Salome SMESH --------------------------
@ -362,6 +396,17 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
find_package(Spnav) find_package(Spnav)
endif(WIN32) endif(WIN32)
# -------------------------------- Shiboken/PySide ------------------------
find_package(Shiboken QUIET)
IF(SHIBOKEN_INCLUDE_DIR)
message("-- Shiboken has been found.")
ENDIF(SHIBOKEN_INCLUDE_DIR)
find_package(PySide QUIET)
IF(PYSIDE_INCLUDE_DIR)
message("-- PySide has been found.")
ENDIF(PYSIDE_INCLUDE_DIR)
# ------------------------------ Matplotlib ------------------------------ # ------------------------------ Matplotlib ------------------------------
find_package(Matplotlib) find_package(Matplotlib)
@ -441,8 +486,14 @@ IF(APPLE)
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so") SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
ENDIF(APPLE) ENDIF(APPLE)
# force build directory to be different to source directory
#if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
#MESSAGE(SEND_ERROR "The build directory (${CMAKE_BINARY_DIR}) must be different to the source directory "
# "(${CMAKE_SOURCE_DIR}). Please choose another build directory!")
#elseif()
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(data) add_subdirectory(data)
#endif()
# ================================================================================ # ================================================================================
# == Packaging =================================================================== # == Packaging ===================================================================

View File

@ -83,3 +83,7 @@ because it contains some Fortran code.
project. project.
9. Build the file vcf2c.lib with "nmake -f makefile.vc" and add it to the MEFISTO2 project as 9. Build the file vcf2c.lib with "nmake -f makefile.vc" and add it to the MEFISTO2 project as
additional library. The linker errors should now go away. additional library. The linker errors should now go away.
* FreeType
http://stackoverflow.com/questions/6207176/compiling-freetype-to-dll-as-opposed-to-static-library

View File

@ -13,6 +13,7 @@ IF (WIN32)
FIND_PATH(COIN3D_INCLUDE_DIR Inventor/So.h FIND_PATH(COIN3D_INCLUDE_DIR Inventor/So.h
/usr/include /usr/include
/usr/local/include /usr/local/include
/usr/include/coin
) )
FIND_LIBRARY(COIN3D_LIBRARY Coin FIND_LIBRARY(COIN3D_LIBRARY Coin

View File

@ -196,6 +196,8 @@ include(AddFileDependencies)
macro(fc_wrap_cpp outfiles ) macro(fc_wrap_cpp outfiles )
QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN})
# fixes bug 0000585: bug with boost 1.48
SET(moc_options ${moc_options} -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
SET(ARGN) SET(ARGN)
foreach(it ${moc_files}) foreach(it ${moc_files})
get_filename_component(it ${it} ABSOLUTE) get_filename_component(it ${it} ABSOLUTE)

View File

@ -207,6 +207,8 @@ include(AddFileDependencies)
macro(fc_wrap_cpp outfiles ) macro(fc_wrap_cpp outfiles )
QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN})
# fixes bug 0000585: bug with boost 1.48
SET(moc_options ${moc_options} -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
SET(ARGN) SET(ARGN)
foreach(it ${moc_files}) foreach(it ${moc_files})
get_filename_component(it ${it} ABSOLUTE) get_filename_component(it ${it} ABSOLUTE)

View File

@ -219,6 +219,8 @@ include(AddFileDependencies)
macro(fc_wrap_cpp outfiles ) macro(fc_wrap_cpp outfiles )
QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN})
# fixes bug 0000585: bug with boost 1.48
SET(moc_options ${moc_options} -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
SET(ARGN) SET(ARGN)
foreach(it ${moc_files}) foreach(it ${moc_files})
get_filename_component(it ${it} ABSOLUTE) get_filename_component(it ${it} ABSOLUTE)
@ -392,5 +394,19 @@ SET(EIGEN3_INCLUDE_DIR ${FREECAD_LIBPACK_DIR}/include/eigen3)
set(EIGEN3_FOUND TRUE) set(EIGEN3_FOUND TRUE)
# FreeType
if(FREECAD_USE_FREETYPE)
set(FREETYPE_LIBRARIES
optimized ${FREECAD_LIBPACK_DIR}/lib/freetype.lib
debug ${FREECAD_LIBPACK_DIR}/lib/freetyped.lib
)
set(FREETYPE_INCLUDE_DIRS
${FREECAD_LIBPACK_DIR}/include/FreeType-2.4.12
)
set(FREETYPE_VERSION_STRING
"2.4.12"
)
set(FREETYPE_FOUND
TRUE
)
endif(FREECAD_USE_FREETYPE)

View File

@ -230,6 +230,8 @@ include(AddFileDependencies)
macro(fc_wrap_cpp outfiles ) macro(fc_wrap_cpp outfiles )
QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN})
# fixes bug 0000585: bug with boost 1.48
SET(moc_options ${moc_options} -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
SET(ARGN) SET(ARGN)
foreach(it ${moc_files}) foreach(it ${moc_files})
get_filename_component(it ${it} ABSOLUTE) get_filename_component(it ${it} ABSOLUTE)
@ -321,72 +323,72 @@ set(NGLIB_DEBUG_LIBRARIES
#set(OCC_INCLUDE_DIR C:/Projects/LibPack/oce-0.10.0/include/oce) #set(OCC_INCLUDE_DIR C:/Projects/LibPack/oce-0.10.0/include/oce)
#set(OCC_LIBRARY_DIR C:/Projects/LibPack/oce-0.10.0/Win64/lib) #set(OCC_LIBRARY_DIR C:/Projects/LibPack/oce-0.10.0/Win64/lib)
#set(OCC_LIBRARIES #set(OCC_LIBRARIES
# ${OCC_LIBRARY_DIR}/TKFillet.lib # ${OCC_LIBRARY_DIR}/TKFillet.lib
# ${OCC_LIBRARY_DIR}/TKMesh.lib # ${OCC_LIBRARY_DIR}/TKMesh.lib
# ${OCC_LIBRARY_DIR}/TKernel.lib # ${OCC_LIBRARY_DIR}/TKernel.lib
# ${OCC_LIBRARY_DIR}/TKG2d.lib # ${OCC_LIBRARY_DIR}/TKG2d.lib
# ${OCC_LIBRARY_DIR}/TKG3d.lib # ${OCC_LIBRARY_DIR}/TKG3d.lib
# ${OCC_LIBRARY_DIR}/TKMath.lib # ${OCC_LIBRARY_DIR}/TKMath.lib
# ${OCC_LIBRARY_DIR}/TKIGES.lib # ${OCC_LIBRARY_DIR}/TKIGES.lib
# ${OCC_LIBRARY_DIR}/TKSTL.lib # ${OCC_LIBRARY_DIR}/TKSTL.lib
# ${OCC_LIBRARY_DIR}/TKShHealing.lib # ${OCC_LIBRARY_DIR}/TKShHealing.lib
# ${OCC_LIBRARY_DIR}/TKXSBase.lib # ${OCC_LIBRARY_DIR}/TKXSBase.lib
# ${OCC_LIBRARY_DIR}/TKBool.lib # ${OCC_LIBRARY_DIR}/TKBool.lib
# ${OCC_LIBRARY_DIR}/TKBO.lib # ${OCC_LIBRARY_DIR}/TKBO.lib
# ${OCC_LIBRARY_DIR}/TKBRep.lib # ${OCC_LIBRARY_DIR}/TKBRep.lib
# ${OCC_LIBRARY_DIR}/TKTopAlgo.lib # ${OCC_LIBRARY_DIR}/TKTopAlgo.lib
# ${OCC_LIBRARY_DIR}/TKGeomAlgo.lib # ${OCC_LIBRARY_DIR}/TKGeomAlgo.lib
# ${OCC_LIBRARY_DIR}/TKGeomBase.lib # ${OCC_LIBRARY_DIR}/TKGeomBase.lib
# ${OCC_LIBRARY_DIR}/TKOffset.lib # ${OCC_LIBRARY_DIR}/TKOffset.lib
# ${OCC_LIBRARY_DIR}/TKPrim.lib # ${OCC_LIBRARY_DIR}/TKPrim.lib
# ${OCC_LIBRARY_DIR}/TKSTEP.lib # ${OCC_LIBRARY_DIR}/TKSTEP.lib
# ${OCC_LIBRARY_DIR}/TKSTEPBase.lib # ${OCC_LIBRARY_DIR}/TKSTEPBase.lib
# ${OCC_LIBRARY_DIR}/TKSTEPAttr.lib # ${OCC_LIBRARY_DIR}/TKSTEPAttr.lib
# ${OCC_LIBRARY_DIR}/TKHLR.lib # ${OCC_LIBRARY_DIR}/TKHLR.lib
# ${OCC_LIBRARY_DIR}/TKFeat.lib # ${OCC_LIBRARY_DIR}/TKFeat.lib
#) #)
#set(OCC_OCAF_LIBRARIES #set(OCC_OCAF_LIBRARIES
# ${OCC_LIBRARY_DIR}/TKCAF.lib # ${OCC_LIBRARY_DIR}/TKCAF.lib
# ${OCC_LIBRARY_DIR}/TKXCAF.lib # ${OCC_LIBRARY_DIR}/TKXCAF.lib
# ${OCC_LIBRARY_DIR}/TKLCAF.lib # ${OCC_LIBRARY_DIR}/TKLCAF.lib
# ${OCC_LIBRARY_DIR}/TKXDESTEP.lib # ${OCC_LIBRARY_DIR}/TKXDESTEP.lib
# ${OCC_LIBRARY_DIR}/TKXDEIGES.lib # ${OCC_LIBRARY_DIR}/TKXDEIGES.lib
#) #)
set(OCC_INCLUDE_DIR ${FREECAD_LIBPACK_DIR}/include/OpenCascade-6.3.0) set(OCC_INCLUDE_DIR ${FREECAD_LIBPACK_DIR}/include/OpenCascade-6.3.0)
set(OCC_LIBRARY_DIR ${FREECAD_LIBPACK_DIR}/lib) set(OCC_LIBRARY_DIR ${FREECAD_LIBPACK_DIR}/lib)
set(OCC_LIBRARIES set(OCC_LIBRARIES
TKFillet TKFillet
TKMesh TKMesh
TKernel TKernel
TKG2d TKG2d
TKG3d TKG3d
TKMath TKMath
TKIGES TKIGES
TKSTL TKSTL
TKShHealing TKShHealing
TKXSBase TKXSBase
TKBool TKBool
TKBO TKBO
TKBRep TKBRep
TKTopAlgo TKTopAlgo
TKGeomAlgo TKGeomAlgo
TKGeomBase TKGeomBase
TKOffset TKOffset
TKPrim TKPrim
TKSTEP TKSTEP
TKSTEPBase TKSTEPBase
TKSTEPAttr TKSTEPAttr
TKHLR TKHLR
TKFeat TKFeat
) )
set(OCC_OCAF_LIBRARIES set(OCC_OCAF_LIBRARIES
TKCAF TKCAF
TKXCAF TKXCAF
TKLCAF TKLCAF
TKXDESTEP TKXDESTEP
TKXDEIGES TKXDEIGES
TKMeshVS TKMeshVS
TKAdvTools TKAdvTools
) )
set(OCC_FOUND TRUE) set(OCC_FOUND TRUE)
@ -400,5 +402,19 @@ set(ODE_INCLUDE_DIRS ${FREECAD_LIBPACK_DIR}/include/ode-0.11.1)
set(ODE_LIBRARIES ${FREECAD_LIBPACK_DIR}/lib/ode_double.lib) set(ODE_LIBRARIES ${FREECAD_LIBPACK_DIR}/lib/ode_double.lib)
set(ODE_FOUND TRUE) set(ODE_FOUND TRUE)
# FreeType
if(FREECAD_USE_FREETYPE)
set(FREETYPE_LIBRARIES
optimized ${FREECAD_LIBPACK_DIR}/lib/freetype.lib
debug ${FREECAD_LIBPACK_DIR}/lib/freetyped.lib
)
set(FREETYPE_INCLUDE_DIRS
${FREECAD_LIBPACK_DIR}/include/FreeType-2.4.12
)
set(FREETYPE_VERSION_STRING
"2.4.12"
)
set(FREETYPE_FOUND
TRUE
)
endif(FREECAD_USE_FREETYPE)

View File

@ -12,7 +12,10 @@ ADD_CUSTOM_TARGET(Example_data ALL
SOURCES ${Examples_Files} SOURCES ${Examples_Files}
) )
fc_copy_sources(Examples "${CMAKE_BINARY_DIR}/data/examples" ${Examples_Files}) # 0001097: CMake stops with error "Circular ... <- ... dependency dropped."
if(NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
fc_copy_sources(Example_data "${CMAKE_BINARY_DIR}/data/examples" ${Examples_Files})
endif()
INSTALL( INSTALL(
FILES FILES

View File

@ -1,3 +1,18 @@
freecad (0.13-1precise2) precise; urgency=low
* Fix hard dependency on libgl1-mesa-glx preventing installation on
Ubuntu 12.04.2 with LTSEnablementStack. Removal of shlibs.local file
and libgl1-mesa-dev deleted from BuildDeps.
* Removed version number from libsoqt4-dev BD.
-- Normand Chamberland <gemnoc@gmail.com> Sun, 05 May 2013 18:31:47 -0400
freecad (0.13-1precise1) precise; urgency=low
* New release for Ubuntu 12.04 (precise)
-- Normand Chamberland <gemnoc@gmail.com> Sun, 06 May 2012 14:38:12 -0400
freecad (0.11.3729.dfsg-2) unstable; urgency=low freecad (0.11.3729.dfsg-2) unstable; urgency=low
* Add gfortran and libopencascade-visualization-dev to BD * Add gfortran and libopencascade-visualization-dev to BD
@ -29,6 +44,25 @@ freecad (0.11.3729.dfsg-1) unstable; urgency=low
-- "Adam C. Powell, IV" <hazelsct@debian.org> Tue, 12 Apr 2011 23:40:30 -0400 -- "Adam C. Powell, IV" <hazelsct@debian.org> Tue, 12 Apr 2011 23:40:30 -0400
freecad (0.10.3247.dfsg-2ubuntu3) natty; urgency=low
* Fix build failure with ld --as-needed.
-- Matthias Klose <doko@ubuntu.com> Wed, 15 Dec 2010 01:12:39 +0100
freecad (0.10.3247.dfsg-2ubuntu2) natty; urgency=low
* Rebuild with python 2.7 as the python default.
-- Matthias Klose <doko@ubuntu.com> Thu, 09 Dec 2010 16:46:45 +0000
freecad (0.10.3247.dfsg-2ubuntu1) natty; urgency=low
* Merge from debian unstable. Remaining changes:
- build on libqtwebkit-dev for qtwebkit transition
-- Bhavani Shankar <bhavi@ubuntu.com> Wed, 20 Oct 2010 08:40:53 +0530
freecad (0.10.3247.dfsg-2) unstable; urgency=low freecad (0.10.3247.dfsg-2) unstable; urgency=low
* control: * control:
@ -43,6 +77,20 @@ freecad (0.10.3247.dfsg-2) unstable; urgency=low
-- Teemu Ikonen <tpikonen@gmail.com> Wed, 18 Aug 2010 19:34:36 +0200 -- Teemu Ikonen <tpikonen@gmail.com> Wed, 18 Aug 2010 19:34:36 +0200
freecad (0.10.3247.dfsg-1ubuntu2) maverick; urgency=low
* Rebuild on libqtwebkit-dev for qtwebkit transition
-- Jonathan Riddell <jriddell@ubuntu.com> Wed, 21 Jul 2010 10:06:31 +0100
freecad (0.10.3247.dfsg-1ubuntu1) maverick; urgency=low
* Merge from Debian unstable, remaining changes:
- debian/control: Build-Depends on libqt4-webkit-dev due to
QtWebKit is no longer part of libqt4-dev (LP: #604078)
-- Artur Rona <ari-tczew@tlen.pl> Sat, 10 Jul 2010 21:06:47 +0200
freecad (0.10.3247.dfsg-1) unstable; urgency=low freecad (0.10.3247.dfsg-1) unstable; urgency=low
* New upstream version (closes: #582627) * New upstream version (closes: #582627)
@ -57,6 +105,12 @@ freecad (0.10.3247.dfsg-1) unstable; urgency=low
-- Teemu Ikonen <tpikonen@gmail.com> Mon, 05 Jul 2010 15:07:49 +0200 -- Teemu Ikonen <tpikonen@gmail.com> Mon, 05 Jul 2010 15:07:49 +0200
freecad (0.9.2646.5.dfsg-1ubuntu1) maverick; urgency=low
* Add build-dep on libqt4-webkit-dev to fix FTBFS with Qt 4.7
-- Scott Kitterman <scott@kitterman.com> Sat, 19 Jun 2010 00:37:12 -0400
freecad (0.9.2646.5.dfsg-1) unstable; urgency=low freecad (0.9.2646.5.dfsg-1) unstable; urgency=low
* Add 'dfsg' extension to upstream version, upstream sources are unchanged. * Add 'dfsg' extension to upstream version, upstream sources are unchanged.

View File

@ -5,25 +5,26 @@ Maintainer: Debian Science Maintainers <debian-science-maintainers@lists.alioth.
Uploaders: Teemu Ikonen <tpikonen@gmail.com>, "Adam C. Powell, IV" <hazelsct@debian.org>, Anton Gladky <gladky.anton@gmail.com> Uploaders: Teemu Ikonen <tpikonen@gmail.com>, "Adam C. Powell, IV" <hazelsct@debian.org>, Anton Gladky <gladky.anton@gmail.com>
Vcs-Browser: http://git.debian.org/?p=debian-science/packages/freecad.git Vcs-Browser: http://git.debian.org/?p=debian-science/packages/freecad.git
Vcs-Git: git://git.debian.org/git/debian-science/packages/freecad.git Vcs-Git: git://git.debian.org/git/debian-science/packages/freecad.git
Homepage: http://juergen-riegel.net/FreeCAD/Docu/index.php?title=Main_Page Homepage: https://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Main_Page
Build-Depends: debhelper (>= 7.0.50~), autotools-dev, libtool, automake, Build-Depends: debhelper (>= 7.0.50~), cmake,
autoconf, libboost-dev, libboost-date-time-dev, libboost-filesystem-dev, libboost-dev, libboost-date-time-dev, libboost-filesystem-dev,
libboost-graph-dev, libboost-iostreams-dev, libboost-program-options-dev, libboost-graph-dev, libboost-iostreams-dev, libboost-program-options-dev,
libboost-regex-dev, libboost-serialization-dev, libboost-signals-dev, libboost-regex-dev, libboost-serialization-dev, libboost-signals-dev,
libboost-python-dev, python-dev, python-support, libboost-thread-dev, libboost-python-dev, python-dev, python-support,
libqt4-dev, libxt-dev, libxext-dev, libxmu-dev, libxi-dev, libx11-dev, libqt4-dev, libxt-dev, libxext-dev, libxmu-dev, libxi-dev, libx11-dev,
libcoin60-dev, libsoqt4-dev (>= 1.4.2~svn20090224), libeigen3-dev, libgl1-mesa-dev, libcoin60-dev, libsoqt4-dev, libeigen3-dev,
zlib1g-dev, libxerces-c2-dev, libopencascade-foundation-dev, libopencascade-modeling-dev, zlib1g-dev, libxerces-c2-dev, libopencascade-foundation-dev,
libopencascade-modeling-dev, libopencascade-ocaf-dev,
libopencascade-visualization-dev, python-cxx-dev, libswscale-dev, libopencascade-visualization-dev, python-cxx-dev, libswscale-dev,
libzipios++-dev, swig, gfortran, libqtwebkit-dev libzipios++-dev, swig, gfortran, f2c, libqtwebkit-dev, libspnav-dev, libfreetype6-dev
Standards-Version: 3.9.2 Standards-Version: 3.9.1
Package: freecad Package: freecad
Architecture: any Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}
Recommends: python-pivy python-matplotlib Recommends: python-pivy, python
Suggests: freecad-doc Suggests: freecad-doc
Description: Extensible Open Source CAx program (alpha) Description: Extensible Open Source CAx program (beta)
FreeCAD is an Open Source CAx RAD based on OpenCasCade, Qt and Python. FreeCAD is an Open Source CAx RAD based on OpenCasCade, Qt and Python.
It features some key concepts like macro recording, workbenches, ability It features some key concepts like macro recording, workbenches, ability
to run as a server and dynamically loadable application extensions and to run as a server and dynamically loadable application extensions and

File diff suppressed because it is too large Load Diff

8
package/debian/dirs Normal file
View File

@ -0,0 +1,8 @@
usr/share/icons/hicolor/16x16/apps
usr/share/icons/hicolor/32x32/apps
usr/share/icons/hicolor/48x48/apps
usr/share/icons/hicolor/64x64/apps
usr/share/icons/hicolor/scalable/apps
usr/share/icons/hicolor/64x64/mimetypes
usr/share/pixmaps

View File

@ -1,9 +0,0 @@
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Type=X-Thumbnailer
Name=FreeCAD Thumbnailer
MimeType=application/x-extension-fcstd;
X-Thumbnailer-Exec=/usr/bin/freecad-thumbnailer %u %o %s
GenericName=FreeCADThumbnailer

View File

@ -0,0 +1 @@
debian/tmp/usr/doc/*

View File

@ -10,7 +10,7 @@ Exec=/usr/bin/freecad %F
Path=/usr/lib/freecad Path=/usr/lib/freecad
Terminal=false Terminal=false
Type=Application Type=Application
Icon=/usr/share/freecad/freecad.xpm Icon=freecad
Categories=Graphics;Science;Engineering Categories=Graphics;Science;Engineering
StartupNotify=true StartupNotify=true
GenericName[de_DE]=Feature-basierter parametrischer Modellierer GenericName[de_DE]=Feature-basierter parametrischer Modellierer

View File

@ -0,0 +1 @@
debian/freecad.1

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'> <mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="application/x-extension-fcstd"> <mime-type type="application/x-extension-fcstd">
<sub-class-of type="application/zip"/> <!-- <sub-class-of type="application/zip"/> -->
<comment>FreeCAD document files</comment> <comment>FreeCAD document files</comment>
<glob pattern="*.fcstd"/> <glob pattern="*.fcstd"/>
</mime-type> </mime-type>

View File

@ -1,4 +0,0 @@
[Thumbnailer Entry]
TryExec=freecad-thumbnailer
Exec=freecad-thumbnailer -s %s %u %o
MimeType=application/x-extension-fcstd;

View File

@ -2,5 +2,5 @@
section="Applications/Science/Engineering"\ section="Applications/Science/Engineering"\
title="FreeCAD"\ title="FreeCAD"\
command="/usr/bin/freecad"\ command="/usr/bin/freecad"\
icon="/usr/share/freecad/freecad.xpm" icon="/usr/share/pixmaps/freecad.xpm"

View File

@ -1,11 +1,16 @@
#!/usr/bin/python #!/usr/bin/python
import sys, zipfile, md5 import sys, zipfile
import getopt import getopt
import gnomevfs from urlparse import urlparse
from urlparse import unquote
opt,par = getopt.getopt(sys.argv[1:],'-s:') opt,par = getopt.getopt(sys.argv[1:],'-s:')
inpfile = gnomevfs.get_local_path_from_uri(par[0]) uri = urlparse(par[0])
if uri.scheme != "file":
sys.exit(1)
inpfile = unquote(uri.path)
outfile = par[1] outfile = par[1]
try: try:
@ -19,8 +24,9 @@ try:
if image in files: if image in files:
image=zfile.read(image) image=zfile.read(image)
else: else:
freecad=open("/usr/share/freecad/freecad-doc.png") #freecad=open("/usr/share/freecad/freecad-doc.png")
image=freecad.read() #image=freecad.read()
sys.exit(1)
thumb=open(outfile,"wb") thumb=open(outfile,"wb")
thumb.write(image) thumb.write(image)

View File

@ -0,0 +1,4 @@
[Thumbnailer Entry]
TryExec=/usr/bin/freecad-thumbnailer
Exec=/usr/bin/freecad-thumbnailer -s %s %u %o
MimeType=application/x-extension-fcstd;

View File

@ -1,78 +0,0 @@
Index: debian/rules
===================================================================
--- debian/rules (revision 1523)
+++ debian/rules (working copy)
@@ -11,6 +11,10 @@
MODULES = Part Mesh Points Raytracing Image Drawing Test
+# Preliminary only as long as no official debian package for
+# OpenCascade is available
+DESTOCCDIR=$(shell pwd)/debian/freecad/usr/lib/freecad/lib
+
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
@@ -85,6 +89,33 @@
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/lib/FreeCAD.so usr/lib/freecad/lib
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/lib/lib*.so.* usr/lib/freecad/lib
+# Preliminary only as long as no official debian package for
+# OpenCascade is available
+ install -m777 /usr/lib/libTKernel-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKMath-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKG2d-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKG3d-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKGeomBase-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKBRep-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKGeomAlgo-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKTopAlgo-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKPrim-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKBO-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKBool-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKShHealing-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKXSBase-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKSTEPBase-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKSTEPAttr-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKSTEP209-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKSTEP-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKFillet-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKOffset-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKIGES-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKMesh-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKHLR-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libTKSTL-6.2.so $(DESTOCCDIR)
+ install -m777 /usr/lib/libSoQt4.so.20 $(DESTOCCDIR)
+
# install the modules
$(foreach MODULE,$(MODULES), \
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/$(MODULE)/$(MODULE)*.so usr/lib/freecad/Mod/$(MODULE); \
Index: debian/shlibs.local
===================================================================
--- debian/shlibs.local (revision 0)
+++ debian/shlibs.local (revision 0)
@@ -0,0 +1,24 @@
+libTKernel 6.2
+libTKMath 6.2
+libTKG2d 6.2
+libTKG3d 6.2
+libTKGeomBase 6.2
+libTKBRep 6.2
+libTKGeomAlgo 6.2
+libTKTopAlgo 6.2
+libTKPrim 6.2
+libTKBO 6.2
+libTKBool 6.2
+libTKShHealing 6.2
+libTKXSBase 6.2
+libTKSTEPAttr 6.2
+libTKSTEPBase 6.2
+libTKSTEP209 6.2
+libTKSTEP 6.2
+libTKFillet 6.2
+libTKOffset 6.2
+libTKIGES 6.2
+libTKMesh 6.2
+libTKHLR 6.2
+libTKSTL 6.2
+libSoQt4 20

View File

@ -1,33 +0,0 @@
Index: control
===================================================================
--- control (revision 2213)
+++ control (working copy)
@@ -4,21 +4,21 @@
Maintainer: Werner Mayer <wmayer@users.sourceforge.net>
Homepage: http://sourceforge.net/projects/free-cad
Build-Depends: debhelper (>= 5), autotools-dev, libc6-dev (>= 2.1.3),
- libstdc++6, libboost-dev, libboost-date-time-dev, libboost-filesystem-dev,
- libboost-graph-dev, libboost-iostreams-dev, libboost-program-options-dev,
- libboost-regex-dev, libboost-serialization-dev, libboost-signals-dev,
- zlib1g-dev, libxerces27-dev | libxerces-c2-dev,
+ libstdc++6, libboost1.37-dev, libboost-date-time1.37-dev, libboost-filesystem1.37-dev,
+ libboost-graph1.37-dev, libboost-iostreams1.37-dev, libboost-program-options1.37-dev,
+ libboost-regex1.37-dev, libboost-serialization1.37-dev, libboost-signals1.37-dev,
+ zlib1g-dev, libxerces-c28 | libxerces-c2-dev,
libxt-dev, libxmu-dev, libxi-dev, libx11-dev, libxext-dev,
- libqt4-dev, libsoqt4-dev, libcoin40-dev, libgl1-mesa-dev,
+ libqt4-dev, libsoqt4-dev, libcoin60-dev, libgl1-mesa-dev,
python2.5-dev, python, python-central (>= 0.5.6),
- libgts-dev, libcv-dev, libopencascade-dev
+ libgts-dev, libcv-dev, libopencascade-foundation-dev, libopencascade-modeling-dev
Standards-Version: 3.7.3
XS-Python-Version: current
Package: freecad
Architecture: any
Section: science
-Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python, python-pivy
XB-Python-Version: ${python:Versions}
Conflicts: freecad (<= 0.6.472-1)
Suggests: gnochm | kchmviewer | kchmviewer-nokde | xchm, python-opencv

View File

@ -1,25 +0,0 @@
Index: debian/control
===================================================================
--- debian/control (Revision 1881)
+++ debian/control (Arbeitskopie)
@@ -4,15 +4,15 @@
Maintainer: Werner Mayer <wmayer@users.sourceforge.net>
Homepage: http://sourceforge.net/projects/free-cad
Build-Depends: debhelper (>= 5), autotools-dev, libc6-dev (>= 2.1.3),
- libstdc++6, libboost-dev, libboost-date-time-dev, libboost-filesystem-dev,
- libboost-graph-dev, libboost-iostreams-dev, libboost-program-options-dev,
- libboost-regex-dev, libboost-serialization-dev, libboost-signals-dev,
- zlib1g-dev, libxerces27-dev | libxerces-c2-dev,
+ libstdc++6, libboost1.35-dev, libboost-date-time1.35-dev, libboost-filesystem1.35-dev,
+ libboost-graph1.35-dev, libboost-iostreams1.35-dev, libboost-program-options1.35-dev,
+ libboost-regex1.35-dev, libboost-serialization1.35-dev, libboost-signals1.35-dev,
+ libboost-system1.35-dev, zlib1g-dev, libxerces27-dev | libxerces-c2-dev,
libxt-dev, libxmu-dev, libxi-dev, libx11-dev, libxext-dev,
libqt4-dev, libsoqt4-dev, libcoin40-dev, libgl1-mesa-dev,
python2.5-dev, python, python-central (>= 0.5.6),
libgts-dev, libcv-dev, libopencascade-dev
-Standards-Version: 3.7.3
+Standards-Version: 3.8.0
XS-Python-Version: current
Package: freecad

View File

@ -1,25 +0,0 @@
Index: debian/control
===================================================================
--- debian/control (Revision 1879)
+++ debian/control (Arbeitskopie)
@@ -4,15 +4,15 @@
Maintainer: Werner Mayer <wmayer@users.sourceforge.net>
Homepage: http://sourceforge.net/projects/free-cad
Build-Depends: debhelper (>= 5), autotools-dev, libc6-dev (>= 2.1.3),
- libstdc++6, libboost-dev, libboost-date-time-dev, libboost-filesystem-dev,
- libboost-graph-dev, libboost-iostreams-dev, libboost-program-options-dev,
- libboost-regex-dev, libboost-serialization-dev, libboost-signals-dev,
- zlib1g-dev, libxerces27-dev | libxerces-c2-dev,
+ libstdc++6, libboost1.35-dev, libboost-date-time1.35-dev, libboost-filesystem1.35-dev,
+ libboost-graph1.35-dev, libboost-iostreams1.35-dev, libboost-program-options1.35-dev,
+ libboost-regex1.35-dev, libboost-serialization1.35-dev, libboost-signals1.35-dev,
+ libboost-system1.35-dev, zlib1g-dev, libxerces27-dev | libxerces-c2-dev,
libxt-dev, libxmu-dev, libxi-dev, libx11-dev, libxext-dev,
libqt4-dev, libsoqt4-dev, libcoin40-dev, libgl1-mesa-dev,
python2.5-dev, python, python-central (>= 0.5.6),
libgts-dev, libcv-dev, libopencascade-dev
-Standards-Version: 3.7.3
+Standards-Version: 3.8.0
XS-Python-Version: current
Package: freecad

View File

@ -4,7 +4,7 @@
# Uncomment this to turn on verbose mode. # Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1 #export DH_VERBOSE=1
MODULES = Part Mesh MeshPart PartDesign Sketcher Points Raytracing Image Drawing ReverseEngineering Complete Fem Robot Import Inspection Arch # For testing: fakeroot debian/rules binary
# These are used for cross-compiling and for saving the configure script # These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already) # from having to guess our platform (since we know it already)
@ -19,58 +19,32 @@ else
CFLAGS += -O2 CFLAGS += -O2
endif endif
patch-stamp: configure:
touch $@
configure: autogen.sh patch-stamp
dh_testdir dh_testdir
for autotools_mod_file in `find . -name Makefile.in` aclocal.m4 \ cmake . \
configure m4/libtool.m4 m4/ltmain.sh m4/ltoptions.m4 \ -DFREECAD_BUILD_DEBIAN=ON \
m4/ltversion.m4 m4/lt~obsolete.m4; do \ -DCMAKE_INSTALL_PREFIX=/usr/lib/freecad \
cp -a $$autotools_mod_file $$autotools_mod_file.setaside; \ -DCMAKE_INSTALL_MANDIR=/usr/share/man \
done -DCMAKE_INSTALL_INFODIR=/usr/share/info \
chmod u+x autogen.sh -DCMAKE_INSTALL_DATADIR=/usr/share/freecad \
./autogen.sh -DCMAKE_INSTALL_INCLUDEDIR=/usr/include/freecad \
-DCMAKE_INSTALL_DOCDIR=/usr/share/doc/freecad
config.status: configure
dh_testdir
./configure --with-occ-include=/usr/include/opencascade \
--with-occ-lib=/usr/lib \
--host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) \
--prefix=/usr/lib/freecad --mandir=/usr/share/man \
--infodir=/usr/share/info --datadir=/usr/share/freecad \
--includedir=/usr/include/freecad --docdir=/usr/share/doc/freecad \
CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs"
touch src/Build/Version.h
build: build-stamp build: build-stamp
build-stamp: config.status build-stamp: configure
dh_testdir dh_testdir
$(MAKE) $(MAKE)
touch $@ touch $@
clean: clean:
mv src/Build/Version.h src/Build/Version.h.old
dh clean dh clean
mv src/Build/Version.h.old src/Build/Version.h
rm -f build-stamp rm -f build-stamp
find -name '*.pyc' | xargs rm -f find -name '*.pyc' | xargs rm -f
find -name 'moc_*.cpp' | xargs rm -f find -name 'moc_*.cpp' | xargs rm -f
find -name '*.lo' | xargs rm -f find -name 'ui_*.h' | xargs rm -f
find -name '*.deps' | xargs rm -rf find -name 'CMakeFiles' | xargs rm -rf
find -name '*.libs' | xargs rm -rf rm -f stamp-h1
rm -f stamp-h1 config.log libtool 71
if [ -e Makefile.in.setaside ]; then \
for autotools_mod_file in `find . -name Makefile.in` aclocal.m4 \
configure m4/libtool.m4 m4/ltmain.sh m4/ltoptions.m4 \
m4/ltversion.m4 m4/lt~obsolete.m4; do \
mv -f $$autotools_mod_file.setaside $$autotools_mod_file; \
done; fi
dh clean
rm -f patch-stamp
#quilt pop -a
#rm -rf .pc/
install: build install-stamp install: build install-stamp
install-stamp: install-stamp:
@ -78,44 +52,34 @@ install-stamp:
dh_testroot dh_testroot
dh_prep dh_prep
dh_installdirs dh_installdirs
$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp/freecad $(MAKE) install/fast DESTDIR=$(CURDIR)/debian/tmp/freecad
# Remove testing modules we don't want to have in the deb
rm -rf debian/tmp/freecad/usr/lib/freecad/Mod/_TEMPLATE_
rm -rf debian/tmp/freecad/usr/lib/freecad/Mod/TemplatePyMod
# install the core system # install the core system
dh_install -pfreecad debian/tmp/freecad/usr/share/freecad/* usr/share/freecad/ dh_install -pfreecad debian/tmp/freecad/usr/share/freecad/* usr/share/freecad/
#dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/share usr/lib/freecad # Desktop icons
dh_install -pfreecad debian/tmp/freecad/usr/share/freecad/freecad.xpm usr/share/pixmaps
install -m 644 debian/tmp/freecad/usr/share/freecad/freecad-icon-16.png debian/freecad/usr/share/icons/hicolor/16x16/apps/freecad.png
install -m 644 debian/tmp/freecad/usr/share/freecad/freecad-icon-32.png debian/freecad/usr/share/icons/hicolor/32x32/apps/freecad.png
install -m 644 debian/tmp/freecad/usr/share/freecad/freecad-icon-32.png debian/freecad/usr/share/icons/hicolor/48x48/apps/freecad.png
install -m 644 debian/tmp/freecad/usr/share/freecad/freecad-icon-64.png debian/freecad/usr/share/icons/hicolor/64x64/apps/freecad.png
install -m 644 debian/tmp/freecad/usr/share/freecad/freecad.svg debian/freecad/usr/share/icons/hicolor/scalable/apps/freecad.svg
install -m 644 debian/tmp/freecad/usr/share/freecad/freecad-doc.png debian/freecad/usr/share/icons/hicolor/64x64/mimetypes/application-x-extension-fcstd.png
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/bin usr/lib/freecad dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/bin usr/lib/freecad
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/lib/FreeCAD.so usr/lib/freecad/lib dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/lib usr/lib/freecad
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/lib/lib*.so.* usr/lib/freecad/lib dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod usr/lib/freecad
dh_install debian/freecad.desktop usr/share/applications dh_install debian/freecad.desktop usr/share/applications
dh_installman debian/freecad.1 dh_installman debian/freecad.1 debian/mime/freecad-thumbnailer.1
dh_installchangelogs ChangeLog.txt dh_installchangelogs ChangeLog.txt
# install the modules # install the headers
$(foreach MODULE,$(MODULES), \ #dh_install -pfreecad-dev debian/tmp/freecad/usr/include/* usr/include
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/$(MODULE)/$(MODULE)*.so usr/lib/freecad/Mod/$(MODULE); \
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/$(MODULE)/lib*.so.* usr/lib/freecad/Mod/$(MODULE); \
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/$(MODULE)/*.py usr/lib/freecad/Mod/$(MODULE);)
# special treating of PartDesign module
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/PartDesign/Scripts/*.py usr/lib/freecad/Mod/PartDesign/Scripts;)
# special treating of Draft module
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/Draft/*.py usr/lib/freecad/Mod/Draft
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/Draft/draftlibs/*.py usr/lib/freecad/Mod/Draft/draftlibs
# special treating of Test module
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/Test/lib*.so.* usr/lib/freecad/Mod/Test
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/Test/*.py usr/lib/freecad/Mod/Test
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/Test/QtUnitGui.so usr/lib/freecad/Mod/Test
dh_install -pfreecad-dev debian/tmp/freecad/usr/include/* usr/include
dh_install -pfreecad-dev debian/tmp/freecad/usr/lib/freecad/lib/lib*.so usr/lib/freecad/lib
$(foreach MODULE,$(MODULES), \
dh_install -pfreecad-dev debian/tmp/freecad/usr/lib/freecad/Mod/$(MODULE)/lib*.la usr/lib/freecad/Mod/$(MODULE); \
dh_install -pfreecad-dev debian/tmp/freecad/usr/lib/freecad/Mod/$(MODULE)/lib*.so usr/lib/freecad/Mod/$(MODULE);)
# special treating of Arch module
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod/Arch/*.py usr/lib/freecad/Mod/Arch
# install the help system # install the help system
dh_install -pfreecad-doc debian/tmp/freecad/usr/share/doc/* usr/share/doc/ dh_install -pfreecad-doc debian/tmp/freecad/usr/share/doc/* usr/share/doc/
# install MIME stuff
dh_install debian/mime/freecad-thumbnailer usr/bin
dh_install debian/mime/freecad.thumbnailer usr/share/thumbnailers
dh_install debian/mime/freecad.schemas etc/gconf/schemas
dh_gconf -pfreecad
dh_installmime
touch install-stamp touch install-stamp
override_dh_compress: override_dh_compress:

View File

@ -0,0 +1,47 @@
#!/bin/bash
# The script creates a tar.xz tarball from git-repository of freecad-project
# ./get_orig_src.sh commitID - creates a tarball of specified commit
# ./get_orig_src.sh - creates a tarball of the latest version
# Packages, that needs to be installed to use the script:
# atool, git-core
set -e
git clone git://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad git_temp_packaging
cd git_temp_packaging
if [ $1 ]
then
echo 'Checking out the revision ' $1
git checkout -b newvers $1
else
echo 'Using the latest revision'
fi
GIT_CMT_COUNT=$(git rev-list HEAD | wc -l)
DEB_VER=0.13.$GIT_CMT_COUNT-dfsg
FOLDER_NAME=freecad-$DEB_VER
TARBALL_NAME=freecad_$DEB_VER.orig.tar.xz
echo $DEB_VER
echo $FOLDER_NAME
echo $TARBALL_NAME
python src/Tools/SubWCRev.py
cd ..
rm -fr $FOLDER_NAME
mv git_temp_packaging $FOLDER_NAME
rm -rf $FOLDER_NAME/.git
rm -rf $FOLDER_NAME/src/3rdParty/CxImage
rm -rf $FOLDER_NAME/src/3rdParty/Pivy
rm -rf $FOLDER_NAME/src/3rdParty/Pivy-0.5
tar Jcvf $TARBALL_NAME $FOLDER_NAME
rm -fr $FOLDER_NAME

View File

@ -1,2 +0,0 @@
libGL 1 libgl1-mesa-glx (>= 7.7.1-1)
libSoQt4 20 libsoqt4-20 (>= 1.4.2~svn20090224)

View File

@ -1 +1 @@
3.0 (quilt) 1.0

View File

@ -1,3 +1,3 @@
# Lintian thinks uploader Adam Powell's name violates policy # Lintian thinks uploader Adam Powell's name violates policy
freecad source: uploader-address-missing "Adam C. Powell freecad source: uploader-address-missing "Adam C. Powell
freecad source: uploader-not-full-name IV" freecad source: uploader-not-full-name IV"

View File

@ -16,68 +16,36 @@
# http://www.grymoire.com/Unix/Sed.html # http://www.grymoire.com/Unix/Sed.html
# global settings # global settings
REV_FILE=./revision.m4
TMP_PATH=/tmp TMP_PATH=/tmp
MAJ=0 MAJ=0
MIN=12 MIN=13
ALIAS="Vulcan"
# go to root directory # go to root directory
CUR_DIR=$PWD CUR_DIR=$PWD
verz=`dirname $(readlink -f ${0})` verz=`dirname $(readlink -f ${0})`
cd $verz && cd .. cd $verz && cd ..
# let's import OLD_REV (if there) # http://blog.marcingil.com/2011/11/creating-build-numbers-using-git-commits/
if [ -f ./.last_revision ]; then if git log -1 >/dev/null 2>&1; then
. ./.last_revision REV=`git rev-list HEAD | wc -l | sed -e 's/ *//g' | xargs -n1 printf %04d`
else
OLD_REV=0
fi
if svn --xml info >/dev/null 2>&1; then
REV=`svn --xml info | tr -d '\r\n' | sed -e 's/.*<commit.*revision="\([0-9]*\)".*<\/commit>.*/\1/'`
LCD=`svn --xml info | tr -d '\r\n' | sed -e 's/.*<commit.*<date>\([0-9\-]*\)\T\([0-9\:]*\)\..*<\/date>.*<\/commit>.*/\1 \2/'`
URL=`svn --xml info | tr -d '\r\n' | sed -e 's/.*<url>\(.*\)<\/url>.*/\1/'`
elif svn --version --quiet >/dev/null 2>&1; then
REV=`svn info | grep "^Revision:" | cut -d" " -f2`
LCD=`svn info | grep "^Last Changed Date:" | cut -d" " -f4,5`
URL=`svn info | grep "^URL:" | cut -d" " -f2`
else else
REV=0 REV=0
LCD=""
URL=""
fi fi
if [ "x$REV" != "x$OLD_REV" -o ! -r $REV_FILE ]; then
echo "m4_define([FREECAD_MAJOR], $MAJ)" > $REV_FILE
echo "m4_define([FREECAD_MINOR], $MIN)" >> $REV_FILE
echo "m4_define([FREECAD_MICRO], $REV)" >> $REV_FILE
#echo "#define FCVersionMajor \"$MAJ\"" > src/Build/Version.h
#echo "#define FCVersionMinor \"$MIN\"" >> src/Build/Version.h
#echo "#define FCVersionName \"$ALIAS\"" >> src/Build/Version.h
#echo "#define FCRevision \"$REV\"" >> src/Build/Version.h
#echo "#define FCRepositoryURL \"$URL\"" >> src/Build/Version.h
#echo "#define FCCurrentDateT \"$LCD\"\n" >> src/Build/Version.h
touch src/Build/Version.h.in
fi
echo "OLD_REV=$REV" > ./.last_revision
SRC_DIR=$PWD SRC_DIR=$PWD
# Prepare source tarball and unpack it in build directory # Prepare source tarball and unpack it in build directory
cd $CUR_DIR cd $CUR_DIR
make dist make dist-git
cd $verz && cd ..
rm -rf $TMP_PATH/freecad-$REV rm -rf $TMP_PATH/freecad-$REV
mkdir $TMP_PATH/freecad-$REV mkdir $TMP_PATH/freecad-$REV
mv FreeCAD-$MAJ.$MIN.$REV.tar.gz $TMP_PATH/freecad-$REV/freecad_$MAJ.$MIN.$REV.orig.tar.gz mv freecad-$MAJ.$MIN.$REV.tar.gz $TMP_PATH/freecad-$REV/freecad_$MAJ.$MIN.$REV.orig.tar.gz
cd $TMP_PATH/freecad-$REV cd $TMP_PATH/freecad-$REV
tar -xzf freecad_$MAJ.$MIN.$REV.orig.tar.gz tar -xzf freecad_$MAJ.$MIN.$REV.orig.tar.gz
mv FreeCAD-$MAJ.$MIN.$REV freecad-$MAJ.$MIN.$REV
cd freecad-$MAJ.$MIN.$REV cd freecad-$MAJ.$MIN.$REV
rm -rf src/CXX #rm -rf src/CXX
rm -rf src/zipios++ #rm -rf src/zipios++
# Prepare debian folder and set the revision number in debian/changelog # Prepare debian folder and set the revision number in debian/changelog
# for package versioning # for package versioning

View File

@ -42,9 +42,13 @@
#include "utilities.h" #include "utilities.h"
#include <Standard_Version.hxx>
#include <BRepAdaptor_Curve.hxx> #include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx> #include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepTools.hxx> #include <BRepTools.hxx>
#if OCC_VERSION_HEX >= 0x060600
#include <BRepClass3d.hxx>
#endif
#include <TopExp_Explorer.hxx> #include <TopExp_Explorer.hxx>
#include <TopoDS.hxx> #include <TopoDS.hxx>
#include <TopoDS_Shell.hxx> #include <TopoDS_Shell.hxx>
@ -159,7 +163,11 @@ bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& a
// get 2 shells // get 2 shells
TopoDS_Solid solid = TopoDS::Solid( aShape ); TopoDS_Solid solid = TopoDS::Solid( aShape );
#if OCC_VERSION_HEX >= 0x060600
TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid );
#else
TopoDS_Shell outerShell = BRepTools::OuterShell( solid ); TopoDS_Shell outerShell = BRepTools::OuterShell( solid );
#endif
TopoDS_Shape innerShell; TopoDS_Shape innerShell;
int nbShells = 0; int nbShells = 0;
for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells ) for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells )

View File

@ -1008,7 +1008,10 @@ void Application::initTypes(void)
App ::PropertyPercent ::init(); App ::PropertyPercent ::init();
App ::PropertyEnumeration ::init(); App ::PropertyEnumeration ::init();
App ::PropertyIntegerList ::init(); App ::PropertyIntegerList ::init();
App ::PropertyIntegerSet ::init();
App ::PropertyMap ::init();
App ::PropertyString ::init(); App ::PropertyString ::init();
App ::PropertyUUID ::init();
App ::PropertyFont ::init(); App ::PropertyFont ::init();
App ::PropertyStringList ::init(); App ::PropertyStringList ::init();
App ::PropertyLink ::init(); App ::PropertyLink ::init();
@ -1211,9 +1214,10 @@ void Application::processCmdLineFiles(void)
Base::Interpreter().runFile(File.filePath().c_str(), true); Base::Interpreter().runFile(File.filePath().c_str(), true);
} }
else if (File.hasExtension("py")) { else if (File.hasExtension("py")) {
try{ try {
Base::Interpreter().loadModule(File.fileNamePure().c_str()); Base::Interpreter().loadModule(File.fileNamePure().c_str());
}catch(PyException){ }
catch(const PyException&) {
// if module load not work, just try run the script (run in __main__) // if module load not work, just try run the script (run in __main__)
Base::Interpreter().runFile(File.filePath().c_str(),true); Base::Interpreter().runFile(File.filePath().c_str(),true);
} }

View File

@ -64,6 +64,10 @@ recompute path. Also enables more complicated dependencies beyond trees.
#include <boost/graph/graphviz.hpp> #include <boost/graph/graphviz.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/unordered_set.hpp>
#include <QCoreApplication>
#include <QCryptographicHash>
#include "Document.h" #include "Document.h"
@ -433,8 +437,41 @@ unsigned int Document::getMaxUndoStackSize(void)const
void Document::onChanged(const Property* prop) void Document::onChanged(const Property* prop)
{ {
// the Name property is a label for display purposes // the Name property is a label for display purposes
if (prop == &Label) if (prop == &Label) {
App::GetApplication().signalRelabelDocument(*this); App::GetApplication().signalRelabelDocument(*this);
}
else if (prop == &Uid) {
std::string new_dir = getTransientDirectoryName(this->Uid.getValueStr(),this->FileName.getStrValue());
std::string old_dir = this->TransientDir.getStrValue();
Base::FileInfo TransDirNew(new_dir);
Base::FileInfo TransDirOld(old_dir);
// this directory should not exist
if (!TransDirNew.exists()) {
if (TransDirOld.exists()) {
if (!TransDirOld.renameFile(new_dir.c_str()))
Base::Console().Warning("Failed to rename '%s' to '%s'\n", old_dir.c_str(), new_dir.c_str());
else
this->TransientDir.setValue(new_dir);
}
else {
if (!TransDirNew.createDirectory())
Base::Console().Warning("Failed to create '%s'\n", new_dir.c_str());
else
this->TransientDir.setValue(new_dir);
}
}
// when reloading an existing document the transient directory doesn't change
// so we must avoid to generate a new uuid
else if (TransDirNew.filePath() != TransDirOld.filePath()) {
// make sure that the uuid is unique
std::string uuid = this->Uid.getValueStr();
Base::Uuid id;
Base::Console().Warning("Document with the UUID '%s' already exists, change to '%s'\n",
uuid.c_str(), id.getValue().c_str());
// recursive call of onChanged()
this->Uid.setValue(id);
}
}
} }
void Document::onBeforeChangeProperty(const DocumentObject *Who, const Property *What) void Document::onBeforeChangeProperty(const DocumentObject *Who, const Property *What)
@ -525,7 +562,7 @@ Document::Document(void)
#endif #endif
ADD_PROPERTY_TYPE(Label,("Unnamed"),0,Prop_None,"The name of the document"); ADD_PROPERTY_TYPE(Label,("Unnamed"),0,Prop_None,"The name of the document");
ADD_PROPERTY_TYPE(FileName,(""),0,Prop_None,"The path to the file where the document is saved to"); ADD_PROPERTY_TYPE(FileName,(""),0,Prop_ReadOnly,"The path to the file where the document is saved to");
ADD_PROPERTY_TYPE(CreatedBy,(""),0,Prop_None,"The creator of the document"); ADD_PROPERTY_TYPE(CreatedBy,(""),0,Prop_None,"The creator of the document");
ADD_PROPERTY_TYPE(CreationDate,(Base::TimeInfo::currentDateTimeString()),0,Prop_ReadOnly,"Date of creation"); ADD_PROPERTY_TYPE(CreationDate,(Base::TimeInfo::currentDateTimeString()),0,Prop_ReadOnly,"Date of creation");
ADD_PROPERTY_TYPE(LastModifiedBy,(""),0,Prop_None,0); ADD_PROPERTY_TYPE(LastModifiedBy,(""),0,Prop_None,0);
@ -537,19 +574,16 @@ Document::Document(void)
// create the uuid for the document // create the uuid for the document
Base::Uuid id; Base::Uuid id;
ADD_PROPERTY_TYPE(Id,(""),0,Prop_None,"ID of the document"); ADD_PROPERTY_TYPE(Id,(""),0,Prop_None,"ID of the document");
ADD_PROPERTY_TYPE(Uid,(id),0,Prop_None,"UUID of the document"); ADD_PROPERTY_TYPE(Uid,(id),0,Prop_ReadOnly,"UUID of the document");
// license stuff // license stuff
ADD_PROPERTY_TYPE(License,("CC-BY 3.0"),0,Prop_None,"License string of the Item"); ADD_PROPERTY_TYPE(License,("CC-BY 3.0"),0,Prop_None,"License string of the Item");
ADD_PROPERTY_TYPE(LicenseURL,("http://creativecommons.org/licenses/by/3.0/"),0,Prop_None,"URL to the license text/contract"); ADD_PROPERTY_TYPE(LicenseURL,("http://creativecommons.org/licenses/by/3.0/"),0,Prop_None,"URL to the license text/contract");
// create transient directory // this creates and sets 'TransientDir' in onChanged()
std::string basePath = Base::FileInfo::getTempPath() + GetApplication().getExecutableName(); ADD_PROPERTY_TYPE(TransientDir,(""),0,PropertyType(Prop_Transient|Prop_ReadOnly),
Base::FileInfo TransDir(basePath + "_Doc_" + id.getValue());
if (!TransDir.exists())
TransDir.createDirectory();
ADD_PROPERTY_TYPE(TransientDir,(TransDir.filePath().c_str()),0,Prop_Transient,
"Transient directory, where the files live while the document is open"); "Transient directory, where the files live while the document is open");
Uid.touch();
} }
Document::~Document() Document::~Document()
@ -574,7 +608,7 @@ Document::~Document()
// Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed
// Python object or not. In the constructor we forced the wrapper to own the object so we need // Python object or not. In the constructor we forced the wrapper to own the object so we need
// not to dec'ref the Python object any more. // not to dec'ref the Python object any more.
// But we must still invalidate the Python object because it need not to be // But we must still invalidate the Python object because it doesn't need to be
// destructed right now because the interpreter can own several references to it. // destructed right now because the interpreter can own several references to it.
Base::PyObjectBase* doc = (Base::PyObjectBase*)DocumentPythonObject.ptr(); Base::PyObjectBase* doc = (Base::PyObjectBase*)DocumentPythonObject.ptr();
// Call before decrementing the reference counter, otherwise a heap error can occur // Call before decrementing the reference counter, otherwise a heap error can occur
@ -586,6 +620,19 @@ Document::~Document()
delete d; delete d;
} }
std::string Document::getTransientDirectoryName(const std::string& uuid, const std::string& filename) const
{
// Create a directory name of the form: {ExeName}_Doc_{UUID}_{HASH}_{PID}
std::stringstream s;
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData(filename.c_str(), filename.size());
s << Base::FileInfo::getTempPath() << GetApplication().getExecutableName()
<< "_Doc_" << uuid
<< "_" << hash.result().toHex().left(6).constData()
<< "_" << QCoreApplication::applicationPid();
return s.str();
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// Exported functions // Exported functions
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -623,12 +670,7 @@ void Document::Restore(Base::XMLReader &reader)
std::string FilePath = FileName.getValue(); std::string FilePath = FileName.getValue();
std::string DocLabel = Label.getValue(); std::string DocLabel = Label.getValue();
// remove previous Transient directory // read the Document Properties, when reading in Uid the transient directory gets renamed automatically
Base::FileInfo TransDir(TransientDir.getValue());
TransDir.deleteDirectoryRecursive();
// read the Document Properties
PropertyContainer::Restore(reader); PropertyContainer::Restore(reader);
// We must restore the correct 'FileName' property again because the stored // We must restore the correct 'FileName' property again because the stored
@ -636,14 +678,6 @@ void Document::Restore(Base::XMLReader &reader)
FileName.setValue(FilePath.c_str()); FileName.setValue(FilePath.c_str());
Label.setValue(DocLabel.c_str()); Label.setValue(DocLabel.c_str());
// create new transient directory
std::string basePath = Base::FileInfo::getTempPath() + GetApplication().getExecutableName();
Base::FileInfo TransDirNew(basePath + "_Doc_" + Uid.getValueStr());
if(!TransDirNew.exists())
TransDirNew.createDirectory();
TransientDir.setValue(TransDirNew.filePath());
// SchemeVersion "2" // SchemeVersion "2"
if ( scheme == 2 ) { if ( scheme == 2 ) {
// read the feature types // read the feature types
@ -769,8 +803,8 @@ Document::readObjects(Base::XMLReader& reader)
reader.addName(name.c_str(), obj->getNameInDocument()); reader.addName(name.c_str(), obj->getNameInDocument());
} }
} }
catch (Base::Exception&) { catch (const Base::Exception& e) {
Base::Console().Message("Cannot create object '%s'\n", name.c_str()); Base::Console().Error("Cannot create object '%s': (%s)\n", name.c_str(), e.what());
} }
} }
reader.readEndElement("Objects"); reader.readEndElement("Objects");
@ -857,6 +891,18 @@ void Document::exportGraphviz(std::ostream& out)
boost::write_graphviz(out, DepList, boost::make_label_writer(&(names[0]))); boost::write_graphviz(out, DepList, boost::make_label_writer(&(names[0])));
} }
bool Document::saveAs(const char* file)
{
Base::FileInfo fi(file);
if (this->FileName.getStrValue() != file) {
this->FileName.setValue(file);
this->Label.setValue(fi.fileNamePure());
this->Uid.touch(); // this forces a rename of the transient directory
}
return save();
}
// Save the document under the name it has been opened // Save the document under the name it has been opened
bool Document::save (void) bool Document::save (void)
{ {
@ -1090,6 +1136,58 @@ std::vector<App::DocumentObject*> Document::getInList(const DocumentObject* me)
return result; return result;
} }
std::vector<App::DocumentObject*>
Document::getDependencyList(const std::vector<App::DocumentObject*>& objs) const
{
DependencyList DepList;
std::map<DocumentObject*,Vertex> ObjectMap;
std::map<Vertex,DocumentObject*> VertexMap;
// Filling up the adjacency List
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
// add the object as Vertex and remember the index
Vertex v = add_vertex(DepList);
ObjectMap[It->second] = v;
VertexMap[v] = It->second;
}
// add the edges
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
std::vector<DocumentObject*> OutList = It->second->getOutList();
for (std::vector<DocumentObject*>::const_iterator It2=OutList.begin();It2!=OutList.end();++It2) {
if (*It2)
add_edge(ObjectMap[It->second],ObjectMap[*It2],DepList);
}
}
std::list<Vertex> make_order;
DependencyList::out_edge_iterator j, jend;
try {
// this sort gives the execute
boost::topological_sort(DepList, std::front_inserter(make_order));
}
catch (const std::exception&) {
return std::vector<App::DocumentObject*>();
}
//std::vector<App::DocumentObject*> out;
boost::unordered_set<App::DocumentObject*> out;
for (std::vector<App::DocumentObject*>::const_iterator it = objs.begin(); it != objs.end(); ++it) {
std::map<DocumentObject*,Vertex>::iterator jt = ObjectMap.find(*it);
// ok, object is part of this graph
if (jt != ObjectMap.end()) {
for (boost::tie(j, jend) = boost::out_edges(jt->second, DepList); j != jend; ++j) {
out.insert(VertexMap[boost::target(*j, DepList)]);
}
out.insert(*it);
}
}
std::vector<App::DocumentObject*> ary;
ary.insert(ary.end(), out.begin(), out.end());
return ary;
}
void Document::_rebuildDependencyList(void) void Document::_rebuildDependencyList(void)
{ {
d->VertexObjectList.clear(); d->VertexObjectList.clear();
@ -1119,21 +1217,6 @@ void Document::recompute()
// updates the dependency graph // updates the dependency graph
_rebuildDependencyList(); _rebuildDependencyList();
//DependencyList DepList;
//std::map<DocumentObject*,Vertex> VertexObjectList;
//// Filling up the adjacency List
//for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It)
// // add the object as Vertex and remember the index
// VertexObjectList[It->second] = add_vertex(DepList);
//// add the edges
//for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
// std::vector<DocumentObject*> OutList = It->second->getOutList();
// for (std::vector<DocumentObject*>::const_iterator It2=OutList.begin();It2!=OutList.end();++It2)
// if (*It2)
// add_edge(VertexObjectList[It->second],VertexObjectList[*It2],DepList);
//}
std::list<Vertex> make_order; std::list<Vertex> make_order;
DependencyList::out_edge_iterator j, jend; DependencyList::out_edge_iterator j, jend;

View File

@ -133,6 +133,7 @@ public:
//void saveAs (const char* Name); //void saveAs (const char* Name);
/// Save the document to the file in Property Path /// Save the document to the file in Property Path
bool save (void); bool save (void);
bool saveAs(const char* file);
/// Restore the document from the file in Property Path /// Restore the document from the file in Property Path
void restore (void); void restore (void);
void exportObjects(const std::vector<App::DocumentObject*>&, std::ostream&); void exportObjects(const std::vector<App::DocumentObject*>&, std::ostream&);
@ -264,6 +265,10 @@ public:
bool checkOnCycle(void); bool checkOnCycle(void);
/// get a list of all objects linking to the given object /// get a list of all objects linking to the given object
std::vector<App::DocumentObject*> getInList(const DocumentObject* me) const; std::vector<App::DocumentObject*> getInList(const DocumentObject* me) const;
/// Get a complete list of all objects the given objects depend on. The list
/// also contains the given objects!
std::vector<App::DocumentObject*> getDependencyList
(const std::vector<App::DocumentObject*>&) const;
// set Changed // set Changed
//void setChanged(DocumentObject* change); //void setChanged(DocumentObject* change);
//@} //@}
@ -303,6 +308,7 @@ protected:
void _clearRedos(); void _clearRedos();
/// refresh the internal dependency graph /// refresh the internal dependency graph
void _rebuildDependencyList(void); void _rebuildDependencyList(void);
std::string getTransientDirectoryName(const std::string& uuid, const std::string& filename) const;
private: private:

View File

@ -38,6 +38,15 @@ namespace App
class Document; class Document;
class DocumentObjectPy; class DocumentObjectPy;
enum ObjectStatus {
Touch = 0,
Error = 1,
New = 2,
Recompute = 3,
Restore = 4,
Expand = 16
};
/** Return object for feature execution /** Return object for feature execution
*/ */
class AppExport DocumentObjectExecReturn class AppExport DocumentObjectExecReturn
@ -105,9 +114,11 @@ public:
virtual App::DocumentObjectExecReturn *recompute(void); virtual App::DocumentObjectExecReturn *recompute(void);
/// return the status bits /// return the status bits
unsigned long getStatus() const {return StatusBits.to_ulong();} unsigned long getStatus() const {return StatusBits.to_ulong();}
bool testStatus(ObjectStatus pos) const {return StatusBits.test((size_t)pos);}
void setStatus(ObjectStatus pos, bool on) {StatusBits.set((size_t)pos, on);}
//@} //@}
/// returns a list of objects this object is pointing to by Links /// returns a list of objects this object is pointing to by Links
std::vector<App::DocumentObject*> getOutList(void) const; std::vector<App::DocumentObject*> getOutList(void) const;
/// get all objects link to this object /// get all objects link to this object
std::vector<App::DocumentObject*> getInList(void) const; std::vector<App::DocumentObject*> getInList(void) const;
@ -129,7 +140,7 @@ public:
/** Called in case of loosing a link /** Called in case of loosing a link
* Get called by the document when a object got deleted a link property of this * Get called by the document when a object got deleted a link property of this
* object ist pointing to. The standard behaivour of the DocumentObject implementation * object ist pointing to. The standard behaviour of the DocumentObject implementation
* is to reset the links to nothing. You may overide this method to implement * is to reset the links to nothing. You may overide this method to implement
*additional or different behavior. *additional or different behavior.
*/ */
@ -160,14 +171,15 @@ protected:
* The first 8 bits are used for the base system the rest can be used in * The first 8 bits are used for the base system the rest can be used in
* descendent classes to to mark special stati on the objects. * descendent classes to to mark special stati on the objects.
* The bits and their meaning are listed below: * The bits and their meaning are listed below:
* 0 - object is marked as 'touched' * 0 - object is marked as 'touched'
* 1 - object is marked as 'erroneous' * 1 - object is marked as 'erroneous'
* 2 - object is marked as 'new' * 2 - object is marked as 'new'
* 3 - object is marked as 'recompute', i.e. the object gets recomputed now * 3 - object is marked as 'recompute', i.e. the object gets recomputed now
* 4 - object is marked as 'restoring', i.e. the object gets loaded at the moment * 4 - object is marked as 'restoring', i.e. the object gets loaded at the moment
* 5 - reserved * 5 - reserved
* 6 - reserved * 6 - reserved
* 7 - reserved * 7 - reserved
* 16 - object is marked as 'expanded' in the tree view
*/ */
std::bitset<32> StatusBits; std::bitset<32> StatusBits;

View File

@ -101,7 +101,7 @@ void DocumentObserverPython::slotCreatedDocument(const App::Document& Doc)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("%s\n", e.what()); e.ReportException();
} }
} }
@ -118,7 +118,7 @@ void DocumentObserverPython::slotDeletedDocument(const App::Document& Doc)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("%s\n", e.what()); e.ReportException();
} }
} }
@ -135,7 +135,7 @@ void DocumentObserverPython::slotRelabelDocument(const App::Document& Doc)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("%s\n", e.what()); e.ReportException();
} }
} }
@ -152,7 +152,7 @@ void DocumentObserverPython::slotActivateDocument(const App::Document& Doc)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("%s\n", e.what()); e.ReportException();
} }
} }
@ -169,7 +169,7 @@ void DocumentObserverPython::slotCreatedObject(const App::DocumentObject& Obj)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("%s\n", e.what()); e.ReportException();
} }
} }
@ -186,7 +186,7 @@ void DocumentObserverPython::slotDeletedObject(const App::DocumentObject& Obj)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("%s\n", e.what()); e.ReportException();
} }
} }
@ -206,6 +206,6 @@ void DocumentObserverPython::slotChangedObject(const App::DocumentObject& Obj,
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("%s\n", e.what()); e.ReportException();
} }
} }

View File

@ -15,12 +15,17 @@
</Documentation> </Documentation>
<Methode Name="save"> <Methode Name="save">
<Documentation> <Documentation>
<UserDocu>Save the document to disc</UserDocu> <UserDocu>Save the document to disk</UserDocu>
</Documentation>
</Methode>
<Methode Name="saveAs">
<Documentation>
<UserDocu>Save the document under a new name to disk</UserDocu>
</Documentation> </Documentation>
</Methode> </Methode>
<Methode Name="restore"> <Methode Name="restore">
<Documentation> <Documentation>
<UserDocu>Restore the document from disc</UserDocu> <UserDocu>Restore the document from disk</UserDocu>
</Documentation> </Documentation>
</Methode> </Methode>
<Methode Name="exportGraphviz"> <Methode Name="exportGraphviz">

View File

@ -69,6 +69,25 @@ PyObject* DocumentPy::save(PyObject * args)
Py_Return; Py_Return;
} }
PyObject* DocumentPy::saveAs(PyObject * args)
{
char* fn;
if (!PyArg_ParseTuple(args, "s", &fn)) // convert args: Python->C
return NULL; // NULL triggers exception
if (!getDocumentPtr()->saveAs(fn)) {
PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set");
return NULL;
}
Base::FileInfo fi(fn);
if (!fi.isReadable()) {
PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", fn);
return NULL;
}
Py_Return;
}
PyObject* DocumentPy::restore(PyObject * args) PyObject* DocumentPy::restore(PyObject * args)
{ {
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C if (!PyArg_ParseTuple(args, "")) // convert args: Python->C

View File

@ -67,6 +67,7 @@ DocumentObjectExecReturn *FeaturePythonImp::execute()
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
e.ReportException();
std::stringstream str; std::stringstream str;
str << object->Label.getValue() << ": " << e.what(); str << object->Label.getValue() << ": " << e.what();
return new App::DocumentObjectExecReturn(str.str()); return new App::DocumentObjectExecReturn(str.str());
@ -104,8 +105,7 @@ void FeaturePythonImp::onChanged(const Property* prop)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Error("FeaturePython::onChanged (%s): %s\n", e.ReportException();
object->Label.getValue(), e.what());
} }
} }

View File

@ -61,7 +61,7 @@ public:
*/ */
virtual unsigned int getMemSize (void) const { virtual unsigned int getMemSize (void) const {
// you have to implement this method in all property classes! // you have to implement this method in all property classes!
return Base::Persistence::getMemSize() + sizeof(father) + sizeof(StatusBits); return sizeof(father) + sizeof(StatusBits);
} }
/// get the name of this property in the belonging container /// get the name of this property in the belonging container

View File

@ -24,6 +24,7 @@
#include "PreCompiled.h" #include "PreCompiled.h"
#ifndef _PreComp_ #ifndef _PreComp_
# include <algorithm>
# include <sstream> # include <sstream>
#endif #endif
@ -35,12 +36,13 @@
#include <Base/Stream.h> #include <Base/Stream.h>
#include <Base/Console.h> #include <Base/Console.h>
#include <Base/PyObjectBase.h> #include <Base/PyObjectBase.h>
#include <Base/Uuid.h>
#include "PropertyFile.h" #include "PropertyFile.h"
#include "Document.h" #include "Document.h"
#include "PropertyContainer.h" #include "PropertyContainer.h"
#include "DocumentObject.h" #include "DocumentObject.h"
#define new DEBUG_CLIENTBLOCK
using namespace App; using namespace App;
using namespace Base; using namespace Base;
using namespace std; using namespace std;
@ -53,6 +55,7 @@ using namespace std;
TYPESYSTEM_SOURCE(App::PropertyFileIncluded , App::Property); TYPESYSTEM_SOURCE(App::PropertyFileIncluded , App::Property);
PropertyFileIncluded::PropertyFileIncluded() PropertyFileIncluded::PropertyFileIncluded()
{ {
@ -63,17 +66,45 @@ PropertyFileIncluded::~PropertyFileIncluded()
// clean up // clean up
if (!_cValue.empty()) { if (!_cValue.empty()) {
Base::FileInfo file(_cValue.c_str()); Base::FileInfo file(_cValue.c_str());
file.setPermissions(Base::FileInfo::ReadWrite);
file.deleteFile(); file.deleteFile();
} }
} }
void PropertyFileIncluded::aboutToSetValue(void)
{
// This is a trick to check in Copy() if it is called
// directly from outside or by the Undo/Redo mechanism.
// In the latter case it is sufficient to rename the file
// because another file will be assigned afterwards.
// If Copy() is directly called (e.g. to copy the file to
// another document) a copy of the file needs to be created.
// This copy will be deleted again in the class destructor.
this->StatusBits.set(10);
Property::aboutToSetValue();
this->StatusBits.reset(10);
}
std::string PropertyFileIncluded::getDocTransientPath(void) const std::string PropertyFileIncluded::getDocTransientPath(void) const
{ {
std::string path;
PropertyContainer *co = getContainer(); PropertyContainer *co = getContainer();
if (co->isDerivedFrom(DocumentObject::getClassTypeId())) if (co->isDerivedFrom(DocumentObject::getClassTypeId())) {
return dynamic_cast<DocumentObject*>(co)->getDocument()->TransientDir.getValue(); path = dynamic_cast<DocumentObject*>(co)->getDocument()->TransientDir.getValue();
std::replace(path.begin(), path.end(), '\\', '/');
}
return path;
}
return std::string(); std::string PropertyFileIncluded::getUniqueFileName(const std::string& path, const std::string& filename) const
{
Base::Uuid uuid;
Base::FileInfo fi(path + "/" + filename);
while (fi.exists()) {
fi.setFile(path + "/" + filename + "." + uuid.getValue());
}
return fi.filePath();
} }
std::string PropertyFileIncluded::getExchangeTempFile(void) const std::string PropertyFileIncluded::getExchangeTempFile(void) const
@ -97,34 +128,40 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
throw Base::Exception(str.str()); throw Base::Exception(str.str());
} }
aboutToSetValue(); // undo redo by move the file away with temp name aboutToSetValue(); // undo/redo by moving the file away with temp name
// remove old file (if not moved by undo) // remove old file (if not moved by undo)
Base::FileInfo value(_cValue); Base::FileInfo value(_cValue);
std::string pathAct = value.dirPath(); std::string pathAct = value.dirPath();
if (value.exists()) if (value.exists()) {
value.setPermissions(Base::FileInfo::ReadWrite);
value.deleteFile(); value.deleteFile();
}
// if a special name given, use this instead // if a special name given, use this instead
if (sName) { if (sName) {
Base::FileInfo ExtraName(path + "/" + sName); Base::FileInfo fi(pathTrans + "/" + sName);
if (ExtraName.exists() ) { if (fi.exists()) {
// if a file with this name already exists search for a new one // if a file with this name already exists search for a new one
std::string dir = pathTrans;
std::string fnp = fi.fileNamePure();
std::string ext = fi.extension(false);
int i=0; int i=0;
do { do {
i++; i++;
std::stringstream str; std::stringstream str;
str << path << "/" << sName << i; str << dir << "/" << fnp << i;
ExtraName.setFile(str.str()); if (!ext.empty())
str << "." << ext;
fi.setFile(str.str());
} }
while (ExtraName.exists()); while (fi.exists());
_cValue = ExtraName.filePath();
_BaseFileName = ExtraName.fileName();
_cValue = fi.filePath();
_BaseFileName = fi.fileName();
} }
else { else {
_cValue = path + "/" + sName; _cValue = pathTrans + "/" + sName;
_BaseFileName = sName; _BaseFileName = sName;
} }
} }
@ -133,39 +170,61 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
_BaseFileName = file.fileName(); _BaseFileName = file.fileName();
} }
// if the files is already in transient dir of the document, just use it // The following applies only on files that are inside the transient
if (path == pathTrans) { // directory:
// When a file is read-only it is supposed to be assigned to a
// PropertyFileIncluded instance. In this case we must copy the
// file because otherwise the above instance looses its data.
// If the file is writable it is supposed to be of free use and
// it can be simply renamed.
// if the file is already in transient dir of the document, just use it
if (path == pathTrans && file.isWritable()) {
bool done = file.renameFile(_cValue.c_str()); bool done = file.renameFile(_cValue.c_str());
//assert(done);
if (!done) { if (!done) {
std::stringstream str; std::stringstream str;
str << "Cannot rename file " << file.filePath() << " to " << _cValue; str << "Cannot rename file " << file.filePath() << " to " << _cValue;
throw Base::Exception(str.str()); throw Base::Exception(str.str());
} }
// make the file read-only
Base::FileInfo dst(_cValue);
dst.setPermissions(Base::FileInfo::ReadOnly);
} }
// otherwise copy from origin location // otherwise copy from origin location
else { else {
// if file already exists in transient dir make a new unique name // if file already exists in transient dir make a new unique name
Base::FileInfo fi(_cValue); Base::FileInfo fi(_cValue);
if (fi.exists()) { if (fi.exists()) {
Base::FileInfo fi2(Base::FileInfo::getTempFileName()); // if a file with this name already exists search for a new one
std::stringstream str; std::string dir = fi.dirPath();
str << fi.dirPath() << "/" << fi2.fileNamePure(); std::string fnp = fi.fileNamePure();
std::string ext = fi.extension(false); std::string ext = fi.extension(false);
if (!ext.empty()) int i=0;
str << "." << ext; do {
Base::FileInfo fi3(str.str()); i++;
_cValue = fi3.filePath(); std::stringstream str;
_BaseFileName = fi3.fileName(); str << dir << "/" << fnp << i;
if (!ext.empty())
str << "." << ext;
fi.setFile(str.str());
}
while (fi.exists());
_cValue = fi.filePath();
_BaseFileName = fi.fileName();
} }
bool done = file.copyTo(_cValue.c_str()); bool done = file.copyTo(_cValue.c_str());
//assert(done);
if (!done) { if (!done) {
std::stringstream str; std::stringstream str;
str << "Cannot copy file from " << file.filePath() << " to " << _cValue; str << "Cannot copy file from " << file.filePath() << " to " << _cValue;
throw Base::Exception(str.str()); throw Base::Exception(str.str());
} }
// make the file read-only
Base::FileInfo dst(_cValue);
dst.setPermissions(Base::FileInfo::ReadOnly);
} }
hasSetValue(); hasSetValue();
@ -180,7 +239,7 @@ const char* PropertyFileIncluded::getValue(void) const
PyObject *PropertyFileIncluded::getPyObject(void) PyObject *PropertyFileIncluded::getPyObject(void)
{ {
PyObject *p = PyUnicode_DecodeUTF8(_cValue.c_str(),_cValue.size(),0); PyObject *p = PyUnicode_DecodeUTF8(_cValue.c_str(),_cValue.size(),0);
if (!p) throw Base::Exception("UTF8 conversion failure at PropertyString::getPyObject()"); if (!p) throw Base::Exception("PropertyFileIncluded: UTF-8 conversion failure");
return p; return p;
} }
@ -201,7 +260,7 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
} }
else if (PyTuple_Check(value)) { else if (PyTuple_Check(value)) {
if (PyTuple_Size(value) != 2) if (PyTuple_Size(value) != 2)
throw Py::TypeError("Tuple need size of (filePath,newFileName)"); throw Base::TypeError("Tuple needs size of (filePath,newFileName)");
PyObject* file = PyTuple_GetItem(value,0); PyObject* file = PyTuple_GetItem(value,0);
PyObject* name = PyTuple_GetItem(value,1); PyObject* name = PyTuple_GetItem(value,1);
@ -220,9 +279,9 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
fileStr = PyString_AsString(FileName); fileStr = PyString_AsString(FileName);
} }
else { else {
std::string error = std::string("first in tuple must be a file or string"); std::string error = std::string("First item in tuple must be a file or string");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
// decoding name // decoding name
@ -235,19 +294,18 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
nameStr = PyString_AsString(FileName); nameStr = PyString_AsString(FileName);
} }
else { else {
std::string error = std::string("second in tuple must be a string"); std::string error = std::string("Second item in tuple must be a string");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
setValue(fileStr.c_str(),nameStr.c_str()); setValue(fileStr.c_str(),nameStr.c_str());
return; return;
} }
else { else {
std::string error = std::string("type must be str or file"); std::string error = std::string("Type must be string or file");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
// assign the string // assign the string
@ -256,29 +314,39 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
void PropertyFileIncluded::Save (Base::Writer &writer) const void PropertyFileIncluded::Save (Base::Writer &writer) const
{ {
// when saving a document under a new file name the transient directory
// name changes and thus the stored file name doesn't work any more.
if (!_cValue.empty() && !Base::FileInfo(_cValue).exists()) {
Base::FileInfo fi(getDocTransientPath() + "/" + _BaseFileName);
if (fi.exists())
_cValue = fi.filePath();
}
if (writer.isForceXML()) { if (writer.isForceXML()) {
if (!_cValue.empty()) { if (!_cValue.empty()) {
Base::FileInfo file(_cValue.c_str()); Base::FileInfo file(_cValue.c_str());
writer.Stream() << writer.ind() << "<FileIncluded data=\"" << writer.Stream() << writer.ind() << "<FileIncluded data=\""
file.fileName() << "\">" << std::endl; << file.fileName() << "\">" << std::endl;
// write the file in the XML stream // write the file in the XML stream
writer.incInd(); writer.incInd();
writer.insertBinFile(_cValue.c_str()); writer.insertBinFile(_cValue.c_str());
writer.decInd(); writer.decInd();
writer.Stream() << writer.ind() <<"</FileIncluded>" << endl; writer.Stream() << writer.ind() <<"</FileIncluded>" << endl;
} }
else else {
writer.Stream() << writer.ind() << "<FileIncluded data=\"\"/>" << std::endl; writer.Stream() << writer.ind() << "<FileIncluded data=\"\"/>" << std::endl;
}
} }
else { else {
// instead initiate an extra file // instead initiate an extra file
if (!_cValue.empty()) { if (!_cValue.empty()) {
Base::FileInfo file(_cValue.c_str()); Base::FileInfo file(_cValue.c_str());
writer.Stream() << writer.ind() << "<FileIncluded file=\"" << writer.Stream() << writer.ind() << "<FileIncluded file=\""
writer.addFile(file.fileName().c_str(), this) << "\"/>" << std::endl; << writer.addFile(file.fileName().c_str(), this) << "\"/>" << std::endl;
} }
else else {
writer.Stream() << writer.ind() << "<FileIncluded file=\"\"/>" << std::endl; writer.Stream() << writer.ind() << "<FileIncluded file=\"\"/>" << std::endl;
}
} }
} }
@ -307,6 +375,9 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader)
reader.readBinFile(_cValue.c_str()); reader.readBinFile(_cValue.c_str());
reader.readEndElement("FileIncluded"); reader.readEndElement("FileIncluded");
_BaseFileName = file; _BaseFileName = file;
// set read-only after restoring the file
Base::FileInfo fi(_cValue.c_str());
fi.setPermissions(Base::FileInfo::ReadOnly);
hasSetValue(); hasSetValue();
} }
} }
@ -315,9 +386,12 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader)
void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
{ {
Base::ifstream from(Base::FileInfo(_cValue.c_str())); Base::ifstream from(Base::FileInfo(_cValue.c_str()));
if (!from) if (!from) {
throw Base::Exception("PropertyFileIncluded::SaveDocFile() " std::stringstream str;
"File in document transient dir deleted"); str << "PropertyFileIncluded::SaveDocFile(): "
<< "File '" << _cValue << "' in transient directory doesn't exist.";
throw Base::Exception(str.str());
}
// copy plain data // copy plain data
unsigned char c; unsigned char c;
@ -329,10 +403,14 @@ void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader) void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
{ {
Base::ofstream to(Base::FileInfo(_cValue.c_str())); Base::FileInfo fi(_cValue.c_str());
if (!to) Base::ofstream to(fi);
throw Base::Exception("PropertyFileIncluded::RestoreDocFile() " if (!to) {
"File in document transient dir deleted"); std::stringstream str;
str << "PropertyFileIncluded::RestoreDocFile(): "
<< "File '" << _cValue << "' in transient directory doesn't exist.";
throw Base::Exception(str.str());
}
// copy plain data // copy plain data
aboutToSetValue(); aboutToSetValue();
@ -341,6 +419,9 @@ void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
to.put((const char)c); to.put((const char)c);
} }
to.close(); to.close();
// set read-only after restoring the file
fi.setPermissions(Base::FileInfo::ReadOnly);
hasSetValue(); hasSetValue();
} }
@ -351,18 +432,39 @@ Property *PropertyFileIncluded::Copy(void) const
// remember the base name // remember the base name
prop->_BaseFileName = _BaseFileName; prop->_BaseFileName = _BaseFileName;
if (!_cValue.empty()) { Base::FileInfo file(_cValue);
Base::FileInfo file(_cValue); if (file.exists()) {
// create a new name in the document transient directory // create a new name in the document transient directory
Base::FileInfo NewName(Base::FileInfo::getTempFileName(file.fileName().c_str(),file.dirPath().c_str())); Base::FileInfo newName(getUniqueFileName(file.dirPath(), file.fileName()));
NewName.deleteFile(); if (this->StatusBits.test(10)) {
// move the file // rename the file
bool done = file.renameFile(NewName.filePath().c_str()); bool done = file.renameFile(newName.filePath().c_str());
assert(done); if (!done) {
std::stringstream str;
str << "PropertyFileIncluded::Copy(): "
<< "Renaming the file '" << file.filePath() << "' to '"
<< newName.filePath() << "' failed.";
throw Base::Exception(str.str());
}
}
else {
// copy the file
bool done = file.copyTo(newName.filePath().c_str());
if (!done) {
std::stringstream str;
str << "PropertyFileIncluded::Copy(): "
<< "Copying the file '" << file.filePath() << "' to '"
<< newName.filePath() << "' failed.";
throw Base::Exception(str.str());
}
}
// remember the new name for the Undo // remember the new name for the Undo
Base::Console().Log("Copy this=%p Before=%s After=%s\n",prop,prop->_cValue.c_str(),NewName.filePath().c_str()); Base::Console().Log("Copy '%s' to '%s'\n",_cValue.c_str(),newName.filePath().c_str());
prop->_cValue = NewName.filePath().c_str(); prop->_cValue = newName.filePath().c_str();
// make backup files writable to avoid copying them again on undo/redo
newName.setPermissions(Base::FileInfo::ReadWrite);
} }
return prop; return prop;
@ -371,26 +473,65 @@ Property *PropertyFileIncluded::Copy(void) const
void PropertyFileIncluded::Paste(const Property &from) void PropertyFileIncluded::Paste(const Property &from)
{ {
aboutToSetValue(); aboutToSetValue();
Base::FileInfo file(_cValue); const PropertyFileIncluded &prop = dynamic_cast<const PropertyFileIncluded&>(from);
// delete old file (if still there) // make sure that source and destination file are different
file.deleteFile(); if (_cValue != prop._cValue) {
const PropertyFileIncluded &fileInc = dynamic_cast<const PropertyFileIncluded&>(from); // delete old file (if still there)
Base::FileInfo fi(_cValue);
fi.setPermissions(Base::FileInfo::ReadWrite);
fi.deleteFile();
// set the base name // get path to destination which can be the transient directory
_BaseFileName = fileInc._BaseFileName; // of another document
std::string pathTrans = getDocTransientPath();
Base::FileInfo fiSrc(prop._cValue);
Base::FileInfo fiDst(pathTrans + "/" + prop._BaseFileName);
std::string path = fiSrc.dirPath();
if (!fileInc._cValue.empty()) { if (fiSrc.exists()) {
// move the saved files back in place fiDst.setFile(getUniqueFileName(fiDst.dirPath(), fiDst.fileName()));
Base::FileInfo NewFile(fileInc._cValue);
_cValue = NewFile.dirPath() + "/" + fileInc._BaseFileName; // if the file is already in transient dir of the document, just use it
bool done = NewFile.renameFile(_cValue.c_str()); if (path == pathTrans) {
assert(done); if (!fiSrc.renameFile(fiDst.filePath().c_str())) {
std::stringstream str;
str << "PropertyFileIncluded::Paste(): "
<< "Renaming the file '" << fiSrc.filePath() << "' to '"
<< fiDst.filePath() << "' failed.";
throw Base::Exception(str.str());
}
}
else {
if (!fiSrc.copyTo(fiDst.filePath().c_str())) {
std::stringstream str;
str << "PropertyFileIncluded::Paste(): "
<< "Copying the file '" << fiSrc.filePath() << "' to '"
<< fiDst.filePath() << "' failed.";
throw Base::Exception(str.str());
}
}
// set the file again read-only
fiDst.setPermissions(Base::FileInfo::ReadOnly);
_cValue = fiDst.filePath();
}
else {
_cValue.clear();
}
// set the base name
_BaseFileName = prop._BaseFileName;
} }
else
_cValue.clear();
hasSetValue(); hasSetValue();
} }
unsigned int PropertyFileIncluded::getMemSize (void) const
{
unsigned int mem = Property::getMemSize();
mem += _cValue.size();
mem += _BaseFileName.size();
return mem;
}
//************************************************************************** //**************************************************************************
// PropertyFile // PropertyFile

View File

@ -95,9 +95,7 @@ public:
virtual Property *Copy(void) const; virtual Property *Copy(void) const;
virtual void Paste(const Property &from); virtual void Paste(const Property &from);
virtual unsigned int getMemSize (void) const;
// get the transient path if the property is in a DocumentObject
std::string getDocTransientPath(void) const;
/** get a temp file name in the transient path of the document. /** get a temp file name in the transient path of the document.
* Using this file for new Version of the file and set * Using this file for new Version of the file and set
@ -107,8 +105,14 @@ public:
std::string getExchangeTempFile(void) const; std::string getExchangeTempFile(void) const;
protected: protected:
std::string _cValue; // get the transient path if the property is in a DocumentObject
std::string _BaseFileName; std::string getDocTransientPath(void) const;
std::string getUniqueFileName(const std::string&, const std::string&) const;
void aboutToSetValue(void);
protected:
mutable std::string _cValue;
mutable std::string _BaseFileName;
}; };

View File

@ -117,7 +117,7 @@ void PropertyVector::setPyObject(PyObject *value)
else if (PyInt_Check(item)) else if (PyInt_Check(item))
cVec.x = (float)PyInt_AsLong(item); cVec.x = (float)PyInt_AsLong(item);
else else
throw Base::Exception("Not allowed type used in tuple (float expected)..."); throw Base::TypeError("Not allowed type used in tuple (float expected)...");
// y // y
item = PyTuple_GetItem(value,1); item = PyTuple_GetItem(value,1);
if (PyFloat_Check(item)) if (PyFloat_Check(item))
@ -125,7 +125,7 @@ void PropertyVector::setPyObject(PyObject *value)
else if (PyInt_Check(item)) else if (PyInt_Check(item))
cVec.y = (float)PyInt_AsLong(item); cVec.y = (float)PyInt_AsLong(item);
else else
throw Base::Exception("Not allowed type used in tuple (float expected)..."); throw Base::TypeError("Not allowed type used in tuple (float expected)...");
// z // z
item = PyTuple_GetItem(value,2); item = PyTuple_GetItem(value,2);
if (PyFloat_Check(item)) if (PyFloat_Check(item))
@ -133,13 +133,13 @@ void PropertyVector::setPyObject(PyObject *value)
else if (PyInt_Check(item)) else if (PyInt_Check(item))
cVec.z = (float)PyInt_AsLong(item); cVec.z = (float)PyInt_AsLong(item);
else else
throw Base::Exception("Not allowed type used in tuple (float expected)..."); throw Base::TypeError("Not allowed type used in tuple (float expected)...");
setValue( cVec ); setValue( cVec );
} }
else { else {
std::string error = std::string("type must be 'Vector' or tuple of three floats, not "); std::string error = std::string("type must be 'Vector' or tuple of three floats, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -271,7 +271,7 @@ void PropertyVectorList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'Vector' or list of 'Vector', not "); std::string error = std::string("type must be 'Vector' or list of 'Vector', not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -396,7 +396,7 @@ void PropertyMatrix::setPyObject(PyObject *value)
else if (PyInt_Check(item)) else if (PyInt_Check(item))
cMatrix[x][y] = (double)PyInt_AsLong(item); cMatrix[x][y] = (double)PyInt_AsLong(item);
else else
throw Base::Exception("Not allowed type used in matrix tuple (a number expected)..."); throw Base::TypeError("Not allowed type used in matrix tuple (a number expected)...");
} }
} }
@ -405,7 +405,7 @@ void PropertyMatrix::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'Matrix' or tuple of 16 float or int, not "); std::string error = std::string("type must be 'Matrix' or tuple of 16 float or int, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -520,7 +520,7 @@ void PropertyPlacement::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'Matrix' or 'Placement', not "); std::string error = std::string("type must be 'Matrix' or 'Placement', not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }

View File

@ -110,7 +110,7 @@ void PropertyLink::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'DocumentObject' or 'NoneType', not "); std::string error = std::string("type must be 'DocumentObject' or 'NoneType', not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -257,7 +257,7 @@ void PropertyLinkSub::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type of first element in tuple must be 'DocumentObject', not "); std::string error = std::string("type of first element in tuple must be 'DocumentObject', not ");
error += tup[0].ptr()->ob_type->tp_name; error += tup[0].ptr()->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
else if(Py_None == value) { else if(Py_None == value) {
@ -266,7 +266,7 @@ void PropertyLinkSub::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not "); std::string error = std::string("type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -409,7 +409,7 @@ void PropertyLinkList::setPyObject(PyObject *value)
if (!PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) { if (!PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) {
std::string error = std::string("type in list must be 'DocumentObject', not "); std::string error = std::string("type in list must be 'DocumentObject', not ");
error += (*item)->ob_type->tp_name; error += (*item)->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
values[i] = static_cast<DocumentObjectPy*>(*item)->getDocumentObjectPtr(); values[i] = static_cast<DocumentObjectPy*>(*item)->getDocumentObjectPtr();
@ -424,7 +424,7 @@ void PropertyLinkList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not "); std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -609,7 +609,7 @@ void PropertyLinkSubList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not "); std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }

View File

@ -108,7 +108,7 @@ std::string PropertyPythonObject::toString() const
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Warning("PropertyPythonObject::toString: %s\n", e.what()); e.ReportException();
} }
return repr; return repr;
@ -139,7 +139,7 @@ void PropertyPythonObject::fromString(const std::string& repr)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Warning("PropertyPythonObject::fromString: %s\n", e.what()); e.ReportException();
} }
} }
@ -165,7 +165,7 @@ void PropertyPythonObject::loadPickle(const std::string& str)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Warning("PropertyPythonObject::loadPickle: %s\n", e.what()); e.ReportException();
} }
} }
@ -283,7 +283,7 @@ void PropertyPythonObject::Save (Base::Writer &writer) const
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Warning("PropertyPythonObject::Save: %s\n", e.what()); e.ReportException();
} }
saveObject(writer); saveObject(writer);
@ -350,7 +350,7 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader)
} }
catch (Py::Exception&) { catch (Py::Exception&) {
Base::PyException e; // extract the Python error text Base::PyException e; // extract the Python error text
Base::Console().Warning("PropertyPythonObject::Restore: %s\n", e.what()); e.ReportException();
this->object = Py::None(); this->object = Py::None();
load_failed = true; load_failed = true;
} }

View File

@ -98,7 +98,7 @@ void PropertyInteger::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be int, not "); std::string error = std::string("type must be int, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -211,7 +211,7 @@ void PropertyPath::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be str or unicode, not "); std::string error = std::string("type must be str or unicode, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
// assign the path // assign the path
@ -472,7 +472,7 @@ void PropertyEnumeration::setPyObject(PyObject *value)
long i=0; long i=0;
while(*(plEnums++) != NULL)i++; while(*(plEnums++) != NULL)i++;
if (val < 0 || i <= val) if (val < 0 || i <= val)
throw Py::ValueError("Out of range"); throw Base::ValueError("Out of range");
PropertyInteger::setValue(val); PropertyInteger::setValue(val);
} }
} }
@ -481,7 +481,7 @@ void PropertyEnumeration::setPyObject(PyObject *value)
if (_EnumArray && isPartOf(str)) if (_EnumArray && isPartOf(str))
setValue(PyString_AsString (value)); setValue(PyString_AsString (value));
else else
throw Py::ValueError("not part of the enum"); throw Base::ValueError("not part of the enum");
} }
else if (PyList_Check(value)) { else if (PyList_Check(value)) {
Py_ssize_t nSize = PyList_Size(value); Py_ssize_t nSize = PyList_Size(value);
@ -493,7 +493,7 @@ void PropertyEnumeration::setPyObject(PyObject *value)
if (!PyString_Check(item)) { if (!PyString_Check(item)) {
std::string error = std::string("type in list must be str, not "); std::string error = std::string("type in list must be str, not ");
error += item->ob_type->tp_name; error += item->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
values[i] = PyString_AsString(item); values[i] = PyString_AsString(item);
} }
@ -505,10 +505,33 @@ void PropertyEnumeration::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be int or str, not "); std::string error = std::string("type must be int or str, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
Property *PropertyEnumeration::Copy(void) const
{
PropertyEnumeration *p= new PropertyEnumeration();
p->_lValue = _lValue;
if (_CustomEnum) {
p->_CustomEnum = true;
p->setEnumVector(getEnumVector());
}
return p;
}
void PropertyEnumeration::Paste(const Property &from)
{
aboutToSetValue();
const PropertyEnumeration& prop = dynamic_cast<const PropertyEnumeration&>(from);
_lValue = prop._lValue;
if (prop._CustomEnum) {
this->_CustomEnum = true;
this->setEnumVector(prop.getEnumVector());
}
hasSetValue();
}
//************************************************************************** //**************************************************************************
//************************************************************************** //**************************************************************************
// PropertyIntegerConstraint // PropertyIntegerConstraint
@ -559,7 +582,7 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be int, not "); std::string error = std::string("type must be int, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -654,7 +677,7 @@ void PropertyIntegerList::setPyObject(PyObject *value)
if (!PyInt_Check(item)) { if (!PyInt_Check(item)) {
std::string error = std::string("type in list must be int, not "); std::string error = std::string("type in list must be int, not ");
error += item->ob_type->tp_name; error += item->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
values[i] = PyInt_AsLong(item); values[i] = PyInt_AsLong(item);
} }
@ -667,7 +690,7 @@ void PropertyIntegerList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be int or list of int, not "); std::string error = std::string("type must be int or list of int, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -782,7 +805,7 @@ void PropertyIntegerSet::setPyObject(PyObject *value)
if (!PyInt_Check(item)) { if (!PyInt_Check(item)) {
std::string error = std::string("type in list must be int, not "); std::string error = std::string("type in list must be int, not ");
error += item->ob_type->tp_name; error += item->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
values.insert(PyInt_AsLong(item)); values.insert(PyInt_AsLong(item));
} }
@ -795,7 +818,7 @@ void PropertyIntegerSet::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be int or list of int, not "); std::string error = std::string("type must be int or list of int, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -822,7 +845,7 @@ void PropertyIntegerSet::Restore(Base::XMLReader &reader)
values.insert(reader.getAttributeAsInteger("v")); values.insert(reader.getAttributeAsInteger("v"));
} }
reader.readEndElement("IntegerList"); reader.readEndElement("IntegerSet");
//assignment //assignment
setValues(values); setValues(values);
@ -905,7 +928,7 @@ void PropertyFloat::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be float or int, not "); std::string error = std::string("type must be float or int, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -999,7 +1022,7 @@ void PropertyFloatConstraint::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be float, not "); std::string error = std::string("type must be float, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -1072,7 +1095,7 @@ void PropertyFloatList::setPyObject(PyObject *value)
if (!PyFloat_Check(item)) { if (!PyFloat_Check(item)) {
std::string error = std::string("type in list must be float, not "); std::string error = std::string("type in list must be float, not ");
error += item->ob_type->tp_name; error += item->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
values[i] = (float) PyFloat_AsDouble(item); values[i] = (float) PyFloat_AsDouble(item);
@ -1086,7 +1109,7 @@ void PropertyFloatList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be float or list of float, not "); std::string error = std::string("type must be float or list of float, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -1217,7 +1240,7 @@ void PropertyString::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be str or unicode, not "); std::string error = std::string("type must be str or unicode, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
// assign the string // assign the string
@ -1322,11 +1345,18 @@ void PropertyUUID::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be a str, not "); std::string error = std::string("type must be a str, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
// assign the string try {
setValue(string); // assign the string
Base::Uuid uid;
uid.setValue(string);
setValue(uid);
}
catch (const std::exception& e) {
throw Base::RuntimeError(e.what());
}
} }
void PropertyUUID::Save (Base::Writer &writer) const void PropertyUUID::Save (Base::Writer &writer) const
@ -1465,7 +1495,7 @@ void PropertyStringList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type in list must be str or unicode, not "); std::string error = std::string("type in list must be str or unicode, not ");
error += item->ob_type->tp_name; error += item->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -1477,7 +1507,7 @@ void PropertyStringList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be str or list of str, not "); std::string error = std::string("type must be str or list of str, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -1625,7 +1655,7 @@ void PropertyMap::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type of the key need to be a string, not"); std::string error = std::string("type of the key need to be a string, not");
error += key->ob_type->tp_name; error += key->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
// check on the item: // check on the item:
@ -1641,7 +1671,7 @@ void PropertyMap::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type in list must be string or unicode, not "); std::string error = std::string("type in list must be string or unicode, not ");
error += item->ob_type->tp_name; error += item->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -1650,7 +1680,7 @@ void PropertyMap::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be a dict object"); std::string error = std::string("type must be a dict object");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -1764,7 +1794,7 @@ void PropertyBool::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be bool, not "); std::string error = std::string("type must be bool, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -1876,17 +1906,17 @@ void PropertyColor::setPyObject(PyObject *value)
if (PyFloat_Check(item)) if (PyFloat_Check(item))
cCol.r = (float)PyFloat_AsDouble(item); cCol.r = (float)PyFloat_AsDouble(item);
else else
throw Base::Exception("Type in tuple must be float"); throw Base::TypeError("Type in tuple must be float");
item = PyTuple_GetItem(value,1); item = PyTuple_GetItem(value,1);
if (PyFloat_Check(item)) if (PyFloat_Check(item))
cCol.g = (float)PyFloat_AsDouble(item); cCol.g = (float)PyFloat_AsDouble(item);
else else
throw Base::Exception("Type in tuple must be float"); throw Base::TypeError("Type in tuple must be float");
item = PyTuple_GetItem(value,2); item = PyTuple_GetItem(value,2);
if (PyFloat_Check(item)) if (PyFloat_Check(item))
cCol.b = (float)PyFloat_AsDouble(item); cCol.b = (float)PyFloat_AsDouble(item);
else else
throw Base::Exception("Type in tuple must be float"); throw Base::TypeError("Type in tuple must be float");
} }
else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) { else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) {
PyObject* item; PyObject* item;
@ -1894,22 +1924,22 @@ void PropertyColor::setPyObject(PyObject *value)
if (PyFloat_Check(item)) if (PyFloat_Check(item))
cCol.r = (float)PyFloat_AsDouble(item); cCol.r = (float)PyFloat_AsDouble(item);
else else
throw Base::Exception("Type in tuple must be float"); throw Base::TypeError("Type in tuple must be float");
item = PyTuple_GetItem(value,1); item = PyTuple_GetItem(value,1);
if (PyFloat_Check(item)) if (PyFloat_Check(item))
cCol.g = (float)PyFloat_AsDouble(item); cCol.g = (float)PyFloat_AsDouble(item);
else else
throw Base::Exception("Type in tuple must be float"); throw Base::TypeError("Type in tuple must be float");
item = PyTuple_GetItem(value,2); item = PyTuple_GetItem(value,2);
if (PyFloat_Check(item)) if (PyFloat_Check(item))
cCol.b = (float)PyFloat_AsDouble(item); cCol.b = (float)PyFloat_AsDouble(item);
else else
throw Base::Exception("Type in tuple must be float"); throw Base::TypeError("Type in tuple must be float");
item = PyTuple_GetItem(value,3); item = PyTuple_GetItem(value,3);
if (PyFloat_Check(item)) if (PyFloat_Check(item))
cCol.a = (float)PyFloat_AsDouble(item); cCol.a = (float)PyFloat_AsDouble(item);
else else
throw Base::Exception("Type in tuple must be float"); throw Base::TypeError("Type in tuple must be float");
} }
else if (PyLong_Check(value)) { else if (PyLong_Check(value)) {
cCol.setPackedValue(PyLong_AsUnsignedLong(value)); cCol.setPackedValue(PyLong_AsUnsignedLong(value));
@ -1917,7 +1947,7 @@ void PropertyColor::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be int or tuple of float, not "); std::string error = std::string("type must be int or tuple of float, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
setValue( cCol ); setValue( cCol );
@ -2050,7 +2080,7 @@ void PropertyColorList::setPyObject(PyObject *value)
else { else {
std::string error = std::string("not allowed type, "); std::string error = std::string("not allowed type, ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }
@ -2201,7 +2231,7 @@ void PropertyMaterial::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be 'Material', not "); std::string error = std::string("type must be 'Material', not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
} }

View File

@ -183,6 +183,9 @@ public:
virtual void Save (Base::Writer &writer) const; virtual void Save (Base::Writer &writer) const;
virtual void Restore(Base::XMLReader &reader); virtual void Restore(Base::XMLReader &reader);
virtual Property *Copy(void) const;
virtual void Paste(const Property &from);
private: private:
bool _CustomEnum; bool _CustomEnum;
const char** _EnumArray; const char** _EnumArray;

View File

@ -102,11 +102,11 @@ void PropertyLength::setPyObject(PyObject *value)
else { else {
std::string error = std::string("type must be float or int, not "); std::string error = std::string("type must be float or int, not ");
error += value->ob_type->tp_name; error += value->ob_type->tp_name;
throw Py::TypeError(error); throw Base::TypeError(error);
} }
if (val < 0.0f) if (val < 0.0f)
throw Py::ValueError("value must be nonnegative"); throw Base::ValueError("value must be nonnegative");
setValue(val); setValue(val);
#endif #endif

View File

@ -24,11 +24,11 @@
<UserDocu>Returns all descentences</UserDocu> <UserDocu>Returns all descentences</UserDocu>
</Documentation> </Documentation>
</Methode> </Methode>
<Attribute Name="Type" ReadOnly="true"> <Attribute Name="TypeId" ReadOnly="true">
<Documentation> <Documentation>
<UserDocu>Is the type of the FreeCAD object with module domain</UserDocu> <UserDocu>Is the type of the FreeCAD object with module domain</UserDocu>
</Documentation> </Documentation>
<Parameter Name="Type" Type="String" /> <Parameter Name="TypeId" Type="String" />
</Attribute> </Attribute>
<Attribute Name="Module" ReadOnly="true"> <Attribute Name="Module" ReadOnly="true">
<Documentation> <Documentation>

View File

@ -68,7 +68,7 @@ PyObject* BaseClassPy::getAllDerivedFrom(PyObject *args)
return Py::new_reference_to(res); return Py::new_reference_to(res);
} }
Py::String BaseClassPy::getType(void) const Py::String BaseClassPy::getTypeId(void) const
{ {
return Py::String(std::string(getBaseClassPtr()->getTypeId().getName())); return Py::String(std::string(getBaseClassPtr()->getTypeId().getName()));
} }
@ -78,8 +78,15 @@ Py::Int BaseClassPy::getModule(void) const
return Py::Int(); return Py::Int();
} }
PyObject *BaseClassPy::getCustomAttributes(const char* /*attr*/) const PyObject *BaseClassPy::getCustomAttributes(const char* attr) const
{ {
// this attribute is marked 'deprecated' but to keep old code working we
// handle it here. In a future version this will be removed.
if (strcmp(attr, "Type") == 0) {
PyErr_SetString(PyExc_DeprecationWarning, "Use 'TypeId' instead");
PyErr_Print();
return Py::new_reference_to(Py::String(std::string(getBaseClassPtr()->getTypeId().getName())));
}
return 0; return 0;
} }

View File

@ -236,6 +236,74 @@ ProgramInformation::ProgramInformation(const ProgramInformation &inst)
// --------------------------------------------------------- // ---------------------------------------------------------
TypeError::TypeError(const char * sMessage)
: Exception(sMessage)
{
}
TypeError::TypeError(const std::string& sMessage)
: Exception(sMessage)
{
}
TypeError::TypeError(const TypeError &inst)
: Exception(inst)
{
}
// ---------------------------------------------------------
ValueError::ValueError(const char * sMessage)
: Exception(sMessage)
{
}
ValueError::ValueError(const std::string& sMessage)
: Exception(sMessage)
{
}
ValueError::ValueError(const ValueError &inst)
: Exception(inst)
{
}
// ---------------------------------------------------------
AttributeError::AttributeError(const char * sMessage)
: Exception(sMessage)
{
}
AttributeError::AttributeError(const std::string& sMessage)
: Exception(sMessage)
{
}
AttributeError::AttributeError(const AttributeError &inst)
: Exception(inst)
{
}
// ---------------------------------------------------------
RuntimeError::RuntimeError(const char * sMessage)
: Exception(sMessage)
{
}
RuntimeError::RuntimeError(const std::string& sMessage)
: Exception(sMessage)
{
}
RuntimeError::RuntimeError(const RuntimeError &inst)
: Exception(inst)
{
}
// ---------------------------------------------------------
#if defined(__GNUC__) && defined (FC_OS_LINUX) #if defined(__GNUC__) && defined (FC_OS_LINUX)
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>

View File

@ -48,7 +48,7 @@ public:
Exception &operator=(const Exception &inst); Exception &operator=(const Exception &inst);
virtual const char* what(void) const throw(); virtual const char* what(void) const throw();
void ReportException (void) const; virtual void ReportException (void) const;
inline void setMessage(const char * sMessage); inline void setMessage(const char * sMessage);
inline void setMessage(const std::string& sMessage); inline void setMessage(const std::string& sMessage);
@ -206,6 +206,70 @@ public:
virtual ~ProgramInformation() throw() {} virtual ~ProgramInformation() throw() {}
}; };
/**
* The TypeError can be used to indicate the usage of a wrong type.
* @author Werner Mayer
*/
class BaseExport TypeError : public Exception
{
public:
/// Construction
TypeError(const char * sMessage);
TypeError(const std::string& sMessage);
/// Construction
TypeError(const TypeError &inst);
/// Destruction
virtual ~TypeError() throw() {}
};
/**
* The ValueError can be used to indicate the usage of a wrong value.
* @author Werner Mayer
*/
class BaseExport ValueError : public Exception
{
public:
/// Construction
ValueError(const char * sMessage);
ValueError(const std::string& sMessage);
/// Construction
ValueError(const ValueError &inst);
/// Destruction
virtual ~ValueError() throw() {}
};
/**
* The AttributeError can be used to indicate the usage of a wrong value.
* @author Werner Mayer
*/
class BaseExport AttributeError : public Exception
{
public:
/// Construction
AttributeError(const char * sMessage);
AttributeError(const std::string& sMessage);
/// Construction
AttributeError(const AttributeError &inst);
/// Destruction
virtual ~AttributeError() throw() {}
};
/**
* The RuntimeError can be used to indicate an unknown exception at runtime.
* @author Werner Mayer
*/
class BaseExport RuntimeError : public Exception
{
public:
/// Construction
RuntimeError(const char * sMessage);
RuntimeError(const std::string& sMessage);
/// Construction
RuntimeError(const RuntimeError &inst);
/// Destruction
virtual ~RuntimeError() throw() {}
};
inline void Exception::setMessage(const char * sMessage) inline void Exception::setMessage(const char * sMessage)
{ {

View File

@ -26,6 +26,7 @@
#include "PreCompiled.h" #include "PreCompiled.h"
#ifndef _PreComp_ #ifndef _PreComp_
# include <algorithm>
# include <cassert> # include <cassert>
# include <cstdio> # include <cstdio>
# include <cstdlib> # include <cstdlib>
@ -51,10 +52,20 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <cstdio> #include <cstdio>
#define new DEBUG_CLIENTBLOCK
using namespace Base; using namespace Base;
#ifndef R_OK
#define R_OK 4 /* Test for read permission */
#endif
#ifndef W_OK
#define W_OK 2 /* Test for write permission */
#endif
#ifndef X_OK
#define X_OK 1 /* Test for execute permission */
#endif
#ifndef F_OK
#define F_OK 0 /* Test for existence */
#endif
//********************************************************************************** //**********************************************************************************
// helper // helper
@ -188,22 +199,13 @@ std::string FileInfo::getTempFileName(const char* FileName, const char* Path)
void FileInfo::setFile(const char* name) void FileInfo::setFile(const char* name)
{ {
std::string result; if (!name) {
const char *It=name; FileName.clear();
return;
while(*It != '\0') {
switch(*It)
{
case '\\':
result += "/";
break;
default:
result += *It;
}
It++;
} }
FileName = result; FileName = name;
std::replace(FileName.begin(), FileName.end(), '\\', '/');
} }
std::string FileInfo::filePath () const std::string FileInfo::filePath () const
@ -271,9 +273,9 @@ bool FileInfo::exists () const
{ {
#if defined (FC_OS_WIN32) #if defined (FC_OS_WIN32)
std::wstring wstr = toStdWString(); std::wstring wstr = toStdWString();
return _waccess(wstr.c_str(),0) == 0; return _waccess(wstr.c_str(),F_OK) == 0;
#elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD) #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
return access(FileName.c_str(),0) == 0; return access(FileName.c_str(),F_OK) == 0;
#endif #endif
} }
@ -281,9 +283,9 @@ bool FileInfo::isReadable () const
{ {
#if defined (FC_OS_WIN32) #if defined (FC_OS_WIN32)
std::wstring wstr = toStdWString(); std::wstring wstr = toStdWString();
return _waccess(wstr.c_str(),4) == 0; return _waccess(wstr.c_str(),R_OK) == 0;
#elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD) #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
return access(FileName.c_str(),4) == 0; return access(FileName.c_str(),R_OK) == 0;
#endif #endif
} }
@ -291,9 +293,29 @@ bool FileInfo::isWritable () const
{ {
#if defined (FC_OS_WIN32) #if defined (FC_OS_WIN32)
std::wstring wstr = toStdWString(); std::wstring wstr = toStdWString();
return _waccess(wstr.c_str(),2) == 0; return _waccess(wstr.c_str(),W_OK) == 0;
#elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD) #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
return access(FileName.c_str(),2) == 0; return access(FileName.c_str(),W_OK) == 0;
#endif
}
bool FileInfo::setPermissions (Permissions perms)
{
bool ret = false;
int mode = 0;
if (perms & FileInfo::ReadOnly)
mode |= S_IREAD;
if (perms & FileInfo::WriteOnly)
mode |= S_IWRITE;
if (mode == 0) // bad argument
return false;
#if defined (FC_OS_WIN32)
std::wstring wstr = toStdWString();
return _wchmod(wstr.c_str(),mode) == 0;
#elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
return chmod(FileName.c_str(),mode) == 0;
#endif #endif
} }
@ -428,7 +450,6 @@ bool FileInfo::renameFile(const char* NewName)
#else #else
# error "FileInfo::renameFile() not implemented for this platform!" # error "FileInfo::renameFile() not implemented for this platform!"
#endif #endif
setFile(NewName);
return res; return res;
} }
@ -482,12 +503,17 @@ bool FileInfo::deleteDirectoryRecursive(void) const
std::vector<Base::FileInfo> List = getDirectoryContent(); std::vector<Base::FileInfo> List = getDirectoryContent();
for (std::vector<Base::FileInfo>::iterator It = List.begin();It!=List.end();++It) { for (std::vector<Base::FileInfo>::iterator It = List.begin();It!=List.end();++It) {
if (It->isDir()) if (It->isDir()) {
It->setPermissions(FileInfo::ReadWrite);
It->deleteDirectoryRecursive(); It->deleteDirectoryRecursive();
else if(It->isFile()) }
else if (It->isFile()) {
It->setPermissions(FileInfo::ReadWrite);
It->deleteFile(); It->deleteFile();
else }
else {
Base::Exception("FileInfo::deleteDirectoryRecursive(): Unknown object Type in directory!"); Base::Exception("FileInfo::deleteDirectoryRecursive(): Unknown object Type in directory!");
}
} }
return deleteDirectory(); return deleteDirectory();
} }

View File

@ -42,6 +42,12 @@ namespace Base
class BaseExport FileInfo class BaseExport FileInfo
{ {
public: public:
enum Permissions {
WriteOnly = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x03,
};
/// Constrction /// Constrction
FileInfo (const char* _FileName=""); FileInfo (const char* _FileName="");
FileInfo (const std::string &_FileName); FileInfo (const std::string &_FileName);
@ -89,6 +95,8 @@ public:
bool isReadable () const; bool isReadable () const;
/// Checks if the file exist and is writable /// Checks if the file exist and is writable
bool isWritable () const; bool isWritable () const;
/// Tries to set the file permisson
bool setPermissions (Permissions);
/// Checks if it is a file (not a direrctory) /// Checks if it is a file (not a direrctory)
bool isFile () const; bool isFile () const;
/// Checks if it is a directory (not a file) /// Checks if it is a directory (not a file)
@ -109,7 +117,7 @@ public:
std::vector<Base::FileInfo> getDirectoryContent(void) const; std::vector<Base::FileInfo> getDirectoryContent(void) const;
/// Delete an empty directory /// Delete an empty directory
bool deleteDirectory(void) const; bool deleteDirectory(void) const;
/// Delete a directory and all its content /// Delete a directory and all its content.
bool deleteDirectoryRecursive(void) const; bool deleteDirectoryRecursive(void) const;
//@} //@}

View File

@ -71,9 +71,18 @@ PyException::PyException(void)
_stackTrace = PP_last_error_trace; /* exception traceback text */ _stackTrace = PP_last_error_trace; /* exception traceback text */
}
PyException::~PyException() throw()
{
PyGILStateLocker locker;
PyErr_Clear(); // must be called to keep Python interpreter in a valid state (Werner) PyErr_Clear(); // must be called to keep Python interpreter in a valid state (Werner)
}
void PyException::ReportException (void) const
{
Base::Console().Error("%s%s: %s\n",
_stackTrace.c_str(), _errorType.c_str(), what());
} }
// --------------------------------------------------------- // ---------------------------------------------------------

View File

@ -54,11 +54,12 @@ class BaseExport PyException : public Exception
public: public:
/// constructor does the whole job /// constructor does the whole job
PyException(void); PyException(void);
~PyException() throw() {} ~PyException() throw();
/// this function returns the stack trace /// this function returns the stack trace
const std::string &getStackTrace(void) const {return _stackTrace;} const std::string &getStackTrace(void) const {return _stackTrace;}
const std::string &getErrorType(void) const {return _errorType;} const std::string &getErrorType(void) const {return _errorType;}
void ReportException (void) const;
protected: protected:
std::string _stackTrace; std::string _stackTrace;

View File

@ -38,9 +38,16 @@ using namespace Base;
std::string RotationPy::representation(void) const std::string RotationPy::representation(void) const
{ {
RotationPy::PointerType ptr = reinterpret_cast<RotationPy::PointerType>(_pcTwinPointer); RotationPy::PointerType ptr = reinterpret_cast<RotationPy::PointerType>(_pcTwinPointer);
Py::Float q0(ptr->getValue()[0]);
Py::Float q1(ptr->getValue()[1]);
Py::Float q2(ptr->getValue()[2]);
Py::Float q3(ptr->getValue()[3]);
std::stringstream str; std::stringstream str;
str << "Quaternion ("; str << "Rotation (";
str << ptr->getValue()[0] << ","<< ptr->getValue()[1] << "," << ptr->getValue()[2] << "," << ptr->getValue()[3]; str << (std::string)q0.repr() << ", "
<< (std::string)q1.repr() << ", "
<< (std::string)q2.repr() << ", "
<< (std::string)q3.repr();
str << ")"; str << ")";
return str.str(); return str.str();

View File

@ -40,9 +40,12 @@ using namespace Base;
std::string VectorPy::representation(void) const std::string VectorPy::representation(void) const
{ {
VectorPy::PointerType ptr = reinterpret_cast<VectorPy::PointerType>(_pcTwinPointer); VectorPy::PointerType ptr = reinterpret_cast<VectorPy::PointerType>(_pcTwinPointer);
Py::Float x(ptr->x);
Py::Float y(ptr->y);
Py::Float z(ptr->z);
std::stringstream str; std::stringstream str;
str << "Vector ("; str << "Vector (";
str << ptr->x << ", "<< ptr->y << ", "<< ptr->z; str << (std::string)x.repr() << ", "<< (std::string)y.repr() << ", "<< (std::string)z.repr();
str << ")"; str << ")";
return str.str(); return str.str();

View File

@ -1,7 +1,7 @@
// Version Number // Version Number
#define FCVersionMajor "0" #define FCVersionMajor "0"
#define FCVersionMinor "13" #define FCVersionMinor "14"
#define FCVersionName "Vulcan" #define FCVersionName "Vulcan"
// test: $Format:Hash (%H), Date: %ci$ // test: $Format:Hash (%H), Date: %ci$
#define FCRevision "$WCREV$" //Highest committed revision number #define FCRevision "$WCREV$" //Highest committed revision number

View File

@ -41,8 +41,11 @@
# include <QGLFramebufferObject> # include <QGLFramebufferObject>
#endif #endif
# include <QSessionManager> # include <QSessionManager>
# include <QTextStream>
#endif #endif
#include <boost/interprocess/sync/file_lock.hpp>
// FreeCAD Base header // FreeCAD Base header
#include <Base/Console.h> #include <Base/Console.h>
@ -336,6 +339,18 @@ Application::Application(bool GUIenabled)
("User parameter:BaseApp/Preferences/Units"); ("User parameter:BaseApp/Preferences/Units");
Base::UnitsApi::setDecimals(hUnits->GetInt("Decimals", Base::UnitsApi::getDecimals())); Base::UnitsApi::setDecimals(hUnits->GetInt("Decimals", Base::UnitsApi::getDecimals()));
// Check for the symbols for group separator and deciaml point. They must be different otherwise
// Qt doesn't work properly.
#if defined(Q_OS_WIN32)
if (QLocale::system().groupSeparator() == QLocale::system().decimalPoint()) {
QMessageBox::critical(0, QLatin1String("Invalid system settings"),
QLatin1String("Your system uses the same symbol for decimal point and group separator.\n\n"
"This causes serious problems and makes the application fail to work properly.\n"
"Go to the system configuration panel of the OS and fix this issue, please."));
throw Base::Exception("Invalid system settings");
}
#endif
// setting up Python binding // setting up Python binding
Base::PyGILStateLocker lock; Base::PyGILStateLocker lock;
PyObject* module = Py_InitModule3("FreeCADGui", Application::Methods, PyObject* module = Py_InitModule3("FreeCADGui", Application::Methods,
@ -1739,9 +1754,24 @@ void Application::runApplication(void)
Base::Console().Log("Init: Entering event loop\n"); Base::Console().Log("Init: Entering event loop\n");
try { try {
std::stringstream s;
s << Base::FileInfo::getTempPath() << App::GetApplication().getExecutableName()
<< "_" << QCoreApplication::applicationPid() << ".lock";
// open a lock file with the PID
Base::FileInfo fi(s.str());
Base::ofstream lock(fi);
boost::interprocess::file_lock flock(s.str().c_str());
flock.lock();
int ret = mainApp.exec(); int ret = mainApp.exec();
if (ret == systemExit) if (ret == systemExit)
throw Base::SystemExitException(); throw Base::SystemExitException();
// close the lock file, in case of a crash we can see the existing lock file
// on the next restart and try to repair the documents, if needed.
flock.unlock();
lock.close();
fi.deleteFile();
} }
catch (const Base::SystemExitException&) { catch (const Base::SystemExitException&) {
Base::Console().Message("System exit\n"); Base::Console().Message("System exit\n");
@ -1756,3 +1786,66 @@ void Application::runApplication(void)
Base::Console().Log("Finish: Event loop left\n"); Base::Console().Log("Finish: Event loop left\n");
} }
void Application::checkForPreviousCrashes()
{
QDir tmp = QDir::temp();
tmp.setNameFilters(QStringList() << QString::fromAscii("*.lock"));
tmp.setFilter(QDir::Files);
QList<QFileInfo> restoreDocFiles;
QString exeName = QString::fromAscii(App::GetApplication().getExecutableName());
QList<QFileInfo> locks = tmp.entryInfoList();
for (QList<QFileInfo>::iterator it = locks.begin(); it != locks.end(); ++it) {
QString bn = it->baseName();
// ignore the lock file for this instance
QString pid = QString::number(QCoreApplication::applicationPid());
if (bn.startsWith(exeName) && bn.indexOf(pid) < 0) {
QString fn = it->absoluteFilePath();
boost::interprocess::file_lock flock((const char*)fn.toLocal8Bit());
if (flock.try_lock()) {
// OK, this file is a leftover from a previous crash
QString crashed_pid = bn.mid(exeName.length()+1);
// search for transient directories with this PID
QString filter;
QTextStream str(&filter);
str << exeName << "_Doc_*_" << crashed_pid;
tmp.setNameFilters(QStringList() << filter);
tmp.setFilter(QDir::Dirs);
QList<QFileInfo> dirs = tmp.entryInfoList();
if (dirs.isEmpty()) {
// delete the lock file immediately if not transient directories are related
tmp.remove(fn);
}
else {
int countDeletedDocs = 0;
for (QList<QFileInfo>::iterator it = dirs.begin(); it != dirs.end(); ++it) {
QDir doc_dir(it->absoluteFilePath());
doc_dir.setFilter(QDir::NoDotAndDotDot|QDir::AllEntries);
uint entries = doc_dir.entryList().count();
if (entries == 0) {
// in this case we can delete the transient directory because
// we cannot do anything
if (tmp.rmdir(it->filePath()))
countDeletedDocs++;
}
else {
// store the transient directory in case it's not empty
restoreDocFiles << *it;
}
}
// all directories corresponding to the lock file have been deleted
// so delete the lock file, too
if (countDeletedDocs == dirs.size()) {
tmp.remove(fn);
}
}
}
}
}
if (!restoreDocFiles.isEmpty()) {
//TODO:
}
}

View File

@ -157,6 +157,7 @@ public:
/// true when the application shuting down /// true when the application shuting down
bool isClosing(void); bool isClosing(void);
void checkForPreviousCrashes();
/** @name workbench handling */ /** @name workbench handling */
//@{ //@{
@ -210,6 +211,7 @@ public:
PYFUNCDEF_S(sSendActiveView); PYFUNCDEF_S(sSendActiveView);
PYFUNCDEF_S(sGetMainWindow);
PYFUNCDEF_S(sUpdateGui); PYFUNCDEF_S(sUpdateGui);
PYFUNCDEF_S(sUpdateLocale); PYFUNCDEF_S(sUpdateLocale);
PYFUNCDEF_S(sGetLocale); PYFUNCDEF_S(sGetLocale);

View File

@ -83,6 +83,9 @@ PyMethodDef Application::Methods[] = {
{"addIcon", (PyCFunction) Application::sAddIcon, 1, {"addIcon", (PyCFunction) Application::sAddIcon, 1,
"addIcon(string, string or list) -> None\n\n" "addIcon(string, string or list) -> None\n\n"
"Add an icon as file name or in XPM format to the system"}, "Add an icon as file name or in XPM format to the system"},
{"getMainWindow", (PyCFunction) Application::sGetMainWindow, 1,
"getMainWindow() -> QMainWindow\n\n"
"Return the main window instance"},
{"updateGui", (PyCFunction) Application::sUpdateGui, 1, {"updateGui", (PyCFunction) Application::sUpdateGui, 1,
"updateGui() -> None\n\n" "updateGui() -> None\n\n"
"Update the main window and all its windows"}, "Update the main window and all its windows"},
@ -418,6 +421,22 @@ PyObject* Application::sSendActiveView(PyObject * /*self*/, PyObject *args,PyObj
return Py_None; return Py_None;
} }
PyObject* Application::sGetMainWindow(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
PythonWrapper wrap;
wrap.loadCoreModule();
wrap.loadGuiModule();
try {
return Py::new_reference_to(wrap.fromQWidget(Gui::getMainWindow(), "QMainWindow"));
}
catch (const Py::Exception&) {
return 0;
}
}
PyObject* Application::sUpdateGui(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) PyObject* Application::sUpdateGui(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
{ {
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C if (!PyArg_ParseTuple(args, "")) // convert args: Python->C

View File

@ -84,7 +84,7 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev)
// up the inheritance hierarchy. // up the inheritance hierarchy.
if (this->isSeekMode()) { return inherited::processSoEvent(ev); } if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
// Switch off viewing mode (Bug #0000911) // Switch off viewing mode (Bug #0000911)
if (!this->isSeekMode() && this->isViewing()) if (!this->isSeekMode() && !this->isAnimating() && this->isViewing())
this->setViewing(false); // by default disable viewing mode to render the scene this->setViewing(false); // by default disable viewing mode to render the scene
const SoType type(ev->getTypeId()); const SoType type(ev->getTypeId());

View File

@ -86,7 +86,7 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev)
if (this->isSeekMode()) { return inherited::processSoEvent(ev); } if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
#else #else
// Switch off viewing mode (Bug #0000911) // Switch off viewing mode (Bug #0000911)
if (!this->isSeekMode() && this->isViewing()) if (!this->isSeekMode() && !this->isAnimating() && this->isViewing())
this->setViewing(false); // by default disable viewing mode to render the scene this->setViewing(false); // by default disable viewing mode to render the scene
#endif #endif

View File

@ -3,6 +3,7 @@
if(WIN32) if(WIN32)
add_definitions(-DFCGui -DQIIS_MAKEDLL) add_definitions(-DFCGui -DQIIS_MAKEDLL)
endif(WIN32) endif(WIN32)
if (FREECAD_USE_3DCONNEXION) if (FREECAD_USE_3DCONNEXION)
add_definitions(-D_USE_3DCONNEXION_SDK) add_definitions(-D_USE_3DCONNEXION_SDK)
endif(FREECAD_USE_3DCONNEXION) endif(FREECAD_USE_3DCONNEXION)
@ -59,6 +60,30 @@ IF(SPNAV_FOUND)
) )
ENDIF(SPNAV_FOUND) ENDIF(SPNAV_FOUND)
if(SHIBOKEN_INCLUDE_DIR)
add_definitions(-DHAVE_SHIBOKEN)
include_directories(
${SHIBOKEN_INCLUDE_DIR}
)
set(FreeCADGui_LIBS
${FreeCADGui_LIBS}
${SHIBOKEN_LIBRARY}
)
endif(SHIBOKEN_INCLUDE_DIR)
if(PYSIDE_INCLUDE_DIR)
add_definitions(-DHAVE_PYSIDE)
include_directories(
${PYSIDE_INCLUDE_DIR}
${PYSIDE_INCLUDE_DIR}/QtCore
${PYSIDE_INCLUDE_DIR}/QtGui
)
set(FreeCADGui_LIBS
${FreeCADGui_LIBS}
${PYSIDE_LIBRARY}
)
endif(PYSIDE_INCLUDE_DIR)
generate_from_xml(DocumentPy) generate_from_xml(DocumentPy)
generate_from_xml(PythonWorkbenchPy) generate_from_xml(PythonWorkbenchPy)
generate_from_xml(ViewProviderPy) generate_from_xml(ViewProviderPy)
@ -97,8 +122,11 @@ set(Gui_MOC_HDRS
CallTips.h CallTips.h
CombiView.h CombiView.h
Control.h Control.h
Clipping.h
DemoMode.h DemoMode.h
DownloadDialog.h DownloadDialog.h
DownloadItem.h
DownloadManager.h
DlgActionsImp.h DlgActionsImp.h
DlgActivateWindowImp.h DlgActivateWindowImp.h
DlgCommandsImp.h DlgCommandsImp.h
@ -186,6 +214,7 @@ fc_wrap_cpp(Gui_MOC_SRCS ${Gui_MOC_HDRS})
SET(Gui_UIC_SRCS SET(Gui_UIC_SRCS
AboutApplication.ui AboutApplication.ui
Clipping.ui
DemoMode.ui DemoMode.ui
DlgActions.ui DlgActions.ui
DlgActivateWindow.ui DlgActivateWindow.ui
@ -220,6 +249,8 @@ SET(Gui_UIC_SRCS
DlgTreeWidget.ui DlgTreeWidget.ui
DlgLocationAngle.ui DlgLocationAngle.ui
DlgLocationPos.ui DlgLocationPos.ui
DownloadManager.ui
DownloadItem.ui
MouseButtons.ui MouseButtons.ui
SceneInspector.ui SceneInspector.ui
InputVector.ui InputVector.ui
@ -260,6 +291,7 @@ SOURCE_GROUP("Command" FILES ${Command_SRCS})
# The dialog sources # The dialog sources
SET(Dialog_CPP_SRCS SET(Dialog_CPP_SRCS
Clipping.cpp
DemoMode.cpp DemoMode.cpp
DlgActivateWindowImp.cpp DlgActivateWindowImp.cpp
DlgDisplayPropertiesImp.cpp DlgDisplayPropertiesImp.cpp
@ -282,9 +314,12 @@ SET(Dialog_CPP_SRCS
TextureMapping.cpp TextureMapping.cpp
Transform.cpp Transform.cpp
DownloadDialog.cpp DownloadDialog.cpp
DownloadItem.cpp
DownloadManager.cpp
) )
SET(Dialog_HPP_SRCS SET(Dialog_HPP_SRCS
Clipping.h
DemoMode.h DemoMode.h
DlgActivateWindowImp.h DlgActivateWindowImp.h
DlgDisplayPropertiesImp.h DlgDisplayPropertiesImp.h
@ -307,17 +342,22 @@ SET(Dialog_HPP_SRCS
TextureMapping.h TextureMapping.h
Transform.h Transform.h
DownloadDialog.h DownloadDialog.h
DownloadItem.h
DownloadManager.h
) )
SET(Dialog_SRCS SET(Dialog_SRCS
${Dialog_CPP_SRCS} ${Dialog_CPP_SRCS}
${Dialog_HPP_SRCS} ${Dialog_HPP_SRCS}
AboutApplication.ui AboutApplication.ui
Clipping.ui
DemoMode.ui DemoMode.ui
DlgActivateWindow.ui DlgActivateWindow.ui
DlgAuthorization.ui DlgAuthorization.ui
DlgDisplayProperties.ui DlgDisplayProperties.ui
DlgInputDialog.ui DlgInputDialog.ui
DlgLocationAngle.ui
DlgLocationPos.ui
DlgMacroExecute.ui DlgMacroExecute.ui
DlgRunExternal.ui DlgRunExternal.ui
DlgMacroRecord.ui DlgMacroRecord.ui
@ -327,6 +367,8 @@ SET(Dialog_SRCS
DlgProjectUtility.ui DlgProjectUtility.ui
DlgTipOfTheDay.ui DlgTipOfTheDay.ui
DlgTreeWidget.ui DlgTreeWidget.ui
DownloadManager.ui
DownloadItem.ui
MouseButtons.ui MouseButtons.ui
InputVector.ui InputVector.ui
Placement.ui Placement.ui
@ -884,7 +926,13 @@ else(WIN32)
INSTALL(TARGETS FreeCADGui INSTALL(TARGETS FreeCADGui
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
) )
INSTALL(FILES Icons/freecad.xpm Icons/freecad-doc.png INSTALL(FILES Icons/freecad.xpm
Icons/freecad-icon-16.png
Icons/freecad-icon-32.png
Icons/freecad-icon-48.png
Icons/freecad-icon-64.png
Icons/freecad.svg
Icons/freecad-doc.png
DESTINATION ${CMAKE_INSTALL_DATADIR} DESTINATION ${CMAKE_INSTALL_DATADIR}
) )
endif(WIN32) endif(WIN32)

315
src/Gui/Clipping.cpp Normal file
View File

@ -0,0 +1,315 @@
/***************************************************************************
* Copyright (c) 2013 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/actions/SoGetBoundingBoxAction.h>
# include <Inventor/nodes/SoClipPlane.h>
# include <Inventor/nodes/SoGroup.h>
# include <QPointer>
#endif
# include <Inventor/sensors/SoTimerSensor.h>
#include "Clipping.h"
#include "ui_Clipping.h"
#include "Application.h"
#include "View3DInventor.h"
#include "View3DInventorViewer.h"
using namespace Gui::Dialog;
class Clipping::Private {
public:
Ui_Clipping ui;
QPointer<Gui::View3DInventor> view;
SoGroup* node;
SoClipPlane* clipX;
SoClipPlane* clipY;
SoClipPlane* clipZ;
SoClipPlane* clipView;
bool flipX;
bool flipY;
bool flipZ;
SoTimerSensor* sensor;
Private() : flipX(false), flipY(false), flipZ(false)
{
clipX = new SoClipPlane();
clipX->on.setValue(false);
clipX->plane.setValue(SbPlane(SbVec3f(1,0,0),0));
clipX->ref();
clipY = new SoClipPlane();
clipY->on.setValue(false);
clipY->plane.setValue(SbPlane(SbVec3f(0,1,0),0));
clipY->ref();
clipZ = new SoClipPlane();
clipZ->on.setValue(false);
clipZ->plane.setValue(SbPlane(SbVec3f(0,0,1),0));
clipZ->ref();
clipView = new SoClipPlane();
clipView->on.setValue(false);
clipView->plane.setValue(SbPlane(SbVec3f(0,0,1),0));
clipView->ref();
sensor = new SoTimerSensor(moveCallback, this);
}
~Private()
{
clipX->unref();
clipY->unref();
clipZ->unref();
clipView->unref();
delete sensor;
}
static void moveCallback(void * data, SoSensor * sensor)
{
Private* self = reinterpret_cast<Private*>(data);
if (self->view) {
Gui::View3DInventorViewer* view = self->view->getViewer();
SoClipPlane* clip = self->clipView;
SbPlane pln = clip->plane.getValue();
clip->plane.setValue(SbPlane(view->getViewDirection(),pln.getDistanceFromOrigin()));
}
}
};
/* TRANSLATOR Gui::Dialog::Clipping */
Clipping::Clipping(Gui::View3DInventor* view, QWidget* parent)
: QWidget(parent), d(new Private)
{
// create widgets
d->ui.setupUi(this);
d->ui.clipView->setRange(-INT_MAX,INT_MAX);
d->ui.clipView->setSingleStep(0.1f);
d->ui.clipX->setRange(-INT_MAX,INT_MAX);
d->ui.clipX->setSingleStep(0.1f);
d->ui.clipY->setRange(-INT_MAX,INT_MAX);
d->ui.clipY->setSingleStep(0.1f);
d->ui.clipZ->setRange(-INT_MAX,INT_MAX);
d->ui.clipZ->setSingleStep(0.1f);
d->ui.dirX->setRange(-INT_MAX,INT_MAX);
d->ui.dirX->setSingleStep(0.1f);
d->ui.dirY->setRange(-INT_MAX,INT_MAX);
d->ui.dirY->setSingleStep(0.1f);
d->ui.dirZ->setRange(-INT_MAX,INT_MAX);
d->ui.dirZ->setSingleStep(0.1f);
d->ui.dirZ->setValue(1.0f);
d->view = view;
View3DInventorViewer* viewer = view->getViewer();
d->node = static_cast<SoGroup*>(viewer->getSceneGraph());
d->node->ref();
d->node->insertChild(d->clipX, 0);
d->node->insertChild(d->clipY, 0);
d->node->insertChild(d->clipZ, 0);
d->node->insertChild(d->clipView, 0);
SoGetBoundingBoxAction action(viewer->getViewportRegion());
action.apply(viewer->getSceneGraph());
SbBox3f box = action.getBoundingBox();
if (!box.isEmpty()) {
SbVec3f cnt = box.getCenter();
d->ui.clipView->setValue(cnt[2]);
d->ui.clipX->setValue(cnt[0]);
d->ui.clipY->setValue(cnt[1]);
d->ui.clipZ->setValue(cnt[2]);
}
}
/** Destroys the object and frees any allocated resources */
Clipping::~Clipping()
{
d->node->removeChild(d->clipX);
d->node->removeChild(d->clipY);
d->node->removeChild(d->clipZ);
d->node->removeChild(d->clipView);
d->node->unref();
delete d;
}
void Clipping::on_groupBoxX_toggled(bool on)
{
if (on) {
d->ui.groupBoxView->setChecked(false);
}
d->clipX->on.setValue(on);
}
void Clipping::on_groupBoxY_toggled(bool on)
{
if (on) {
d->ui.groupBoxView->setChecked(false);
}
d->clipY->on.setValue(on);
}
void Clipping::on_groupBoxZ_toggled(bool on)
{
if (on) {
d->ui.groupBoxView->setChecked(false);
}
d->clipZ->on.setValue(on);
}
void Clipping::on_clipX_valueChanged(double val)
{
SbPlane pln = d->clipX->plane.getValue();
d->clipX->plane.setValue(SbPlane(pln.getNormal(),d->flipX ? -val : val));
}
void Clipping::on_clipY_valueChanged(double val)
{
SbPlane pln = d->clipY->plane.getValue();
d->clipY->plane.setValue(SbPlane(pln.getNormal(),d->flipY ? -val : val));
}
void Clipping::on_clipZ_valueChanged(double val)
{
SbPlane pln = d->clipZ->plane.getValue();
d->clipZ->plane.setValue(SbPlane(pln.getNormal(),d->flipZ ? -val : val));
}
void Clipping::on_flipClipX_clicked()
{
d->flipX = !d->flipX;
SbPlane pln = d->clipX->plane.getValue();
d->clipX->plane.setValue(SbPlane(-pln.getNormal(),-pln.getDistanceFromOrigin()));
}
void Clipping::on_flipClipY_clicked()
{
d->flipY = !d->flipY;
SbPlane pln = d->clipY->plane.getValue();
d->clipY->plane.setValue(SbPlane(-pln.getNormal(),-pln.getDistanceFromOrigin()));
}
void Clipping::on_flipClipZ_clicked()
{
d->flipZ = !d->flipZ;
SbPlane pln = d->clipZ->plane.getValue();
d->clipZ->plane.setValue(SbPlane(-pln.getNormal(),-pln.getDistanceFromOrigin()));
}
void Clipping::on_groupBoxView_toggled(bool on)
{
if (on) {
d->ui.groupBoxX->setChecked(false);
d->ui.groupBoxY->setChecked(false);
d->ui.groupBoxZ->setChecked(false);
}
d->clipView->on.setValue(on);
}
void Clipping::on_clipView_valueChanged(double val)
{
SbPlane pln = d->clipView->plane.getValue();
d->clipView->plane.setValue(SbPlane(pln.getNormal(),val));
}
void Clipping::on_fromView_clicked()
{
if (d->view) {
Gui::View3DInventorViewer* view = d->view->getViewer();
SbVec3f dir = view->getViewDirection();
SbPlane pln = d->clipView->plane.getValue();
d->clipView->plane.setValue(SbPlane(dir,pln.getDistanceFromOrigin()));
}
}
void Clipping::on_adjustViewdirection_toggled(bool on)
{
d->ui.dirX->setDisabled(on);
d->ui.dirY->setDisabled(on);
d->ui.dirZ->setDisabled(on);
d->ui.fromView->setDisabled(on);
if (on)
d->sensor->schedule();
else
d->sensor->unschedule();
}
void Clipping::on_dirX_valueChanged(double)
{
double x = d->ui.dirX->value();
double y = d->ui.dirY->value();
double z = d->ui.dirZ->value();
SbPlane pln = d->clipView->plane.getValue();
SbVec3f normal(x,y,z);
if (normal.sqrLength() > 0.0f)
d->clipView->plane.setValue(SbPlane(normal,pln.getDistanceFromOrigin()));
}
void Clipping::on_dirY_valueChanged(double)
{
double x = d->ui.dirX->value();
double y = d->ui.dirY->value();
double z = d->ui.dirZ->value();
SbPlane pln = d->clipView->plane.getValue();
SbVec3f normal(x,y,z);
if (normal.sqrLength() > 0.0f)
d->clipView->plane.setValue(SbPlane(normal,pln.getDistanceFromOrigin()));
}
void Clipping::on_dirZ_valueChanged(double)
{
double x = d->ui.dirX->value();
double y = d->ui.dirY->value();
double z = d->ui.dirZ->value();
SbPlane pln = d->clipView->plane.getValue();
SbVec3f normal(x,y,z);
if (normal.sqrLength() > 0.0f)
d->clipView->plane.setValue(SbPlane(normal,pln.getDistanceFromOrigin()));
}
// ---------------------------------------
/* TRANSLATOR Gui::Dialog::TaskClipping */
TaskClipping::TaskClipping(Gui::View3DInventor* view)
{
QWidget* widget = new Clipping(view);
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
QPixmap(), widget->windowTitle(), false, 0);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
TaskClipping::~TaskClipping()
{
// automatically deleted in the sub-class
}
#include "moc_Clipping.cpp"

88
src/Gui/Clipping.h Normal file
View File

@ -0,0 +1,88 @@
/***************************************************************************
* Copyright (c) 2013 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 *
* *
***************************************************************************/
#ifndef GUI_DIALOG_CLIPPING_H
#define GUI_DIALOG_CLIPPING_H
#include <Gui/TaskView/TaskDialog.h>
#include <Gui/TaskView/TaskView.h>
#include <QWidget>
namespace Gui {
class View3DInventor;
namespace Dialog {
/**
* @author Werner Mayer
*/
class GuiExport Clipping : public QWidget
{
Q_OBJECT
public:
Clipping(Gui::View3DInventor* view, QWidget* parent = 0);
~Clipping();
protected Q_SLOTS:
void on_groupBoxX_toggled(bool);
void on_groupBoxY_toggled(bool);
void on_groupBoxZ_toggled(bool);
void on_clipX_valueChanged(double);
void on_clipY_valueChanged(double);
void on_clipZ_valueChanged(double);
void on_flipClipX_clicked();
void on_flipClipY_clicked();
void on_flipClipZ_clicked();
void on_groupBoxView_toggled(bool);
void on_clipView_valueChanged(double);
void on_fromView_clicked();
void on_adjustViewdirection_toggled(bool);
void on_dirX_valueChanged(double);
void on_dirY_valueChanged(double);
void on_dirZ_valueChanged(double);
private:
private:
class Private;
Private* d;
};
/**
* Embed the panel into a task dialog.
*/
class TaskClipping : public Gui::TaskView::TaskDialog
{
public:
TaskClipping(Gui::View3DInventor* view);
~TaskClipping();
public:
virtual QDialogButtonBox::StandardButtons getStandardButtons() const
{ return QDialogButtonBox::Close; }
};
} // namespace Dialog
} // namespace Gui
#endif // GUI_DIALOG_CLIPPING_H

244
src/Gui/Clipping.ui Normal file
View File

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Gui::Dialog::Clipping</class>
<widget class="QWidget" name="Gui::Dialog::Clipping">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>304</width>
<height>430</height>
</rect>
</property>
<property name="windowTitle">
<string>Clipping</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBoxX">
<property name="title">
<string>Clipping X</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="clipX"/>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="flipClipX">
<property name="text">
<string>Flip</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBoxY">
<property name="title">
<string>Clipping Y</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="clipY"/>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="flipClipY">
<property name="text">
<string>Flip</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBoxZ">
<property name="title">
<string>Clipping Z</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="clipZ"/>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="flipClipZ">
<property name="text">
<string>Flip</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="groupBoxView">
<property name="title">
<string>Clipping custom direction</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>84</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="fromView">
<property name="text">
<string>View</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="5">
<widget class="QCheckBox" name="adjustViewdirection">
<property name="text">
<string>Adjust to view direction</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="5">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Direction</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="dirX"/>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="dirY"/>
</item>
<item row="0" column="2">
<widget class="QDoubleSpinBox" name="dirZ"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QDoubleSpinBox" name="clipView"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>groupBoxX</tabstop>
<tabstop>clipX</tabstop>
<tabstop>flipClipX</tabstop>
<tabstop>groupBoxY</tabstop>
<tabstop>clipY</tabstop>
<tabstop>flipClipY</tabstop>
<tabstop>groupBoxZ</tabstop>
<tabstop>clipZ</tabstop>
<tabstop>flipClipZ</tabstop>
<tabstop>groupBoxView</tabstop>
<tabstop>clipView</tabstop>
<tabstop>fromView</tabstop>
<tabstop>adjustViewdirection</tabstop>
<tabstop>dirX</tabstop>
<tabstop>dirY</tabstop>
<tabstop>dirZ</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -581,6 +581,12 @@ void Command::applyCommandData(Action* action)
action->setWhatsThis(QCoreApplication::translate( action->setWhatsThis(QCoreApplication::translate(
this->className(), sToolTipText, 0, this->className(), sToolTipText, 0,
QCoreApplication::UnicodeUTF8)); QCoreApplication::UnicodeUTF8));
QString accel = action->shortcut().toString();
if (!accel.isEmpty()) {
QString tip = QString::fromAscii("(%1)\t%2")
.arg(accel).arg(action->statusTip());
action->setStatusTip(tip);
}
} }
const char* Command::keySequenceToAccel(int sk) const const char* Command::keySequenceToAccel(int sk) const

View File

@ -841,7 +841,6 @@ void StdCmdCopy::activated(int iMsg)
{ {
bool done = getGuiApplication()->sendMsgToActiveView("Copy"); bool done = getGuiApplication()->sendMsgToActiveView("Copy");
if (!done) { if (!done) {
WaitCursor wc;
QMimeData * mimeData = getMainWindow()->createMimeDataFromSelection(); QMimeData * mimeData = getMainWindow()->createMimeDataFromSelection();
QClipboard* cb = QApplication::clipboard(); QClipboard* cb = QApplication::clipboard();
cb->setMimeData(mimeData); cb->setMimeData(mimeData);
@ -910,59 +909,54 @@ StdCmdDuplicateSelection::StdCmdDuplicateSelection()
void StdCmdDuplicateSelection::activated(int iMsg) void StdCmdDuplicateSelection::activated(int iMsg)
{ {
App::Document* act = App::GetApplication().getActiveDocument(); std::vector<SelectionSingleton::SelObj> sel = Selection().getCompleteSelection();
if (!act) std::map< App::Document*, std::vector<App::DocumentObject*> > objs;
return; // no active document found
Gui::Document* doc = Gui::Application::Instance->getDocument(act);
std::vector<Gui::SelectionSingleton::SelObj> sel = Gui::Selection().getCompleteSelection();
for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) { for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
if (!it->pObject) if (it->pObject && it->pObject->getDocument()) {
continue; // should actually not happen objs[it->pObject->getDocument()].push_back(it->pObject);
// create a copy of the object
App::DocumentObject* copy = act->copyObject(it->pObject, false);
if (!copy) // continue if no copy could be created
continue;
// mark all properties of the copy as "touched" which are touched in the original object
std::map<std::string,App::Property*> props;
it->pObject->getPropertyMap(props);
std::map<std::string,App::Property*> copy_props;
copy->getPropertyMap(copy_props);
for (std::map<std::string,App::Property*>::iterator jt = props.begin(); jt != props.end(); ++jt) {
if (jt->second->isTouched()) {
std::map<std::string,App::Property*>::iterator kt;
kt = copy_props.find(jt->first);
if (kt != copy_props.end()) {
kt->second->touch();
}
}
}
Gui::Document* parent = Gui::Application::Instance->getDocument(it->pObject->getDocument());
if (!parent || !doc)
continue; // should not happen
// copy the properties of the associated view providers
Gui::ViewProvider* view = parent->getViewProvider(it->pObject);
Gui::ViewProvider* copy_view = doc->getViewProvider(copy);
copy_view->addDynamicProperties(view);
if (!view || !copy_view)
continue; // should not happen
// get the properties of the view provider
props.clear();
view->getPropertyMap(props);
copy_props.clear();
copy_view->getPropertyMap(copy_props);
for (std::map<std::string,App::Property*>::iterator jt = props.begin(); jt != props.end(); ++jt) {
std::map<std::string,App::Property*>::iterator kt;
kt = copy_props.find(jt->first);
if (kt != copy_props.end()) {
std::auto_ptr<App::Property> data(jt->second->Copy());
if (data.get()) {
kt->second->Paste(*data);
}
}
} }
} }
if (objs.empty())
return;
Base::FileInfo fi(Base::FileInfo::getTempFileName());
{
std::vector<App::DocumentObject*> sel; // selected
std::vector<App::DocumentObject*> all; // object sub-graph
for (std::map< App::Document*, std::vector<App::DocumentObject*> >::iterator it = objs.begin(); it != objs.end(); ++it) {
std::vector<App::DocumentObject*> dep = it->first->getDependencyList(it->second);
sel.insert(sel.end(), it->second.begin(), it->second.end());
all.insert(all.end(), dep.begin(), dep.end());
}
if (all.size() > sel.size()) {
int ret = QMessageBox::question(getMainWindow(),
qApp->translate("Std_DuplicateSelection","Object dependencies"),
qApp->translate("Std_DuplicateSelection","The selected objects have a dependency to unselected objects.\n"
"Do you want to duplicate them, too?"),
QMessageBox::Yes,QMessageBox::No);
if (ret == QMessageBox::Yes) {
sel = all;
}
}
// save stuff to file
Base::ofstream str(fi, std::ios::out | std::ios::binary);
App::Document* doc = sel.front()->getDocument();
MergeDocuments mimeView(doc);
doc->exportObjects(sel, str);
str.close();
}
App::Document* doc = App::GetApplication().getActiveDocument();
if (doc) {
// restore objects from file and add to active document
Base::ifstream str(fi, std::ios::in | std::ios::binary);
MergeDocuments mimeView(doc);
mimeView.importObjects(str);
str.close();
}
fi.deleteFile();
} }
bool StdCmdDuplicateSelection::isActive(void) bool StdCmdDuplicateSelection::isActive(void)
@ -1032,17 +1026,52 @@ void StdCmdDelete::activated(int iMsg)
Gui::Document* pGuiDoc = Gui::Application::Instance->getDocument(*it); Gui::Document* pGuiDoc = Gui::Application::Instance->getDocument(*it);
std::vector<Gui::SelectionObject> sel = rSel.getSelectionEx((*it)->getName()); std::vector<Gui::SelectionObject> sel = rSel.getSelectionEx((*it)->getName());
if (!sel.empty()) { if (!sel.empty()) {
(*it)->openTransaction("Delete"); bool doDeletion = true;
// check if we can delete the object
for (std::vector<Gui::SelectionObject>::iterator ft = sel.begin(); ft != sel.end(); ++ft) { for (std::vector<Gui::SelectionObject>::iterator ft = sel.begin(); ft != sel.end(); ++ft) {
App::DocumentObject* obj = ft->getObject();
Gui::ViewProvider* vp = pGuiDoc->getViewProvider(ft->getObject()); Gui::ViewProvider* vp = pGuiDoc->getViewProvider(ft->getObject());
if (vp) { // if the object is in edit mode we allow to continue because only sub-elements will be removed
// ask the ViewProvider if its want to do some clean up if (!vp || !vp->isEditing()) {
if (vp->onDelete(ft->getSubNames())) std::vector<App::DocumentObject*> links = obj->getInList();
doCommand(Doc,"App.getDocument(\"%s\").removeObject(\"%s\")" if (!links.empty()) {
,(*it)->getName(), ft->getFeatName()); // check if the referenced objects are groups or are selected too
for (std::vector<App::DocumentObject*>::iterator lt = links.begin(); lt != links.end(); ++lt) {
if (!(*lt)->getTypeId().isDerivedFrom(App::DocumentObjectGroup::getClassTypeId()) && !rSel.isSelected(*lt)) {
doDeletion = false;
break;
}
}
if (!doDeletion) {
break;
}
}
} }
} }
(*it)->commitTransaction();
if (!doDeletion) {
int ret = QMessageBox::question(Gui::getMainWindow(),
qApp->translate("Std_Delete", "Object dependencies"),
qApp->translate("Std_Delete", "This object is referenced by other objects and thus these objects might get broken.\n"
"Are you sure to continue?"),
QMessageBox::Yes, QMessageBox::No);
if (ret == QMessageBox::Yes)
doDeletion = true;
}
if (doDeletion) {
(*it)->openTransaction("Delete");
for (std::vector<Gui::SelectionObject>::iterator ft = sel.begin(); ft != sel.end(); ++ft) {
Gui::ViewProvider* vp = pGuiDoc->getViewProvider(ft->getObject());
if (vp) {
// ask the ViewProvider if it wants to do some clean up
if (vp->onDelete(ft->getSubNames()))
doCommand(Doc,"App.getDocument(\"%s\").removeObject(\"%s\")"
,(*it)->getName(), ft->getFeatName());
}
}
(*it)->commitTransaction();
}
} }
} }
} }

View File

@ -38,6 +38,7 @@
#include "Application.h" #include "Application.h"
#include "BitmapFactory.h" #include "BitmapFactory.h"
#include "Control.h" #include "Control.h"
#include "Clipping.h"
#include "FileDialog.h" #include "FileDialog.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "Tree.h" #include "Tree.h"
@ -49,6 +50,7 @@
#include "Selection.h" #include "Selection.h"
#include "SoFCOffscreenRenderer.h" #include "SoFCOffscreenRenderer.h"
#include "SoFCBoundingBox.h" #include "SoFCBoundingBox.h"
#include "SoFCUnifiedSelection.h"
#include "SoAxisCrossKit.h" #include "SoAxisCrossKit.h"
#include "View3DInventor.h" #include "View3DInventor.h"
#include "View3DInventorViewer.h" #include "View3DInventorViewer.h"
@ -473,12 +475,15 @@ StdCmdToggleClipPlane::StdCmdToggleClipPlane()
Action * StdCmdToggleClipPlane::createAction(void) Action * StdCmdToggleClipPlane::createAction(void)
{ {
Action *pcAction = (Action*)Command::createAction(); Action *pcAction = (Action*)Command::createAction();
#if 0
pcAction->setCheckable(true); pcAction->setCheckable(true);
#endif
return pcAction; return pcAction;
} }
void StdCmdToggleClipPlane::activated(int iMsg) void StdCmdToggleClipPlane::activated(int iMsg)
{ {
#if 0
View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow()); View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow());
if (view) { if (view) {
if (iMsg > 0 && !view->hasClippingPlane()) if (iMsg > 0 && !view->hasClippingPlane())
@ -486,10 +491,17 @@ void StdCmdToggleClipPlane::activated(int iMsg)
else if (iMsg == 0 && view->hasClippingPlane()) else if (iMsg == 0 && view->hasClippingPlane())
view->toggleClippingPlane(); view->toggleClippingPlane();
} }
#else
View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow());
if (view) {
Gui::Control().showDialog(new Gui::Dialog::TaskClipping(view));
}
#endif
} }
bool StdCmdToggleClipPlane::isActive(void) bool StdCmdToggleClipPlane::isActive(void)
{ {
#if 0
View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow()); View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow());
if (view) { if (view) {
Action* action = qobject_cast<Action*>(_pcAction); Action* action = qobject_cast<Action*>(_pcAction);
@ -503,6 +515,11 @@ bool StdCmdToggleClipPlane::isActive(void)
action->setChecked(false); action->setChecked(false);
return false; return false;
} }
#else
if (Gui::Control().activeDialog())
return false;
return true;
#endif
} }
DEF_STD_CMD_ACL(StdCmdDrawStyle); DEF_STD_CMD_ACL(StdCmdDrawStyle);
@ -1922,6 +1939,9 @@ static void selectionCallback(void * ud, SoEventCallback * cb)
{ {
Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(cb->getUserData()); Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(cb->getUserData());
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback, ud); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback, ud);
SoNode* root = view->getSceneGraph();
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(TRUE);
std::vector<SbVec2f> picked = view->getGLPolygon(); std::vector<SbVec2f> picked = view->getGLPolygon();
SoCamera* cam = view->getCamera(); SoCamera* cam = view->getCamera();
SbViewVolume vv = cam->getViewVolume(); SbViewVolume vv = cam->getViewVolume();
@ -1972,8 +1992,10 @@ void StdBoxSelection::activated(int iMsg)
if (view) { if (view) {
View3DInventorViewer* viewer = view->getViewer(); View3DInventorViewer* viewer = view->getViewer();
if (!viewer->isSelecting()) { if (!viewer->isSelecting()) {
viewer->startSelection(View3DInventorViewer::Rectangle); viewer->startSelection(View3DInventorViewer::Rubberband);
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback); viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback);
SoNode* root = viewer->getSceneGraph();
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(FALSE);
} }
} }
} }

View File

@ -26,6 +26,7 @@
# include <cmath> # include <cmath>
# include <float.h> # include <float.h>
# include <climits> # include <climits>
# include <QCursor>
# include <QTimer> # include <QTimer>
#include <Inventor/nodes/SoCamera.h> #include <Inventor/nodes/SoCamera.h>
#endif #endif
@ -53,6 +54,11 @@ DemoMode::DemoMode(QWidget* parent, Qt::WFlags fl)
timer->setInterval(1000 * ui->timeout->value()); timer->setInterval(1000 * ui->timeout->value());
connect(timer, SIGNAL(timeout()), this, SLOT(onAutoPlay())); connect(timer, SIGNAL(timeout()), this, SLOT(onAutoPlay()));
oldvalue = ui->angleSlider->value(); oldvalue = ui->angleSlider->value();
wasHidden = false;
showHideTimer = new QTimer(this);
showHideTimer->setInterval(5000);
connect(showHideTimer, SIGNAL(timeout()), this, SLOT(hide()));
} }
/** Destroys the object and frees any allocated resources */ /** Destroys the object and frees any allocated resources */
@ -82,6 +88,35 @@ void DemoMode::reject()
QDialog::reject(); QDialog::reject();
} }
bool DemoMode::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseMove) {
if (ui->fullscreen->isChecked()) {
QPoint point = QCursor::pos() - oldPos;
if (point.manhattanLength() > 5) {
show();
showHideTimer->start();
}
}
}
return QDialog::eventFilter(obj, event);
}
void DemoMode::showEvent(QShowEvent *)
{
if (this->wasHidden)
this->move(this->pnt);
this->wasHidden = false;
}
void DemoMode::hideEvent(QHideEvent *)
{
this->pnt = this->pos();
this->wasHidden = true;
this->oldPos = QCursor::pos();
showHideTimer->stop();
}
Gui::View3DInventor* DemoMode::activeView() const Gui::View3DInventor* DemoMode::activeView() const
{ {
Document* doc = Application::Instance->activeDocument(); Document* doc = Application::Instance->activeDocument();
@ -186,6 +221,14 @@ void DemoMode::on_fullscreen_toggled(bool on)
view->setCurrentViewMode(on ? MDIView::/*TopLevel*/FullScreen : MDIView::Child); view->setCurrentViewMode(on ? MDIView::/*TopLevel*/FullScreen : MDIView::Child);
this->activateWindow(); this->activateWindow();
} }
if (on) {
qApp->installEventFilter(this);
showHideTimer->start();
}
else {
qApp->removeEventFilter(this);
showHideTimer->stop();
}
} }
void DemoMode::on_timeout_valueChanged(int v) void DemoMode::on_timeout_valueChanged(int v)

View File

@ -68,12 +68,19 @@ private:
Gui::View3DInventor* activeView() const; Gui::View3DInventor* activeView() const;
void startAnimation(Gui::View3DInventor*); void startAnimation(Gui::View3DInventor*);
void changeEvent(QEvent *e); void changeEvent(QEvent *e);
bool eventFilter(QObject *, QEvent *);
void showEvent(QShowEvent *);
void hideEvent(QHideEvent *);
private: private:
int oldvalue; int oldvalue;
SbVec3f viewAxis; SbVec3f viewAxis;
bool wasHidden;
QPoint pnt;
QPoint oldPos;
Ui_DemoMode* ui; Ui_DemoMode* ui;
QTimer* timer; QTimer* timer;
QTimer* showHideTimer;
}; };
} // namespace Dialog } // namespace Dialog

View File

@ -1,118 +1,55 @@
<ui version="4.0" > <?xml version="1.0" encoding="UTF-8"?>
<author></author> <ui version="4.0">
<comment></comment>
<exportmacro></exportmacro>
<class>Gui::Dialog::DlgAuthorization</class> <class>Gui::Dialog::DlgAuthorization</class>
<widget class="QDialog" name="Gui::Dialog::DlgAuthorization" > <widget class="QDialog" name="Gui::Dialog::DlgAuthorization">
<property name="geometry" > <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>304</width> <width>284</width>
<height>189</height> <height>128</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle">
<string>Authorization</string> <string>Authorization</string>
</property> </property>
<property name="sizeGripEnabled" > <property name="sizeGripEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QGridLayout" > <layout class="QGridLayout" name="gridLayout">
<property name="margin" > <item row="1" column="0">
<number>11</number> <widget class="QLabel" name="textLabel1">
</property> <property name="text">
<property name="spacing" > <string>Username:</string>
<number>6</number>
</property>
<item row="5" column="0" >
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="buttonOk" >
<property name="text" >
<string>&amp;OK</string>
</property>
<property name="shortcut" >
<string/>
</property>
<property name="autoDefault" >
<bool>true</bool>
</property>
<property name="default" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size>
<width>140</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonCancel" >
<property name="text" >
<string>&amp;Cancel</string>
</property>
<property name="shortcut" >
<string/>
</property>
<property name="autoDefault" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" >
<widget class="QLineEdit" name="password" >
<property name="echoMode" >
<enum>QLineEdit::Password</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0" > <item row="1" column="1">
<widget class="QLabel" name="textLabel2" > <widget class="QLineEdit" name="username"/>
<property name="text" > </item>
<item row="2" column="0">
<widget class="QLabel" name="textLabel2">
<property name="text">
<string>Password:</string> <string>Password:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0" > <item row="2" column="1">
<widget class="QLineEdit" name="username" /> <widget class="QLineEdit" name="password">
</item> <property name="echoMode">
<item row="0" column="0" > <enum>QLineEdit::Password</enum>
<widget class="QLabel" name="textLabel1" >
<property name="text" >
<string>User name:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" > <item row="3" column="0" colspan="2">
<spacer> <spacer>
<property name="orientation" > <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeType" > <property name="sizeType">
<enum>QSizePolicy::Expanding</enum> <enum>QSizePolicy::Expanding</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0">
<size> <size>
<width>21</width> <width>21</width>
<height>41</height> <height>41</height>
@ -120,48 +57,43 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Site:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="siteDescription">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>%1 at %2</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<layoutdefault spacing="6" margin="11" /> <layoutdefault spacing="6" margin="11"/>
<tabstops> <tabstops>
<tabstop>username</tabstop> <tabstop>username</tabstop>
<tabstop>password</tabstop> <tabstop>password</tabstop>
<tabstop>buttonOk</tabstop>
<tabstop>buttonCancel</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections/>
<connection>
<sender>buttonOk</sender>
<signal>clicked()</signal>
<receiver>Gui::Dialog::DlgAuthorization</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>20</x>
<y>20</y>
</hint>
<hint type="destinationlabel" >
<x>20</x>
<y>20</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonCancel</sender>
<signal>clicked()</signal>
<receiver>Gui::Dialog::DlgAuthorization</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>20</x>
<y>20</y>
</hint>
<hint type="destinationlabel" >
<x>20</x>
<y>20</y>
</hint>
</hints>
</connection>
</connections>
</ui> </ui>

View File

@ -40,9 +40,6 @@
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<item rowspan="2" row="7" column="1" >
<widget class="QTextEdit" name="textEditComment" />
</item>
<item row="0" column="0" > <item row="0" column="0" >
<widget class="QLabel" name="textLabelName" > <widget class="QLabel" name="textLabelName" >
<property name="text" > <property name="text" >
@ -56,32 +53,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="0" > <item row="0" column="1" >
<spacer> <widget class="QLineEdit" name="lineEditName" >
<property name="orientation" > <property name="minimumSize" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size> <size>
<width>91</width> <width>0</width>
<height>240</height> <height>25</height>
</size> </size>
</property> </property>
</spacer> <property name="readOnly" >
</item> <bool>true</bool>
<item row="7" column="0" >
<widget class="QLabel" name="textLabelComment" >
<property name="text" >
<string>Commen&amp;t:</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>textEditComment</cstring>
</property> </property>
</widget> </widget>
</item> </item>
@ -108,40 +89,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1" > <item row="2" column="0" >
<widget class="QLineEdit" name="lineEditCreator" > <widget class="QLabel" name="textLabelUuid" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
</widget>
</item>
<item row="4" column="1" >
<widget class="QLineEdit" name="lineEditLastMod" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
</widget>
</item>
<item row="4" column="0" >
<widget class="QLabel" name="textLabelLastMod" >
<property name="text" > <property name="text" >
<string>&amp;Last modified by:</string> <string>UUID:</string>
</property> </property>
<property name="alignment" > <property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy" > </widget>
<cstring>lineEditLastMod</cstring> </item>
<item row="2" column="1" >
<widget class="QLineEdit" name="lineEditUuid" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="readOnly" >
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0" > <item row="3" column="0" >
<widget class="QLabel" name="textLabelCreator" > <widget class="QLabel" name="textLabelCreator" >
<property name="text" > <property name="text" >
<string>Created &amp;by:</string> <string>Created &amp;by:</string>
@ -154,20 +125,66 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0" > <item row="3" column="1" >
<widget class="QLabel" name="textLabelCompany" > <widget class="QLineEdit" name="lineEditCreator" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
</widget>
</item>
<item row="4" column="0" >
<widget class="QLabel" name="textLabelCreateDate" >
<property name="text" > <property name="text" >
<string>Com&amp;pany:</string> <string>Creation &amp;date:</string>
</property> </property>
<property name="alignment" > <property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy" > <property name="buddy" >
<cstring>lineEditCompany</cstring> <cstring>lineEditDate</cstring>
</property>
</widget>
</item>
<item row="4" column="1" >
<widget class="QLineEdit" name="lineEditDate" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="readOnly" >
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" > <item row="5" column="0" >
<widget class="QLabel" name="textLabelLastMod" >
<property name="text" >
<string>&amp;Last modified by:</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>lineEditLastMod</cstring>
</property>
</widget>
</item>
<item row="5" column="1" >
<widget class="QLineEdit" name="lineEditLastMod" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
</widget>
</item>
<item row="6" column="0" >
<widget class="QLabel" name="textLabelLastModDate" > <widget class="QLabel" name="textLabelLastModDate" >
<property name="text" > <property name="text" >
<string>Last &amp;modification date:</string> <string>Last &amp;modification date:</string>
@ -181,29 +198,6 @@
</widget> </widget>
</item> </item>
<item row="6" column="1" > <item row="6" column="1" >
<widget class="QLineEdit" name="lineEditCompany" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
</widget>
</item>
<item row="3" column="1" >
<widget class="QLineEdit" name="lineEditDate" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="1" >
<widget class="QLineEdit" name="lineEditLastModDate" > <widget class="QLineEdit" name="lineEditLastModDate" >
<property name="minimumSize" > <property name="minimumSize" >
<size> <size>
@ -216,32 +210,61 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" > <item row="7" column="0" >
<widget class="QLabel" name="textLabelCreateDate" > <widget class="QLabel" name="textLabelCompany" >
<property name="text" > <property name="text" >
<string>Creation &amp;date:</string> <string>Com&amp;pany:</string>
</property> </property>
<property name="alignment" > <property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy" > <property name="buddy" >
<cstring>lineEditDate</cstring> <cstring>lineEditCompany</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1" > <item row="7" column="1" >
<widget class="QLineEdit" name="lineEditName" > <widget class="QLineEdit" name="lineEditCompany" >
<property name="minimumSize" > <property name="minimumSize" >
<size> <size>
<width>0</width> <width>0</width>
<height>25</height> <height>25</height>
</size> </size>
</property> </property>
<property name="readOnly" > </widget>
<bool>true</bool> </item>
<item row="8" column="0" >
<widget class="QLabel" name="textLabelComment" >
<property name="text" >
<string>Commen&amp;t:</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>textEditComment</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item rowspan="2" row="8" column="1" >
<widget class="QTextEdit" name="textEditComment" />
</item>
<item row="9" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size>
<width>91</width>
<height>240</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -304,14 +327,6 @@
</widget> </widget>
<layoutdefault spacing="6" margin="11" /> <layoutdefault spacing="6" margin="11" />
<tabstops> <tabstops>
<tabstop>lineEditName</tabstop>
<tabstop>lineEditCreator</tabstop>
<tabstop>lineEditDate</tabstop>
<tabstop>lineEditLastMod</tabstop>
<tabstop>lineEditLastModDate</tabstop>
<tabstop>lineEditCompany</tabstop>
<tabstop>buttonOk</tabstop>
<tabstop>buttonCancel</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections>

View File

@ -46,6 +46,7 @@ DlgProjectInformationImp::DlgProjectInformationImp( App::Document* doc, QWidget*
this->setupUi(this); this->setupUi(this);
lineEditName->setText(QString::fromUtf8(doc->Label.getValue())); lineEditName->setText(QString::fromUtf8(doc->Label.getValue()));
lineEditPath->setText(QString::fromUtf8(doc->FileName.getValue())); lineEditPath->setText(QString::fromUtf8(doc->FileName.getValue()));
lineEditUuid->setText(QString::fromUtf8(doc->Uid.getValueStr().c_str()));
lineEditCreator->setText(QString::fromUtf8(doc->CreatedBy.getValue())); lineEditCreator->setText(QString::fromUtf8(doc->CreatedBy.getValue()));
lineEditDate->setText(QString::fromUtf8(doc->CreationDate.getValue())); lineEditDate->setText(QString::fromUtf8(doc->CreationDate.getValue()));
lineEditLastMod->setText(QString::fromUtf8(doc->LastModifiedBy.getValue())); lineEditLastMod->setText(QString::fromUtf8(doc->LastModifiedBy.getValue()));

View File

@ -71,6 +71,7 @@ void DlgSettingsViewColor::saveSettings()
EditedVertexColor->onSave(); EditedVertexColor->onSave();
ConstructionColor->onSave(); ConstructionColor->onSave();
FullyConstrainedColor->onSave(); FullyConstrainedColor->onSave();
BoundingBoxColor->onSave();
DefaultShapeColor->onSave(); DefaultShapeColor->onSave();
DefaultShapeLineColor->onSave(); DefaultShapeLineColor->onSave();
DefaultShapeLineWidth->onSave(); DefaultShapeLineWidth->onSave();
@ -94,6 +95,7 @@ void DlgSettingsViewColor::loadSettings()
EditedVertexColor->onRestore(); EditedVertexColor->onRestore();
ConstructionColor->onRestore(); ConstructionColor->onRestore();
FullyConstrainedColor->onRestore(); FullyConstrainedColor->onRestore();
BoundingBoxColor->onRestore();
DefaultShapeColor->onRestore(); DefaultShapeColor->onRestore();
DefaultShapeLineColor->onRestore(); DefaultShapeLineColor->onRestore();
DefaultShapeLineWidth->onRestore(); DefaultShapeLineWidth->onRestore();

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>601</width> <width>601</width>
<height>565</height> <height>598</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -520,6 +520,33 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Bounding box color</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="Gui::PrefColorButton" name="BoundingBoxColor">
<property name="toolTip">
<string>The color of bounding boxes in the 3D view</string>
</property>
<property name="color">
<color>
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</property>
<property name="prefEntry" stdset="0">
<cstring>BoundingBoxColor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>View</cstring>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
@ -660,6 +687,7 @@
<tabstop>EditedVertexColor</tabstop> <tabstop>EditedVertexColor</tabstop>
<tabstop>ConstructionColor</tabstop> <tabstop>ConstructionColor</tabstop>
<tabstop>FullyConstrainedColor</tabstop> <tabstop>FullyConstrainedColor</tabstop>
<tabstop>BoundingBoxColor</tabstop>
<tabstop>radioButtonSimple</tabstop> <tabstop>radioButtonSimple</tabstop>
<tabstop>SelectionColor_Background</tabstop> <tabstop>SelectionColor_Background</tabstop>
<tabstop>radioButtonGradient</tabstop> <tabstop>radioButtonGradient</tabstop>

View File

@ -288,7 +288,11 @@ void DlgCustomToolbars::on_moveActionRightButton_clicked()
QTreeWidgetItem* item = commandTreeWidget->currentItem(); QTreeWidgetItem* item = commandTreeWidget->currentItem();
if (item) { if (item) {
QTreeWidgetItem* current = toolbarTreeWidget->currentItem(); QTreeWidgetItem* current = toolbarTreeWidget->currentItem();
if (current && !current->parent() && toolbarTreeWidget->isItemSelected(current)) { if (!current)
current = toolbarTreeWidget->topLevelItem(0);
else if (current->parent())
current = current->parent();
if (current && !current->parent()) {
QTreeWidgetItem* copy = new QTreeWidgetItem(current); QTreeWidgetItem* copy = new QTreeWidgetItem(current);
copy->setText(0, item->text(1)); copy->setText(0, item->text(1));
copy->setIcon(0, item->icon(0)); copy->setIcon(0, item->icon(0));

View File

@ -571,43 +571,18 @@ bool Document::saveAs(void)
getMainWindow()->showMessage(QObject::tr("Save document under new filename...")); getMainWindow()->showMessage(QObject::tr("Save document under new filename..."));
QString exe = qApp->applicationName(); QString exe = qApp->applicationName();
QString fn = QFileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe), QString fn = FileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe),
FileDialog::getWorkingDirectory(), QObject::tr("%1 document (*.FCStd)").arg(exe)); QString(), QObject::tr("%1 document (*.FCStd)").arg(exe));
if (!fn.isEmpty()) {
FileDialog::setWorkingDirectory(fn);
QString file = fn.toLower();
if (!file.endsWith(QLatin1String(".fcstd"))) {
fn += QLatin1String(".fcstd");
QFileInfo fi;
fi.setFile(fn);
if (fi.exists()) {
// if we auto-append the extension make sure that we don't override an existing file
int ret = QMessageBox::question(getMainWindow(), QObject::tr("Save As"),
QObject::tr("%1 already exists.\n"
"Do you want to replace it?").arg(fn),
QMessageBox::Yes|QMessageBox::Default,
QMessageBox::No|QMessageBox::Escape);
if (ret != QMessageBox::Yes)
fn = QString();
}
}
}
if (!fn.isEmpty()) { if (!fn.isEmpty()) {
QFileInfo fi; QFileInfo fi;
fi.setFile(fn); fi.setFile(fn);
QString bn = fi.baseName();
const char * DocName = App::GetApplication().getDocumentName(getDocument()); const char * DocName = App::GetApplication().getDocumentName(getDocument());
// save as new file name // save as new file name
Gui::WaitCursor wc; Gui::WaitCursor wc;
Command::doCommand(Command::Doc,"App.getDocument(\"%s\").FileName = \"%s\"" Command::doCommand(Command::Doc,"App.getDocument(\"%s\").saveAs('%s')"
, DocName, (const char*)fn.toUtf8()); , DocName, (const char*)fn.toUtf8());
Command::doCommand(Command::Doc,"App.getDocument(\"%s\").Label = \"%s\""
, DocName, (const char*)bn.toUtf8());
Command::doCommand(Command::Doc,"App.getDocument(\"%s\").save()"
, DocName);
setModified(false); setModified(false);
getMainWindow()->appendRecentFile(fi.filePath()); getMainWindow()->appendRecentFile(fi.filePath());
@ -695,9 +670,20 @@ void Document::RestoreDocFile(Base::Reader &reader)
for (i=0 ;i<Cnt ;i++) { for (i=0 ;i<Cnt ;i++) {
xmlReader.readElement("ViewProvider"); xmlReader.readElement("ViewProvider");
std::string name = xmlReader.getAttribute("name"); std::string name = xmlReader.getAttribute("name");
bool expanded = false;
if (xmlReader.hasAttribute("expanded")) {
const char* attr = xmlReader.getAttribute("expanded");
if (strcmp(attr,"1") == 0) {
expanded = true;
}
}
ViewProvider* pObj = getViewProviderByName(name.c_str()); ViewProvider* pObj = getViewProviderByName(name.c_str());
if (pObj) // check if this feature has been registered if (pObj) // check if this feature has been registered
pObj->Restore(xmlReader); pObj->Restore(xmlReader);
if (expanded) {
Gui::ViewProviderDocumentObject* vp = static_cast<Gui::ViewProviderDocumentObject*>(pObj);
this->signalExpandObject(*vp, Gui::Expand);
}
xmlReader.readEndElement("ViewProvider"); xmlReader.readEndElement("ViewProvider");
} }
xmlReader.readEndElement("ViewProviderData"); xmlReader.readEndElement("ViewProviderData");
@ -784,7 +770,9 @@ void Document::SaveDocFile (Base::Writer &writer) const
const App::DocumentObject* doc = it->first; const App::DocumentObject* doc = it->first;
ViewProvider* obj = it->second; ViewProvider* obj = it->second;
writer.Stream() << writer.ind() << "<ViewProvider name=\"" writer.Stream() << writer.ind() << "<ViewProvider name=\""
<< doc->getNameInDocument() << "\">" << std::endl; << doc->getNameInDocument() << "\" "
<< "expanded=\"" << (doc->testStatus(App::Expand) ? 1:0)
<< "\">" << std::endl;
obj->Save(writer); obj->Save(writer);
writer.Stream() << writer.ind() << "</ViewProvider>" << std::endl; writer.Stream() << writer.ind() << "</ViewProvider>" << std::endl;
} }

View File

@ -30,6 +30,8 @@
# include <boost/bind.hpp> # include <boost/bind.hpp>
#endif #endif
#include <boost/unordered_set.hpp>
#include "DocumentModel.h" #include "DocumentModel.h"
#include "Application.h" #include "Application.h"
#include "BitmapFactory.h" #include "BitmapFactory.h"
@ -54,8 +56,6 @@ namespace Gui {
virtual ~DocumentModelIndex() virtual ~DocumentModelIndex()
{ qDeleteAll(childItems); } { qDeleteAll(childItems); }
void reset()
{ qDeleteAll(childItems); childItems.clear(); }
void setParent(DocumentModelIndex* parent) void setParent(DocumentModelIndex* parent)
{ parentItem = parent; } { parentItem = parent; }
DocumentModelIndex *parent() const DocumentModelIndex *parent() const
@ -64,7 +64,12 @@ namespace Gui {
{ childItems.append(child); child->setParent(this); } { childItems.append(child); child->setParent(this); }
void removeChild(int row) void removeChild(int row)
{ childItems.removeAt(row); } { childItems.removeAt(row); }
QList<DocumentModelIndex*> removeAll()
{
QList<DocumentModelIndex*> list = childItems;
childItems.clear();
return list;
}
DocumentModelIndex *child(int row) DocumentModelIndex *child(int row)
{ return childItems.value(row); } { return childItems.value(row); }
int row() const int row() const
@ -91,11 +96,18 @@ namespace Gui {
return Qt::ItemIsSelectable|Qt::ItemIsEnabled; return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
} }
protected:
void reset()
{ qDeleteAll(childItems); childItems.clear(); }
protected: protected:
DocumentModelIndex() : parentItem(0) {} DocumentModelIndex() : parentItem(0) {}
DocumentModelIndex *parentItem; DocumentModelIndex *parentItem;
QList<DocumentModelIndex*> childItems; QList<DocumentModelIndex*> childItems;
}; };
// ------------------------------------------------------------------------
// Root node // Root node
class ApplicationIndex : public DocumentModelIndex class ApplicationIndex : public DocumentModelIndex
{ {
@ -104,24 +116,22 @@ namespace Gui {
public: public:
ApplicationIndex(){} ApplicationIndex(){}
int findChild(const Gui::Document& d) const; int findChild(const Gui::Document& d) const;
Qt::ItemFlags flags() const Qt::ItemFlags flags() const;
{ return Qt::ItemIsEnabled; } QVariant data(int role) const;
QVariant data(int role) const
{
if (role == Qt::DecorationRole) {
return qApp->windowIcon();
}
else if (role == Qt::DisplayRole) {
return DocumentModel::tr("Application");
}
return QVariant();
}
}; };
// ------------------------------------------------------------------------
// Document nodes // Document nodes
class DocumentIndex : public DocumentModelIndex class DocumentIndex : public DocumentModelIndex
{ {
friend class ViewProviderIndex;
TYPESYSTEM_HEADER(); TYPESYSTEM_HEADER();
static QIcon* documentIcon; static QIcon* documentIcon;
typedef boost::unordered_set<ViewProviderIndex*> IndexSet;
std::map<const ViewProviderDocumentObject*, IndexSet> vp_nodes;
void addToDocument(ViewProviderIndex*);
void removeFromDocument(ViewProviderIndex*);
public: public:
const Gui::Document& d; const Gui::Document& d;
@ -130,30 +140,18 @@ namespace Gui {
if (!documentIcon) if (!documentIcon)
documentIcon = new QIcon(Gui::BitmapFactory().pixmap("Document")); documentIcon = new QIcon(Gui::BitmapFactory().pixmap("Document"));
} }
int findViewProvider(const ViewProvider&) const; ~DocumentIndex()
void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const;
QVariant data(int role) const
{ {
if (role == Qt::DecorationRole) { qDeleteAll(childItems); childItems.clear();
return *documentIcon;
}
else if (role == Qt::DisplayRole) {
App::Document* doc = d.getDocument();
return QString::fromUtf8(doc->Label.getValue());
}
else if (role == Qt::FontRole) {
Document* doc = Application::Instance->activeDocument();
QFont font;
font.setBold(doc==&d);
QVariant variant;
variant.setValue<QFont>(font);
return variant;
}
return QVariant();
} }
ViewProviderIndex* cloneViewProvider(const ViewProviderDocumentObject&) const;
int rowOfViewProvider(const ViewProviderDocumentObject&) const;
void findViewProviders(const ViewProviderDocumentObject&, QList<ViewProviderIndex*>&) const;
QVariant data(int role) const;
}; };
// ------------------------------------------------------------------------
// Object nodes // Object nodes
class ViewProviderIndex : public DocumentModelIndex class ViewProviderIndex : public DocumentModelIndex
{ {
@ -161,31 +159,18 @@ namespace Gui {
public: public:
const Gui::ViewProviderDocumentObject& v; const Gui::ViewProviderDocumentObject& v;
ViewProviderIndex(const Gui::ViewProviderDocumentObject& v) : v(v){} ViewProviderIndex(const Gui::ViewProviderDocumentObject& v, DocumentIndex* d);
void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const; ~ViewProviderIndex();
QVariant data(int role) const ViewProviderIndex* clone() const;
{ void findViewProviders(const ViewProviderDocumentObject&, QList<ViewProviderIndex*>&) const;
if (role == Qt::DecorationRole) { QVariant data(int role) const;
return v.getIcon();
}
else if (role == Qt::DisplayRole) {
App::DocumentObject* obj = v.getObject();
return QString::fromUtf8(obj->Label.getValue());
}
else if (role == Qt::FontRole) {
App::DocumentObject* obj = v.getObject();
App::DocumentObject* act = obj->getDocument()->getActiveObject();
QFont font;
font.setBold(obj==act);
QVariant variant;
variant.setValue<QFont>(font);
return variant;
}
return QVariant(); private:
} DocumentIndex* d;
}; };
// ------------------------------------------------------------------------
int ApplicationIndex::findChild(const Gui::Document& d) const int ApplicationIndex::findChild(const Gui::Document& d) const
{ {
int child=0; int child=0;
@ -199,9 +184,50 @@ namespace Gui {
return -1; return -1;
} }
Qt::ItemFlags ApplicationIndex::flags() const
{
return Qt::ItemIsEnabled;
}
QVariant ApplicationIndex::data(int role) const
{
if (role == Qt::DecorationRole) {
return qApp->windowIcon();
}
else if (role == Qt::DisplayRole) {
return DocumentModel::tr("Application");
}
return QVariant();
}
// ------------------------------------------------------------------------
QIcon* DocumentIndex::documentIcon = 0; QIcon* DocumentIndex::documentIcon = 0;
void DocumentIndex::findViewProviders(const ViewProvider& vp, void DocumentIndex::addToDocument(ViewProviderIndex* vp)
{
vp_nodes[&vp->v].insert(vp);
}
void DocumentIndex::removeFromDocument(ViewProviderIndex* vp)
{
vp_nodes[&vp->v].erase(vp);
}
ViewProviderIndex*
DocumentIndex::cloneViewProvider(const ViewProviderDocumentObject& vp) const
{
std::map<const ViewProviderDocumentObject*, boost::unordered_set<ViewProviderIndex*> >::const_iterator it;
it = vp_nodes.find(&vp);
if (it != vp_nodes.end()) {
boost::unordered_set<ViewProviderIndex*>::const_iterator v;
v = it->second.begin();
return (*v)->clone();
}
return new ViewProviderIndex(vp, const_cast<DocumentIndex*>(this));
}
void DocumentIndex::findViewProviders(const ViewProviderDocumentObject& vp,
QList<ViewProviderIndex*>& index) const QList<ViewProviderIndex*>& index) const
{ {
QList<DocumentModelIndex*>::const_iterator it; QList<DocumentModelIndex*>::const_iterator it;
@ -211,7 +237,7 @@ namespace Gui {
} }
} }
int DocumentIndex::findViewProvider(const ViewProvider& vp) const int DocumentIndex::rowOfViewProvider(const ViewProviderDocumentObject& vp) const
{ {
QList<DocumentModelIndex*>::const_iterator it; QList<DocumentModelIndex*>::const_iterator it;
int index=0; int index=0;
@ -224,8 +250,52 @@ namespace Gui {
return -1; return -1;
} }
void ViewProviderIndex::findViewProviders(const ViewProvider& vp, QVariant DocumentIndex::data(int role) const
QList<ViewProviderIndex*>& index) const {
if (role == Qt::DecorationRole) {
return *documentIcon;
}
else if (role == Qt::DisplayRole) {
App::Document* doc = d.getDocument();
return QString::fromUtf8(doc->Label.getValue());
}
else if (role == Qt::FontRole) {
Document* doc = Application::Instance->activeDocument();
QFont font;
font.setBold(doc==&d);
QVariant variant;
variant.setValue<QFont>(font);
return variant;
}
return QVariant();
}
// ------------------------------------------------------------------------
ViewProviderIndex::ViewProviderIndex(const Gui::ViewProviderDocumentObject& v, DocumentIndex* d)
: v(v),d(d)
{
if (d) d->addToDocument(this);
}
ViewProviderIndex::~ViewProviderIndex()
{
if (d) d->removeFromDocument(this);
}
ViewProviderIndex* ViewProviderIndex::clone() const
{
ViewProviderIndex* copy = new ViewProviderIndex(this->v, this->d);
for (QList<DocumentModelIndex*>::const_iterator it = childItems.begin(); it != childItems.end(); ++it) {
ViewProviderIndex* c = static_cast<ViewProviderIndex*>(*it)->clone();
copy->appendChild(c);
}
return copy;
}
void ViewProviderIndex::findViewProviders(const ViewProviderDocumentObject& vp,
QList<ViewProviderIndex*>& index) const
{ {
if (&this->v == &vp) if (&this->v == &vp)
index.push_back(const_cast<ViewProviderIndex*>(this)); index.push_back(const_cast<ViewProviderIndex*>(this));
@ -236,6 +306,30 @@ namespace Gui {
} }
} }
QVariant ViewProviderIndex::data(int role) const
{
if (role == Qt::DecorationRole) {
return v.getIcon();
}
else if (role == Qt::DisplayRole) {
App::DocumentObject* obj = v.getObject();
return QString::fromUtf8(obj->Label.getValue());
}
else if (role == Qt::FontRole) {
App::DocumentObject* obj = v.getObject();
App::DocumentObject* act = obj->getDocument()->getActiveObject();
QFont font;
font.setBold(obj==act);
QVariant variant;
variant.setValue<QFont>(font);
return variant;
}
return QVariant();
}
// ------------------------------------------------------------------------
TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentModelIndex, Base::BaseClass); TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentModelIndex, Base::BaseClass);
TYPESYSTEM_SOURCE_ABSTRACT(Gui::ApplicationIndex,Gui::DocumentModelIndex); TYPESYSTEM_SOURCE_ABSTRACT(Gui::ApplicationIndex,Gui::DocumentModelIndex);
TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentIndex, Gui::DocumentModelIndex); TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentIndex, Gui::DocumentModelIndex);
@ -350,7 +444,7 @@ void DocumentModel::slotNewObject(const Gui::ViewProviderDocumentObject& obj)
QModelIndex parent = createIndex(index->row(),0,index); QModelIndex parent = createIndex(index->row(),0,index);
int count_obj = index->childCount(); int count_obj = index->childCount();
beginInsertRows(parent, count_obj, count_obj); beginInsertRows(parent, count_obj, count_obj);
index->appendChild(new ViewProviderIndex(obj)); index->appendChild(new ViewProviderIndex(obj, index));
endInsertRows(); endInsertRows();
} }
} }
@ -399,35 +493,47 @@ void DocumentModel::slotChangeObject(const Gui::ViewProviderDocumentObject& obj,
else if (isPropertyLink(Prop)) { else if (isPropertyLink(Prop)) {
App::Document* doc = fea->getDocument(); App::Document* doc = fea->getDocument();
Gui::Document* gdc = Application::Instance->getDocument(doc); Gui::Document* gdc = Application::Instance->getDocument(doc);
std::vector<ViewProviderDocumentObject*> views = getLinkedObjects(*gdc, Prop); std::vector<ViewProviderDocumentObject*> views = claimChildren(*gdc, obj);
int row = d->rootItem->findChild(*gdc); int row = d->rootItem->findChild(*gdc);
if (row > -1) { if (row > -1) {
QList<DocumentModelIndex*> del_items;
DocumentIndex* doc_index = static_cast<DocumentIndex*>(d->rootItem->child(row)); DocumentIndex* doc_index = static_cast<DocumentIndex*>(d->rootItem->child(row));
QList<ViewProviderIndex*> obj_index;
doc_index->findViewProviders(obj, obj_index);
// remove from top level in document
for (std::vector<ViewProviderDocumentObject*>::iterator vp = views.begin(); vp != views.end(); ++vp) { for (std::vector<ViewProviderDocumentObject*>::iterator vp = views.begin(); vp != views.end(); ++vp) {
int row = doc_index->findViewProvider(**vp); int row = doc_index->rowOfViewProvider(**vp);
// is it a top-level child in the document
if (row >= 0) { if (row >= 0) {
DocumentModelIndex* child = doc_index->child(row); DocumentModelIndex* child = doc_index->child(row);
del_items.push_back(child);
QModelIndex parent = createIndex(doc_index->row(), 0, doc_index); QModelIndex parent = createIndex(doc_index->row(), 0, doc_index);
beginRemoveRows(parent, row, row); beginRemoveRows(parent, row, row);
doc_index->removeChild(row); doc_index->removeChild(row);
delete child;
endRemoveRows(); endRemoveRows();
} }
} }
// get all occurrences of the view provider in the tree structure
QList<ViewProviderIndex*> obj_index;
doc_index->findViewProviders(obj, obj_index);
for (QList<ViewProviderIndex*>::iterator it = obj_index.begin(); it != obj_index.end(); ++it) { for (QList<ViewProviderIndex*>::iterator it = obj_index.begin(); it != obj_index.end(); ++it) {
QModelIndex parent = createIndex((*it)->row(),0,*it); QModelIndex parent = createIndex((*it)->row(),0,*it);
int count_obj = (*it)->childCount(); int count_obj = (*it)->childCount();
beginInsertRows(parent, count_obj, count_obj + (int)views.size()); beginRemoveRows(parent, 0, count_obj);
for (std::vector<ViewProviderDocumentObject*>::iterator jt = views.begin(); jt != views.end(); ++jt) // remove all children but do not yet delete them
(*it)->appendChild(new ViewProviderIndex(**jt)); QList<DocumentModelIndex*> items = (*it)->removeAll();
endRemoveRows();
beginInsertRows(parent, 0, (int)views.size());
for (std::vector<ViewProviderDocumentObject*>::iterator vp = views.begin(); vp != views.end(); ++vp) {
ViewProviderIndex* clone = doc_index->cloneViewProvider(**vp);
(*it)->appendChild(clone);
}
endInsertRows(); endInsertRows();
del_items.append(items);
} }
qDeleteAll(del_items);
} }
} }
} }
@ -461,33 +567,27 @@ bool DocumentModel::isPropertyLink(const App::Property& prop) const
{ {
if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId())) if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId()))
return true; return true;
if (prop.isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
return true;
if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId())) if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId()))
return true; return true;
if (prop.isDerivedFrom(App::PropertyLinkSubList::getClassTypeId()))
return true;
return false; return false;
} }
std::vector<ViewProviderDocumentObject*> std::vector<ViewProviderDocumentObject*>
DocumentModel::getLinkedObjects(const Gui::Document& doc, const App::Property& prop) const DocumentModel::claimChildren(const Gui::Document& doc, const ViewProviderDocumentObject& obj) const
{ {
std::vector<ViewProviderDocumentObject*> links; std::vector<ViewProviderDocumentObject*> views;
if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId())) { std::vector<App::DocumentObject*> childs = obj.claimChildren();
App::DocumentObject* obj; for (std::vector<App::DocumentObject*>::iterator it = childs.begin(); it != childs.end(); ++it) {
obj = static_cast<const App::PropertyLink&>(prop).getValue(); ViewProvider* view = doc.getViewProvider(*it);
ViewProvider* view = doc.getViewProvider(obj);
if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
links.push_back(static_cast<ViewProviderDocumentObject*>(view)); views.push_back(static_cast<ViewProviderDocumentObject*>(view));
}
else if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
const std::vector<App::DocumentObject*>& refs = static_cast
<const App::PropertyLinkList&>(prop).getValues();
for (std::vector<App::DocumentObject*>::const_iterator it = refs.begin();it != refs.end(); ++it) {
ViewProvider* view = doc.getViewProvider(*it);
if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
links.push_back(static_cast<ViewProviderDocumentObject*>(view));
}
} }
return links; return views;
} }
int DocumentModel::columnCount (const QModelIndex & /*parent*/) const int DocumentModel::columnCount (const QModelIndex & /*parent*/) const

View File

@ -67,8 +67,8 @@ private:
const Document* getDocument(const QModelIndex&) const; const Document* getDocument(const QModelIndex&) const;
bool isPropertyLink(const App::Property&) const; bool isPropertyLink(const App::Property&) const;
std::vector<ViewProviderDocumentObject*> getLinkedObjects std::vector<ViewProviderDocumentObject*> claimChildren
(const Gui::Document&, const App::Property&) const; (const Document&, const ViewProviderDocumentObject&) const;
private: private:
struct DocumentModelP *d; struct DocumentModelP *d;

View File

@ -27,7 +27,9 @@
# include <QHBoxLayout> # include <QHBoxLayout>
#endif #endif
#include <QAuthenticator>
#include "DownloadDialog.h" #include "DownloadDialog.h"
#include "ui_DlgAuthorization.h"
using namespace Gui::Dialog; using namespace Gui::Dialog;
@ -202,6 +204,16 @@ void DownloadDialog::updateDataReadProgress(int bytesRead, int totalBytes)
void DownloadDialog::slotAuthenticationRequired(const QString &hostName, quint16, QAuthenticator *authenticator) void DownloadDialog::slotAuthenticationRequired(const QString &hostName, quint16, QAuthenticator *authenticator)
{ {
QDialog dlg;
Ui_DlgAuthorization ui;
ui.setupUi(&dlg);
dlg.adjustSize();
ui.siteDescription->setText(tr("%1 at %2").arg(authenticator->realm()).arg(hostName));
if (dlg.exec() == QDialog::Accepted) {
authenticator->setUser(ui.username->text());
authenticator->setPassword(ui.password->text());
}
} }

583
src/Gui/DownloadItem.cpp Normal file
View File

@ -0,0 +1,583 @@
/***************************************************************************
* Copyright (c) 2013 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#include <stdio.h>
#include <math.h>
#include <QAuthenticator>
#include <QContextMenuEvent>
#include <QFileInfo>
#include <QMenu>
#include <QNetworkDiskCache>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QSettings>
#include <QMetaObject>
#include <QDesktopServices>
#include <QFileDialog>
#include <QHeaderView>
#include <QDebug>
#include <QKeyEvent>
#include <QTextDocument>
#include <App/Document.h>
#include "DownloadItem.h"
#include "DownloadManager.h"
#include "Application.h"
#include "Document.h"
#include "MainWindow.h"
#include "FileDialog.h"
#include "ui_DlgAuthorization.h"
using namespace Gui::Dialog;
EditTableView::EditTableView(QWidget *parent)
: QTableView(parent)
{
}
void EditTableView::keyPressEvent(QKeyEvent *event)
{
if ((event->key() == Qt::Key_Delete
|| event->key() == Qt::Key_Backspace)
&& model()) {
removeOne();
} else {
QAbstractItemView::keyPressEvent(event);
}
}
void EditTableView::removeOne()
{
if (!model() || !selectionModel())
return;
int row = currentIndex().row();
model()->removeRow(row, rootIndex());
QModelIndex idx = model()->index(row, 0, rootIndex());
if (!idx.isValid())
idx = model()->index(row - 1, 0, rootIndex());
selectionModel()->select(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}
void EditTableView::removeAll()
{
if (model())
model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
}
// ----------------------------------------------------------------------------
SqueezeLabel::SqueezeLabel(QWidget *parent) : QLabel(parent)
{
}
void SqueezeLabel::paintEvent(QPaintEvent *event)
{
QFontMetrics fm = fontMetrics();
if (fm.width(text()) > contentsRect().width()) {
QString elided = fm.elidedText(text(), Qt::ElideMiddle, width());
QString oldText = text();
setText(elided);
QLabel::paintEvent(event);
setText(oldText);
} else {
QLabel::paintEvent(event);
}
}
// ----------------------------------------------------------------------------
#define AUTOSAVE_IN 1000 * 3 // seconds
#define MAXWAIT 1000 * 15 // seconds
AutoSaver::AutoSaver(QObject *parent) : QObject(parent)
{
Q_ASSERT(parent);
}
AutoSaver::~AutoSaver()
{
if (m_timer.isActive())
qWarning() << "AutoSaver: still active when destroyed, changes not saved.";
}
void AutoSaver::changeOccurred()
{
if (m_firstChange.isNull())
m_firstChange.start();
if (m_firstChange.elapsed() > MAXWAIT) {
saveIfNeccessary();
} else {
m_timer.start(AUTOSAVE_IN, this);
}
}
void AutoSaver::timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_timer.timerId()) {
saveIfNeccessary();
} else {
QObject::timerEvent(event);
}
}
void AutoSaver::saveIfNeccessary()
{
if (!m_timer.isActive())
return;
m_timer.stop();
m_firstChange = QTime();
if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) {
qWarning() << "AutoSaver: error invoking slot save() on parent";
}
}
// ----------------------------------------------------------------------------
NetworkAccessManager::NetworkAccessManager(QObject *parent)
: QNetworkAccessManager(parent)
{
connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
connect(this, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
SLOT(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
QString location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
diskCache->setCacheDirectory(location);
setCache(diskCache);
}
void NetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
{
QWidget *mainWindow = Gui::getMainWindow();
QDialog dialog(mainWindow);
dialog.setWindowFlags(Qt::Sheet);
Ui_DlgAuthorization passwordDialog;
passwordDialog.setupUi(&dialog);
dialog.adjustSize();
QString introMessage = tr("<qt>Enter username and password for \"%1\" at %2</qt>");
introMessage = introMessage.arg(Qt::escape(reply->url().toString())).arg(Qt::escape(reply->url().toString()));
passwordDialog.siteDescription->setText(introMessage);
passwordDialog.siteDescription->setWordWrap(true);
if (dialog.exec() == QDialog::Accepted) {
auth->setUser(passwordDialog.username->text());
auth->setPassword(passwordDialog.password->text());
}
}
void NetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth)
{
QWidget *mainWindow = Gui::getMainWindow();
QDialog dialog(mainWindow);
dialog.setWindowFlags(Qt::Sheet);
Ui_DlgAuthorization proxyDialog;
proxyDialog.setupUi(&dialog);
dialog.adjustSize();
QString introMessage = tr("<qt>Connect to proxy \"%1\" using:</qt>");
introMessage = introMessage.arg(Qt::escape(proxy.hostName()));
proxyDialog.siteDescription->setText(introMessage);
proxyDialog.siteDescription->setWordWrap(true);
if (dialog.exec() == QDialog::Accepted) {
auth->setUser(proxyDialog.username->text());
auth->setPassword(proxyDialog.password->text());
}
}
// ----------------------------------------------------------------------------
DownloadItem::DownloadItem(QNetworkReply *reply, bool requestFileName, QWidget *parent)
: QWidget(parent)
, m_reply(reply)
, m_requestFileName(requestFileName)
, m_bytesReceived(0)
{
setupUi(this);
QPalette p = downloadInfoLabel->palette();
p.setColor(QPalette::Text, Qt::darkGray);
downloadInfoLabel->setPalette(p);
progressBar->setMaximum(0);
tryAgainButton->hide();
connect(stopButton, SIGNAL(clicked()), this, SLOT(stop()));
connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
connect(tryAgainButton, SIGNAL(clicked()), this, SLOT(tryAgain()));
init();
}
void DownloadItem::init()
{
if (!m_reply)
return;
// attach to the m_reply
m_url = m_reply->url();
m_reply->setParent(this);
connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(error(QNetworkReply::NetworkError)));
connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(downloadProgress(qint64, qint64)));
connect(m_reply, SIGNAL(metaDataChanged()),
this, SLOT(metaDataChanged()));
connect(m_reply, SIGNAL(finished()),
this, SLOT(finished()));
// reset info
downloadInfoLabel->clear();
progressBar->setValue(0);
getFileName();
// start timer for the download estimation
m_downloadTime.start();
if (m_reply->error() != QNetworkReply::NoError) {
error(m_reply->error());
finished();
}
}
QString DownloadItem::getDownloadDirectory() const
{
QString exe = QString::fromAscii(App::GetApplication().getExecutableName());
QString path = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
QString dirPath = QDir(path).filePath(exe);
Base::Reference<ParameterGrp> hPath = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
->GetGroup("Preferences")->GetGroup("General");
std::string dir = hPath->GetASCII("DownloadPath", "");
if (!dir.empty()) {
dirPath = QString::fromUtf8(dir.c_str());
}
if (QFileInfo(dirPath).exists() || QDir().mkpath(dirPath)) {
return dirPath;
}
else {
return path;
}
}
void DownloadItem::getFileName()
{
QSettings settings;
settings.beginGroup(QLatin1String("downloadmanager"));
//QString defaultLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
QString defaultLocation = getDownloadDirectory();
QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString();
if (!downloadDirectory.isEmpty())
downloadDirectory += QLatin1Char('/');
QString defaultFileName = saveFileName(downloadDirectory);
QString fileName = defaultFileName;
if (m_requestFileName) {
fileName = QFileDialog::getSaveFileName(this, tr("Save File"), defaultFileName);
if (fileName.isEmpty()) {
m_reply->close();
fileNameLabel->setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName()));
return;
}
}
m_output.setFileName(fileName);
fileNameLabel->setText(QFileInfo(m_output.fileName()).fileName());
fileNameLabel->setToolTip(m_output.fileName());
if (m_requestFileName)
downloadReadyRead();
}
QString DownloadItem::saveFileName(const QString &directory) const
{
// Move this function into QNetworkReply to also get file name sent from the server
QString path = m_url.path();
if (!m_fileName.isEmpty())
path = m_fileName;
QFileInfo info(path);
QString baseName = info.completeBaseName();
QString endName = info.suffix();
if (baseName.isEmpty()) {
baseName = QLatin1String("unnamed_download");
qDebug() << "DownloadManager:: downloading unknown file:" << m_url;
}
QString name = directory + baseName + QLatin1Char('.') + endName;
if (QFile::exists(name)) {
// already exists, don't overwrite
int i = 1;
do {
name = directory + baseName + QLatin1Char('-') + QString::number(i++) + QLatin1Char('.') + endName;
} while (QFile::exists(name));
}
return name;
}
void DownloadItem::stop()
{
setUpdatesEnabled(false);
stopButton->setEnabled(false);
stopButton->hide();
tryAgainButton->setEnabled(true);
tryAgainButton->show();
setUpdatesEnabled(true);
m_reply->abort();
}
void DownloadItem::open()
{
QFileInfo info(m_output);
QString selectedFilter;
QStringList fileList;
fileList << info.absoluteFilePath();
SelectModule::Dict dict = SelectModule::importHandler(fileList, selectedFilter);
// load the files with the associated modules
if (!dict.isEmpty()) {
Gui::Document* doc = Gui::Application::Instance->activeDocument();
if (doc) {
for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
Gui::Application::Instance->importFrom(it.key().toUtf8(),
doc->getDocument()->getName(), it.value().toAscii());
}
}
else {
for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
Gui::Application::Instance->open(it.key().toUtf8(), it.value().toAscii());
}
}
}
else {
QUrl url = QUrl::fromLocalFile(info.absolutePath());
QDesktopServices::openUrl(url);
}
}
void DownloadItem::openFolder()
{
QFileInfo info(m_output);
QUrl url = QUrl::fromLocalFile(info.absolutePath());
QDesktopServices::openUrl(url);
}
void DownloadItem::tryAgain()
{
if (!tryAgainButton->isEnabled())
return;
tryAgainButton->setEnabled(false);
tryAgainButton->setVisible(false);
stopButton->setEnabled(true);
stopButton->setVisible(true);
progressBar->setVisible(true);
QNetworkReply *r = DownloadManager::getInstance()->networkAccessManager()->get(QNetworkRequest(m_url));
if (m_reply)
m_reply->deleteLater();
if (m_output.exists())
m_output.remove();
m_reply = r;
init();
/*emit*/ statusChanged();
}
void DownloadItem::contextMenuEvent (QContextMenuEvent * e)
{
QMenu menu;
QAction* a = menu.addAction(tr("Open containing folder"), this, SLOT(openFolder()));
a->setEnabled(m_output.exists());
menu.exec(e->globalPos());
}
void DownloadItem::downloadReadyRead()
{
if (m_requestFileName && m_output.fileName().isEmpty())
return;
if (!m_output.isOpen()) {
// in case someone else has already put a file there
if (!m_requestFileName)
getFileName();
if (!m_output.open(QIODevice::WriteOnly)) {
downloadInfoLabel->setText(tr("Error opening save file: %1")
.arg(m_output.errorString()));
stopButton->click();
/*emit*/ statusChanged();
return;
}
downloadInfoLabel->setToolTip(m_url.toString());
/*emit*/ statusChanged();
}
if (-1 == m_output.write(m_reply->readAll())) {
downloadInfoLabel->setText(tr("Error saving: %1")
.arg(m_output.errorString()));
stopButton->click();
}
}
void DownloadItem::error(QNetworkReply::NetworkError)
{
qDebug() << "DownloadItem::error" << m_reply->errorString() << m_url;
downloadInfoLabel->setText(tr("Network Error: %1").arg(m_reply->errorString()));
tryAgainButton->setEnabled(true);
tryAgainButton->setVisible(true);
}
void DownloadItem::metaDataChanged()
{
if (m_reply->hasRawHeader(QByteArray("Content-Disposition"))) {
QByteArray header = m_reply->rawHeader(QByteArray("Content-Disposition"));
int index = header.indexOf("filename=");
if (index >= 0) {
header = header.mid(index+9);
if (header.startsWith("\"") || header.startsWith("'"))
header = header.mid(1);
if (header.endsWith("\"") || header.endsWith("'"))
header.chop(1);
m_fileName = QUrl::fromPercentEncoding(header);
}
else {
index = header.indexOf("filename*=UTF-8''");
if (index >= 0) {
header = header.mid(index+17);
if (header.startsWith("\"") || header.startsWith("'"))
header = header.mid(1);
if (header.endsWith("\"") || header.endsWith("'"))
header.chop(1);
m_fileName = QUrl::fromPercentEncoding(header);
}
}
}
QVariant statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (!statusCode.isValid())
return;
int status = statusCode.toInt();
if (status != 200) {
QString reason = m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
qDebug() << reason;
}
}
void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
m_bytesReceived = bytesReceived;
if (bytesTotal == -1) {
progressBar->setValue(0);
progressBar->setMaximum(0);
} else {
progressBar->setValue(bytesReceived);
progressBar->setMaximum(bytesTotal);
}
updateInfoLabel();
}
void DownloadItem::updateInfoLabel()
{
//if (m_reply->error() == QNetworkReply::NoError)
// return;
qint64 bytesTotal = progressBar->maximum();
bool running = !downloadedSuccessfully();
// update info label
double speed = m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
double timeRemaining = ((double)(bytesTotal - m_bytesReceived)) / speed;
QString timeRemainingString = tr("seconds");
if (timeRemaining > 60) {
timeRemaining = timeRemaining / 60;
timeRemainingString = tr("minutes");
}
timeRemaining = floor(timeRemaining);
// When downloading the eta should never be 0
if (timeRemaining == 0)
timeRemaining = 1;
QString info;
if (running) {
QString remaining;
if (bytesTotal != 0)
remaining = tr("- %4 %5 remaining")
.arg(timeRemaining)
.arg(timeRemainingString);
info = QString(tr("%1 of %2 (%3/sec) %4"))
.arg(dataString(m_bytesReceived))
.arg(bytesTotal == 0 ? tr("?") : dataString(bytesTotal))
.arg(dataString((int)speed))
.arg(remaining);
} else {
if (m_bytesReceived == bytesTotal)
info = dataString(m_output.size());
else
info = tr("%1 of %2 - Stopped")
.arg(dataString(m_bytesReceived))
.arg(dataString(bytesTotal));
}
downloadInfoLabel->setText(info);
}
QString DownloadItem::dataString(int size) const
{
QString unit;
if (size < 1024) {
unit = tr("bytes");
} else if (size < 1024*1024) {
size /= 1024;
unit = tr("kB");
} else {
size /= 1024*1024;
unit = tr("MB");
}
return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
}
bool DownloadItem::downloading() const
{
return (progressBar->isVisible());
}
bool DownloadItem::downloadedSuccessfully() const
{
return (stopButton->isHidden() && tryAgainButton->isHidden());
}
void DownloadItem::finished()
{
progressBar->hide();
stopButton->setEnabled(false);
stopButton->hide();
m_output.close();
updateInfoLabel();
/*emit*/ statusChanged();
}
#include "moc_DownloadItem.cpp"

155
src/Gui/DownloadItem.h Normal file
View File

@ -0,0 +1,155 @@
/***************************************************************************
* Copyright (c) 2013 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 *
* *
***************************************************************************/
#ifndef GUI_DIALOG_DOWNLOADITEM_H
#define GUI_DIALOG_DOWNLOADITEM_H
#include <QBasicTimer>
#include <QFile>
#include <QTime>
#include <QUrl>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QLabel>
#include <QTableView>
class AutoSaver;
class QFileIconProvider;
class EditTableView : public QTableView
{
Q_OBJECT
public:
EditTableView(QWidget *parent = 0);
void keyPressEvent(QKeyEvent *event);
public Q_SLOTS:
void removeOne();
void removeAll();
};
class SqueezeLabel : public QLabel
{
Q_OBJECT
public:
SqueezeLabel(QWidget *parent = 0);
protected:
void paintEvent(QPaintEvent *event);
};
/*
This class will call the save() slot on the parent object when the parent changes.
It will wait several seconds after changed() to combining multiple changes and
prevent continuous writing to disk.
*/
class AutoSaver : public QObject {
Q_OBJECT
public:
AutoSaver(QObject *parent);
~AutoSaver();
void saveIfNeccessary();
public Q_SLOTS:
void changeOccurred();
protected:
void timerEvent(QTimerEvent *event);
private:
QBasicTimer m_timer;
QTime m_firstChange;
};
class NetworkAccessManager : public QNetworkAccessManager
{
Q_OBJECT
public:
NetworkAccessManager(QObject *parent = 0);
private Q_SLOTS:
void authenticationRequired(QNetworkReply *reply, QAuthenticator *auth);
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
};
#include "ui_DownloadItem.h"
namespace Gui {
namespace Dialog {
class DownloadModel;
class DownloadItem : public QWidget, public Ui_DownloadItem
{
Q_OBJECT
Q_SIGNALS:
void statusChanged();
public:
DownloadItem(QNetworkReply *reply = 0, bool requestFileName = false, QWidget *parent = 0);
bool downloading() const;
bool downloadedSuccessfully() const;
QUrl m_url;
QString m_fileName;
QFile m_output;
QNetworkReply *m_reply;
private Q_SLOTS:
void stop();
void tryAgain();
void open();
void openFolder();
void downloadReadyRead();
void error(QNetworkReply::NetworkError code);
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void metaDataChanged();
void finished();
private:
void contextMenuEvent(QContextMenuEvent *);
void getFileName();
void init();
void updateInfoLabel();
QString dataString(int size) const;
QString getDownloadDirectory() const;
QString saveFileName(const QString &directory) const;
bool m_requestFileName;
qint64 m_bytesReceived;
QTime m_downloadTime;
};
} // namespace Dialog
} // namespace Gui
#endif // GUI_DIALOG_DOWNLOADITEM_H

140
src/Gui/DownloadItem.ui Normal file
View File

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DownloadItem</class>
<widget class="QWidget" name="DownloadItem">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>423</width>
<height>98</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="fileIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Ico</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="SqueezeLabel" name="fileNameLabel" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" stdset="0">
<string>Filename</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="SqueezeLabel" name="downloadInfoLabel" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" stdset="0">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="tryAgainButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/view-refresh.svg</normaloff>:/icons/view-refresh.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopButton">
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/process-stop.svg</normaloff>:/icons/process-stop.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openButton">
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/document-open.svg</normaloff>:/icons/document-open.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SqueezeLabel</class>
<extends>QWidget</extends>
<header>DownloadItem.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="Icons/resource.qrc"/>
</resources>
<connections/>
</ui>

303
src/Gui/DownloadManager.cpp Normal file
View File

@ -0,0 +1,303 @@
/***************************************************************************
* Copyright (c) 2013 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#include <stdio.h>
#include <math.h>
#include <QByteArray>
#include <QDockWidget>
#include <QFileInfo>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QMetaEnum>
#include <QSettings>
#include <QFileIconProvider>
#include <QWebSettings>
#include "DownloadItem.h"
#include "DownloadManager.h"
#include "ui_DownloadManager.h"
#include "DockWindowManager.h"
#include "MainWindow.h"
using namespace Gui::Dialog;
/* TRANSLATOR Gui::Dialog::DownloadManager */
DownloadManager* DownloadManager::self = 0;
DownloadManager* DownloadManager::getInstance()
{
if (!self)
self = new DownloadManager(Gui::getMainWindow());
return self;
}
DownloadManager::DownloadManager(QWidget *parent)
: QDialog(parent)
, m_autoSaver(new AutoSaver(this))
, m_manager(new NetworkAccessManager(this))
, m_iconProvider(0)
, m_removePolicy(Never)
, ui(new Ui_DownloadManager())
{
ui->setupUi(this);
ui->downloadsView->setShowGrid(false);
ui->downloadsView->verticalHeader()->hide();
ui->downloadsView->horizontalHeader()->hide();
ui->downloadsView->setAlternatingRowColors(true);
ui->downloadsView->horizontalHeader()->setStretchLastSection(true);
m_model = new DownloadModel(this);
ui->downloadsView->setModel(m_model);
connect(ui->cleanupButton, SIGNAL(clicked()), this, SLOT(cleanup()));
load();
Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
QDockWidget* dw = pDockMgr->addDockWindow(QT_TR_NOOP("Download Manager"),
this, Qt::BottomDockWidgetArea);
dw->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
dw->show();
}
DownloadManager::~DownloadManager()
{
m_autoSaver->changeOccurred();
m_autoSaver->saveIfNeccessary();
if (m_iconProvider)
delete m_iconProvider;
delete ui;
}
int DownloadManager::activeDownloads() const
{
int count = 0;
for (int i = 0; i < m_downloads.count(); ++i) {
if (m_downloads.at(i)->stopButton->isEnabled())
++count;
}
return count;
}
void DownloadManager::download(const QNetworkRequest &request, bool requestFileName)
{
if (request.url().isEmpty())
return;
handleUnsupportedContent(m_manager->get(request), requestFileName);
}
void DownloadManager::handleUnsupportedContent(QNetworkReply *reply, bool requestFileName)
{
if (!reply || reply->url().isEmpty())
return;
QVariant header = reply->header(QNetworkRequest::ContentLengthHeader);
bool ok;
int size = header.toInt(&ok);
if (ok && size == 0)
return;
DownloadItem *item = new DownloadItem(reply, requestFileName, this);
addItem(item);
}
void DownloadManager::addItem(DownloadItem *item)
{
connect(item, SIGNAL(statusChanged()), this, SLOT(updateRow()));
int row = m_downloads.count();
m_model->beginInsertRows(QModelIndex(), row, row);
m_downloads.append(item);
m_model->endInsertRows();
updateItemCount();
show();
ui->downloadsView->setIndexWidget(m_model->index(row, 0), item);
QIcon icon = style()->standardIcon(QStyle::SP_FileIcon);
item->fileIcon->setPixmap(icon.pixmap(48, 48));
ui->downloadsView->setRowHeight(row, item->sizeHint().height());
}
void DownloadManager::updateRow()
{
DownloadItem *item = qobject_cast<DownloadItem*>(sender());
int row = m_downloads.indexOf(item);
if (-1 == row)
return;
if (!m_iconProvider)
m_iconProvider = new QFileIconProvider();
QIcon icon = m_iconProvider->icon(item->m_output.fileName());
if (icon.isNull())
icon = style()->standardIcon(QStyle::SP_FileIcon);
item->fileIcon->setPixmap(icon.pixmap(48, 48));
ui->downloadsView->setRowHeight(row, item->minimumSizeHint().height());
bool remove = false;
QWebSettings *globalSettings = QWebSettings::globalSettings();
if (!item->downloading()
&& globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled))
remove = true;
if (item->downloadedSuccessfully()
&& removePolicy() == DownloadManager::SuccessFullDownload) {
remove = true;
}
if (remove)
m_model->removeRow(row);
ui->cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0);
}
DownloadManager::RemovePolicy DownloadManager::removePolicy() const
{
return m_removePolicy;
}
void DownloadManager::setRemovePolicy(RemovePolicy policy)
{
if (policy == m_removePolicy)
return;
m_removePolicy = policy;
m_autoSaver->changeOccurred();
}
void DownloadManager::save() const
{
QSettings settings;
settings.beginGroup(QLatin1String("downloadmanager"));
QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
settings.setValue(QLatin1String("removeDownloadsPolicy"), QLatin1String(removePolicyEnum.valueToKey(m_removePolicy)));
settings.setValue(QLatin1String("size"), size());
if (m_removePolicy == Exit)
return;
for (int i = 0; i < m_downloads.count(); ++i) {
QString key = QString(QLatin1String("download_%1_")).arg(i);
settings.setValue(key + QLatin1String("url"), m_downloads[i]->m_url);
settings.setValue(key + QLatin1String("location"), QFileInfo(m_downloads[i]->m_output).filePath());
settings.setValue(key + QLatin1String("done"), m_downloads[i]->downloadedSuccessfully());
}
int i = m_downloads.count();
QString key = QString(QLatin1String("download_%1_")).arg(i);
while (settings.contains(key + QLatin1String("url"))) {
settings.remove(key + QLatin1String("url"));
settings.remove(key + QLatin1String("location"));
settings.remove(key + QLatin1String("done"));
key = QString(QLatin1String("download_%1_")).arg(++i);
}
}
void DownloadManager::load()
{
QSettings settings;
settings.beginGroup(QLatin1String("downloadmanager"));
QSize size = settings.value(QLatin1String("size")).toSize();
if (size.isValid())
resize(size);
QByteArray value = settings.value(QLatin1String("removeDownloadsPolicy"), QLatin1String("Never")).toByteArray();
QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
m_removePolicy = removePolicyEnum.keyToValue(value) == -1 ?
Never :
static_cast<RemovePolicy>(removePolicyEnum.keyToValue(value));
int i = 0;
QString key = QString(QLatin1String("download_%1_")).arg(i);
while (settings.contains(key + QLatin1String("url"))) {
QUrl url = settings.value(key + QLatin1String("url")).toUrl();
QString fileName = settings.value(key + QLatin1String("location")).toString();
bool done = settings.value(key + QLatin1String("done"), true).toBool();
if (!url.isEmpty() && !fileName.isEmpty()) {
DownloadItem *item = new DownloadItem(0, this);
item->m_output.setFileName(fileName);
item->fileNameLabel->setText(QFileInfo(item->m_output.fileName()).fileName());
item->m_url = url;
item->stopButton->setVisible(false);
item->stopButton->setEnabled(false);
item->tryAgainButton->setVisible(!done);
item->tryAgainButton->setEnabled(!done);
item->progressBar->setVisible(!done);
addItem(item);
}
key = QString(QLatin1String("download_%1_")).arg(++i);
}
ui->cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0);
}
void DownloadManager::cleanup()
{
if (m_downloads.isEmpty())
return;
m_model->removeRows(0, m_downloads.count());
updateItemCount();
if (m_downloads.isEmpty() && m_iconProvider) {
delete m_iconProvider;
m_iconProvider = 0;
}
m_autoSaver->changeOccurred();
}
void DownloadManager::updateItemCount()
{
int count = m_downloads.count();
ui->itemCount->setText(count == 1 ? tr("1 Download") : tr("%1 Downloads").arg(count));
}
// ----------------------------------------------------------------------------
DownloadModel::DownloadModel(DownloadManager *downloadManager, QObject *parent)
: QAbstractListModel(parent)
, m_downloadManager(downloadManager)
{
}
QVariant DownloadModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= rowCount(index.parent()))
return QVariant();
if (role == Qt::ToolTipRole)
if (!m_downloadManager->m_downloads.at(index.row())->downloadedSuccessfully())
return m_downloadManager->m_downloads.at(index.row())->downloadInfoLabel->text();
return QVariant();
}
int DownloadModel::rowCount(const QModelIndex &parent) const
{
return (parent.isValid()) ? 0 : m_downloadManager->m_downloads.count();
}
bool DownloadModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (parent.isValid())
return false;
int lastRow = row + count - 1;
for (int i = lastRow; i >= row; --i) {
if (m_downloadManager->m_downloads.at(i)->downloadedSuccessfully()
|| m_downloadManager->m_downloads.at(i)->tryAgainButton->isEnabled()) {
beginRemoveRows(parent, i, i);
m_downloadManager->m_downloads.takeAt(i)->deleteLater();
endRemoveRows();
}
}
m_downloadManager->m_autoSaver->changeOccurred();
return true;
}
#include "moc_DownloadManager.cpp"

116
src/Gui/DownloadManager.h Normal file
View File

@ -0,0 +1,116 @@
/***************************************************************************
* Copyright (c) 2013 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 *
* *
***************************************************************************/
#ifndef GUI_DIALOG_DOWNLOADMANAGER_H
#define GUI_DIALOG_DOWNLOADMANAGER_H
#include <QDialog>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class AutoSaver;
class QFileIconProvider;
namespace Gui {
namespace Dialog {
class DownloadItem;
class DownloadModel;
class Ui_DownloadManager;
class GuiExport DownloadManager : public QDialog
{
Q_OBJECT
Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy)
Q_ENUMS(RemovePolicy)
public:
enum RemovePolicy {
Never,
Exit,
SuccessFullDownload
};
static DownloadManager* getInstance();
private:
DownloadManager(QWidget *parent = 0);
~DownloadManager();
public:
int activeDownloads() const;
QNetworkAccessManager * networkAccessManager()
{ return m_manager; }
RemovePolicy removePolicy() const;
void setRemovePolicy(RemovePolicy policy);
public Q_SLOTS:
void download(const QNetworkRequest &request, bool requestFileName = false);
inline void download(const QUrl &url, bool requestFileName = false)
{ download(QNetworkRequest(url), requestFileName); }
void handleUnsupportedContent(QNetworkReply *reply, bool requestFileName = false);
void cleanup();
private Q_SLOTS:
void save() const;
void updateRow();
private:
void addItem(DownloadItem *item);
void updateItemCount();
void load();
AutoSaver *m_autoSaver;
DownloadModel *m_model;
QNetworkAccessManager *m_manager;
QFileIconProvider *m_iconProvider;
QList<DownloadItem*> m_downloads;
RemovePolicy m_removePolicy;
friend class DownloadModel;
private:
Ui_DownloadManager* ui;
static DownloadManager* self;
};
class DownloadModel : public QAbstractListModel
{
friend class DownloadManager;
Q_OBJECT
public:
DownloadModel(DownloadManager *downloadManager, QObject *parent = 0);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
private:
DownloadManager *m_downloadManager;
};
} // namespace Dialog
} // namespace Gui
#endif // GUI_DIALOG_DOWNLOADMANAGER_H

View File

@ -0,0 +1,83 @@
<ui version="4.0" >
<class>Gui::Dialog::DownloadManager</class>
<widget class="QDialog" name="Gui::Dialog::DownloadManager" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>332</width>
<height>252</height>
</rect>
</property>
<property name="windowTitle" >
<string>Downloads</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>0</number>
</property>
<item row="0" column="0" colspan="3" >
<widget class="EditTableView" name="downloadsView" />
</item>
<item row="1" column="0" >
<layout class="QHBoxLayout" name="horizontalLayout" >
<item>
<widget class="QPushButton" name="cleanupButton" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>Clean up</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>58</width>
<height>24</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="1" >
<widget class="QLabel" name="itemCount" >
<property name="text" >
<string>0 Items</string>
</property>
</widget>
</item>
<item row="1" column="2" >
<spacer name="horizontalSpacer" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>148</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>EditTableView</class>
<extends>QTableView</extends>
<header>DownloadItem.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -26,11 +26,14 @@
# include <QApplication> # include <QApplication>
# include <QButtonGroup> # include <QButtonGroup>
# include <QComboBox> # include <QComboBox>
# include <QDesktopServices>
# include <QGridLayout> # include <QGridLayout>
# include <QGroupBox> # include <QGroupBox>
# include <QLineEdit> # include <QLineEdit>
# include <QPushButton> # include <QPushButton>
# include <QRadioButton> # include <QRadioButton>
# include <QStyle>
# include <QUrl>
#endif #endif
#include <Base/Parameter.h> #include <Base/Parameter.h>
@ -45,6 +48,32 @@ using namespace Gui;
/* TRANSLATOR Gui::FileDialog */ /* TRANSLATOR Gui::FileDialog */
FileDialog::FileDialog(QWidget * parent)
: QFileDialog(parent)
{
connect(this, SIGNAL(filterSelected(const QString&)),
this, SLOT(onSelectedFilter(const QString&)));
}
FileDialog::~FileDialog()
{
}
void FileDialog::onSelectedFilter(const QString& filter)
{
QRegExp rx(QLatin1String("\\(\\*.(\\w+)"));
QString suf = selectedFilter();
if (rx.indexIn(suf) >= 0) {
suf = rx.cap(1);
setDefaultSuffix(suf.toLower());
}
}
void FileDialog::accept()
{
QFileDialog::accept();
}
/** /**
* This is a convenience static function that will return a file name selected by the user. The file does not have to exist. * This is a convenience static function that will return a file name selected by the user. The file does not have to exist.
*/ */
@ -84,7 +113,37 @@ QString FileDialog::getSaveFileName (QWidget * parent, const QString & caption,
// NOTE: We must not change the specified file name afterwards as we may return the name of an already // NOTE: We must not change the specified file name afterwards as we may return the name of an already
// existing file. Hence we must extract the first matching suffix from the filter list and append it // existing file. Hence we must extract the first matching suffix from the filter list and append it
// before showing the file dialog. // before showing the file dialog.
#if defined(FC_OS_LINUX)
QList<QUrl> urls;
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation));
urls << QUrl::fromLocalFile(getWorkingDirectory());
QString file;
FileDialog dlg(parent);
dlg.setWindowTitle(windowTitle);
dlg.setSidebarUrls(urls);
dlg.setIconProvider(new FileIconProvider());
dlg.setFileMode(QFileDialog::AnyFile);
dlg.setAcceptMode(QFileDialog::AcceptSave);
dlg.setDirectory(dirName);
dlg.setOptions(options);
dlg.setFilters(filter.split(QLatin1String(";;")));
dlg.onSelectedFilter(dlg.selectedFilter());
dlg.setNameFilterDetailsVisible(true);
dlg.setConfirmOverwrite(true);
if (dlg.exec() == QDialog::Accepted) {
if (selectedFilter)
*selectedFilter = dlg.selectedFilter();
file = dlg.selectedFiles().front();
}
#else
QString file = QFileDialog::getSaveFileName(parent, windowTitle, dirName, filter, selectedFilter, options); QString file = QFileDialog::getSaveFileName(parent, windowTitle, dirName, filter, selectedFilter, options);
#endif
if (!file.isEmpty()) { if (!file.isEmpty()) {
setWorkingDirectory(file); setWorkingDirectory(file);
return file; return file;
@ -129,7 +188,36 @@ QString FileDialog::getOpenFileName(QWidget * parent, const QString & caption, c
#if defined(FC_OS_MACOSX) #if defined(FC_OS_MACOSX)
options |= QFileDialog::DontUseNativeDialog; options |= QFileDialog::DontUseNativeDialog;
#endif #endif
#if defined(FC_OS_LINUX)
QList<QUrl> urls;
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation));
urls << QUrl::fromLocalFile(getWorkingDirectory());
QString file;
FileDialog dlg(parent);
dlg.setWindowTitle(windowTitle);
dlg.setSidebarUrls(urls);
dlg.setIconProvider(new FileIconProvider());
dlg.setFileMode(QFileDialog::ExistingFile);
dlg.setAcceptMode(QFileDialog::AcceptOpen);
dlg.setDirectory(dirName);
dlg.setOptions(options);
dlg.setFilters(filter.split(QLatin1String(";;")));
dlg.setNameFilterDetailsVisible(true);
if (dlg.exec() == QDialog::Accepted) {
if (selectedFilter)
*selectedFilter = dlg.selectedFilter();
file = dlg.selectedFiles().front();
}
#else
QString file = QFileDialog::getOpenFileName(parent, windowTitle, dirName, filter, selectedFilter, options); QString file = QFileDialog::getOpenFileName(parent, windowTitle, dirName, filter, selectedFilter, options);
#endif
if (!file.isEmpty()) { if (!file.isEmpty()) {
setWorkingDirectory(file); setWorkingDirectory(file);
return file; return file;
@ -155,7 +243,36 @@ QStringList FileDialog::getOpenFileNames (QWidget * parent, const QString & capt
#if defined(FC_OS_MACOSX) #if defined(FC_OS_MACOSX)
options |= QFileDialog::DontUseNativeDialog; options |= QFileDialog::DontUseNativeDialog;
#endif #endif
#if defined(FC_OS_LINUX)
QList<QUrl> urls;
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation));
urls << QUrl::fromLocalFile(getWorkingDirectory());
QStringList files;
FileDialog dlg(parent);
dlg.setWindowTitle(windowTitle);
dlg.setSidebarUrls(urls);
dlg.setIconProvider(new FileIconProvider());
dlg.setFileMode(QFileDialog::ExistingFiles);
dlg.setAcceptMode(QFileDialog::AcceptOpen);
dlg.setDirectory(dirName);
dlg.setOptions(options);
dlg.setFilters(filter.split(QLatin1String(";;")));
dlg.setNameFilterDetailsVisible(true);
if (dlg.exec() == QDialog::Accepted) {
if (selectedFilter)
*selectedFilter = dlg.selectedFilter();
files = dlg.selectedFiles();
}
#else
QStringList files = QFileDialog::getOpenFileNames(parent, windowTitle, dirName, filter, selectedFilter, options); QStringList files = QFileDialog::getOpenFileNames(parent, windowTitle, dirName, filter, selectedFilter, options);
#endif
if (!files.isEmpty()) { if (!files.isEmpty()) {
setWorkingDirectory(files.front()); setWorkingDirectory(files.front());
} }
@ -322,17 +439,17 @@ FileIconProvider::~FileIconProvider()
{ {
} }
QIcon FileIconProvider::icon ( IconType type ) const QIcon FileIconProvider::icon(IconType type) const
{ {
return QFileIconProvider::icon(type); return QFileIconProvider::icon(type);
} }
QIcon FileIconProvider::icon ( const QFileInfo & info ) const QIcon FileIconProvider::icon(const QFileInfo & info) const
{ {
return QFileIconProvider::icon(info); return QFileIconProvider::icon(info);
} }
QString FileIconProvider::type ( const QFileInfo & info ) const QString FileIconProvider::type(const QFileInfo & info) const
{ {
return QFileIconProvider::type(info); return QFileIconProvider::type(info);
} }

View File

@ -56,6 +56,14 @@ public:
static QString getWorkingDirectory(); static QString getWorkingDirectory();
static void setWorkingDirectory( const QString& ); static void setWorkingDirectory( const QString& );
FileDialog(QWidget * parent = 0);
~FileDialog();
void accept();
private Q_SLOTS:
void onSelectedFilter(const QString&);
}; };
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -105,9 +113,9 @@ public:
FileIconProvider(); FileIconProvider();
~FileIconProvider(); ~FileIconProvider();
QIcon icon ( IconType type ) const; QIcon icon(IconType type) const;
QIcon icon ( const QFileInfo & info ) const; QIcon icon(const QFileInfo & info) const;
QString type ( const QFileInfo & info ) const; QString type(const QFileInfo & info) const;
}; };
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------

View File

@ -25,10 +25,10 @@
#ifndef _PreComp_ #ifndef _PreComp_
# include <QMenu> # include <QMenu>
# include <QMouseEvent> # include <QMouseEvent>
# include <Inventor/nodes/SoCamera.h>
#endif #endif
#include <Inventor/SbVec2s.h> #include <Inventor/SbVec2s.h>
#include "View3DInventorViewer.h" #include "View3DInventorViewer.h"
#include "GLPainter.h"
#include "Flag.h" #include "Flag.h"
@ -455,4 +455,76 @@ QSize FlagLayout::calculateSize(SizeType sizeType) const
return totalSize; return totalSize;
} }
TYPESYSTEM_SOURCE_ABSTRACT(Gui::GLFlagWindow, Gui::GLGraphicsItem);
GLFlagWindow::GLFlagWindow(View3DInventorViewer* view) : _viewer(view), _flagLayout(0)
{
}
GLFlagWindow::~GLFlagWindow()
{
deleteFlags();
if (_flagLayout)
_flagLayout->deleteLater();
}
void GLFlagWindow::deleteFlags()
{
if (_flagLayout) {
int ct = _flagLayout->count();
for (int i=0; i<ct;i++) {
QWidget* flag = _flagLayout->itemAt(0)->widget();
if (flag) {
_flagLayout->removeWidget(flag);
flag->deleteLater();
}
}
}
}
void GLFlagWindow::addFlag(Flag* item, FlagLayout::Position pos)
{
if (!_flagLayout) {
_flagLayout = new FlagLayout(3);
_viewer->getGLWidget()->setLayout(_flagLayout);
}
item->setParent(_viewer->getGLWidget());
_flagLayout->addWidget(item, pos);
item->show();
_viewer->scheduleRedraw();
}
void GLFlagWindow::removeFlag(Flag* item)
{
if (_flagLayout) {
_flagLayout->removeWidget(item);
}
}
void GLFlagWindow::paintGL()
{
// draw lines for the flags
if (_flagLayout) {
// it can happen that the GL widget gets replaced internally by SoQt which
// causes to destroy the FlagLayout instance
int ct = _flagLayout->count();
const SbViewportRegion vp = _viewer->getViewportRegion();
SbVec2s size = vp.getViewportSizePixels();
float aspectratio = float(size[0])/float(size[1]);
SbViewVolume vv = _viewer->getCamera()->getViewVolume(aspectratio);
for (int i=0; i<ct;i++) {
Flag* flag = qobject_cast<Flag*>(_flagLayout->itemAt(i)->widget());
if (flag) {
SbVec3f pt = flag->getOrigin();
vv.projectToScreen(pt, pt);
int tox = (int)(pt[0] * size[0]);
int toy = (int)((1.0f-pt[1]) * size[1]);
flag->drawLine(_viewer, tox, toy);
}
}
}
}
#include "moc_Flag.cpp" #include "moc_Flag.cpp"

View File

@ -29,9 +29,11 @@
#include <QWidgetItem> #include <QWidgetItem>
#include <QGLWidget> #include <QGLWidget>
#include <Inventor/SbVec3f.h> #include <Inventor/SbVec3f.h>
#include <Gui/GLPainter.h>
namespace Gui { namespace Gui {
class View3DInventorViewer; class View3DInventorViewer;
/** /**
* @author Werner Mayer * @author Werner Mayer
*/ */
@ -98,6 +100,8 @@ private:
class FlagLayout : public QLayout class FlagLayout : public QLayout
{ {
Q_OBJECT
public: public:
enum Position { TopLeft, TopRight, BottomLeft, BottomRight }; enum Position { TopLeft, TopRight, BottomLeft, BottomRight };
@ -136,6 +140,24 @@ private:
QList<ItemWrapper *> list; QList<ItemWrapper *> list;
}; };
class GuiExport GLFlagWindow : public Gui::GLGraphicsItem
{
TYPESYSTEM_HEADER();
public:
GLFlagWindow(View3DInventorViewer*);
virtual ~GLFlagWindow();
void addFlag(Flag* item, FlagLayout::Position pos);
void removeFlag(Flag* item);
void deleteFlags();
void paintGL();
private:
View3DInventorViewer* _viewer;
FlagLayout* _flagLayout;
};
} // namespace Gui } // namespace Gui

View File

@ -31,6 +31,8 @@
using namespace Gui; using namespace Gui;
TYPESYSTEM_SOURCE_ABSTRACT(Gui::GLGraphicsItem, Base::BaseClass);
GLPainter::GLPainter() : viewer(0), logicOp(false), lineStipple(false) GLPainter::GLPainter() : viewer(0), logicOp(false), lineStipple(false)
{ {
} }

View File

@ -33,6 +33,8 @@
#include <GL/gl.h> #include <GL/gl.h>
#endif #endif
#include <Base/BaseClass.h>
namespace Gui { namespace Gui {
class View3DInventorViewer; class View3DInventorViewer;
class GuiExport GLPainter class GuiExport GLPainter
@ -71,6 +73,20 @@ private:
bool lineStipple; bool lineStipple;
}; };
class GuiExport GLGraphicsItem : public Base::BaseClass
{
TYPESYSTEM_HEADER();
public:
GLGraphicsItem()
{
}
virtual ~GLGraphicsItem()
{
}
virtual void paintGL() = 0;
};
} // namespace Gui } // namespace Gui
#endif // GUI_GLPAINTER_H #endif // GUI_GLPAINTER_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

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