Merge branch 'refs/heads/master' into jriegel/develop-fem
This commit is contained in:
commit
9d05dcc85c
|
@ -209,30 +209,64 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
|
|||
#first, look for OpenCASCADE Community Edition (OCE)
|
||||
#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
|
||||
if( NOT DEFINED OCE_DIR )
|
||||
if( UNIX )
|
||||
set( OCE_DIR "/usr/local/share/cmake/" )
|
||||
else()
|
||||
set( OCE_DIR "c:/OCE-0.4.0/share/cmake" )
|
||||
endif()
|
||||
endif()
|
||||
find_package ( OCE )
|
||||
if( ${OCE_FOUND} )
|
||||
message("-- OpenCASCADE Community Edition has been found.")
|
||||
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
|
||||
set( OCC_OCAF_LIBRARIES "TKCAF;TKXCAF;TKLCAF;TKXDESTEP;TKXDEIGES;TKMeshVS;TKAdvTools" ) #lib list copied from FreeCAD's FindOpenCasCade.cmake
|
||||
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()
|
||||
if(NOT DEFINED OCE_DIR)
|
||||
if(UNIX)
|
||||
set(OCE_DIR "/usr/local/share/cmake/")
|
||||
elseif(WIN32)
|
||||
set(OCE_DIR "c:/OCE-0.4.0/share/cmake")
|
||||
endif()
|
||||
endif()
|
||||
find_package (OCE QUIET)
|
||||
if(${OCE_FOUND})
|
||||
message("-- OpenCASCADE Community Edition has been found.")
|
||||
add_definitions (-DHAVE_CONFIG_H)
|
||||
#lib list copied from FreeCAD's FindOpenCasCade.cmake
|
||||
set(OCC_LIBRARIES
|
||||
TKFillet
|
||||
TKMesh
|
||||
TKernel
|
||||
TKG2d
|
||||
TKG3d
|
||||
TKMath
|
||||
TKIGES
|
||||
TKSTL
|
||||
TKShHealing
|
||||
TKXSBase
|
||||
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 --------------------------
|
||||
|
||||
|
@ -362,6 +396,17 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
|
|||
find_package(Spnav)
|
||||
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 ------------------------------
|
||||
|
||||
find_package(Matplotlib)
|
||||
|
@ -441,8 +486,14 @@ IF(APPLE)
|
|||
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
|
||||
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(data)
|
||||
#endif()
|
||||
|
||||
# ================================================================================
|
||||
# == Packaging ===================================================================
|
||||
|
|
|
@ -83,3 +83,7 @@ because it contains some Fortran code.
|
|||
project.
|
||||
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.
|
||||
|
||||
* FreeType
|
||||
|
||||
http://stackoverflow.com/questions/6207176/compiling-freetype-to-dll-as-opposed-to-static-library
|
||||
|
|
|
@ -13,6 +13,7 @@ IF (WIN32)
|
|||
FIND_PATH(COIN3D_INCLUDE_DIR Inventor/So.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/usr/include/coin
|
||||
)
|
||||
|
||||
FIND_LIBRARY(COIN3D_LIBRARY Coin
|
||||
|
|
|
@ -196,6 +196,8 @@ include(AddFileDependencies)
|
|||
|
||||
macro(fc_wrap_cpp outfiles )
|
||||
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)
|
||||
foreach(it ${moc_files})
|
||||
get_filename_component(it ${it} ABSOLUTE)
|
||||
|
|
|
@ -207,6 +207,8 @@ include(AddFileDependencies)
|
|||
|
||||
macro(fc_wrap_cpp outfiles )
|
||||
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)
|
||||
foreach(it ${moc_files})
|
||||
get_filename_component(it ${it} ABSOLUTE)
|
||||
|
|
|
@ -219,6 +219,8 @@ include(AddFileDependencies)
|
|||
|
||||
macro(fc_wrap_cpp outfiles )
|
||||
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)
|
||||
foreach(it ${moc_files})
|
||||
get_filename_component(it ${it} ABSOLUTE)
|
||||
|
@ -392,5 +394,19 @@ SET(EIGEN3_INCLUDE_DIR ${FREECAD_LIBPACK_DIR}/include/eigen3)
|
|||
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)
|
||||
|
|
|
@ -230,6 +230,8 @@ include(AddFileDependencies)
|
|||
|
||||
macro(fc_wrap_cpp outfiles )
|
||||
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)
|
||||
foreach(it ${moc_files})
|
||||
get_filename_component(it ${it} ABSOLUTE)
|
||||
|
@ -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_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)
|
||||
|
|
|
@ -12,7 +12,10 @@ ADD_CUSTOM_TARGET(Example_data ALL
|
|||
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(
|
||||
FILES
|
||||
|
|
|
@ -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
|
||||
|
||||
* 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
|
||||
|
||||
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
|
||||
|
||||
* 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
|
||||
|
||||
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
|
||||
|
||||
* 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
|
||||
|
||||
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
|
||||
|
||||
* Add 'dfsg' extension to upstream version, upstream sources are unchanged.
|
||||
|
|
|
@ -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>
|
||||
Vcs-Browser: http://git.debian.org/?p=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
|
||||
Build-Depends: debhelper (>= 7.0.50~), autotools-dev, libtool, automake,
|
||||
autoconf, libboost-dev, libboost-date-time-dev, libboost-filesystem-dev,
|
||||
Homepage: https://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Main_Page
|
||||
Build-Depends: debhelper (>= 7.0.50~), cmake,
|
||||
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,
|
||||
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,
|
||||
libcoin60-dev, libsoqt4-dev (>= 1.4.2~svn20090224), libeigen3-dev, libgl1-mesa-dev,
|
||||
zlib1g-dev, libxerces-c2-dev, libopencascade-foundation-dev, libopencascade-modeling-dev,
|
||||
libcoin60-dev, libsoqt4-dev, libeigen3-dev,
|
||||
zlib1g-dev, libxerces-c2-dev, libopencascade-foundation-dev,
|
||||
libopencascade-modeling-dev, libopencascade-ocaf-dev,
|
||||
libopencascade-visualization-dev, python-cxx-dev, libswscale-dev,
|
||||
libzipios++-dev, swig, gfortran, libqtwebkit-dev
|
||||
Standards-Version: 3.9.2
|
||||
libzipios++-dev, swig, gfortran, f2c, libqtwebkit-dev, libspnav-dev, libfreetype6-dev
|
||||
Standards-Version: 3.9.1
|
||||
|
||||
Package: freecad
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}
|
||||
Recommends: python-pivy python-matplotlib
|
||||
Recommends: python-pivy, python
|
||||
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.
|
||||
It features some key concepts like macro recording, workbenches, ability
|
||||
to run as a server and dynamically loadable application extensions and
|
||||
|
|
1018
package/debian/diff/freecad_precise.diff
Normal file
1018
package/debian/diff/freecad_precise.diff
Normal file
File diff suppressed because it is too large
Load Diff
8
package/debian/dirs
Normal file
8
package/debian/dirs
Normal 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
|
||||
|
|
@ -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
|
1
package/debian/freecad-doc.docs
Normal file
1
package/debian/freecad-doc.docs
Normal file
|
@ -0,0 +1 @@
|
|||
debian/tmp/usr/doc/*
|
|
@ -10,7 +10,7 @@ Exec=/usr/bin/freecad %F
|
|||
Path=/usr/lib/freecad
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=/usr/share/freecad/freecad.xpm
|
||||
Icon=freecad
|
||||
Categories=Graphics;Science;Engineering
|
||||
StartupNotify=true
|
||||
GenericName[de_DE]=Feature-basierter parametrischer Modellierer
|
||||
|
|
1
package/debian/freecad.manpages
Normal file
1
package/debian/freecad.manpages
Normal file
|
@ -0,0 +1 @@
|
|||
debian/freecad.1
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
|
||||
<mime-type type="application/x-extension-fcstd">
|
||||
<sub-class-of type="application/zip"/>
|
||||
<!-- <sub-class-of type="application/zip"/> -->
|
||||
<comment>FreeCAD document files</comment>
|
||||
<glob pattern="*.fcstd"/>
|
||||
</mime-type>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[Thumbnailer Entry]
|
||||
TryExec=freecad-thumbnailer
|
||||
Exec=freecad-thumbnailer -s %s %u %o
|
||||
MimeType=application/x-extension-fcstd;
|
|
@ -2,5 +2,5 @@
|
|||
section="Applications/Science/Engineering"\
|
||||
title="FreeCAD"\
|
||||
command="/usr/bin/freecad"\
|
||||
icon="/usr/share/freecad/freecad.xpm"
|
||||
icon="/usr/share/pixmaps/freecad.xpm"
|
||||
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import sys, zipfile, md5
|
||||
import sys, zipfile
|
||||
import getopt
|
||||
import gnomevfs
|
||||
from urlparse import urlparse
|
||||
from urlparse import unquote
|
||||
|
||||
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]
|
||||
|
||||
try:
|
||||
|
@ -19,8 +24,9 @@ try:
|
|||
if image in files:
|
||||
image=zfile.read(image)
|
||||
else:
|
||||
freecad=open("/usr/share/freecad/freecad-doc.png")
|
||||
image=freecad.read()
|
||||
#freecad=open("/usr/share/freecad/freecad-doc.png")
|
||||
#image=freecad.read()
|
||||
sys.exit(1)
|
||||
|
||||
thumb=open(outfile,"wb")
|
||||
thumb.write(image)
|
||||
|
|
4
package/debian/mime/freecad.thumbnailer
Normal file
4
package/debian/mime/freecad.thumbnailer
Normal 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;
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -4,7 +4,7 @@
|
|||
# Uncomment this to turn on verbose mode.
|
||||
#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
|
||||
# from having to guess our platform (since we know it already)
|
||||
|
@ -19,58 +19,32 @@ else
|
|||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
patch-stamp:
|
||||
touch $@
|
||||
|
||||
configure: autogen.sh patch-stamp
|
||||
configure:
|
||||
dh_testdir
|
||||
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 \
|
||||
cp -a $$autotools_mod_file $$autotools_mod_file.setaside; \
|
||||
done
|
||||
chmod u+x autogen.sh
|
||||
./autogen.sh
|
||||
|
||||
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
|
||||
cmake . \
|
||||
-DFREECAD_BUILD_DEBIAN=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/lib/freecad \
|
||||
-DCMAKE_INSTALL_MANDIR=/usr/share/man \
|
||||
-DCMAKE_INSTALL_INFODIR=/usr/share/info \
|
||||
-DCMAKE_INSTALL_DATADIR=/usr/share/freecad \
|
||||
-DCMAKE_INSTALL_INCLUDEDIR=/usr/include/freecad \
|
||||
-DCMAKE_INSTALL_DOCDIR=/usr/share/doc/freecad
|
||||
|
||||
build: build-stamp
|
||||
|
||||
build-stamp: config.status
|
||||
build-stamp: configure
|
||||
dh_testdir
|
||||
$(MAKE)
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
mv src/Build/Version.h src/Build/Version.h.old
|
||||
dh clean
|
||||
mv src/Build/Version.h.old src/Build/Version.h
|
||||
rm -f build-stamp
|
||||
find -name '*.pyc' | xargs rm -f
|
||||
find -name 'moc_*.cpp' | xargs rm -f
|
||||
find -name '*.lo' | xargs rm -f
|
||||
find -name '*.deps' | xargs rm -rf
|
||||
find -name '*.libs' | xargs rm -rf
|
||||
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/
|
||||
find -name 'ui_*.h' | xargs rm -f
|
||||
find -name 'CMakeFiles' | xargs rm -rf
|
||||
rm -f stamp-h1
|
||||
|
||||
install: build install-stamp
|
||||
install-stamp:
|
||||
|
@ -78,44 +52,34 @@ install-stamp:
|
|||
dh_testroot
|
||||
dh_prep
|
||||
dh_installdirs
|
||||
$(MAKE) install 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
|
||||
$(MAKE) install/fast DESTDIR=$(CURDIR)/debian/tmp/freecad
|
||||
# install the core system
|
||||
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/lib/FreeCAD.so usr/lib/freecad/lib
|
||||
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/lib usr/lib/freecad
|
||||
dh_install -pfreecad debian/tmp/freecad/usr/lib/freecad/Mod usr/lib/freecad
|
||||
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
|
||||
# install the modules
|
||||
$(foreach MODULE,$(MODULES), \
|
||||
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 headers
|
||||
#dh_install -pfreecad-dev debian/tmp/freecad/usr/include/* usr/include
|
||||
# install the help system
|
||||
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
|
||||
|
||||
override_dh_compress:
|
||||
|
|
47
package/debian/scripts/get_git_orig_src.sh
Normal file
47
package/debian/scripts/get_git_orig_src.sh
Normal 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
|
|
@ -1,2 +0,0 @@
|
|||
libGL 1 libgl1-mesa-glx (>= 7.7.1-1)
|
||||
libSoQt4 20 libsoqt4-20 (>= 1.4.2~svn20090224)
|
|
@ -1 +1 @@
|
|||
3.0 (quilt)
|
||||
1.0
|
||||
|
|
|
@ -16,68 +16,36 @@
|
|||
# http://www.grymoire.com/Unix/Sed.html
|
||||
|
||||
# global settings
|
||||
REV_FILE=./revision.m4
|
||||
TMP_PATH=/tmp
|
||||
MAJ=0
|
||||
MIN=12
|
||||
ALIAS="Vulcan"
|
||||
MIN=13
|
||||
|
||||
# go to root directory
|
||||
CUR_DIR=$PWD
|
||||
verz=`dirname $(readlink -f ${0})`
|
||||
cd $verz && cd ..
|
||||
|
||||
# let's import OLD_REV (if there)
|
||||
if [ -f ./.last_revision ]; then
|
||||
. ./.last_revision
|
||||
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`
|
||||
# http://blog.marcingil.com/2011/11/creating-build-numbers-using-git-commits/
|
||||
if git log -1 >/dev/null 2>&1; then
|
||||
REV=`git rev-list HEAD | wc -l | sed -e 's/ *//g' | xargs -n1 printf %04d`
|
||||
else
|
||||
REV=0
|
||||
LCD=""
|
||||
URL=""
|
||||
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
|
||||
|
||||
# Prepare source tarball and unpack it in build directory
|
||||
cd $CUR_DIR
|
||||
make dist
|
||||
make dist-git
|
||||
cd $verz && cd ..
|
||||
rm -rf $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
|
||||
tar -xzf freecad_$MAJ.$MIN.$REV.orig.tar.gz
|
||||
mv FreeCAD-$MAJ.$MIN.$REV freecad-$MAJ.$MIN.$REV
|
||||
cd freecad-$MAJ.$MIN.$REV
|
||||
rm -rf src/CXX
|
||||
rm -rf src/zipios++
|
||||
#rm -rf src/CXX
|
||||
#rm -rf src/zipios++
|
||||
|
||||
# Prepare debian folder and set the revision number in debian/changelog
|
||||
# for package versioning
|
||||
|
|
|
@ -42,9 +42,13 @@
|
|||
|
||||
#include "utilities.h"
|
||||
|
||||
#include <Standard_Version.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#if OCC_VERSION_HEX >= 0x060600
|
||||
#include <BRepClass3d.hxx>
|
||||
#endif
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Shell.hxx>
|
||||
|
@ -159,7 +163,11 @@ bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& a
|
|||
|
||||
// get 2 shells
|
||||
TopoDS_Solid solid = TopoDS::Solid( aShape );
|
||||
#if OCC_VERSION_HEX >= 0x060600
|
||||
TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid );
|
||||
#else
|
||||
TopoDS_Shell outerShell = BRepTools::OuterShell( solid );
|
||||
#endif
|
||||
TopoDS_Shape innerShell;
|
||||
int nbShells = 0;
|
||||
for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells )
|
||||
|
|
|
@ -1008,7 +1008,10 @@ void Application::initTypes(void)
|
|||
App ::PropertyPercent ::init();
|
||||
App ::PropertyEnumeration ::init();
|
||||
App ::PropertyIntegerList ::init();
|
||||
App ::PropertyIntegerSet ::init();
|
||||
App ::PropertyMap ::init();
|
||||
App ::PropertyString ::init();
|
||||
App ::PropertyUUID ::init();
|
||||
App ::PropertyFont ::init();
|
||||
App ::PropertyStringList ::init();
|
||||
App ::PropertyLink ::init();
|
||||
|
@ -1211,9 +1214,10 @@ void Application::processCmdLineFiles(void)
|
|||
Base::Interpreter().runFile(File.filePath().c_str(), true);
|
||||
}
|
||||
else if (File.hasExtension("py")) {
|
||||
try{
|
||||
try {
|
||||
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__)
|
||||
Base::Interpreter().runFile(File.filePath().c_str(),true);
|
||||
}
|
||||
|
|
|
@ -64,6 +64,10 @@ recompute path. Also enables more complicated dependencies beyond trees.
|
|||
#include <boost/graph/graphviz.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
|
||||
#include "Document.h"
|
||||
|
@ -433,8 +437,41 @@ unsigned int Document::getMaxUndoStackSize(void)const
|
|||
void Document::onChanged(const Property* prop)
|
||||
{
|
||||
// the Name property is a label for display purposes
|
||||
if (prop == &Label)
|
||||
if (prop == &Label) {
|
||||
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)
|
||||
|
@ -525,7 +562,7 @@ Document::Document(void)
|
|||
#endif
|
||||
|
||||
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(CreationDate,(Base::TimeInfo::currentDateTimeString()),0,Prop_ReadOnly,"Date of creation");
|
||||
ADD_PROPERTY_TYPE(LastModifiedBy,(""),0,Prop_None,0);
|
||||
|
@ -537,19 +574,16 @@ Document::Document(void)
|
|||
// create the uuid for the document
|
||||
Base::Uuid id;
|
||||
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
|
||||
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");
|
||||
|
||||
// create transient directory
|
||||
std::string basePath = Base::FileInfo::getTempPath() + GetApplication().getExecutableName();
|
||||
Base::FileInfo TransDir(basePath + "_Doc_" + id.getValue());
|
||||
if (!TransDir.exists())
|
||||
TransDir.createDirectory();
|
||||
ADD_PROPERTY_TYPE(TransientDir,(TransDir.filePath().c_str()),0,Prop_Transient,
|
||||
// this creates and sets 'TransientDir' in onChanged()
|
||||
ADD_PROPERTY_TYPE(TransientDir,(""),0,PropertyType(Prop_Transient|Prop_ReadOnly),
|
||||
"Transient directory, where the files live while the document is open");
|
||||
Uid.touch();
|
||||
}
|
||||
|
||||
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
|
||||
// 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.
|
||||
// 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.
|
||||
Base::PyObjectBase* doc = (Base::PyObjectBase*)DocumentPythonObject.ptr();
|
||||
// Call before decrementing the reference counter, otherwise a heap error can occur
|
||||
|
@ -586,6 +620,19 @@ Document::~Document()
|
|||
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
|
||||
//--------------------------------------------------------------------------
|
||||
|
@ -623,12 +670,7 @@ void Document::Restore(Base::XMLReader &reader)
|
|||
std::string FilePath = FileName.getValue();
|
||||
std::string DocLabel = Label.getValue();
|
||||
|
||||
// remove previous Transient directory
|
||||
Base::FileInfo TransDir(TransientDir.getValue());
|
||||
TransDir.deleteDirectoryRecursive();
|
||||
|
||||
|
||||
// read the Document Properties
|
||||
// read the Document Properties, when reading in Uid the transient directory gets renamed automatically
|
||||
PropertyContainer::Restore(reader);
|
||||
|
||||
// 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());
|
||||
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"
|
||||
if ( scheme == 2 ) {
|
||||
// read the feature types
|
||||
|
@ -769,8 +803,8 @@ Document::readObjects(Base::XMLReader& reader)
|
|||
reader.addName(name.c_str(), obj->getNameInDocument());
|
||||
}
|
||||
}
|
||||
catch (Base::Exception&) {
|
||||
Base::Console().Message("Cannot create object '%s'\n", name.c_str());
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("Cannot create object '%s': (%s)\n", name.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
reader.readEndElement("Objects");
|
||||
|
@ -857,6 +891,18 @@ void Document::exportGraphviz(std::ostream& out)
|
|||
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
|
||||
bool Document::save (void)
|
||||
{
|
||||
|
@ -1090,6 +1136,58 @@ std::vector<App::DocumentObject*> Document::getInList(const DocumentObject* me)
|
|||
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)
|
||||
{
|
||||
d->VertexObjectList.clear();
|
||||
|
@ -1119,21 +1217,6 @@ void Document::recompute()
|
|||
// updates the dependency graph
|
||||
_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;
|
||||
DependencyList::out_edge_iterator j, jend;
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
//void saveAs (const char* Name);
|
||||
/// Save the document to the file in Property Path
|
||||
bool save (void);
|
||||
bool saveAs(const char* file);
|
||||
/// Restore the document from the file in Property Path
|
||||
void restore (void);
|
||||
void exportObjects(const std::vector<App::DocumentObject*>&, std::ostream&);
|
||||
|
@ -264,6 +265,10 @@ public:
|
|||
bool checkOnCycle(void);
|
||||
/// get a list of all objects linking to the given object
|
||||
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
|
||||
//void setChanged(DocumentObject* change);
|
||||
//@}
|
||||
|
@ -303,6 +308,7 @@ protected:
|
|||
void _clearRedos();
|
||||
/// refresh the internal dependency graph
|
||||
void _rebuildDependencyList(void);
|
||||
std::string getTransientDirectoryName(const std::string& uuid, const std::string& filename) const;
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
@ -38,6 +38,15 @@ namespace App
|
|||
class Document;
|
||||
class DocumentObjectPy;
|
||||
|
||||
enum ObjectStatus {
|
||||
Touch = 0,
|
||||
Error = 1,
|
||||
New = 2,
|
||||
Recompute = 3,
|
||||
Restore = 4,
|
||||
Expand = 16
|
||||
};
|
||||
|
||||
/** Return object for feature execution
|
||||
*/
|
||||
class AppExport DocumentObjectExecReturn
|
||||
|
@ -105,9 +114,11 @@ public:
|
|||
virtual App::DocumentObjectExecReturn *recompute(void);
|
||||
/// return the status bits
|
||||
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;
|
||||
/// get all objects link to this object
|
||||
std::vector<App::DocumentObject*> getInList(void) const;
|
||||
|
@ -129,7 +140,7 @@ public:
|
|||
|
||||
/** Called in case of loosing a link
|
||||
* 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
|
||||
*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
|
||||
* descendent classes to to mark special stati on the objects.
|
||||
* The bits and their meaning are listed below:
|
||||
* 0 - object is marked as 'touched'
|
||||
* 1 - object is marked as 'erroneous'
|
||||
* 2 - object is marked as 'new'
|
||||
* 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
|
||||
* 5 - reserved
|
||||
* 6 - reserved
|
||||
* 7 - reserved
|
||||
* 0 - object is marked as 'touched'
|
||||
* 1 - object is marked as 'erroneous'
|
||||
* 2 - object is marked as 'new'
|
||||
* 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
|
||||
* 5 - reserved
|
||||
* 6 - reserved
|
||||
* 7 - reserved
|
||||
* 16 - object is marked as 'expanded' in the tree view
|
||||
*/
|
||||
std::bitset<32> StatusBits;
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ void DocumentObserverPython::slotCreatedDocument(const App::Document& Doc)
|
|||
}
|
||||
catch (Py::Exception&) {
|
||||
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&) {
|
||||
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&) {
|
||||
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&) {
|
||||
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&) {
|
||||
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&) {
|
||||
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&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
e.ReportException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,17 @@
|
|||
</Documentation>
|
||||
<Methode Name="save">
|
||||
<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>
|
||||
</Methode>
|
||||
<Methode Name="restore">
|
||||
<Documentation>
|
||||
<UserDocu>Restore the document from disc</UserDocu>
|
||||
<UserDocu>Restore the document from disk</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="exportGraphviz">
|
||||
|
|
|
@ -69,6 +69,25 @@ PyObject* DocumentPy::save(PyObject * args)
|
|||
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)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
|
|
|
@ -67,6 +67,7 @@ DocumentObjectExecReturn *FeaturePythonImp::execute()
|
|||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.ReportException();
|
||||
std::stringstream str;
|
||||
str << object->Label.getValue() << ": " << e.what();
|
||||
return new App::DocumentObjectExecReturn(str.str());
|
||||
|
@ -104,8 +105,7 @@ void FeaturePythonImp::onChanged(const Property* prop)
|
|||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Error("FeaturePython::onChanged (%s): %s\n",
|
||||
object->Label.getValue(), e.what());
|
||||
e.ReportException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
*/
|
||||
virtual unsigned int getMemSize (void) const {
|
||||
// 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
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <algorithm>
|
||||
# include <sstream>
|
||||
#endif
|
||||
|
||||
|
@ -35,12 +36,13 @@
|
|||
#include <Base/Stream.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
#include <Base/Uuid.h>
|
||||
|
||||
#include "PropertyFile.h"
|
||||
#include "Document.h"
|
||||
#include "PropertyContainer.h"
|
||||
#include "DocumentObject.h"
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
|
||||
using namespace App;
|
||||
using namespace Base;
|
||||
using namespace std;
|
||||
|
@ -53,6 +55,7 @@ using namespace std;
|
|||
|
||||
TYPESYSTEM_SOURCE(App::PropertyFileIncluded , App::Property);
|
||||
|
||||
|
||||
PropertyFileIncluded::PropertyFileIncluded()
|
||||
{
|
||||
|
||||
|
@ -63,17 +66,45 @@ PropertyFileIncluded::~PropertyFileIncluded()
|
|||
// clean up
|
||||
if (!_cValue.empty()) {
|
||||
Base::FileInfo file(_cValue.c_str());
|
||||
file.setPermissions(Base::FileInfo::ReadWrite);
|
||||
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 path;
|
||||
PropertyContainer *co = getContainer();
|
||||
if (co->isDerivedFrom(DocumentObject::getClassTypeId()))
|
||||
return dynamic_cast<DocumentObject*>(co)->getDocument()->TransientDir.getValue();
|
||||
if (co->isDerivedFrom(DocumentObject::getClassTypeId())) {
|
||||
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
|
||||
|
@ -97,34 +128,40 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
|
|||
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)
|
||||
Base::FileInfo value(_cValue);
|
||||
std::string pathAct = value.dirPath();
|
||||
if (value.exists())
|
||||
if (value.exists()) {
|
||||
value.setPermissions(Base::FileInfo::ReadWrite);
|
||||
value.deleteFile();
|
||||
}
|
||||
|
||||
// if a special name given, use this instead
|
||||
if (sName) {
|
||||
Base::FileInfo ExtraName(path + "/" + sName);
|
||||
if (ExtraName.exists() ) {
|
||||
Base::FileInfo fi(pathTrans + "/" + sName);
|
||||
if (fi.exists()) {
|
||||
// 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;
|
||||
|
||||
do {
|
||||
i++;
|
||||
std::stringstream str;
|
||||
str << path << "/" << sName << i;
|
||||
ExtraName.setFile(str.str());
|
||||
str << dir << "/" << fnp << i;
|
||||
if (!ext.empty())
|
||||
str << "." << ext;
|
||||
fi.setFile(str.str());
|
||||
}
|
||||
while (ExtraName.exists());
|
||||
_cValue = ExtraName.filePath();
|
||||
_BaseFileName = ExtraName.fileName();
|
||||
while (fi.exists());
|
||||
|
||||
_cValue = fi.filePath();
|
||||
_BaseFileName = fi.fileName();
|
||||
}
|
||||
else {
|
||||
_cValue = path + "/" + sName;
|
||||
_cValue = pathTrans + "/" + sName;
|
||||
_BaseFileName = sName;
|
||||
}
|
||||
}
|
||||
|
@ -133,39 +170,61 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
|
|||
_BaseFileName = file.fileName();
|
||||
}
|
||||
|
||||
// if the files is already in transient dir of the document, just use it
|
||||
if (path == pathTrans) {
|
||||
// The following applies only on files that are inside the transient
|
||||
// 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());
|
||||
//assert(done);
|
||||
if (!done) {
|
||||
std::stringstream str;
|
||||
str << "Cannot rename file " << file.filePath() << " to " << _cValue;
|
||||
throw Base::Exception(str.str());
|
||||
}
|
||||
|
||||
// make the file read-only
|
||||
Base::FileInfo dst(_cValue);
|
||||
dst.setPermissions(Base::FileInfo::ReadOnly);
|
||||
}
|
||||
// otherwise copy from origin location
|
||||
else {
|
||||
// if file already exists in transient dir make a new unique name
|
||||
Base::FileInfo fi(_cValue);
|
||||
if (fi.exists()) {
|
||||
Base::FileInfo fi2(Base::FileInfo::getTempFileName());
|
||||
std::stringstream str;
|
||||
str << fi.dirPath() << "/" << fi2.fileNamePure();
|
||||
// if a file with this name already exists search for a new one
|
||||
std::string dir = fi.dirPath();
|
||||
std::string fnp = fi.fileNamePure();
|
||||
std::string ext = fi.extension(false);
|
||||
if (!ext.empty())
|
||||
str << "." << ext;
|
||||
Base::FileInfo fi3(str.str());
|
||||
_cValue = fi3.filePath();
|
||||
_BaseFileName = fi3.fileName();
|
||||
int i=0;
|
||||
do {
|
||||
i++;
|
||||
std::stringstream str;
|
||||
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());
|
||||
//assert(done);
|
||||
if (!done) {
|
||||
std::stringstream str;
|
||||
str << "Cannot copy file from " << file.filePath() << " to " << _cValue;
|
||||
throw Base::Exception(str.str());
|
||||
}
|
||||
|
||||
// make the file read-only
|
||||
Base::FileInfo dst(_cValue);
|
||||
dst.setPermissions(Base::FileInfo::ReadOnly);
|
||||
}
|
||||
|
||||
hasSetValue();
|
||||
|
@ -180,7 +239,7 @@ const char* PropertyFileIncluded::getValue(void) const
|
|||
PyObject *PropertyFileIncluded::getPyObject(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -201,7 +260,7 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
|
|||
}
|
||||
else if (PyTuple_Check(value)) {
|
||||
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* name = PyTuple_GetItem(value,1);
|
||||
|
||||
|
@ -220,9 +279,9 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
|
|||
fileStr = PyString_AsString(FileName);
|
||||
}
|
||||
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;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
// decoding name
|
||||
|
@ -235,19 +294,18 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
|
|||
nameStr = PyString_AsString(FileName);
|
||||
}
|
||||
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;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
setValue(fileStr.c_str(),nameStr.c_str());
|
||||
return;
|
||||
|
||||
}
|
||||
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;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
// assign the string
|
||||
|
@ -256,29 +314,39 @@ void PropertyFileIncluded::setPyObject(PyObject *value)
|
|||
|
||||
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 (!_cValue.empty()) {
|
||||
Base::FileInfo file(_cValue.c_str());
|
||||
writer.Stream() << writer.ind() << "<FileIncluded data=\"" <<
|
||||
file.fileName() << "\">" << std::endl;
|
||||
writer.Stream() << writer.ind() << "<FileIncluded data=\""
|
||||
<< file.fileName() << "\">" << std::endl;
|
||||
// write the file in the XML stream
|
||||
writer.incInd();
|
||||
writer.insertBinFile(_cValue.c_str());
|
||||
writer.decInd();
|
||||
writer.Stream() << writer.ind() <<"</FileIncluded>" << endl;
|
||||
}
|
||||
else
|
||||
else {
|
||||
writer.Stream() << writer.ind() << "<FileIncluded data=\"\"/>" << std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// instead initiate an extra file
|
||||
if (!_cValue.empty()) {
|
||||
Base::FileInfo file(_cValue.c_str());
|
||||
writer.Stream() << writer.ind() << "<FileIncluded file=\"" <<
|
||||
writer.addFile(file.fileName().c_str(), this) << "\"/>" << std::endl;
|
||||
writer.Stream() << writer.ind() << "<FileIncluded file=\""
|
||||
<< writer.addFile(file.fileName().c_str(), this) << "\"/>" << std::endl;
|
||||
}
|
||||
else
|
||||
else {
|
||||
writer.Stream() << writer.ind() << "<FileIncluded file=\"\"/>" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,6 +375,9 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader)
|
|||
reader.readBinFile(_cValue.c_str());
|
||||
reader.readEndElement("FileIncluded");
|
||||
_BaseFileName = file;
|
||||
// set read-only after restoring the file
|
||||
Base::FileInfo fi(_cValue.c_str());
|
||||
fi.setPermissions(Base::FileInfo::ReadOnly);
|
||||
hasSetValue();
|
||||
}
|
||||
}
|
||||
|
@ -315,9 +386,12 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader)
|
|||
void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
|
||||
{
|
||||
Base::ifstream from(Base::FileInfo(_cValue.c_str()));
|
||||
if (!from)
|
||||
throw Base::Exception("PropertyFileIncluded::SaveDocFile() "
|
||||
"File in document transient dir deleted");
|
||||
if (!from) {
|
||||
std::stringstream str;
|
||||
str << "PropertyFileIncluded::SaveDocFile(): "
|
||||
<< "File '" << _cValue << "' in transient directory doesn't exist.";
|
||||
throw Base::Exception(str.str());
|
||||
}
|
||||
|
||||
// copy plain data
|
||||
unsigned char c;
|
||||
|
@ -329,10 +403,14 @@ void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
|
|||
|
||||
void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
|
||||
{
|
||||
Base::ofstream to(Base::FileInfo(_cValue.c_str()));
|
||||
if (!to)
|
||||
throw Base::Exception("PropertyFileIncluded::RestoreDocFile() "
|
||||
"File in document transient dir deleted");
|
||||
Base::FileInfo fi(_cValue.c_str());
|
||||
Base::ofstream to(fi);
|
||||
if (!to) {
|
||||
std::stringstream str;
|
||||
str << "PropertyFileIncluded::RestoreDocFile(): "
|
||||
<< "File '" << _cValue << "' in transient directory doesn't exist.";
|
||||
throw Base::Exception(str.str());
|
||||
}
|
||||
|
||||
// copy plain data
|
||||
aboutToSetValue();
|
||||
|
@ -341,6 +419,9 @@ void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
|
|||
to.put((const char)c);
|
||||
}
|
||||
to.close();
|
||||
|
||||
// set read-only after restoring the file
|
||||
fi.setPermissions(Base::FileInfo::ReadOnly);
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
|
@ -351,18 +432,39 @@ Property *PropertyFileIncluded::Copy(void) const
|
|||
// remember the base name
|
||||
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
|
||||
Base::FileInfo NewName(Base::FileInfo::getTempFileName(file.fileName().c_str(),file.dirPath().c_str()));
|
||||
NewName.deleteFile();
|
||||
// move the file
|
||||
bool done = file.renameFile(NewName.filePath().c_str());
|
||||
assert(done);
|
||||
Base::FileInfo newName(getUniqueFileName(file.dirPath(), file.fileName()));
|
||||
if (this->StatusBits.test(10)) {
|
||||
// rename the file
|
||||
bool done = file.renameFile(newName.filePath().c_str());
|
||||
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
|
||||
Base::Console().Log("Copy this=%p Before=%s After=%s\n",prop,prop->_cValue.c_str(),NewName.filePath().c_str());
|
||||
prop->_cValue = 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();
|
||||
|
||||
// make backup files writable to avoid copying them again on undo/redo
|
||||
newName.setPermissions(Base::FileInfo::ReadWrite);
|
||||
}
|
||||
|
||||
return prop;
|
||||
|
@ -371,26 +473,65 @@ Property *PropertyFileIncluded::Copy(void) const
|
|||
void PropertyFileIncluded::Paste(const Property &from)
|
||||
{
|
||||
aboutToSetValue();
|
||||
Base::FileInfo file(_cValue);
|
||||
// delete old file (if still there)
|
||||
file.deleteFile();
|
||||
const PropertyFileIncluded &fileInc = dynamic_cast<const PropertyFileIncluded&>(from);
|
||||
const PropertyFileIncluded &prop = dynamic_cast<const PropertyFileIncluded&>(from);
|
||||
// make sure that source and destination file are different
|
||||
if (_cValue != prop._cValue) {
|
||||
// delete old file (if still there)
|
||||
Base::FileInfo fi(_cValue);
|
||||
fi.setPermissions(Base::FileInfo::ReadWrite);
|
||||
fi.deleteFile();
|
||||
|
||||
// set the base name
|
||||
_BaseFileName = fileInc._BaseFileName;
|
||||
// get path to destination which can be the transient directory
|
||||
// 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()) {
|
||||
// move the saved files back in place
|
||||
Base::FileInfo NewFile(fileInc._cValue);
|
||||
_cValue = NewFile.dirPath() + "/" + fileInc._BaseFileName;
|
||||
bool done = NewFile.renameFile(_cValue.c_str());
|
||||
assert(done);
|
||||
if (fiSrc.exists()) {
|
||||
fiDst.setFile(getUniqueFileName(fiDst.dirPath(), fiDst.fileName()));
|
||||
|
||||
// if the file is already in transient dir of the document, just use it
|
||||
if (path == pathTrans) {
|
||||
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();
|
||||
}
|
||||
|
||||
unsigned int PropertyFileIncluded::getMemSize (void) const
|
||||
{
|
||||
unsigned int mem = Property::getMemSize();
|
||||
mem += _cValue.size();
|
||||
mem += _BaseFileName.size();
|
||||
return mem;
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// PropertyFile
|
||||
|
|
|
@ -95,9 +95,7 @@ public:
|
|||
|
||||
virtual Property *Copy(void) const;
|
||||
virtual void Paste(const Property &from);
|
||||
|
||||
// get the transient path if the property is in a DocumentObject
|
||||
std::string getDocTransientPath(void) const;
|
||||
virtual unsigned int getMemSize (void) const;
|
||||
|
||||
/** get a temp file name in the transient path of the document.
|
||||
* Using this file for new Version of the file and set
|
||||
|
@ -107,8 +105,14 @@ public:
|
|||
std::string getExchangeTempFile(void) const;
|
||||
|
||||
protected:
|
||||
std::string _cValue;
|
||||
std::string _BaseFileName;
|
||||
// get the transient path if the property is in a DocumentObject
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ void PropertyVector::setPyObject(PyObject *value)
|
|||
else if (PyInt_Check(item))
|
||||
cVec.x = (float)PyInt_AsLong(item);
|
||||
else
|
||||
throw Base::Exception("Not allowed type used in tuple (float expected)...");
|
||||
throw Base::TypeError("Not allowed type used in tuple (float expected)...");
|
||||
// y
|
||||
item = PyTuple_GetItem(value,1);
|
||||
if (PyFloat_Check(item))
|
||||
|
@ -125,7 +125,7 @@ void PropertyVector::setPyObject(PyObject *value)
|
|||
else if (PyInt_Check(item))
|
||||
cVec.y = (float)PyInt_AsLong(item);
|
||||
else
|
||||
throw Base::Exception("Not allowed type used in tuple (float expected)...");
|
||||
throw Base::TypeError("Not allowed type used in tuple (float expected)...");
|
||||
// z
|
||||
item = PyTuple_GetItem(value,2);
|
||||
if (PyFloat_Check(item))
|
||||
|
@ -133,13 +133,13 @@ void PropertyVector::setPyObject(PyObject *value)
|
|||
else if (PyInt_Check(item))
|
||||
cVec.z = (float)PyInt_AsLong(item);
|
||||
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 );
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be 'Vector' or tuple of three floats, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ void PropertyVectorList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be 'Vector' or list of 'Vector', not ");
|
||||
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))
|
||||
cMatrix[x][y] = (double)PyInt_AsLong(item);
|
||||
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 {
|
||||
std::string error = std::string("type must be 'Matrix' or tuple of 16 float or int, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ void PropertyPlacement::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be 'Matrix' or 'Placement', not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ void PropertyLink::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be 'DocumentObject' or 'NoneType', not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ void PropertyLinkSub::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type of first element in tuple must be 'DocumentObject', not ");
|
||||
error += tup[0].ptr()->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
else if(Py_None == value) {
|
||||
|
@ -266,7 +266,7 @@ void PropertyLinkSub::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not ");
|
||||
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))) {
|
||||
std::string error = std::string("type in list must be 'DocumentObject', not ");
|
||||
error += (*item)->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
values[i] = static_cast<DocumentObjectPy*>(*item)->getDocumentObjectPtr();
|
||||
|
@ -424,7 +424,7 @@ void PropertyLinkList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,7 +609,7 @@ void PropertyLinkSubList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ std::string PropertyPythonObject::toString() const
|
|||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Warning("PropertyPythonObject::toString: %s\n", e.what());
|
||||
e.ReportException();
|
||||
}
|
||||
|
||||
return repr;
|
||||
|
@ -139,7 +139,7 @@ void PropertyPythonObject::fromString(const std::string& repr)
|
|||
}
|
||||
catch (Py::Exception&) {
|
||||
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&) {
|
||||
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&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Warning("PropertyPythonObject::Save: %s\n", e.what());
|
||||
e.ReportException();
|
||||
}
|
||||
|
||||
saveObject(writer);
|
||||
|
@ -350,7 +350,7 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader)
|
|||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Warning("PropertyPythonObject::Restore: %s\n", e.what());
|
||||
e.ReportException();
|
||||
this->object = Py::None();
|
||||
load_failed = true;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ void PropertyInteger::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be int, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@ void PropertyPath::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be str or unicode, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
// assign the path
|
||||
|
@ -472,7 +472,7 @@ void PropertyEnumeration::setPyObject(PyObject *value)
|
|||
long i=0;
|
||||
while(*(plEnums++) != NULL)i++;
|
||||
if (val < 0 || i <= val)
|
||||
throw Py::ValueError("Out of range");
|
||||
throw Base::ValueError("Out of range");
|
||||
PropertyInteger::setValue(val);
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +481,7 @@ void PropertyEnumeration::setPyObject(PyObject *value)
|
|||
if (_EnumArray && isPartOf(str))
|
||||
setValue(PyString_AsString (value));
|
||||
else
|
||||
throw Py::ValueError("not part of the enum");
|
||||
throw Base::ValueError("not part of the enum");
|
||||
}
|
||||
else if (PyList_Check(value)) {
|
||||
Py_ssize_t nSize = PyList_Size(value);
|
||||
|
@ -493,7 +493,7 @@ void PropertyEnumeration::setPyObject(PyObject *value)
|
|||
if (!PyString_Check(item)) {
|
||||
std::string error = std::string("type in list must be str, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
values[i] = PyString_AsString(item);
|
||||
}
|
||||
|
@ -505,10 +505,33 @@ void PropertyEnumeration::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be int or str, not ");
|
||||
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
|
||||
|
@ -559,7 +582,7 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be int, not ");
|
||||
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)) {
|
||||
std::string error = std::string("type in list must be int, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
values[i] = PyInt_AsLong(item);
|
||||
}
|
||||
|
@ -667,7 +690,7 @@ void PropertyIntegerList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be int or list of int, not ");
|
||||
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)) {
|
||||
std::string error = std::string("type in list must be int, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
values.insert(PyInt_AsLong(item));
|
||||
}
|
||||
|
@ -795,7 +818,7 @@ void PropertyIntegerSet::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be int or list of int, not ");
|
||||
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"));
|
||||
}
|
||||
|
||||
reader.readEndElement("IntegerList");
|
||||
reader.readEndElement("IntegerSet");
|
||||
|
||||
//assignment
|
||||
setValues(values);
|
||||
|
@ -905,7 +928,7 @@ void PropertyFloat::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be float or int, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -999,7 +1022,7 @@ void PropertyFloatConstraint::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be float, not ");
|
||||
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)) {
|
||||
std::string error = std::string("type in list must be float, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
values[i] = (float) PyFloat_AsDouble(item);
|
||||
|
@ -1086,7 +1109,7 @@ void PropertyFloatList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be float or list of float, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1217,7 +1240,7 @@ void PropertyString::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be str or unicode, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
// assign the string
|
||||
|
@ -1322,11 +1345,18 @@ void PropertyUUID::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be a str, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
// assign the string
|
||||
setValue(string);
|
||||
try {
|
||||
// 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
|
||||
|
@ -1465,7 +1495,7 @@ void PropertyStringList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type in list must be str or unicode, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1477,7 +1507,7 @@ void PropertyStringList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be str or list of str, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1625,7 +1655,7 @@ void PropertyMap::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type of the key need to be a string, not");
|
||||
error += key->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
// check on the item:
|
||||
|
@ -1641,7 +1671,7 @@ void PropertyMap::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type in list must be string or unicode, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1650,7 +1680,7 @@ void PropertyMap::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be a dict object");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1764,7 +1794,7 @@ void PropertyBool::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be bool, not ");
|
||||
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))
|
||||
cCol.r = (float)PyFloat_AsDouble(item);
|
||||
else
|
||||
throw Base::Exception("Type in tuple must be float");
|
||||
throw Base::TypeError("Type in tuple must be float");
|
||||
item = PyTuple_GetItem(value,1);
|
||||
if (PyFloat_Check(item))
|
||||
cCol.g = (float)PyFloat_AsDouble(item);
|
||||
else
|
||||
throw Base::Exception("Type in tuple must be float");
|
||||
throw Base::TypeError("Type in tuple must be float");
|
||||
item = PyTuple_GetItem(value,2);
|
||||
if (PyFloat_Check(item))
|
||||
cCol.b = (float)PyFloat_AsDouble(item);
|
||||
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) {
|
||||
PyObject* item;
|
||||
|
@ -1894,22 +1924,22 @@ void PropertyColor::setPyObject(PyObject *value)
|
|||
if (PyFloat_Check(item))
|
||||
cCol.r = (float)PyFloat_AsDouble(item);
|
||||
else
|
||||
throw Base::Exception("Type in tuple must be float");
|
||||
throw Base::TypeError("Type in tuple must be float");
|
||||
item = PyTuple_GetItem(value,1);
|
||||
if (PyFloat_Check(item))
|
||||
cCol.g = (float)PyFloat_AsDouble(item);
|
||||
else
|
||||
throw Base::Exception("Type in tuple must be float");
|
||||
throw Base::TypeError("Type in tuple must be float");
|
||||
item = PyTuple_GetItem(value,2);
|
||||
if (PyFloat_Check(item))
|
||||
cCol.b = (float)PyFloat_AsDouble(item);
|
||||
else
|
||||
throw Base::Exception("Type in tuple must be float");
|
||||
throw Base::TypeError("Type in tuple must be float");
|
||||
item = PyTuple_GetItem(value,3);
|
||||
if (PyFloat_Check(item))
|
||||
cCol.a = (float)PyFloat_AsDouble(item);
|
||||
else
|
||||
throw Base::Exception("Type in tuple must be float");
|
||||
throw Base::TypeError("Type in tuple must be float");
|
||||
}
|
||||
else if (PyLong_Check(value)) {
|
||||
cCol.setPackedValue(PyLong_AsUnsignedLong(value));
|
||||
|
@ -1917,7 +1947,7 @@ void PropertyColor::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be int or tuple of float, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
setValue( cCol );
|
||||
|
@ -2050,7 +2080,7 @@ void PropertyColorList::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("not allowed type, ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2201,7 +2231,7 @@ void PropertyMaterial::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be 'Material', not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -183,6 +183,9 @@ public:
|
|||
virtual void Save (Base::Writer &writer) const;
|
||||
virtual void Restore(Base::XMLReader &reader);
|
||||
|
||||
virtual Property *Copy(void) const;
|
||||
virtual void Paste(const Property &from);
|
||||
|
||||
private:
|
||||
bool _CustomEnum;
|
||||
const char** _EnumArray;
|
||||
|
|
|
@ -102,11 +102,11 @@ void PropertyLength::setPyObject(PyObject *value)
|
|||
else {
|
||||
std::string error = std::string("type must be float or int, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
if (val < 0.0f)
|
||||
throw Py::ValueError("value must be nonnegative");
|
||||
throw Base::ValueError("value must be nonnegative");
|
||||
|
||||
setValue(val);
|
||||
#endif
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
<UserDocu>Returns all descentences</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="Type" ReadOnly="true">
|
||||
<Attribute Name="TypeId" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Is the type of the FreeCAD object with module domain</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Type" Type="String" />
|
||||
<Parameter Name="TypeId" Type="String" />
|
||||
</Attribute>
|
||||
<Attribute Name="Module" ReadOnly="true">
|
||||
<Documentation>
|
||||
|
|
|
@ -68,7 +68,7 @@ PyObject* BaseClassPy::getAllDerivedFrom(PyObject *args)
|
|||
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()));
|
||||
}
|
||||
|
@ -78,8 +78,15 @@ Py::Int BaseClassPy::getModule(void) const
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
|
||||
Exception &operator=(const Exception &inst);
|
||||
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 std::string& sMessage);
|
||||
|
||||
|
@ -206,6 +206,70 @@ public:
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <algorithm>
|
||||
# include <cassert>
|
||||
# include <cstdio>
|
||||
# include <cstdlib>
|
||||
|
@ -51,10 +52,20 @@
|
|||
#include <sys/stat.h>
|
||||
#include <cstdio>
|
||||
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
|
||||
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
|
||||
|
@ -188,22 +199,13 @@ std::string FileInfo::getTempFileName(const char* FileName, const char* Path)
|
|||
|
||||
void FileInfo::setFile(const char* name)
|
||||
{
|
||||
std::string result;
|
||||
const char *It=name;
|
||||
|
||||
while(*It != '\0') {
|
||||
switch(*It)
|
||||
{
|
||||
case '\\':
|
||||
result += "/";
|
||||
break;
|
||||
default:
|
||||
result += *It;
|
||||
}
|
||||
It++;
|
||||
if (!name) {
|
||||
FileName.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
FileName = result;
|
||||
FileName = name;
|
||||
std::replace(FileName.begin(), FileName.end(), '\\', '/');
|
||||
}
|
||||
|
||||
std::string FileInfo::filePath () const
|
||||
|
@ -271,9 +273,9 @@ bool FileInfo::exists () const
|
|||
{
|
||||
#if defined (FC_OS_WIN32)
|
||||
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)
|
||||
return access(FileName.c_str(),0) == 0;
|
||||
return access(FileName.c_str(),F_OK) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -281,9 +283,9 @@ bool FileInfo::isReadable () const
|
|||
{
|
||||
#if defined (FC_OS_WIN32)
|
||||
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)
|
||||
return access(FileName.c_str(),4) == 0;
|
||||
return access(FileName.c_str(),R_OK) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -291,9 +293,29 @@ bool FileInfo::isWritable () const
|
|||
{
|
||||
#if defined (FC_OS_WIN32)
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -428,7 +450,6 @@ bool FileInfo::renameFile(const char* NewName)
|
|||
#else
|
||||
# error "FileInfo::renameFile() not implemented for this platform!"
|
||||
#endif
|
||||
setFile(NewName);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -482,12 +503,17 @@ bool FileInfo::deleteDirectoryRecursive(void) const
|
|||
std::vector<Base::FileInfo> List = getDirectoryContent();
|
||||
|
||||
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();
|
||||
else if(It->isFile())
|
||||
}
|
||||
else if (It->isFile()) {
|
||||
It->setPermissions(FileInfo::ReadWrite);
|
||||
It->deleteFile();
|
||||
else
|
||||
}
|
||||
else {
|
||||
Base::Exception("FileInfo::deleteDirectoryRecursive(): Unknown object Type in directory!");
|
||||
}
|
||||
}
|
||||
return deleteDirectory();
|
||||
}
|
||||
|
|
|
@ -42,6 +42,12 @@ namespace Base
|
|||
class BaseExport FileInfo
|
||||
{
|
||||
public:
|
||||
enum Permissions {
|
||||
WriteOnly = 0x01,
|
||||
ReadOnly = 0x02,
|
||||
ReadWrite = 0x03,
|
||||
};
|
||||
|
||||
/// Constrction
|
||||
FileInfo (const char* _FileName="");
|
||||
FileInfo (const std::string &_FileName);
|
||||
|
@ -89,6 +95,8 @@ public:
|
|||
bool isReadable () const;
|
||||
/// Checks if the file exist and is writable
|
||||
bool isWritable () const;
|
||||
/// Tries to set the file permisson
|
||||
bool setPermissions (Permissions);
|
||||
/// Checks if it is a file (not a direrctory)
|
||||
bool isFile () const;
|
||||
/// Checks if it is a directory (not a file)
|
||||
|
@ -109,7 +117,7 @@ public:
|
|||
std::vector<Base::FileInfo> getDirectoryContent(void) const;
|
||||
/// Delete an empty directory
|
||||
bool deleteDirectory(void) const;
|
||||
/// Delete a directory and all its content
|
||||
/// Delete a directory and all its content.
|
||||
bool deleteDirectoryRecursive(void) const;
|
||||
//@}
|
||||
|
||||
|
|
|
@ -71,9 +71,18 @@ PyException::PyException(void)
|
|||
|
||||
|
||||
_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)
|
||||
}
|
||||
|
||||
void PyException::ReportException (void) const
|
||||
{
|
||||
Base::Console().Error("%s%s: %s\n",
|
||||
_stackTrace.c_str(), _errorType.c_str(), what());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
|
|
@ -54,11 +54,12 @@ class BaseExport PyException : public Exception
|
|||
public:
|
||||
/// constructor does the whole job
|
||||
PyException(void);
|
||||
~PyException() throw() {}
|
||||
~PyException() throw();
|
||||
|
||||
/// this function returns the stack trace
|
||||
const std::string &getStackTrace(void) const {return _stackTrace;}
|
||||
const std::string &getErrorType(void) const {return _errorType;}
|
||||
void ReportException (void) const;
|
||||
|
||||
protected:
|
||||
std::string _stackTrace;
|
||||
|
|
|
@ -38,9 +38,16 @@ using namespace Base;
|
|||
std::string RotationPy::representation(void) const
|
||||
{
|
||||
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;
|
||||
str << "Quaternion (";
|
||||
str << ptr->getValue()[0] << ","<< ptr->getValue()[1] << "," << ptr->getValue()[2] << "," << ptr->getValue()[3];
|
||||
str << "Rotation (";
|
||||
str << (std::string)q0.repr() << ", "
|
||||
<< (std::string)q1.repr() << ", "
|
||||
<< (std::string)q2.repr() << ", "
|
||||
<< (std::string)q3.repr();
|
||||
str << ")";
|
||||
|
||||
return str.str();
|
||||
|
|
|
@ -40,9 +40,12 @@ using namespace Base;
|
|||
std::string VectorPy::representation(void) const
|
||||
{
|
||||
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;
|
||||
str << "Vector (";
|
||||
str << ptr->x << ", "<< ptr->y << ", "<< ptr->z;
|
||||
str << (std::string)x.repr() << ", "<< (std::string)y.repr() << ", "<< (std::string)z.repr();
|
||||
str << ")";
|
||||
|
||||
return str.str();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
// Version Number
|
||||
#define FCVersionMajor "0"
|
||||
#define FCVersionMinor "13"
|
||||
#define FCVersionMinor "14"
|
||||
#define FCVersionName "Vulcan"
|
||||
// test: $Format:Hash (%H), Date: %ci$
|
||||
#define FCRevision "$WCREV$" //Highest committed revision number
|
||||
|
|
|
@ -41,8 +41,11 @@
|
|||
# include <QGLFramebufferObject>
|
||||
#endif
|
||||
# include <QSessionManager>
|
||||
# include <QTextStream>
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/sync/file_lock.hpp>
|
||||
|
||||
|
||||
// FreeCAD Base header
|
||||
#include <Base/Console.h>
|
||||
|
@ -336,6 +339,18 @@ Application::Application(bool GUIenabled)
|
|||
("User parameter:BaseApp/Preferences/Units");
|
||||
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
|
||||
Base::PyGILStateLocker lock;
|
||||
PyObject* module = Py_InitModule3("FreeCADGui", Application::Methods,
|
||||
|
@ -1739,9 +1754,24 @@ void Application::runApplication(void)
|
|||
Base::Console().Log("Init: Entering event loop\n");
|
||||
|
||||
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();
|
||||
if (ret == systemExit)
|
||||
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&) {
|
||||
Base::Console().Message("System exit\n");
|
||||
|
@ -1756,3 +1786,66 @@ void Application::runApplication(void)
|
|||
|
||||
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:
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ public:
|
|||
|
||||
/// true when the application shuting down
|
||||
bool isClosing(void);
|
||||
void checkForPreviousCrashes();
|
||||
|
||||
/** @name workbench handling */
|
||||
//@{
|
||||
|
@ -210,6 +211,7 @@ public:
|
|||
|
||||
PYFUNCDEF_S(sSendActiveView);
|
||||
|
||||
PYFUNCDEF_S(sGetMainWindow);
|
||||
PYFUNCDEF_S(sUpdateGui);
|
||||
PYFUNCDEF_S(sUpdateLocale);
|
||||
PYFUNCDEF_S(sGetLocale);
|
||||
|
|
|
@ -83,6 +83,9 @@ PyMethodDef Application::Methods[] = {
|
|||
{"addIcon", (PyCFunction) Application::sAddIcon, 1,
|
||||
"addIcon(string, string or list) -> None\n\n"
|
||||
"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() -> None\n\n"
|
||||
"Update the main window and all its windows"},
|
||||
|
@ -418,6 +421,22 @@ PyObject* Application::sSendActiveView(PyObject * /*self*/, PyObject *args,PyObj
|
|||
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*/)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
|
|
|
@ -84,7 +84,7 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev)
|
|||
// up the inheritance hierarchy.
|
||||
if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
|
||||
// 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
|
||||
|
||||
const SoType type(ev->getTypeId());
|
||||
|
|
|
@ -86,7 +86,7 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev)
|
|||
if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
|
||||
#else
|
||||
// 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
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
if(WIN32)
|
||||
add_definitions(-DFCGui -DQIIS_MAKEDLL)
|
||||
endif(WIN32)
|
||||
|
||||
if (FREECAD_USE_3DCONNEXION)
|
||||
add_definitions(-D_USE_3DCONNEXION_SDK)
|
||||
endif(FREECAD_USE_3DCONNEXION)
|
||||
|
@ -59,6 +60,30 @@ IF(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(PythonWorkbenchPy)
|
||||
generate_from_xml(ViewProviderPy)
|
||||
|
@ -97,8 +122,11 @@ set(Gui_MOC_HDRS
|
|||
CallTips.h
|
||||
CombiView.h
|
||||
Control.h
|
||||
Clipping.h
|
||||
DemoMode.h
|
||||
DownloadDialog.h
|
||||
DownloadItem.h
|
||||
DownloadManager.h
|
||||
DlgActionsImp.h
|
||||
DlgActivateWindowImp.h
|
||||
DlgCommandsImp.h
|
||||
|
@ -186,6 +214,7 @@ fc_wrap_cpp(Gui_MOC_SRCS ${Gui_MOC_HDRS})
|
|||
|
||||
SET(Gui_UIC_SRCS
|
||||
AboutApplication.ui
|
||||
Clipping.ui
|
||||
DemoMode.ui
|
||||
DlgActions.ui
|
||||
DlgActivateWindow.ui
|
||||
|
@ -220,6 +249,8 @@ SET(Gui_UIC_SRCS
|
|||
DlgTreeWidget.ui
|
||||
DlgLocationAngle.ui
|
||||
DlgLocationPos.ui
|
||||
DownloadManager.ui
|
||||
DownloadItem.ui
|
||||
MouseButtons.ui
|
||||
SceneInspector.ui
|
||||
InputVector.ui
|
||||
|
@ -260,6 +291,7 @@ SOURCE_GROUP("Command" FILES ${Command_SRCS})
|
|||
|
||||
# The dialog sources
|
||||
SET(Dialog_CPP_SRCS
|
||||
Clipping.cpp
|
||||
DemoMode.cpp
|
||||
DlgActivateWindowImp.cpp
|
||||
DlgDisplayPropertiesImp.cpp
|
||||
|
@ -282,9 +314,12 @@ SET(Dialog_CPP_SRCS
|
|||
TextureMapping.cpp
|
||||
Transform.cpp
|
||||
DownloadDialog.cpp
|
||||
DownloadItem.cpp
|
||||
DownloadManager.cpp
|
||||
)
|
||||
|
||||
SET(Dialog_HPP_SRCS
|
||||
Clipping.h
|
||||
DemoMode.h
|
||||
DlgActivateWindowImp.h
|
||||
DlgDisplayPropertiesImp.h
|
||||
|
@ -307,17 +342,22 @@ SET(Dialog_HPP_SRCS
|
|||
TextureMapping.h
|
||||
Transform.h
|
||||
DownloadDialog.h
|
||||
DownloadItem.h
|
||||
DownloadManager.h
|
||||
)
|
||||
|
||||
SET(Dialog_SRCS
|
||||
${Dialog_CPP_SRCS}
|
||||
${Dialog_HPP_SRCS}
|
||||
AboutApplication.ui
|
||||
Clipping.ui
|
||||
DemoMode.ui
|
||||
DlgActivateWindow.ui
|
||||
DlgAuthorization.ui
|
||||
DlgDisplayProperties.ui
|
||||
DlgInputDialog.ui
|
||||
DlgLocationAngle.ui
|
||||
DlgLocationPos.ui
|
||||
DlgMacroExecute.ui
|
||||
DlgRunExternal.ui
|
||||
DlgMacroRecord.ui
|
||||
|
@ -327,6 +367,8 @@ SET(Dialog_SRCS
|
|||
DlgProjectUtility.ui
|
||||
DlgTipOfTheDay.ui
|
||||
DlgTreeWidget.ui
|
||||
DownloadManager.ui
|
||||
DownloadItem.ui
|
||||
MouseButtons.ui
|
||||
InputVector.ui
|
||||
Placement.ui
|
||||
|
@ -884,7 +926,13 @@ else(WIN32)
|
|||
INSTALL(TARGETS FreeCADGui
|
||||
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}
|
||||
)
|
||||
endif(WIN32)
|
||||
|
|
315
src/Gui/Clipping.cpp
Normal file
315
src/Gui/Clipping.cpp
Normal 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
88
src/Gui/Clipping.h
Normal 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
244
src/Gui/Clipping.ui
Normal 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>
|
|
@ -581,6 +581,12 @@ void Command::applyCommandData(Action* action)
|
|||
action->setWhatsThis(QCoreApplication::translate(
|
||||
this->className(), sToolTipText, 0,
|
||||
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
|
||||
|
|
|
@ -841,7 +841,6 @@ void StdCmdCopy::activated(int iMsg)
|
|||
{
|
||||
bool done = getGuiApplication()->sendMsgToActiveView("Copy");
|
||||
if (!done) {
|
||||
WaitCursor wc;
|
||||
QMimeData * mimeData = getMainWindow()->createMimeDataFromSelection();
|
||||
QClipboard* cb = QApplication::clipboard();
|
||||
cb->setMimeData(mimeData);
|
||||
|
@ -910,59 +909,54 @@ StdCmdDuplicateSelection::StdCmdDuplicateSelection()
|
|||
|
||||
void StdCmdDuplicateSelection::activated(int iMsg)
|
||||
{
|
||||
App::Document* act = App::GetApplication().getActiveDocument();
|
||||
if (!act)
|
||||
return; // no active document found
|
||||
Gui::Document* doc = Gui::Application::Instance->getDocument(act);
|
||||
std::vector<Gui::SelectionSingleton::SelObj> sel = Gui::Selection().getCompleteSelection();
|
||||
std::vector<SelectionSingleton::SelObj> sel = Selection().getCompleteSelection();
|
||||
std::map< App::Document*, std::vector<App::DocumentObject*> > objs;
|
||||
for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
|
||||
if (!it->pObject)
|
||||
continue; // should actually not happen
|
||||
// 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 (it->pObject && it->pObject->getDocument()) {
|
||||
objs[it->pObject->getDocument()].push_back(it->pObject);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -1032,17 +1026,52 @@ void StdCmdDelete::activated(int iMsg)
|
|||
Gui::Document* pGuiDoc = Gui::Application::Instance->getDocument(*it);
|
||||
std::vector<Gui::SelectionObject> sel = rSel.getSelectionEx((*it)->getName());
|
||||
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) {
|
||||
App::DocumentObject* obj = ft->getObject();
|
||||
Gui::ViewProvider* vp = pGuiDoc->getViewProvider(ft->getObject());
|
||||
if (vp) {
|
||||
// ask the ViewProvider if its want to do some clean up
|
||||
if (vp->onDelete(ft->getSubNames()))
|
||||
doCommand(Doc,"App.getDocument(\"%s\").removeObject(\"%s\")"
|
||||
,(*it)->getName(), ft->getFeatName());
|
||||
// if the object is in edit mode we allow to continue because only sub-elements will be removed
|
||||
if (!vp || !vp->isEditing()) {
|
||||
std::vector<App::DocumentObject*> links = obj->getInList();
|
||||
if (!links.empty()) {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "Application.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "Control.h"
|
||||
#include "Clipping.h"
|
||||
#include "FileDialog.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Tree.h"
|
||||
|
@ -49,6 +50,7 @@
|
|||
#include "Selection.h"
|
||||
#include "SoFCOffscreenRenderer.h"
|
||||
#include "SoFCBoundingBox.h"
|
||||
#include "SoFCUnifiedSelection.h"
|
||||
#include "SoAxisCrossKit.h"
|
||||
#include "View3DInventor.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
|
@ -473,12 +475,15 @@ StdCmdToggleClipPlane::StdCmdToggleClipPlane()
|
|||
Action * StdCmdToggleClipPlane::createAction(void)
|
||||
{
|
||||
Action *pcAction = (Action*)Command::createAction();
|
||||
#if 0
|
||||
pcAction->setCheckable(true);
|
||||
#endif
|
||||
return pcAction;
|
||||
}
|
||||
|
||||
void StdCmdToggleClipPlane::activated(int iMsg)
|
||||
{
|
||||
#if 0
|
||||
View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow());
|
||||
if (view) {
|
||||
if (iMsg > 0 && !view->hasClippingPlane())
|
||||
|
@ -486,10 +491,17 @@ void StdCmdToggleClipPlane::activated(int iMsg)
|
|||
else if (iMsg == 0 && view->hasClippingPlane())
|
||||
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)
|
||||
{
|
||||
#if 0
|
||||
View3DInventor* view = qobject_cast<View3DInventor*>(getMainWindow()->activeWindow());
|
||||
if (view) {
|
||||
Action* action = qobject_cast<Action*>(_pcAction);
|
||||
|
@ -503,6 +515,11 @@ bool StdCmdToggleClipPlane::isActive(void)
|
|||
action->setChecked(false);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (Gui::Control().activeDialog())
|
||||
return false;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
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());
|
||||
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback, ud);
|
||||
SoNode* root = view->getSceneGraph();
|
||||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(TRUE);
|
||||
|
||||
std::vector<SbVec2f> picked = view->getGLPolygon();
|
||||
SoCamera* cam = view->getCamera();
|
||||
SbViewVolume vv = cam->getViewVolume();
|
||||
|
@ -1972,8 +1992,10 @@ void StdBoxSelection::activated(int iMsg)
|
|||
if (view) {
|
||||
View3DInventorViewer* viewer = view->getViewer();
|
||||
if (!viewer->isSelecting()) {
|
||||
viewer->startSelection(View3DInventorViewer::Rectangle);
|
||||
viewer->startSelection(View3DInventorViewer::Rubberband);
|
||||
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback);
|
||||
SoNode* root = viewer->getSceneGraph();
|
||||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
# include <cmath>
|
||||
# include <float.h>
|
||||
# include <climits>
|
||||
# include <QCursor>
|
||||
# include <QTimer>
|
||||
#include <Inventor/nodes/SoCamera.h>
|
||||
#endif
|
||||
|
@ -53,6 +54,11 @@ DemoMode::DemoMode(QWidget* parent, Qt::WFlags fl)
|
|||
timer->setInterval(1000 * ui->timeout->value());
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(onAutoPlay()));
|
||||
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 */
|
||||
|
@ -82,6 +88,35 @@ void DemoMode::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
|
||||
{
|
||||
Document* doc = Application::Instance->activeDocument();
|
||||
|
@ -186,6 +221,14 @@ void DemoMode::on_fullscreen_toggled(bool on)
|
|||
view->setCurrentViewMode(on ? MDIView::/*TopLevel*/FullScreen : MDIView::Child);
|
||||
this->activateWindow();
|
||||
}
|
||||
if (on) {
|
||||
qApp->installEventFilter(this);
|
||||
showHideTimer->start();
|
||||
}
|
||||
else {
|
||||
qApp->removeEventFilter(this);
|
||||
showHideTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void DemoMode::on_timeout_valueChanged(int v)
|
||||
|
|
|
@ -68,12 +68,19 @@ private:
|
|||
Gui::View3DInventor* activeView() const;
|
||||
void startAnimation(Gui::View3DInventor*);
|
||||
void changeEvent(QEvent *e);
|
||||
bool eventFilter(QObject *, QEvent *);
|
||||
void showEvent(QShowEvent *);
|
||||
void hideEvent(QHideEvent *);
|
||||
|
||||
private:
|
||||
int oldvalue;
|
||||
SbVec3f viewAxis;
|
||||
bool wasHidden;
|
||||
QPoint pnt;
|
||||
QPoint oldPos;
|
||||
Ui_DemoMode* ui;
|
||||
QTimer* timer;
|
||||
QTimer* showHideTimer;
|
||||
};
|
||||
|
||||
} // namespace Dialog
|
||||
|
|
|
@ -1,118 +1,55 @@
|
|||
<ui version="4.0" >
|
||||
<author></author>
|
||||
<comment></comment>
|
||||
<exportmacro></exportmacro>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::Dialog::DlgAuthorization</class>
|
||||
<widget class="QDialog" name="Gui::Dialog::DlgAuthorization" >
|
||||
<property name="geometry" >
|
||||
<widget class="QDialog" name="Gui::Dialog::DlgAuthorization">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>304</width>
|
||||
<height>189</height>
|
||||
<width>284</width>
|
||||
<height>128</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<property name="windowTitle">
|
||||
<string>Authorization</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled" >
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<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>&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>&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>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="textLabel1">
|
||||
<property name="text">
|
||||
<string>Username:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="textLabel2" >
|
||||
<property name="text" >
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="username"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="textLabel2">
|
||||
<property name="text">
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLineEdit" name="username" />
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="textLabel1" >
|
||||
<property name="text" >
|
||||
<string>User name:</string>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<item row="3" column="0" colspan="2">
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>21</width>
|
||||
<height>41</height>
|
||||
|
@ -120,48 +57,43 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</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>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11" />
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<tabstops>
|
||||
<tabstop>username</tabstop>
|
||||
<tabstop>password</tabstop>
|
||||
<tabstop>buttonOk</tabstop>
|
||||
<tabstop>buttonCancel</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<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>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -40,9 +40,6 @@
|
|||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item rowspan="2" row="7" column="1" >
|
||||
<widget class="QTextEdit" name="textEditComment" />
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="textLabelName" >
|
||||
<property name="text" >
|
||||
|
@ -56,32 +53,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLineEdit" name="lineEditName" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>91</width>
|
||||
<height>240</height>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="0" >
|
||||
<widget class="QLabel" name="textLabelComment" >
|
||||
<property name="text" >
|
||||
<string>Commen&t:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>textEditComment</cstring>
|
||||
<property name="readOnly" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -108,40 +89,30 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLineEdit" name="lineEditCreator" >
|
||||
<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" >
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="textLabelUuid" >
|
||||
<property name="text" >
|
||||
<string>&Last modified by:</string>
|
||||
<string>UUID:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>lineEditLastMod</cstring>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="textLabelCreator" >
|
||||
<property name="text" >
|
||||
<string>Created &by:</string>
|
||||
|
@ -154,20 +125,66 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" >
|
||||
<widget class="QLabel" name="textLabelCompany" >
|
||||
<item row="3" column="1" >
|
||||
<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" >
|
||||
<string>Com&pany:</string>
|
||||
<string>Creation &date:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<widget class="QLabel" name="textLabelLastMod" >
|
||||
<property name="text" >
|
||||
<string>&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" >
|
||||
<property name="text" >
|
||||
<string>Last &modification date:</string>
|
||||
|
@ -181,29 +198,6 @@
|
|||
</widget>
|
||||
</item>
|
||||
<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" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
|
@ -216,32 +210,61 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="textLabelCreateDate" >
|
||||
<item row="7" column="0" >
|
||||
<widget class="QLabel" name="textLabelCompany" >
|
||||
<property name="text" >
|
||||
<string>Creation &date:</string>
|
||||
<string>Com&pany:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>lineEditDate</cstring>
|
||||
<cstring>lineEditCompany</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLineEdit" name="lineEditName" >
|
||||
<item row="7" column="1" >
|
||||
<widget class="QLineEdit" name="lineEditCompany" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly" >
|
||||
<bool>true</bool>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" >
|
||||
<widget class="QLabel" name="textLabelComment" >
|
||||
<property name="text" >
|
||||
<string>Commen&t:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>textEditComment</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -304,14 +327,6 @@
|
|||
</widget>
|
||||
<layoutdefault spacing="6" margin="11" />
|
||||
<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>
|
||||
<resources/>
|
||||
<connections>
|
||||
|
|
|
@ -46,6 +46,7 @@ DlgProjectInformationImp::DlgProjectInformationImp( App::Document* doc, QWidget*
|
|||
this->setupUi(this);
|
||||
lineEditName->setText(QString::fromUtf8(doc->Label.getValue()));
|
||||
lineEditPath->setText(QString::fromUtf8(doc->FileName.getValue()));
|
||||
lineEditUuid->setText(QString::fromUtf8(doc->Uid.getValueStr().c_str()));
|
||||
lineEditCreator->setText(QString::fromUtf8(doc->CreatedBy.getValue()));
|
||||
lineEditDate->setText(QString::fromUtf8(doc->CreationDate.getValue()));
|
||||
lineEditLastMod->setText(QString::fromUtf8(doc->LastModifiedBy.getValue()));
|
||||
|
|
|
@ -71,6 +71,7 @@ void DlgSettingsViewColor::saveSettings()
|
|||
EditedVertexColor->onSave();
|
||||
ConstructionColor->onSave();
|
||||
FullyConstrainedColor->onSave();
|
||||
BoundingBoxColor->onSave();
|
||||
DefaultShapeColor->onSave();
|
||||
DefaultShapeLineColor->onSave();
|
||||
DefaultShapeLineWidth->onSave();
|
||||
|
@ -94,6 +95,7 @@ void DlgSettingsViewColor::loadSettings()
|
|||
EditedVertexColor->onRestore();
|
||||
ConstructionColor->onRestore();
|
||||
FullyConstrainedColor->onRestore();
|
||||
BoundingBoxColor->onRestore();
|
||||
DefaultShapeColor->onRestore();
|
||||
DefaultShapeLineColor->onRestore();
|
||||
DefaultShapeLineWidth->onRestore();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>601</width>
|
||||
<height>565</height>
|
||||
<height>598</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -520,6 +520,33 @@
|
|||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
|
@ -660,6 +687,7 @@
|
|||
<tabstop>EditedVertexColor</tabstop>
|
||||
<tabstop>ConstructionColor</tabstop>
|
||||
<tabstop>FullyConstrainedColor</tabstop>
|
||||
<tabstop>BoundingBoxColor</tabstop>
|
||||
<tabstop>radioButtonSimple</tabstop>
|
||||
<tabstop>SelectionColor_Background</tabstop>
|
||||
<tabstop>radioButtonGradient</tabstop>
|
||||
|
|
|
@ -288,7 +288,11 @@ void DlgCustomToolbars::on_moveActionRightButton_clicked()
|
|||
QTreeWidgetItem* item = commandTreeWidget->currentItem();
|
||||
if (item) {
|
||||
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);
|
||||
copy->setText(0, item->text(1));
|
||||
copy->setIcon(0, item->icon(0));
|
||||
|
|
|
@ -571,43 +571,18 @@ bool Document::saveAs(void)
|
|||
getMainWindow()->showMessage(QObject::tr("Save document under new filename..."));
|
||||
|
||||
QString exe = qApp->applicationName();
|
||||
QString fn = QFileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe),
|
||||
FileDialog::getWorkingDirectory(), 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString fn = FileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe),
|
||||
QString(), QObject::tr("%1 document (*.FCStd)").arg(exe));
|
||||
if (!fn.isEmpty()) {
|
||||
QFileInfo fi;
|
||||
fi.setFile(fn);
|
||||
QString bn = fi.baseName();
|
||||
|
||||
const char * DocName = App::GetApplication().getDocumentName(getDocument());
|
||||
|
||||
// save as new file name
|
||||
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());
|
||||
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);
|
||||
|
||||
getMainWindow()->appendRecentFile(fi.filePath());
|
||||
|
@ -695,9 +670,20 @@ void Document::RestoreDocFile(Base::Reader &reader)
|
|||
for (i=0 ;i<Cnt ;i++) {
|
||||
xmlReader.readElement("ViewProvider");
|
||||
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());
|
||||
if (pObj) // check if this feature has been registered
|
||||
pObj->Restore(xmlReader);
|
||||
if (expanded) {
|
||||
Gui::ViewProviderDocumentObject* vp = static_cast<Gui::ViewProviderDocumentObject*>(pObj);
|
||||
this->signalExpandObject(*vp, Gui::Expand);
|
||||
}
|
||||
xmlReader.readEndElement("ViewProvider");
|
||||
}
|
||||
xmlReader.readEndElement("ViewProviderData");
|
||||
|
@ -784,7 +770,9 @@ void Document::SaveDocFile (Base::Writer &writer) const
|
|||
const App::DocumentObject* doc = it->first;
|
||||
ViewProvider* obj = it->second;
|
||||
writer.Stream() << writer.ind() << "<ViewProvider name=\""
|
||||
<< doc->getNameInDocument() << "\">" << std::endl;
|
||||
<< doc->getNameInDocument() << "\" "
|
||||
<< "expanded=\"" << (doc->testStatus(App::Expand) ? 1:0)
|
||||
<< "\">" << std::endl;
|
||||
obj->Save(writer);
|
||||
writer.Stream() << writer.ind() << "</ViewProvider>" << std::endl;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
# include <boost/bind.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include "DocumentModel.h"
|
||||
#include "Application.h"
|
||||
#include "BitmapFactory.h"
|
||||
|
@ -54,8 +56,6 @@ namespace Gui {
|
|||
virtual ~DocumentModelIndex()
|
||||
{ qDeleteAll(childItems); }
|
||||
|
||||
void reset()
|
||||
{ qDeleteAll(childItems); childItems.clear(); }
|
||||
void setParent(DocumentModelIndex* parent)
|
||||
{ parentItem = parent; }
|
||||
DocumentModelIndex *parent() const
|
||||
|
@ -64,7 +64,12 @@ namespace Gui {
|
|||
{ childItems.append(child); child->setParent(this); }
|
||||
void removeChild(int row)
|
||||
{ childItems.removeAt(row); }
|
||||
|
||||
QList<DocumentModelIndex*> removeAll()
|
||||
{
|
||||
QList<DocumentModelIndex*> list = childItems;
|
||||
childItems.clear();
|
||||
return list;
|
||||
}
|
||||
DocumentModelIndex *child(int row)
|
||||
{ return childItems.value(row); }
|
||||
int row() const
|
||||
|
@ -91,11 +96,18 @@ namespace Gui {
|
|||
return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
void reset()
|
||||
{ qDeleteAll(childItems); childItems.clear(); }
|
||||
|
||||
protected:
|
||||
DocumentModelIndex() : parentItem(0) {}
|
||||
DocumentModelIndex *parentItem;
|
||||
QList<DocumentModelIndex*> childItems;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Root node
|
||||
class ApplicationIndex : public DocumentModelIndex
|
||||
{
|
||||
|
@ -104,24 +116,22 @@ namespace Gui {
|
|||
public:
|
||||
ApplicationIndex(){}
|
||||
int findChild(const Gui::Document& d) const;
|
||||
Qt::ItemFlags flags() const
|
||||
{ return Qt::ItemIsEnabled; }
|
||||
QVariant data(int role) const
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return qApp->windowIcon();
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
return DocumentModel::tr("Application");
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
Qt::ItemFlags flags() const;
|
||||
QVariant data(int role) const;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Document nodes
|
||||
class DocumentIndex : public DocumentModelIndex
|
||||
{
|
||||
friend class ViewProviderIndex;
|
||||
TYPESYSTEM_HEADER();
|
||||
static QIcon* documentIcon;
|
||||
typedef boost::unordered_set<ViewProviderIndex*> IndexSet;
|
||||
std::map<const ViewProviderDocumentObject*, IndexSet> vp_nodes;
|
||||
void addToDocument(ViewProviderIndex*);
|
||||
void removeFromDocument(ViewProviderIndex*);
|
||||
|
||||
public:
|
||||
const Gui::Document& d;
|
||||
|
@ -130,30 +140,18 @@ namespace Gui {
|
|||
if (!documentIcon)
|
||||
documentIcon = new QIcon(Gui::BitmapFactory().pixmap("Document"));
|
||||
}
|
||||
int findViewProvider(const ViewProvider&) const;
|
||||
void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant data(int role) const
|
||||
~DocumentIndex()
|
||||
{
|
||||
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();
|
||||
qDeleteAll(childItems); childItems.clear();
|
||||
}
|
||||
ViewProviderIndex* cloneViewProvider(const ViewProviderDocumentObject&) const;
|
||||
int rowOfViewProvider(const ViewProviderDocumentObject&) const;
|
||||
void findViewProviders(const ViewProviderDocumentObject&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant data(int role) const;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Object nodes
|
||||
class ViewProviderIndex : public DocumentModelIndex
|
||||
{
|
||||
|
@ -161,31 +159,18 @@ namespace Gui {
|
|||
|
||||
public:
|
||||
const Gui::ViewProviderDocumentObject& v;
|
||||
ViewProviderIndex(const Gui::ViewProviderDocumentObject& v) : v(v){}
|
||||
void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant 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;
|
||||
}
|
||||
ViewProviderIndex(const Gui::ViewProviderDocumentObject& v, DocumentIndex* d);
|
||||
~ViewProviderIndex();
|
||||
ViewProviderIndex* clone() const;
|
||||
void findViewProviders(const ViewProviderDocumentObject&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant data(int role) const;
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
private:
|
||||
DocumentIndex* d;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
int ApplicationIndex::findChild(const Gui::Document& d) const
|
||||
{
|
||||
int child=0;
|
||||
|
@ -199,9 +184,50 @@ namespace Gui {
|
|||
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;
|
||||
|
||||
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<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;
|
||||
int index=0;
|
||||
|
@ -224,8 +250,52 @@ namespace Gui {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void ViewProviderIndex::findViewProviders(const ViewProvider& vp,
|
||||
QList<ViewProviderIndex*>& index) const
|
||||
QVariant DocumentIndex::data(int role) 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)
|
||||
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::ApplicationIndex,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);
|
||||
int count_obj = index->childCount();
|
||||
beginInsertRows(parent, count_obj, count_obj);
|
||||
index->appendChild(new ViewProviderIndex(obj));
|
||||
index->appendChild(new ViewProviderIndex(obj, index));
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
@ -399,35 +493,47 @@ void DocumentModel::slotChangeObject(const Gui::ViewProviderDocumentObject& obj,
|
|||
else if (isPropertyLink(Prop)) {
|
||||
App::Document* doc = fea->getDocument();
|
||||
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);
|
||||
if (row > -1) {
|
||||
QList<DocumentModelIndex*> del_items;
|
||||
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) {
|
||||
int row = doc_index->findViewProvider(**vp);
|
||||
int row = doc_index->rowOfViewProvider(**vp);
|
||||
// is it a top-level child in the document
|
||||
if (row >= 0) {
|
||||
DocumentModelIndex* child = doc_index->child(row);
|
||||
del_items.push_back(child);
|
||||
QModelIndex parent = createIndex(doc_index->row(), 0, doc_index);
|
||||
beginRemoveRows(parent, row, row);
|
||||
doc_index->removeChild(row);
|
||||
delete child;
|
||||
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) {
|
||||
QModelIndex parent = createIndex((*it)->row(),0,*it);
|
||||
int count_obj = (*it)->childCount();
|
||||
beginInsertRows(parent, count_obj, count_obj + (int)views.size());
|
||||
for (std::vector<ViewProviderDocumentObject*>::iterator jt = views.begin(); jt != views.end(); ++jt)
|
||||
(*it)->appendChild(new ViewProviderIndex(**jt));
|
||||
beginRemoveRows(parent, 0, count_obj);
|
||||
// remove all children but do not yet delete them
|
||||
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();
|
||||
|
||||
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()))
|
||||
return true;
|
||||
if (prop.isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
|
||||
return true;
|
||||
if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId()))
|
||||
return true;
|
||||
if (prop.isDerivedFrom(App::PropertyLinkSubList::getClassTypeId()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId())) {
|
||||
App::DocumentObject* obj;
|
||||
obj = static_cast<const App::PropertyLink&>(prop).getValue();
|
||||
ViewProvider* view = doc.getViewProvider(obj);
|
||||
std::vector<ViewProviderDocumentObject*> views;
|
||||
std::vector<App::DocumentObject*> childs = obj.claimChildren();
|
||||
for (std::vector<App::DocumentObject*>::iterator it = childs.begin(); it != childs.end(); ++it) {
|
||||
ViewProvider* view = doc.getViewProvider(*it);
|
||||
if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
|
||||
links.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));
|
||||
}
|
||||
views.push_back(static_cast<ViewProviderDocumentObject*>(view));
|
||||
}
|
||||
|
||||
return links;
|
||||
return views;
|
||||
}
|
||||
|
||||
int DocumentModel::columnCount (const QModelIndex & /*parent*/) const
|
||||
|
|
|
@ -67,8 +67,8 @@ private:
|
|||
|
||||
const Document* getDocument(const QModelIndex&) const;
|
||||
bool isPropertyLink(const App::Property&) const;
|
||||
std::vector<ViewProviderDocumentObject*> getLinkedObjects
|
||||
(const Gui::Document&, const App::Property&) const;
|
||||
std::vector<ViewProviderDocumentObject*> claimChildren
|
||||
(const Document&, const ViewProviderDocumentObject&) const;
|
||||
|
||||
private:
|
||||
struct DocumentModelP *d;
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
# include <QHBoxLayout>
|
||||
#endif
|
||||
|
||||
#include <QAuthenticator>
|
||||
#include "DownloadDialog.h"
|
||||
#include "ui_DlgAuthorization.h"
|
||||
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
|
@ -202,6 +204,16 @@ void DownloadDialog::updateDataReadProgress(int bytesRead, int totalBytes)
|
|||
|
||||
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
583
src/Gui/DownloadItem.cpp
Normal 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
155
src/Gui/DownloadItem.h
Normal 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
140
src/Gui/DownloadItem.ui
Normal 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
303
src/Gui/DownloadManager.cpp
Normal 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
116
src/Gui/DownloadManager.h
Normal 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
|
83
src/Gui/DownloadManager.ui
Normal file
83
src/Gui/DownloadManager.ui
Normal 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>
|
|
@ -26,11 +26,14 @@
|
|||
# include <QApplication>
|
||||
# include <QButtonGroup>
|
||||
# include <QComboBox>
|
||||
# include <QDesktopServices>
|
||||
# include <QGridLayout>
|
||||
# include <QGroupBox>
|
||||
# include <QLineEdit>
|
||||
# include <QPushButton>
|
||||
# include <QRadioButton>
|
||||
# include <QStyle>
|
||||
# include <QUrl>
|
||||
#endif
|
||||
|
||||
#include <Base/Parameter.h>
|
||||
|
@ -45,6 +48,32 @@ using namespace Gui;
|
|||
|
||||
/* 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.
|
||||
*/
|
||||
|
@ -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
|
||||
// existing file. Hence we must extract the first matching suffix from the filter list and append it
|
||||
// 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);
|
||||
#endif
|
||||
if (!file.isEmpty()) {
|
||||
setWorkingDirectory(file);
|
||||
return file;
|
||||
|
@ -129,7 +188,36 @@ QString FileDialog::getOpenFileName(QWidget * parent, const QString & caption, c
|
|||
#if defined(FC_OS_MACOSX)
|
||||
options |= QFileDialog::DontUseNativeDialog;
|
||||
#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);
|
||||
#endif
|
||||
if (!file.isEmpty()) {
|
||||
setWorkingDirectory(file);
|
||||
return file;
|
||||
|
@ -155,7 +243,36 @@ QStringList FileDialog::getOpenFileNames (QWidget * parent, const QString & capt
|
|||
#if defined(FC_OS_MACOSX)
|
||||
options |= QFileDialog::DontUseNativeDialog;
|
||||
#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);
|
||||
#endif
|
||||
if (!files.isEmpty()) {
|
||||
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);
|
||||
}
|
||||
|
||||
QIcon FileIconProvider::icon ( const QFileInfo & info ) const
|
||||
QIcon FileIconProvider::icon(const QFileInfo & info) const
|
||||
{
|
||||
return QFileIconProvider::icon(info);
|
||||
}
|
||||
|
||||
QString FileIconProvider::type ( const QFileInfo & info ) const
|
||||
QString FileIconProvider::type(const QFileInfo & info) const
|
||||
{
|
||||
return QFileIconProvider::type(info);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,14 @@ public:
|
|||
|
||||
static QString getWorkingDirectory();
|
||||
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();
|
||||
|
||||
QIcon icon ( IconType type ) const;
|
||||
QIcon icon ( const QFileInfo & info ) const;
|
||||
QString type ( const QFileInfo & info ) const;
|
||||
QIcon icon(IconType type) const;
|
||||
QIcon icon(const QFileInfo & info) const;
|
||||
QString type(const QFileInfo & info) const;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#ifndef _PreComp_
|
||||
# include <QMenu>
|
||||
# include <QMouseEvent>
|
||||
# include <Inventor/nodes/SoCamera.h>
|
||||
#endif
|
||||
#include <Inventor/SbVec2s.h>
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "GLPainter.h"
|
||||
|
||||
#include "Flag.h"
|
||||
|
||||
|
@ -455,4 +455,76 @@ QSize FlagLayout::calculateSize(SizeType sizeType) const
|
|||
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"
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
#include <QWidgetItem>
|
||||
#include <QGLWidget>
|
||||
#include <Inventor/SbVec3f.h>
|
||||
#include <Gui/GLPainter.h>
|
||||
|
||||
namespace Gui {
|
||||
class View3DInventorViewer;
|
||||
|
||||
/**
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
|
@ -98,6 +100,8 @@ private:
|
|||
|
||||
class FlagLayout : public QLayout
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Position { TopLeft, TopRight, BottomLeft, BottomRight };
|
||||
|
||||
|
@ -136,6 +140,24 @@ private:
|
|||
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
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
using namespace Gui;
|
||||
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Gui::GLGraphicsItem, Base::BaseClass);
|
||||
|
||||
GLPainter::GLPainter() : viewer(0), logicOp(false), lineStipple(false)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
|
||||
namespace Gui {
|
||||
class View3DInventorViewer;
|
||||
class GuiExport GLPainter
|
||||
|
@ -71,6 +73,20 @@ private:
|
|||
bool lineStipple;
|
||||
};
|
||||
|
||||
class GuiExport GLGraphicsItem : public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
GLGraphicsItem()
|
||||
{
|
||||
}
|
||||
virtual ~GLGraphicsItem()
|
||||
{
|
||||
}
|
||||
virtual void paintGL() = 0;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_GLPAINTER_H
|
||||
|
|
BIN
src/Gui/Icons/freecad-icon-16.png
Normal file
BIN
src/Gui/Icons/freecad-icon-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 862 B |
BIN
src/Gui/Icons/freecad-icon-32.png
Normal file
BIN
src/Gui/Icons/freecad-icon-32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
src/Gui/Icons/freecad-icon-48.png
Normal file
BIN
src/Gui/Icons/freecad-icon-48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
src/Gui/Icons/freecad-icon-64.png
Normal file
BIN
src/Gui/Icons/freecad-icon-64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 153 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user