diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..8356b696
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+build-*
+*.user
+*.user.*
+installer/setupvars.iss
+installer/Output
diff --git a/README.md b/README.md
index 9b53e91a..8eba864b 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,42 @@
# Mayo
Mayo is a basic 3D viewer inspired by FreeCad.
-Its primary goal is to visualize CAD files imported/exported
-with the [gmio](https://github.com/fougue/gmio) library.
Current features are :
* Multi-documents support, user can open many parts in the session
* Support of IGES/STEP/BRep formats for import/export operations
-* Support of STL format with either [gmio](https://github.com/fougue/gmio) or OpenCascade(see the speed performance of gmio!)
+* Support of STEP/IGES assemblies (colors and tree structure)
+* Support of STL format with either OpenCascade or [gmio](https://github.com/fougue/gmio) (optional)
+* Perspective/orthographic 3D view projection
+* 3D clip planes with configurable capping
* Save image(snapshot) of the current 3D view
+* Editable name of STEP/IGES entities
* Editable 3D properties of the imported items, eg. material, color, display mode, ...
+* Area and volume properties for meshes and shapes
+
+3D viewer operations :
+* Rotate : mouse left + move
+* Pan : mouse right + move
+* Zoom : mouse wheel(scroll)
+* Window zoom : mouse wheel + move
+* Instant zoom : space bar
# Build instructions
-Mayo requires Qt5 and OpenCascade-7.0.0.
+Mayo requires Qt5 and OpenCascade-7.2.0.
Although only tested with VC++/Windows it should build fine on Linux and MacOS.
+It uses the `CSF_OCCTIncludePath` and `CSF_OCCTLibPath` environment variables to locate
+OpenCascade include and lib paths. On Windows these two variables are set by the `env.bat`
+script which can be found within OpenCascade's base folder. You should run this batch before
+building mayo :
`cd .../mayo`
-`qmake "GMIO_ROOT=path_to_gmio" "CASCADE_ROOT=path_to_opencascade"`
-`(n)make`
+`qmake`
+`(n)make`
+In case you don't want to run this file you can use the `CASCADE_INC_DIR` and `CASCADE_LIB_DIR` qmake
+variables instead :
+`qmake "CASCADE_INC_DIR=occ_include_dir" "CASCADE_LIB_DIR=occ_library_dir"`
+
+To enable optional gmio library, add this option to the qmake command line:
+`"GMIO_ROOT=path_to_gmio"`
-# Screenshots
+# Screencast
-
-
+
diff --git a/doc/screencast.gif b/doc/screencast.gif
new file mode 100644
index 00000000..938268bc
Binary files /dev/null and b/doc/screencast.gif differ
diff --git a/doc/screenshot_irb.png b/doc/screenshot_irb.png
deleted file mode 100644
index 2492d027..00000000
Binary files a/doc/screenshot_irb.png and /dev/null differ
diff --git a/doc/screenshot_stl.png b/doc/screenshot_stl.png
deleted file mode 100644
index 47282ef7..00000000
Binary files a/doc/screenshot_stl.png and /dev/null differ
diff --git a/doc/src_modules.odg b/doc/src_modules.odg
new file mode 100644
index 00000000..b9228c5a
Binary files /dev/null and b/doc/src_modules.odg differ
diff --git a/doc/src_modules.png b/doc/src_modules.png
new file mode 100644
index 00000000..ac3c88b6
Binary files /dev/null and b/doc/src_modules.png differ
diff --git a/images/appicon.ico b/images/appicon.ico
new file mode 100644
index 00000000..b030d122
Binary files /dev/null and b/images/appicon.ico differ
diff --git a/images/appicon_128.png b/images/appicon_128.png
new file mode 100644
index 00000000..5652fb7e
Binary files /dev/null and b/images/appicon_128.png differ
diff --git a/images/appicon_16.png b/images/appicon_16.png
new file mode 100644
index 00000000..6f97902b
Binary files /dev/null and b/images/appicon_16.png differ
diff --git a/images/appicon_24.png b/images/appicon_24.png
new file mode 100644
index 00000000..93f18980
Binary files /dev/null and b/images/appicon_24.png differ
diff --git a/images/appicon_32.png b/images/appicon_32.png
new file mode 100644
index 00000000..1cabbd57
Binary files /dev/null and b/images/appicon_32.png differ
diff --git a/images/appicon_64.png b/images/appicon_64.png
new file mode 100644
index 00000000..537121dc
Binary files /dev/null and b/images/appicon_64.png differ
diff --git a/images/camera_photo.png b/images/camera_photo.png
deleted file mode 100644
index 2faad6b6..00000000
Binary files a/images/camera_photo.png and /dev/null differ
diff --git a/images/credits.txt b/images/credits.txt
new file mode 100644
index 00000000..5d19d78b
--- /dev/null
+++ b/images/credits.txt
@@ -0,0 +1,66 @@
+Logo Cube
+
+
+Gear
+
+
+Import, Export
+
+
+Cross
+
+
+Previous, Next, Expand, Camera
+
+
+Organization
+
+
+Left sidebar
+
+
+Link button
+
+
+Back square button
+
+
+Settings
+
+
+Placeholder
+
+
+Error
+
+
+Settings
+
+
+Zoom In, Zoom Out
+
+
+Dodecahedron(mesh)
+
+
+Cube
+
+
+Clipping
+
+
+View 3d pre-defined orientation
+
+
+Stop(dark-theme)
+
+
+File (sheet)
+
+
+List (XdeDocumentItem)
+
+
+Hierarchy (Assembly)
+
+
diff --git a/images/document.png b/images/document.png
deleted file mode 100644
index e9364865..00000000
Binary files a/images/document.png and /dev/null differ
diff --git a/images/fit_all.png b/images/fit_all.png
deleted file mode 100644
index 3596d08c..00000000
Binary files a/images/fit_all.png and /dev/null differ
diff --git a/images/fougue_logo.png b/images/fougue_logo.png
deleted file mode 100644
index e23af483..00000000
Binary files a/images/fougue_logo.png and /dev/null differ
diff --git a/images/no.png b/images/no.png
deleted file mode 100644
index c56e148d..00000000
Binary files a/images/no.png and /dev/null differ
diff --git a/images/themes/classic/back-square.svg b/images/themes/classic/back-square.svg
new file mode 100644
index 00000000..e836c2b8
--- /dev/null
+++ b/images/themes/classic/back-square.svg
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/back.svg b/images/themes/classic/back.svg
new file mode 100644
index 00000000..eb5c4bf0
--- /dev/null
+++ b/images/themes/classic/back.svg
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/camera.svg b/images/themes/classic/camera.svg
new file mode 100644
index 00000000..c79d212b
--- /dev/null
+++ b/images/themes/classic/camera.svg
@@ -0,0 +1,416 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/clip-plane.svg b/images/themes/classic/clip-plane.svg
new file mode 100644
index 00000000..1d4c54cb
--- /dev/null
+++ b/images/themes/classic/clip-plane.svg
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/cross.svg b/images/themes/classic/cross.svg
new file mode 100644
index 00000000..ad5edf41
--- /dev/null
+++ b/images/themes/classic/cross.svg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/edit.svg b/images/themes/classic/edit.svg
new file mode 100644
index 00000000..61983821
--- /dev/null
+++ b/images/themes/classic/edit.svg
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/expand.svg b/images/themes/classic/expand.svg
new file mode 100644
index 00000000..037c5f7b
--- /dev/null
+++ b/images/themes/classic/expand.svg
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/export.svg b/images/themes/classic/export.svg
new file mode 100644
index 00000000..63ef432d
--- /dev/null
+++ b/images/themes/classic/export.svg
@@ -0,0 +1,799 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/file.svg b/images/themes/classic/file.svg
new file mode 100644
index 00000000..dbc29283
--- /dev/null
+++ b/images/themes/classic/file.svg
@@ -0,0 +1,788 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/gear.svg b/images/themes/classic/gear.svg
new file mode 100644
index 00000000..72f07286
--- /dev/null
+++ b/images/themes/classic/gear.svg
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/import.svg b/images/themes/classic/import.svg
new file mode 100644
index 00000000..dffb49bb
--- /dev/null
+++ b/images/themes/classic/import.svg
@@ -0,0 +1,847 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/indicator-down-disabled_8.png b/images/themes/classic/indicator-down-disabled_8.png
new file mode 100644
index 00000000..ca435467
Binary files /dev/null and b/images/themes/classic/indicator-down-disabled_8.png differ
diff --git a/images/themes/classic/indicator-down_8.png b/images/themes/classic/indicator-down_8.png
new file mode 100644
index 00000000..b308f626
Binary files /dev/null and b/images/themes/classic/indicator-down_8.png differ
diff --git a/images/themes/classic/item-mesh.svg b/images/themes/classic/item-mesh.svg
new file mode 100644
index 00000000..7c64b010
--- /dev/null
+++ b/images/themes/classic/item-mesh.svg
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/item-xde.svg b/images/themes/classic/item-xde.svg
new file mode 100644
index 00000000..b7e02a49
--- /dev/null
+++ b/images/themes/classic/item-xde.svg
@@ -0,0 +1,757 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/left-sidebar.svg b/images/themes/classic/left-sidebar.svg
new file mode 100644
index 00000000..17452652
--- /dev/null
+++ b/images/themes/classic/left-sidebar.svg
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/link.svg b/images/themes/classic/link.svg
new file mode 100644
index 00000000..927f98cb
--- /dev/null
+++ b/images/themes/classic/link.svg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/next.svg b/images/themes/classic/next.svg
new file mode 100644
index 00000000..9c5cd991
--- /dev/null
+++ b/images/themes/classic/next.svg
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/stop.svg b/images/themes/classic/stop.svg
new file mode 100644
index 00000000..7f46b9d2
--- /dev/null
+++ b/images/themes/classic/stop.svg
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/view-back.svg b/images/themes/classic/view-back.svg
new file mode 100644
index 00000000..3e930b22
--- /dev/null
+++ b/images/themes/classic/view-back.svg
@@ -0,0 +1,74 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/view-bottom.svg b/images/themes/classic/view-bottom.svg
new file mode 100644
index 00000000..135284d1
--- /dev/null
+++ b/images/themes/classic/view-bottom.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/view-front.svg b/images/themes/classic/view-front.svg
new file mode 100644
index 00000000..2624c4f3
--- /dev/null
+++ b/images/themes/classic/view-front.svg
@@ -0,0 +1,74 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/view-iso.svg b/images/themes/classic/view-iso.svg
new file mode 100644
index 00000000..b2853dd9
--- /dev/null
+++ b/images/themes/classic/view-iso.svg
@@ -0,0 +1,62 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/view-left.svg b/images/themes/classic/view-left.svg
new file mode 100644
index 00000000..3caa9f6c
--- /dev/null
+++ b/images/themes/classic/view-left.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/view-right.svg b/images/themes/classic/view-right.svg
new file mode 100644
index 00000000..8f5b9405
--- /dev/null
+++ b/images/themes/classic/view-right.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/view-top.svg b/images/themes/classic/view-top.svg
new file mode 100644
index 00000000..c694bec0
--- /dev/null
+++ b/images/themes/classic/view-top.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/classic/xde-assembly.svg b/images/themes/classic/xde-assembly.svg
new file mode 100644
index 00000000..2a9b658d
--- /dev/null
+++ b/images/themes/classic/xde-assembly.svg
@@ -0,0 +1,1439 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/xde-simple-shape.svg b/images/themes/classic/xde-simple-shape.svg
new file mode 100644
index 00000000..2bf93a80
--- /dev/null
+++ b/images/themes/classic/xde-simple-shape.svg
@@ -0,0 +1,1167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/zoom-in.svg b/images/themes/classic/zoom-in.svg
new file mode 100644
index 00000000..92346ca6
--- /dev/null
+++ b/images/themes/classic/zoom-in.svg
@@ -0,0 +1,3354 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/classic/zoom-out.svg b/images/themes/classic/zoom-out.svg
new file mode 100644
index 00000000..cf62fd32
--- /dev/null
+++ b/images/themes/classic/zoom-out.svg
@@ -0,0 +1,3290 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/back-square.svg b/images/themes/dark/back-square.svg
new file mode 100644
index 00000000..e836c2b8
--- /dev/null
+++ b/images/themes/dark/back-square.svg
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/back.svg b/images/themes/dark/back.svg
new file mode 100644
index 00000000..eb5c4bf0
--- /dev/null
+++ b/images/themes/dark/back.svg
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/camera.svg b/images/themes/dark/camera.svg
new file mode 100644
index 00000000..ebc0e4ec
--- /dev/null
+++ b/images/themes/dark/camera.svg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/clip-plane.svg b/images/themes/dark/clip-plane.svg
new file mode 100644
index 00000000..1d4c54cb
--- /dev/null
+++ b/images/themes/dark/clip-plane.svg
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/cross.svg b/images/themes/dark/cross.svg
new file mode 100644
index 00000000..ad5edf41
--- /dev/null
+++ b/images/themes/dark/cross.svg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/edit.svg b/images/themes/dark/edit.svg
new file mode 100644
index 00000000..61983821
--- /dev/null
+++ b/images/themes/dark/edit.svg
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/expand.svg b/images/themes/dark/expand.svg
new file mode 100644
index 00000000..037c5f7b
--- /dev/null
+++ b/images/themes/dark/expand.svg
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/export.svg b/images/themes/dark/export.svg
new file mode 100644
index 00000000..7d9c2031
--- /dev/null
+++ b/images/themes/dark/export.svg
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/file.svg b/images/themes/dark/file.svg
new file mode 100644
index 00000000..a9e9760f
--- /dev/null
+++ b/images/themes/dark/file.svg
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/gear.svg b/images/themes/dark/gear.svg
new file mode 100644
index 00000000..72f07286
--- /dev/null
+++ b/images/themes/dark/gear.svg
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/import.svg b/images/themes/dark/import.svg
new file mode 100644
index 00000000..2caf283f
--- /dev/null
+++ b/images/themes/dark/import.svg
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/indicator-down-disabled_8.png b/images/themes/dark/indicator-down-disabled_8.png
new file mode 100644
index 00000000..ca435467
Binary files /dev/null and b/images/themes/dark/indicator-down-disabled_8.png differ
diff --git a/images/themes/dark/indicator-down_8.png b/images/themes/dark/indicator-down_8.png
new file mode 100644
index 00000000..864e53c1
Binary files /dev/null and b/images/themes/dark/indicator-down_8.png differ
diff --git a/images/themes/dark/item-mesh.svg b/images/themes/dark/item-mesh.svg
new file mode 100644
index 00000000..be3466ce
--- /dev/null
+++ b/images/themes/dark/item-mesh.svg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/item-xde.svg b/images/themes/dark/item-xde.svg
new file mode 100644
index 00000000..92fac5c5
--- /dev/null
+++ b/images/themes/dark/item-xde.svg
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/left-sidebar.svg b/images/themes/dark/left-sidebar.svg
new file mode 100644
index 00000000..17452652
--- /dev/null
+++ b/images/themes/dark/left-sidebar.svg
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/link.svg b/images/themes/dark/link.svg
new file mode 100644
index 00000000..927f98cb
--- /dev/null
+++ b/images/themes/dark/link.svg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/next.svg b/images/themes/dark/next.svg
new file mode 100644
index 00000000..9c5cd991
--- /dev/null
+++ b/images/themes/dark/next.svg
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/stop.svg b/images/themes/dark/stop.svg
new file mode 100644
index 00000000..7f46b9d2
--- /dev/null
+++ b/images/themes/dark/stop.svg
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/view-back.svg b/images/themes/dark/view-back.svg
new file mode 100644
index 00000000..73ac0f92
--- /dev/null
+++ b/images/themes/dark/view-back.svg
@@ -0,0 +1,74 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/view-bottom.svg b/images/themes/dark/view-bottom.svg
new file mode 100644
index 00000000..034287f3
--- /dev/null
+++ b/images/themes/dark/view-bottom.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/view-front.svg b/images/themes/dark/view-front.svg
new file mode 100644
index 00000000..a2ccd9e7
--- /dev/null
+++ b/images/themes/dark/view-front.svg
@@ -0,0 +1,74 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/view-iso.svg b/images/themes/dark/view-iso.svg
new file mode 100644
index 00000000..b2853dd9
--- /dev/null
+++ b/images/themes/dark/view-iso.svg
@@ -0,0 +1,62 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/view-left.svg b/images/themes/dark/view-left.svg
new file mode 100644
index 00000000..92cb6b01
--- /dev/null
+++ b/images/themes/dark/view-left.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/view-right.svg b/images/themes/dark/view-right.svg
new file mode 100644
index 00000000..5e7219bd
--- /dev/null
+++ b/images/themes/dark/view-right.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/view-top.svg b/images/themes/dark/view-top.svg
new file mode 100644
index 00000000..5befd695
--- /dev/null
+++ b/images/themes/dark/view-top.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/xde-assembly.svg b/images/themes/dark/xde-assembly.svg
new file mode 100644
index 00000000..f743cd27
--- /dev/null
+++ b/images/themes/dark/xde-assembly.svg
@@ -0,0 +1,70 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/xde-simple-shape.svg b/images/themes/dark/xde-simple-shape.svg
new file mode 100644
index 00000000..8ce90921
--- /dev/null
+++ b/images/themes/dark/xde-simple-shape.svg
@@ -0,0 +1,64 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/images/themes/dark/zoom-in.svg b/images/themes/dark/zoom-in.svg
new file mode 100644
index 00000000..1883ce6b
--- /dev/null
+++ b/images/themes/dark/zoom-in.svg
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/themes/dark/zoom-out.svg b/images/themes/dark/zoom-out.svg
new file mode 100644
index 00000000..8ffbf8b1
--- /dev/null
+++ b/images/themes/dark/zoom-out.svg
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/view_axo.png b/images/view_axo.png
deleted file mode 100644
index 0f7e4660..00000000
Binary files a/images/view_axo.png and /dev/null differ
diff --git a/images/view_back.png b/images/view_back.png
deleted file mode 100644
index 8e9de6e0..00000000
Binary files a/images/view_back.png and /dev/null differ
diff --git a/images/view_bottom.png b/images/view_bottom.png
deleted file mode 100644
index 84008fd1..00000000
Binary files a/images/view_bottom.png and /dev/null differ
diff --git a/images/view_front.png b/images/view_front.png
deleted file mode 100644
index 51064059..00000000
Binary files a/images/view_front.png and /dev/null differ
diff --git a/images/view_left.png b/images/view_left.png
deleted file mode 100644
index 89aed38a..00000000
Binary files a/images/view_left.png and /dev/null differ
diff --git a/images/view_right.png b/images/view_right.png
deleted file mode 100644
index ff55677f..00000000
Binary files a/images/view_right.png and /dev/null differ
diff --git a/images/view_top.png b/images/view_top.png
deleted file mode 100644
index fb75981d..00000000
Binary files a/images/view_top.png and /dev/null differ
diff --git a/images/xde_reference_16.png b/images/xde_reference_16.png
new file mode 100644
index 00000000..a916ec5c
Binary files /dev/null and b/images/xde_reference_16.png differ
diff --git a/installer/TEMPLATE_setupvars.iss b/installer/TEMPLATE_setupvars.iss
new file mode 100644
index 00000000..78526cd1
--- /dev/null
+++ b/installer/TEMPLATE_setupvars.iss
@@ -0,0 +1,32 @@
+; This file is a template for creating your own local setupvars.iss file included by setup.iss
+; setupvars.iss is not versioned control as it is user-specific
+
+; Directory where is located mayo.exe
+#define AppBuildDir "C:\projects\mayo\build-mayo-Qt_5_11_1_MSVC_2017_x64\release"
+
+; Base directory of Qt(same as environment variable QTDIR)
+#define QtDir "C:\libs\Qt-5.11.1_msvc2017_x64\5.11.1\msvc2017_64"
+
+; Directory for OpenCascade DLLs
+#define OpenCascade_BinDir "C:\libs\OpenCASCADE-7.3.0-vc14-64\opencascade-7.3.0\win64\vc14\bin"
+
+; Directory for OpenCascade sources
+#define OpenCascade_SrcDir "C:\libs\OpenCASCADE-7.3.0-vc14-64\opencascade-7.3.0\src"
+
+; Directory for OpenCascade 3rdparty ffmpeg DLLs
+#define FFMPEG_BinDir "C:\libs\OpenCASCADE-7.3.0-vc14-64\ffmpeg-3.3-lgpl-64\bin"
+
+; Directory for OpenCascade 3rdparty freeimage DLLs
+#define FreeImage_BinDir "C:\libs\OpenCASCADE-7.3.0-vc14-64\freeimage-3.17.0-vc14-64\bin"
+
+; Directory for OpenCascade 3rdparty freetype DLLs
+#define FreeType_BinDir "C:\libs\OpenCASCADE-7.3.0-vc14-64\freetype-2.5.5-vc14-64\bin"
+
+; Directory for OpenCascade 3rdparty tbb DLLs
+#define Tbb_BinDir "C:\libs\OpenCASCADE-7.3.0-vc14-64\tbb_2017.0.100\bin\intel64\vc14"
+
+; Directory for OpenCascade 3rdparty tcltk DLLs
+#define TclTk_BinDir "C:\libs\OpenCASCADE-7.3.0-vc14-64\tcltk-86-64\bin"
+
+; Directory for MSVC 2017 redistributable package (vcredist)
+#define MsvcRedist_Dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Redist\MSVC\14.14.26405"
diff --git a/installer/opencascade.conf b/installer/opencascade.conf
new file mode 100644
index 00000000..ecb9fed9
--- /dev/null
+++ b/installer/opencascade.conf
@@ -0,0 +1,20 @@
+MMGT_OPT=1
+MMGT_CLEAR=1
+MMGT_REENTRANT=0
+CSF_LANGUAGE=us
+CSF_EXCEPTION_PROMPT=1
+
+CSF_SHMessage=OpenCascade/SHMessage
+CSF_MDTVTexturesDirectory=OpenCascade/Textures
+CSF_ShadersDirectory=OpenCascade/Shaders
+CSF_XSMessage=OpenCascade/XSMessage
+CSF_TObjMessage=OpenCascade/TObj
+CSF_StandardDefaults=OpenCascade/StdResource
+CSF_PluginDefaults=OpenCascade/StdResource
+CSF_XCAFDefaults=OpenCascade/StdResource
+CSF_TObjDefaults=OpenCascade/StdResource
+CSF_StandardLiteDefaults=OpenCascade/StdResource
+CSF_IGESDefaults=OpenCascade/XSTEPResource
+CSF_STEPDefaults=OpenCascade/XSTEPResource
+CSF_XmlOcafResource=OpenCascade/XmlOcafResource
+CSF_MIGRATION_TYPES=OpenCascade/StdResource/MigrationSheet.txt
diff --git a/installer/qt.conf b/installer/qt.conf
new file mode 100644
index 00000000..2438eff7
--- /dev/null
+++ b/installer/qt.conf
@@ -0,0 +1,2 @@
+[Paths]
+Plugins = QtPlugins
diff --git a/installer/setup.iss b/installer/setup.iss
new file mode 100644
index 00000000..5416e6f0
--- /dev/null
+++ b/installer/setup.iss
@@ -0,0 +1,119 @@
+#include "setupvars.iss"
+#include "version.iss"
+
+[Setup]
+ArchitecturesInstallIn64BitMode=x64
+AppId={{F1978C7C-3C90-477F-B634-B99746AA153D}
+AppName={#TargetProduct}
+AppVerName={#TargetProduct} v{#VersionNumber}
+AppPublisher={#TargetCompany}
+DefaultGroupName={#TargetCompany}
+DefaultDirName={pf}\{#TargetCompany}\{#TargetProduct}
+OutputBaseFilename={#TargetName}_v{#VersionNumber}_win{#TargetArch}_installer
+Compression=lzma
+SolidCompression=yes
+
+[Icons]
+Name: "{group}\{#TargetProduct}"; Filename: "{app}\{#TargetName}.exe"; WorkingDir: "{app}"; IconFileName: "{app}\{#TargetName}.exe"
+Name: "{commondesktop}\{#TargetProduct}"; Filename: "{app}\{#TargetName}.exe"; Tasks: desktopicon; WorkingDir: "{app}"; IconFileName: "{app}\{#TargetName}.exe"
+
+[Languages]
+Name: "en"; MessagesFile: "compiler:Default.isl"
+Name: "fr"; MessagesFile: "compiler:Languages\French.isl"
+[CustomMessages]
+en.installVcRuntime = Installing redistributable Visual Studio runtime ...
+fr.installVcRuntime = Installation du package redistribuable Visual Studio ...
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Files]
+Source: "{#AppBuildDir}\{#TargetName}.exe"; DestDir: "{app}"; Flags: ignoreversion
+; Source: "{#AppBuildDir}\i18n\*.qm"; DestDir: "{app}\i18n"; Flags: ignoreversion
+
+; First clear the setup folder (in case of a setup overwrite)
+[InstallDelete]
+Type: filesandordirs; Name: "{app}\*"
+
+[Files]
+Source: "{#MsvcRedist_Dir}\vcredist_{#TargetArch}.exe"; DestDir: "{app}"; Flags: deleteafterinstall;
+Source: "opencascade.conf"; DestDir: "{app}";
+Source: "qt.conf"; DestDir: "{app}";
+
+; Qt5
+Source: "{#QtDir}\bin\Qt5Core.dll"; DestDir: "{app}"; Flags: ignoreversion;
+Source: "{#QtDir}\bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: ignoreversion;
+Source: "{#QtDir}\bin\Qt5Svg.dll"; DestDir: "{app}"; Flags: ignoreversion;
+Source: "{#QtDir}\bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion;
+Source: "{#QtDir}\bin\Qt5WinExtras.dll"; DestDir: "{app}"; Flags: ignoreversion;
+Source: "{#QtDir}\plugins\iconengines\qsvgicon.dll"; DestDir: "{app}\QtPlugins\iconengines"; Flags: ignoreversion
+Source: "{#QtDir}\plugins\imageformats\qsvg.dll"; DestDir: "{app}\QtPlugins\imageformats"; Flags: ignoreversion
+Source: "{#QtDir}\plugins\platforms\qwindows.dll"; DestDir: "{app}\QtPlugins\platforms"; Flags: ignoreversion
+
+; OpenCascade
+Source: "{#OpenCascade_BinDir}\TKBO.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKBOOL.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKBRep.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKCAF.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKCDF.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKDraw.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKernel.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKFillet.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKG2d.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKG3d.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKGeomAlgo.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKGeomBase.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKHLR.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKIGES.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKLCAF.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKMath.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKMesh.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKMeshVS.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKOffset.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKOpenGl.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKPrim.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKService.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKShHealing.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKSTEP.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKSTEP209.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKSTEPAttr.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKSTEPBase.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKSTL.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKTopAlgo.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKV3d.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKVCAF.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKViewerTest.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKVRML.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKXCAF.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKXDEIGES.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKXDESTEP.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKXSBase.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#OpenCascade_BinDir}\TKXSDRAW.dll"; DestDir: "{app}"; Flags: ignoreversion
+
+; OpenCascade resources
+Source: "{#OpenCascade_SrcDir}\SHMessage\*.*"; DestDir: "{app}\OpenCascade\SHMessage"; Flags: ignoreversion
+Source: "{#OpenCascade_SrcDir}\Textures\*.*"; DestDir: "{app}\OpenCascade\Textures"; Flags: ignoreversion
+Source: "{#OpenCascade_SrcDir}\Shaders\*.*"; DestDir: "{app}\OpenCascade\Shaders"; Flags: ignoreversion
+Source: "{#OpenCascade_SrcDir}\XSMessage\*.*"; DestDir: "{app}\OpenCascade\XSMessage"; Flags: ignoreversion
+Source: "{#OpenCascade_SrcDir}\TObj\*.msg"; DestDir: "{app}\OpenCascade\TObj"; Flags: ignoreversion
+Source: "{#OpenCascade_SrcDir}\StdResource\*.*"; DestDir: "{app}\OpenCascade\StdResource"; Flags: ignoreversion
+Source: "{#OpenCascade_SrcDir}\XSTEPResource\*.*"; DestDir: "{app}\OpenCascade\XSTEPResource"; Flags: ignoreversion
+Source: "{#OpenCascade_SrcDir}\XmlOcafResource\*.*"; DestDir: "{app}\OpenCascade\XmlOcafResource"; Flags: ignoreversion
+
+; OpenCascade 3rdparty
+Source: "{#Tbb_BinDir}\tbb.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#Tbb_BinDir}\tbbmalloc.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FFMPEG_BinDir}\avcodec*.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FFMPEG_BinDir}\avformat*.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FFMPEG_BinDir}\avutil*.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FFMPEG_BinDir}\swresample*.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FFMPEG_BinDir}\swscale*.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FreeImage_BinDir}\freeimage.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FreeImage_BinDir}\freeimageplus.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#FreeType_BinDir}\freetype.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#TclTk_BinDir}\tcl86.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#TclTk_BinDir}\tk86.dll"; DestDir: "{app}"; Flags: ignoreversion
+; Source: "{#TclTk_BinDir}\zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion
+
+[Run]
+Filename: "{app}\vcredist_{#TargetArch}.exe"; Parameters: "/q"; StatusMsg: "{cm:installVcRuntime}"
diff --git a/installer/version.iss.in b/installer/version.iss.in
new file mode 100644
index 00000000..bb75294d
--- /dev/null
+++ b/installer/version.iss.in
@@ -0,0 +1,5 @@
+#define VersionNumber \"$$MAYO_VERSION\"
+#define TargetName \"$$TARGET\"
+#define TargetArch \"$$VERSION_TARGET_ARCH\"
+#define TargetProduct \"$$QMAKE_TARGET_PRODUCT\"
+#define TargetCompany \"$$QMAKE_TARGET_COMPANY\"
diff --git a/mayo.pro b/mayo.pro
index 1989f366..316aceec 100644
--- a/mayo.pro
+++ b/mayo.pro
@@ -3,116 +3,111 @@ TEMPLATE = app
QT += core gui widgets
+CONFIG += c++17
+CONFIG += file_copies
+
+CONFIG(debug, debug|release) {
+ CONFIG += console
+} else {
+ CONFIG -= console
+ CONFIG += release_with_debuginfo
+}
+
+release_with_debuginfo:*msvc* {
+ # https://docs.microsoft.com/en-us/cpp/build/reference/how-to-debug-a-release-build
+ QMAKE_CXXFLAGS_RELEASE += /Zi
+ QMAKE_LFLAGS_RELEASE += /DEBUG /INCREMENTAL:NO /OPT:REF /OPT:ICF
+}
+
*msvc* {
QMAKE_CXXFLAGS += /we4150 # Deletion of pointer to incomplete type 'XXXX'; no destructor called
+ QMAKE_CXXFLAGS += /std:c++17
+}
+*g++* {
+ QMAKE_CXXFLAGS += -std=c++17
}
+include(version.pri)
+CONFIG(debug, debug|release) {
+ message(Mayo version $$MAYO_VERSION debug)
+} else {
+ message(Mayo version $$MAYO_VERSION release)
+}
+
+INCLUDEPATH += \
+ src/app \
+ src/3rdparty
+
HEADERS += \
- src/brep_shape_item.h \
- src/document.h \
- src/document_item.h \
- src/fougtools/qttools/gui/qwidget_utils.h \
- src/mainwindow.h \
- src/occt_window.h \
- src/qt_occ_view_controller.h \
- src/stl_mesh_item.h \
- src/fougtools/qttools/gui/gui.h \
- src/fougtools/qttools/gui/item_view_utils.h \
- src/fougtools/occtools/occtools.h \
- src/fougtools/occtools/qt_utils.h \
- src/options.h \
- src/application.h \
- src/property.h \
- src/property_enumeration.h \
- src/property_builtins.h \
- src/gui_document.h \
- src/gui_application.h \
- src/gpx_document_item.h \
- src/gpx_brep_shape_item.h \
- src/gpx_stl_mesh_item.h \
- src/dialog_about.h \
- src/dialog_options.h \
- src/dialog_task_manager.h \
- src/dialog_save_image_view.h \
- src/widget_application_tree.h \
- src/widget_document_item_props.h \
- src/widget_message_indicator.h \
- src/widget_gui_document_view3d.h \
- src/widget_occ_view.h \
- src/dialog_export_options.h
+ src/3rdparty/fougtools/qttools/gui/item_view_buttons.h \
+ src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.h \
+ \
+ $$files(src/base/*.h) \
+ $$files(src/gpx/*.h) \
+ $$files(src/gui/*.h) \
+ $$files(src/app/*.h) \
SOURCES += \
- src/brep_shape_item.cpp \
- src/document.cpp \
- src/document_item.cpp \
- src/fougtools/qttools/gui/qwidget_utils.cpp \
- src/main.cpp \
- src/mainwindow.cpp \
- src/occt_window.cpp \
- src/qt_occ_view_controller.cpp \
- src/stl_mesh_item.cpp \
- src/fougtools/qttools/gui/item_view_utils.cpp \
- src/fougtools/occtools/qt_utils.cpp \
- src/options.cpp \
- src/application.cpp \
- src/property.cpp \
- src/property_enumeration.cpp \
- src/gui_document.cpp \
- src/gui_application.cpp \
- src/gpx_document_item.cpp \
- src/gpx_brep_shape_item.cpp \
- src/gpx_stl_mesh_item.cpp \
- src/dialog_about.cpp \
- src/dialog_options.cpp \
- src/dialog_task_manager.cpp \
- src/dialog_save_image_view.cpp \
- src/widget_application_tree.cpp \
- src/widget_document_item_props.cpp \
- src/widget_message_indicator.cpp \
- src/widget_gui_document_view3d.cpp \
- src/widget_occ_view.cpp \
- src/dialog_export_options.cpp
-
-include(src/fougtools/qttools/task/qttools_task.pri)
-include(src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.pri)
-INCLUDEPATH += src/qt-solutions/qtpropertybrowser/src
-
-FORMS += \
- src/mainwindow.ui \
- src/dialog_about.ui \
- src/dialog_options.ui \
- src/dialog_task_manager.ui \
- src/dialog_save_image_view.ui \
- src/widget_application_tree.ui \
- src/widget_document_item_props.ui \
- src/dialog_export_options.ui
+ src/3rdparty/fougtools/occtools/qt_utils.cpp \
+ src/3rdparty/fougtools/qttools/gui/item_view_buttons.cpp \
+ src/3rdparty/fougtools/qttools/gui/item_view_utils.cpp \
+ src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.cpp \
+ src/3rdparty/fougtools/qttools/gui/qwidget_utils.cpp \
+ \
+ $$files(src/base/*.cpp) \
+ $$files(src/gpx/*.cpp) \
+ $$files(src/gui/*.cpp) \
+ $$files(src/app/*.cpp) \
+
+win* {
+ QT += winextras
+ HEADERS += $$files(src/app/windows/*.h)
+ SOURCES += $$files(src/app/windows/*.cpp)
+
+ COPIES += WinInstallerFiles
+ WinInstallerFiles.files = $$files($$PWD/installer/*.iss)
+ WinInstallerFiles.files += $$files($$PWD/installer/*.conf)
+ WinInstallerFiles.path = $$OUT_PWD/installer
+}
+
+include(src/3rdparty/fougtools/qttools/task/qttools_task.pri)
+
+FORMS += $$files(src/app/*.ui)
+
+RESOURCES += mayo.qrc
+RC_ICONS = images/appicon.ico
+
+OTHER_FILES += \
+ README.md \
+ images/credits.txt
# gmio
-isEmpty(GMIO_ROOT):error(Variable GMIO_ROOT is empty)
-CONFIG(debug, debug|release) {
- GMIO_BIN_SUFFIX = _d
+isEmpty(GMIO_ROOT) {
+ message(gmio OFF)
} else {
- GMIO_BIN_SUFFIX =
+ message(gmio ON)
+ CONFIG(debug, debug|release) {
+ GMIO_BIN_SUFFIX = d
+ } else {
+ GMIO_BIN_SUFFIX =
+ }
+
+ INCLUDEPATH += $$GMIO_ROOT/include
+ LIBS += -L$$GMIO_ROOT/lib -lgmio_static$$GMIO_BIN_SUFFIX
+ SOURCES += \
+ $$GMIO_ROOT/src/gmio_support/stl_occ_brep.cpp \
+ $$GMIO_ROOT/src/gmio_support/stl_occ_polytri.cpp \
+ $$GMIO_ROOT/src/gmio_support/stream_qt.cpp
+ DEFINES += HAVE_GMIO
}
-INCLUDEPATH += $$GMIO_ROOT/include
-LIBS += -L$$GMIO_ROOT/lib -lgmio_static$$GMIO_BIN_SUFFIX
-SOURCES += \
- $$GMIO_ROOT/src/gmio_support/stl_occ_brep.cpp \
- $$GMIO_ROOT/src/gmio_support/stl_occ_mesh.cpp \
- $$GMIO_ROOT/src/gmio_support/stl_occ_polytri.cpp \
- $$GMIO_ROOT/src/gmio_support/stream_qt.cpp
# OpenCascade
-#CASCADE_ROOT=C:/dev/libs/OpenCASCADE6.9.1-vc12-64/opencascade-6.9.1
-#CASCADE_ROOT=C:/dev/libs/OpenCASCADE7.0.0-vc12-64/opencascade-7.0.0
-isEmpty(CASCADE_ROOT):error(Variable CASCADE_ROOT is empty)
-include(occ.pri)
+include(opencascade.pri)
LIBS += -lTKernel -lTKMath -lTKTopAlgo -lTKV3d -lTKOpenGl -lTKService
+LIBS += -lTKG2d
LIBS += -lTKBRep -lTKSTL
-LIBS += -lTKXSBase -lTKIGES -lTKSTEP
+LIBS += -lTKXSBase -lTKIGES -lTKSTEP -lTKXDESTEP -lTKXDEIGES
LIBS += -lTKMeshVS -lTKXSDRAW
-
-OCCT_DEFINES = $$(CSF_DEFINES)
-DEFINES += $$split(OCCT_DEFINES, ;)
-
-RESOURCES += mayo.qrc
+LIBS += -lTKLCAF -lTKXCAF -lTKCAF
+LIBS += -lTKG3d
+LIBS += -lTKGeomBase
diff --git a/mayo.qrc b/mayo.qrc
index 2115b858..29255fce 100644
--- a/mayo.qrc
+++ b/mayo.qrc
@@ -1,17 +1,71 @@
- images/fit_all.png
- images/view_axo.png
- images/view_back.png
- images/view_bottom.png
- images/view_front.png
- images/view_left.png
- images/view_right.png
- images/view_top.png
- images/fougue_logo.png
- images/camera_photo.png
- images/document.png
- images/no.png
+ images/appicon_128.png
+ images/appicon_16.png
+ images/appicon_24.png
+ images/appicon_32.png
+ images/appicon_64.png
+ images/themes/classic/back-square.svg
+ images/themes/classic/back.svg
+ images/themes/classic/camera.svg
+ images/themes/classic/clip-plane.svg
+ images/themes/classic/cross.svg
+ images/themes/classic/expand.svg
+ images/themes/classic/export.svg
+ images/themes/classic/file.svg
+ images/themes/classic/gear.svg
+ images/themes/classic/import.svg
+ images/themes/classic/indicator-down-disabled_8.png
+ images/themes/classic/indicator-down_8.png
+ images/themes/classic/item-mesh.svg
+ images/themes/classic/item-xde.svg
+ images/themes/classic/left-sidebar.svg
+ images/themes/classic/link.svg
+ images/themes/classic/next.svg
+ images/themes/classic/stop.svg
+ images/themes/classic/view-back.svg
+ images/themes/classic/view-bottom.svg
+ images/themes/classic/view-front.svg
+ images/themes/classic/view-iso.svg
+ images/themes/classic/view-left.svg
+ images/themes/classic/view-right.svg
+ images/themes/classic/view-top.svg
+ images/themes/classic/xde-assembly.svg
+ images/themes/classic/zoom-in.svg
+ images/themes/classic/zoom-out.svg
+ images/themes/dark/back-square.svg
+ images/themes/dark/back.svg
+ images/themes/dark/camera.svg
+ images/themes/dark/clip-plane.svg
+ images/themes/dark/cross.svg
+ images/themes/dark/expand.svg
+ images/themes/dark/export.svg
+ images/themes/dark/file.svg
+ images/themes/dark/gear.svg
+ images/themes/dark/import.svg
+ images/themes/dark/indicator-down-disabled_8.png
+ images/themes/dark/indicator-down_8.png
+ images/themes/dark/item-mesh.svg
+ images/themes/dark/item-xde.svg
+ images/themes/dark/left-sidebar.svg
+ images/themes/dark/link.svg
+ images/themes/dark/next.svg
+ images/themes/dark/stop.svg
+ images/themes/dark/view-back.svg
+ images/themes/dark/view-bottom.svg
+ images/themes/dark/view-front.svg
+ images/themes/dark/view-iso.svg
+ images/themes/dark/view-left.svg
+ images/themes/dark/view-right.svg
+ images/themes/dark/view-top.svg
+ images/themes/dark/xde-assembly.svg
+ images/themes/dark/xde-simple-shape.svg
+ images/themes/dark/zoom-in.svg
+ images/themes/dark/zoom-out.svg
images/widget_pseudo_fold.png
+ images/xde_reference_16.png
+ images/themes/classic/xde-simple-shape.svg
+ images/themes/classic/edit.svg
+ images/themes/dark/edit.svg
diff --git a/occ.pri b/occ.pri
deleted file mode 100644
index 1009b5d1..00000000
--- a/occ.pri
+++ /dev/null
@@ -1,67 +0,0 @@
-# Return the input path re-written using the system-dependent separator
-defineReplace(sysPath) {
- win*:result = $$replace(1, /, \\)
- else:result = $$1
- return($$result)
-}
-
-INCLUDEPATH += $$CASCADE_ROOT/inc
-
-linux-*:DEFINES += HAVE_CONFIG_H \
- HAVE_FSTREAM \
- HAVE_IOSTREAM \
- HAVE_IOMANIP \
- HAVE_LIMITS_H
-
-win32-*:DEFINES += WNT
-linux-*:DEFINES += LIN LININTEL OCC_CONVERT_SIGNALS
-
-MSVC_VERSION = xx
-win32-msvc2005:MSVC_VERSION = 8
-win32-msvc2008:MSVC_VERSION = 9
-win32-msvc2010:MSVC_VERSION = 10
-win32-msvc2012:MSVC_VERSION = 11
-win32-msvc2013:MSVC_VERSION = 12
-
-# Find OCC version
-OCC_VERSION_FILE_CONTENTS = $$cat($$CASCADE_ROOT/inc/Standard_Version.hxx, lines)
-
-OCC_VERSION_MAJOR = $$find(OCC_VERSION_FILE_CONTENTS, OCC_VERSION_MAJOR\s+[0-9]+)
-OCC_VERSION_MAJOR = $$section(OCC_VERSION_MAJOR, " ", -1)
-OCC_VERSION_MINOR = $$find(OCC_VERSION_FILE_CONTENTS, OCC_VERSION_MINOR\s+[0-9]+)
-OCC_VERSION_MINOR = $$section(OCC_VERSION_MINOR, " ", -1)
-OCC_VERSION_PATCH = $$find(OCC_VERSION_FILE_CONTENTS, OCC_VERSION_MAINTENANCE\s+[0-9]+)
-OCC_VERSION_PATCH = $$section(OCC_VERSION_PATCH, " ", -1)
-
-OCC_VERSION_STR = $$join($$list($$OCC_VERSION_MAJOR, $$OCC_VERSION_MINOR, $$OCC_VERSION_PATCH), .)
-
-message(OCC_VERSION : $$OCC_VERSION_STR)
-
-# Platform dependant config
-equals(QT_ARCH, i386) {
- ARCH_BITS_SIZE = 32
-} else:equals(QT_ARCH, x86_64) {
- ARCH_BITS_SIZE = 64
- DEFINES += _OCC64
-}
-else {
- error(Platform architecture not supported (QT_ARCH = $$QT_ARCH))
-}
-
-# Set CASCADE_SUB_LIB_PATH
-equals(OCC_VERSION_STR, 6.7.1) \
- | equals(OCC_VERSION_STR, 6.8.0) \
- | equals(OCC_VERSION_STR, 6.9.0) \
- | equals(OCC_VERSION_STR, 6.9.1) \
- | equals(OCC_VERSION_STR, 7.0.0) \
-{
- win32:CASCADE_SUB_LIB_PATH = win$${ARCH_BITS_SIZE}/vc$$MSVC_VERSION/lib
- linux-*:CASCADE_SUB_LIB_PATH = lin$${ARCH_BITS_SIZE}/gcc/lib
- CONFIG(debug, debug|release):CASCADE_SUB_LIB_PATH = $${CASCADE_SUB_LIB_PATH}d
-} else {
- CASCADE_SUB_LIB_PATH = lib
-}
-
-CASCADE_LIB_PATH += $$CASCADE_ROOT/$$CASCADE_SUB_LIB_PATH
-LIBS += $$sysPath($$join(CASCADE_LIB_PATH, " -L", -L))
-QMAKE_RPATHDIR += $$CASCADE_LIB_PATH
diff --git a/opencascade.pri b/opencascade.pri
new file mode 100644
index 00000000..29d99e75
--- /dev/null
+++ b/opencascade.pri
@@ -0,0 +1,50 @@
+# Return the input path re-written using the system-dependent separator
+defineReplace(sysPath) {
+ win*:result = $$replace(1, /, \\)
+ else:result = $$1
+ return($$result)
+}
+
+isEmpty(CASCADE_INC_DIR):CASCADE_INC_DIR = $$(CSF_OCCTIncludePath)
+isEmpty(CASCADE_LIB_DIR):CASCADE_LIB_DIR = $$(CSF_OCCTLibPath)
+
+INCLUDEPATH += $$CASCADE_INC_DIR
+
+linux-*:DEFINES += \
+ HAVE_CONFIG_H \
+ HAVE_FSTREAM \
+ HAVE_IOSTREAM \
+ HAVE_IOMANIP \
+ HAVE_LIMITS_H
+
+CASCADE_DEFINES = $$(CSF_DEFINES)
+DEFINES += $$split(OCCT_DEFINES, ;)
+DEFINES += OCCT_HANDLE_NOCAST
+linux-*:DEFINES += LIN LININTEL OCC_CONVERT_SIGNALS
+
+# Find OCC version
+OCC_VERSION_FILE_CONTENTS = $$cat($$CASCADE_INC_DIR/Standard_Version.hxx, lines)
+
+OCC_VERSION_MAJOR = $$find(OCC_VERSION_FILE_CONTENTS, OCC_VERSION_MAJOR\s+[0-9]+)
+OCC_VERSION_MAJOR = $$section(OCC_VERSION_MAJOR, " ", -1)
+OCC_VERSION_MINOR = $$find(OCC_VERSION_FILE_CONTENTS, OCC_VERSION_MINOR\s+[0-9]+)
+OCC_VERSION_MINOR = $$section(OCC_VERSION_MINOR, " ", -1)
+OCC_VERSION_PATCH = $$find(OCC_VERSION_FILE_CONTENTS, OCC_VERSION_MAINTENANCE\s+[0-9]+)
+OCC_VERSION_PATCH = $$section(OCC_VERSION_PATCH, " ", -1)
+
+OCC_VERSION_STR = $$join($$list($$OCC_VERSION_MAJOR, $$OCC_VERSION_MINOR, $$OCC_VERSION_PATCH), .)
+
+message(OpenCascade version $$OCC_VERSION_STR)
+
+# Platform dependent config
+equals(QT_ARCH, i386) {
+ ARCH_BITS_SIZE = 32
+} else:equals(QT_ARCH, x86_64) {
+ ARCH_BITS_SIZE = 64
+ DEFINES += _OCC64
+} else {
+ error(Platform architecture not supported (QT_ARCH = $$QT_ARCH))
+}
+
+LIBS += $$sysPath($$join(CASCADE_LIB_DIR, " -L", -L))
+QMAKE_RPATHDIR += $$CASCADE_LIB_DIR
diff --git a/scripts/bump-version.rb b/scripts/bump-version.rb
new file mode 100644
index 00000000..043c7a6b
--- /dev/null
+++ b/scripts/bump-version.rb
@@ -0,0 +1,36 @@
+##
+## Copyright (c) 2019, Fougue Ltd.
+## All rights reserved.
+## See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt
+##
+
+#!/usr/bin/ruby
+
+if ARGV.empty? then
+ puts "Error: no version argument"
+ return
+end
+
+version_str = ARGV.first
+version_array = ARGV.first.split('.')
+if version_array.size != 3 then
+ puts "Error: wrong version format(maj.min.patch)"
+ return
+end
+
+major = version_array[0]
+minor = version_array[1]
+patch = version_array[2]
+puts "Major: #{major}"
+puts "Minor: #{minor}"
+puts "Patch: #{patch}"
+script_dir_name = File.expand_path(File.dirname(__FILE__))
+
+# ../version.pri
+path_version_pri = "#{script_dir_name}/../version.pri"
+version_pri = File.open(path_version_pri, "r").read
+version_pri.sub!(/(MAYO_VERSION_MAJ\s*=\s*)\d+/, "\\1#{major}")
+version_pri.sub!(/(MAYO_VERSION_MIN\s*=\s*)\d+/, "\\1#{minor}")
+version_pri.sub!(/(MAYO_VERSION_PAT\s*=\s*)\d+/, "\\1#{patch}")
+File.open(path_version_pri, "w").write(version_pri)
+puts "Bumped #{path_version_pri}"
diff --git a/src/fougtools/occtools/occtools.h b/src/3rdparty/fougtools/occtools/occtools.h
similarity index 100%
rename from src/fougtools/occtools/occtools.h
rename to src/3rdparty/fougtools/occtools/occtools.h
diff --git a/src/fougtools/occtools/qt_utils.cpp b/src/3rdparty/fougtools/occtools/qt_utils.cpp
similarity index 100%
rename from src/fougtools/occtools/qt_utils.cpp
rename to src/3rdparty/fougtools/occtools/qt_utils.cpp
diff --git a/src/fougtools/occtools/qt_utils.h b/src/3rdparty/fougtools/occtools/qt_utils.h
similarity index 82%
rename from src/fougtools/occtools/qt_utils.h
rename to src/3rdparty/fougtools/occtools/qt_utils.h
index ffb9f5d2..655650e4 100644
--- a/src/fougtools/occtools/qt_utils.h
+++ b/src/3rdparty/fougtools/occtools/qt_utils.h
@@ -17,6 +17,7 @@
#include "occtools.h"
+#include
#include
#include
#include
@@ -25,6 +26,8 @@
#include
#include
+#include
+
namespace occ {
class OCCTOOLS_EXPORT QtUtils
@@ -73,12 +76,13 @@ QString QtUtils::toQString(
unsigned prec)
{
QString result = format;
- result.replace(
- QLatin1String("%x"), QString::number(pv.X(), realFormat, prec));
- result.replace(
- QLatin1String("%y"), QString::number(pv.Y(), realFormat, prec));
- return result.replace(
- QLatin1String("%z"), QString::number(pv.Z(), realFormat, prec));
+ const double x = std::abs(pv.X()) < Precision::Confusion() ? 0. : pv.X();
+ const double y = std::abs(pv.Y()) < Precision::Confusion() ? 0. : pv.Y();
+ const double z = std::abs(pv.Z()) < Precision::Confusion() ? 0. : pv.Z();
+ result.replace(QLatin1String("%x"), QString::number(x, realFormat, prec));
+ result.replace(QLatin1String("%y"), QString::number(y, realFormat, prec));
+ result.replace(QLatin1String("%z"), QString::number(z, realFormat, prec));
+ return result;
}
} // namespace occ
diff --git a/src/3rdparty/fougtools/qttools/core/qstring_hfunc.h b/src/3rdparty/fougtools/qttools/core/qstring_hfunc.h
new file mode 100644
index 00000000..5f67ba9e
--- /dev/null
+++ b/src/3rdparty/fougtools/qttools/core/qstring_hfunc.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+** FougTools
+** Copyright Fougue (30 Mar. 2015)
+** contact@fougue.pro
+**
+** This software is a computer program whose purpose is to provide utility
+** tools for the C++ language and the Qt toolkit.
+**
+** This software is governed by the CeCILL-C license under French law and
+** abiding by the rules of distribution of free software. You can use,
+** modify and/ or redistribute the software under the terms of the CeCILL-C
+** license as circulated by CEA, CNRS and INRIA at the following URL
+** "http://www.cecill.info".
+****************************************************************************/
+
+#pragma once
+
+#include
+#include
+
+namespace boost {
+
+//! Implementation of Boost's hash function for QString
+inline std::size_t hash_value(const QString& key)
+{
+ return qHash(key);
+}
+
+} // namespace boost
+
+namespace std {
+
+//! Specialization of C++11 std::hash<> functor for QString
+template<> struct hash {
+ inline std::size_t operator()(const QString& key) const
+ {
+ return qHash(key);
+ }
+};
+
+} // namespace std
diff --git a/src/fougtools/qttools/gui/gui.h b/src/3rdparty/fougtools/qttools/gui/gui.h
similarity index 100%
rename from src/fougtools/qttools/gui/gui.h
rename to src/3rdparty/fougtools/qttools/gui/gui.h
diff --git a/src/3rdparty/fougtools/qttools/gui/item_view_buttons.cpp b/src/3rdparty/fougtools/qttools/gui/item_view_buttons.cpp
new file mode 100644
index 00000000..55a21786
--- /dev/null
+++ b/src/3rdparty/fougtools/qttools/gui/item_view_buttons.cpp
@@ -0,0 +1,653 @@
+/****************************************************************************
+** FougTools
+** Copyright Fougue (30 Mar. 2015)
+** contact@fougue.pro
+**
+** This software is a computer program whose purpose is to provide utility
+** tools for the C++ language and the Qt toolkit.
+**
+** This software is governed by the CeCILL-C license under French law and
+** abiding by the rules of distribution of free software. You can use,
+** modify and/ or redistribute the software under the terms of the CeCILL-C
+** license as circulated by CEA, CNRS and INRIA at the following URL
+** "http://www.cecill.info".
+****************************************************************************/
+
+#include "item_view_buttons.h"
+
+#include "proxy_styled_item_delegate.h"
+
+#include
+#include
+#include
+// QtWidgets
+#include
+#include
+#include
+
+namespace qtgui {
+
+namespace cpp {
+
+template
+void checkedAssign(VALUE_TYPE CLASS::*attrMember, CLASS* object, CALL_VALUE_TYPE value)
+{
+ if (object != nullptr && attrMember != nullptr)
+ object->*attrMember = value;
+}
+
+} // namespace cpp
+
+/*! \class ItemViewButtonsPrivate
+ * \brief Internal (pimpl of ItemViewButtons)
+ */
+
+class ItemViewButtons::Private
+{
+public:
+ class ProxyItemDelegate : public ProxyStyledItemDelegate
+ {
+ public:
+ ProxyItemDelegate(
+ const ItemViewButtons* itemBtns,
+ QStyledItemDelegate* srcDelegate,
+ QObject* parent = nullptr);
+
+ void paint(
+ QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+ private:
+ const ItemViewButtons* m_itemBtns;
+ };
+
+ struct ButtonInfo
+ {
+ int index;
+ QIcon icon;
+ QSize iconSize;
+ QString toolTip;
+ int matchRole;
+ QVariant matchData;
+ int displayColumn;
+ ItemViewButtons::ItemSide itemSide;
+ ItemViewButtons::DisplayModes itemDisplayModes;
+ };
+
+ Private(ItemViewButtons* backPtr);
+
+ const ButtonInfo* buttonInfo(int btnId) const;
+ ButtonInfo* mutableButtonInfo(int btnId);
+ void setAllIsOverButtonState(bool on);
+ QModelIndex modelIndexForButtonDisplay(const QModelIndex& index) const;
+ void itemViewUpdateAt(const QModelIndex& index);
+ void paintButton(
+ ButtonInfo *btnInfo,
+ QPainter* painter,
+ const QStyleOptionViewItem& option);
+ void resetButtonUnderMouseState();
+
+ QAbstractItemView* m_view;
+ QHash m_btnInfos;
+ const ButtonInfo* m_buttonUnderMouse;
+
+private:
+ ItemViewButtons* m_backPtr;
+};
+
+ItemViewButtons::Private::ProxyItemDelegate::ProxyItemDelegate(
+ const ItemViewButtons *itemBtns,
+ QStyledItemDelegate *srcDelegate,
+ QObject* parent)
+ : ProxyStyledItemDelegate(srcDelegate, parent),
+ m_itemBtns(itemBtns)
+{
+}
+
+void ItemViewButtons::Private::ProxyItemDelegate::paint(
+ QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ ProxyStyledItemDelegate::paint(painter, option, index);
+ if (m_itemBtns != nullptr)
+ m_itemBtns->paint(painter, option, index);
+}
+
+ItemViewButtons::Private::Private(ItemViewButtons *backPtr)
+ : m_view(nullptr),
+ m_buttonUnderMouse(nullptr),
+ m_backPtr(backPtr)
+{
+}
+
+const ItemViewButtons::Private::ButtonInfo*
+ItemViewButtons::Private::buttonInfo(int btnId) const
+{
+ const auto iBtnInfo = m_btnInfos.find(btnId);
+ if (iBtnInfo != m_btnInfos.constEnd())
+ return &(iBtnInfo.value());
+ return nullptr;
+}
+
+ItemViewButtons::Private::ButtonInfo*
+ItemViewButtons::Private::mutableButtonInfo(int btnId)
+{
+ auto iBtnInfo = m_btnInfos.find(btnId);
+ if (iBtnInfo != m_btnInfos.end())
+ return &(iBtnInfo.value());
+ return nullptr;
+}
+
+QModelIndex ItemViewButtons::Private::modelIndexForButtonDisplay(
+ const QModelIndex &index) const
+{
+ const int btnIndex = m_backPtr->buttonAtModelIndex(index);
+ const auto btnInfo = this->buttonInfo(btnIndex);
+ if (btnInfo != nullptr && btnInfo->displayColumn != -1)
+ return index.sibling(index.row(), btnInfo->displayColumn);
+ return index;
+}
+
+void ItemViewButtons::Private::itemViewUpdateAt(const QModelIndex &index)
+{
+ const QModelIndex displayIndex = this->modelIndexForButtonDisplay(index);
+ if (index.isValid())
+ m_view->update(index);
+ if (displayIndex != index && displayIndex.isValid())
+ m_view->update(displayIndex);
+}
+
+void ItemViewButtons::Private::paintButton(
+ ButtonInfo *btnInfo,
+ QPainter *painter,
+ const QStyleOptionViewItem &option)
+{
+ if (btnInfo == nullptr || painter == nullptr)
+ return;
+
+ const bool isValidBtnIconSize = btnInfo->iconSize.isValid();
+ const int pixWidth =
+ isValidBtnIconSize ?
+ btnInfo->iconSize.width() :
+ option.rect.height();
+ const int pixHeight =
+ isValidBtnIconSize ?
+ btnInfo->iconSize.height() :
+ option.rect.height();
+
+ QRect pixRect;
+ const int yPixPos =
+ option.rect.top() + (option.rect.height() - pixHeight) / 2;
+ if (btnInfo->itemSide == ItemViewButtons::ItemLeftSide)
+ pixRect = QRect(option.rect.left() + 2, yPixPos, pixWidth, pixHeight);
+ else
+ pixRect = QRect(option.rect.right() - pixWidth - 2, yPixPos, pixWidth, pixHeight);
+
+ const bool isInsideButtonRegion =
+ pixRect.contains(m_view->viewport()->mapFromGlobal(QCursor::pos()));
+ const QIcon icon = btnInfo->icon;
+ const QPixmap pix =
+ icon.pixmap(
+ pixWidth,
+ pixHeight,
+ isInsideButtonRegion ? QIcon::Active : QIcon::Normal);
+ painter->drawPixmap(pixRect, pix);
+
+ if (isInsideButtonRegion)
+ m_buttonUnderMouse = btnInfo;
+}
+
+void ItemViewButtons::Private::resetButtonUnderMouseState()
+{
+ m_buttonUnderMouse = nullptr;
+}
+
+/*!
+ * \class ItemViewButtons
+ * \brief Provides buttons integrated to items displayed by QAbstractItemView
+ *
+ * qtgui::ItemViewButtons allows to add buttons inside any QAbstractItemView
+ * without subclassing the item-view class.
+ *
+ * It only requires that its paint() method is called whenever any view item has
+ * to be drawn. If you have a custom delegate (eg. a subclass of QStyledItemDelegate)
+ * then just call at some point qtgui::ItemViewButtons::paint() inside
+ * the delegate's paint() method :
+ * \code
+ * void MyCustomDeleagate::paint(QPainter* painter,
+ * const QStyleOptionViewItem& option,
+ * const QModelIndex& index) const
+ * {
+ * QStyledItemDelegate::paint(painter, option, index);
+ * // Specific paint operations ...
+ *
+ * m_itemViewBtns->paint(painter, option, index);
+ * }
+ * \endcode
+ *
+ * If you do not want to modify your delegate class then createProxyItemDelegate()
+ * might be the right option : this will create a new delegate around yours with
+ * the paint() method correctly called.
+ *
+ * If the item-view does not use any delegate then just call installDefaultItemDelegate()
+ *
+ * ItemViewButtons notifies any button click with signal buttonClicked()
+ *
+ * \example qttools/item_view_buttons/main.cpp
+ *
+ * \headerfile item_view_buttons.h
+ * \ingroup qttools_gui
+ */
+
+/*! \fn void ItemViewButtons::buttonClicked(int btnId, const QModelIndex& index)
+ * \brief This signal is emitted when a button previously added with addButton()
+ * is clicked (i.e. pressed down then released while the mouse cursor is
+ * inside the button)
+ *
+ * \param btnId Identifier of the button clicked (this is the id that was
+ * passed to addButton())
+ * \param index Index of the item model where the button click occured
+ */
+
+ItemViewButtons::ItemViewButtons(QAbstractItemView* view, QObject *parent)
+ : QObject(parent),
+ d(new Private(this))
+{
+ d->m_view = view;
+ if (view != nullptr) {
+ view->viewport()->setMouseTracking(true);
+ view->viewport()->installEventFilter(this);
+ }
+}
+
+ItemViewButtons::~ItemViewButtons()
+{
+ delete d;
+}
+
+QAbstractItemView* ItemViewButtons::itemView() const
+{
+ return d->m_view;
+}
+
+void ItemViewButtons::reset()
+{
+ d->resetButtonUnderMouseState();
+}
+
+bool ItemViewButtons::eventFilter(QObject *object, QEvent *event)
+{
+ if (object == this->itemView()->viewport()) {
+ // If mouse event, retrieve item's model index under mouse
+ const QMouseEvent* mouseEvent = nullptr;
+ if (event->type() == QEvent::MouseMove
+ || event->type() == QEvent::MouseButtonRelease)
+ {
+ mouseEvent = static_cast(event);
+ }
+ const QModelIndex modelIndexUnderMouse =
+ mouseEvent != nullptr ?
+ this->itemView()->indexAt(mouseEvent->pos()) :
+ QModelIndex();
+
+ // Process input event
+ switch (event->type()) {
+ case QEvent::Leave:
+ case QEvent::MouseMove: {
+ d->resetButtonUnderMouseState();
+ d->itemViewUpdateAt(modelIndexUnderMouse);
+ return true;
+ }
+ case QEvent::MouseButtonRelease: {
+ if (mouseEvent != nullptr
+ && mouseEvent->button() == Qt::LeftButton
+ && d->m_buttonUnderMouse != nullptr)
+ {
+ emit buttonClicked(
+ d->m_buttonUnderMouse->index, modelIndexUnderMouse);
+ return true;
+ }
+ return false;
+ }
+ case QEvent::ToolTip: {
+ const QString toolTip =
+ d->m_buttonUnderMouse != nullptr ?
+ d->m_buttonUnderMouse->toolTip :
+ QString();
+ if (!toolTip.isEmpty()) {
+ QToolTip::showText(QCursor::pos(), toolTip, this->itemView());
+ return true;
+ }
+
+ return false;
+ }
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+void ItemViewButtons::paint(
+ QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ bool mouseIsOver = false;
+ if (painter != nullptr
+ && painter->device() != nullptr
+ && painter->device()->devType() == QInternal::Widget)
+ {
+ QWidget* w = static_cast(painter->device());
+ if (w != nullptr) {
+ QPoint mousePos = QCursor::pos();
+ QPoint wMousePos = w->mapFromGlobal(mousePos);
+ mouseIsOver = option.rect.contains(wMousePos);
+ }
+ }
+
+ // QStyledItemDelegate::paint(painter, option, index);
+
+ if (this->itemView()->isEnabled()) {
+ QStyleOptionViewItem optionForBtn(option);
+ optionForBtn.rect =
+ this->itemView()->visualRect(d->modelIndexForButtonDisplay(index));
+ const int btnIndex = this->buttonAtModelIndex(index);
+ Private::ButtonInfo* btnInfo = d->mutableButtonInfo(btnIndex);
+ if (btnInfo == nullptr)
+ return;
+
+ // Check if button can be displayed
+ if (btnInfo->itemDisplayModes.testFlag(DisplayWhenItemSelected)
+ && !option.state.testFlag(QStyle::State_Selected))
+ {
+ // painter->fillRect(optionForBtn.rect, optionForBtn.backgroundBrush);
+ return;
+ }
+
+ if (btnInfo->itemDisplayModes.testFlag(DisplayPermanent)) {
+ d->paintButton(btnInfo, painter, optionForBtn);
+ }
+ else if (btnInfo->itemDisplayModes.testFlag(DisplayOnDetection)) {
+ if (mouseIsOver)
+ d->paintButton(btnInfo, painter, optionForBtn);
+ else
+ painter->fillRect(optionForBtn.rect, optionForBtn.backgroundBrush);
+ }
+ }
+ else {
+ d->resetButtonUnderMouseState();
+ // d->setAllIsOverButtonState(false);
+ }
+}
+
+/*!
+ * \brief Add a button to be furthered configured with setButtonXxx() functions
+ * \param btnId Index of the button (used later to reference the button)
+ * \param icon Icon of the button (ItemViewButtons supports QIcon::Active which
+ * can be used to display an highlighted pixmap when the mouse is
+ * hovering the button)
+ * \param toolTip Tool-tip to be displayed when the mouse stays over the button
+ *
+ * Does nothing if button index \p btnId is already used by some other button.
+ */
+void ItemViewButtons::addButton(
+ int btnId, const QIcon &icon, const QString &toolTip)
+{
+ if (!d->m_btnInfos.contains(btnId)) {
+ Private::ButtonInfo info;
+ info.index = btnId;
+ info.icon = icon;
+ info.toolTip = toolTip;
+ info.matchRole = Qt::UserRole + 1;
+ info.displayColumn = -1;
+ info.itemSide = ItemRightSide;
+ info.itemDisplayModes = DisplayOnDetection;
+ d->m_btnInfos.insert(btnId, info);
+ }
+ else {
+ qWarning() << QString("%1 : there is already a button of index '%2'")
+ .arg(Q_FUNC_INFO).arg(btnId);
+ }
+}
+
+/*!
+ * \brief Copy all properties of a button into another
+ * \param srcBtnId Index of the source button
+ * \param dstBtnId Index of the destination button
+ */
+void ItemViewButtons::copyButtonProperties(int srcBtnId, int dstBtnId)
+{
+ if (srcBtnId == dstBtnId)
+ return;
+
+ const Private::ButtonInfo* srcBtnInfo = d->buttonInfo(srcBtnId);
+ Private::ButtonInfo* dstBtnInfo = d->mutableButtonInfo(dstBtnId);
+
+ if (srcBtnInfo != nullptr) {
+ if (dstBtnInfo != nullptr) {
+ *dstBtnInfo = *srcBtnInfo;
+ dstBtnInfo->index = dstBtnId; // Restore destination button index
+ }
+ else {
+ qWarning() << QString("%1 : no destination button of index '%1'")
+ .arg(Q_FUNC_INFO).arg(dstBtnId);
+ }
+ }
+ else {
+ qWarning() << QString("%1 : no source button of index '%1'")
+ .arg(Q_FUNC_INFO).arg(srcBtnId);
+ }
+}
+
+/*!
+ * \brief The role used when matching item data for button detection
+ *
+ * \param btnId Index of the button
+ * \returns -1 If button does not exist or if no matching role was set
+ *
+ * \sa buttonDetectionMatchData()
+ * \sa QModelIndex::data()
+ * \sa Qt::ItemDataRole
+ */
+int ItemViewButtons::buttonDetectionMatchRole(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->matchRole : -1;
+}
+
+/*!
+ * \brief The data to be matched for button detection
+ *
+ * \param btnId Index of the button
+ * \returns QVariant() If button does not exist
+ *
+ * \sa buttonDetectionMatchRole()
+ */
+QVariant ItemViewButtons::buttonDetectionMatchData(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->matchData : QVariant();
+}
+
+/*!
+ * \brief ItemViewButtons::setButtonDetection
+ *
+ * \param btnId Index of the button
+ * \param matchRole The role used when matching item data for button detection.
+ * In case the button has to be displayed no matter the item, then set
+ * \p matchRole to -1
+ * \param matchData The data to be matched for button detection
+ *
+ * \sa buttonDetectionMatchData()
+ * \sa buttonDetectionMatchRole()
+ * \sa QModelIndex::data()
+ * \sa Qt::ItemDataRole
+ */
+void ItemViewButtons::setButtonDetection(
+ int btnId, int matchRole, const QVariant &matchData)
+{
+ Private::ButtonInfo* btnInfo = d->mutableButtonInfo(btnId);
+ if (btnInfo != nullptr) {
+ btnInfo->matchRole = matchRole;
+ btnInfo->matchData = matchData;
+ }
+}
+
+/*!
+ * \brief Index of the view column where the button is displayed (when detected)
+ * \param btnId Index of the button
+ * \returns -1 If button does not exist
+ */
+int ItemViewButtons::buttonDisplayColumn(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->displayColumn : -1;
+}
+
+void ItemViewButtons::setButtonDisplayColumn(int btnId, int col)
+{
+ cpp::checkedAssign(
+ &Private::ButtonInfo::displayColumn,
+ d->mutableButtonInfo(btnId),
+ col);
+}
+
+/*!
+ * \brief Side in the item's cell where the button is displayed
+ * \param btnId Index of the button
+ * \returns -1 If button does not exist
+ */
+int ItemViewButtons::buttonItemSide(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->itemSide : -1;
+}
+
+void ItemViewButtons::setButtonItemSide(int btnId, ItemSide side)
+{
+ cpp::checkedAssign(
+ &Private::ButtonInfo::itemSide,
+ d->mutableButtonInfo(btnId),
+ side);
+}
+
+/*!
+ * \brief Display modes of the button
+ * \param btnId Index of the button
+ * \returns DisplayModes() If button does not exist
+ */
+ItemViewButtons::DisplayModes ItemViewButtons::buttonDisplayModes(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->itemDisplayModes : DisplayModes();
+}
+
+void ItemViewButtons::setButtonDisplayModes(int btnId, DisplayModes modes)
+{
+ cpp::checkedAssign(
+ &Private::ButtonInfo::itemDisplayModes,
+ d->mutableButtonInfo(btnId),
+ modes);
+}
+
+/*!
+ * \brief Icon of the button
+ * \param btnId Index of the button
+ * \returns QIcon() If button does not exist
+ */
+QIcon ItemViewButtons::buttonIcon(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->icon : QIcon();
+}
+
+void ItemViewButtons::setButtonIcon(int btnId, const QIcon &icon)
+{
+ cpp::checkedAssign(
+ &Private::ButtonInfo::icon,
+ d->mutableButtonInfo(btnId),
+ icon);
+}
+
+/*!
+ * \brief Icon size of the button
+ * \param btnId Index of the button
+ * \returns QSize() If button does not exist
+ */
+QSize ItemViewButtons::buttonIconSize(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->iconSize : QSize();
+}
+
+void ItemViewButtons::setButtonIconSize(int btnId, const QSize &size)
+{
+ cpp::checkedAssign(
+ &Private::ButtonInfo::iconSize,
+ d->mutableButtonInfo(btnId),
+ size);
+}
+
+/*!
+ * \brief Tool-tip of the button
+ * \param btnId Index of the button
+ * \returns QString() If button does not exist
+ */
+QString ItemViewButtons::buttonToolTip(int btnId) const
+{
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(btnId);
+ return btnInfo != nullptr ? btnInfo->toolTip : QString();
+}
+
+void ItemViewButtons::setButtonToolTip(int btnId, const QString &toolTip)
+{
+ cpp::checkedAssign(
+ &Private::ButtonInfo::toolTip,
+ d->mutableButtonInfo(btnId),
+ toolTip);
+}
+
+/*! Install a delegate for the attached view item, allowing the button mechanism
+ * to work
+ */
+void ItemViewButtons::installDefaultItemDelegate()
+{
+ if (d->m_view != nullptr)
+ d->m_view->setItemDelegate(this->createProxyItemDelegate(nullptr));
+}
+
+/*!
+ * Create a proxy delegate around \p sourceDelegate to be further installed with
+ * QAbstractItemView::setItemDelegate()
+ *
+ * This is useful when you have a delegate for an item view but for some reason
+ * don't want to modify it to integrate with ItemViewButtons
+ */
+QStyledItemDelegate* ItemViewButtons::createProxyItemDelegate(
+ QStyledItemDelegate *sourceDelegate, QObject *parent) const
+{
+ return new Private::ProxyItemDelegate(this, sourceDelegate, parent);
+}
+
+int ItemViewButtons::buttonAtModelIndex(const QModelIndex &index) const
+{
+ foreach (int id, d->m_btnInfos.keys()) {
+ const Private::ButtonInfo* btnInfo = d->buttonInfo(id);
+ if (btnInfo->matchRole < 0)
+ return id;
+ const QVariant modelItemData = index.data(btnInfo->matchRole);
+ if ((!btnInfo->matchData.isNull() && btnInfo->matchData.isValid())
+ && (!modelItemData.isNull() && modelItemData.isValid())
+ && (btnInfo->matchData == modelItemData))
+ {
+ return id;
+ }
+ }
+ return -1;
+}
+
+} // namespace qtgui
diff --git a/src/3rdparty/fougtools/qttools/gui/item_view_buttons.h b/src/3rdparty/fougtools/qttools/gui/item_view_buttons.h
new file mode 100644
index 00000000..3290168f
--- /dev/null
+++ b/src/3rdparty/fougtools/qttools/gui/item_view_buttons.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+** FougTools
+** Copyright Fougue (30 Mar. 2015)
+** contact@fougue.pro
+**
+** This software is a computer program whose purpose is to provide utility
+** tools for the C++ language and the Qt toolkit.
+**
+** This software is governed by the CeCILL-C license under French law and
+** abiding by the rules of distribution of free software. You can use,
+** modify and/ or redistribute the software under the terms of the CeCILL-C
+** license as circulated by CEA, CNRS and INRIA at the following URL
+** "http://www.cecill.info".
+****************************************************************************/
+
+#pragma once
+
+class QAbstractItemView;
+class QIcon;
+class QPainter;
+class QStyledItemDelegate;
+class QStyleOptionViewItem;
+
+#include "gui.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace qtgui {
+
+class QTTOOLS_GUI_EXPORT ItemViewButtons : public QObject
+{
+ Q_OBJECT
+
+public:
+ // Types
+ enum ItemSide
+ {
+ ItemLeftSide,
+ ItemRightSide
+ };
+
+ enum DisplayMode
+ {
+ DisplayOnDetection = 0x01,
+ DisplayPermanent = 0x02,
+ DisplayWhenItemSelected = 0x04
+ };
+ typedef QFlags DisplayModes;
+
+ // Ctor & dtor
+ ItemViewButtons(QAbstractItemView* view, QObject* parent = NULL);
+ ~ItemViewButtons();
+
+ // View control
+ QAbstractItemView* itemView() const;
+
+ bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE;
+ void paint(
+ QPainter* painter,
+ const QStyleOptionViewItem& option,
+ const QModelIndex& index) const;
+
+ // Button management
+ void addButton(
+ int btnId,
+ const QIcon& icon = QIcon(),
+ const QString& toolTip = QString());
+ void copyButtonProperties(int srcBtnId, int dstBtnId);
+
+ int buttonDetectionMatchRole(int btnId) const;
+ QVariant buttonDetectionMatchData(int btnId) const;
+ void setButtonDetection(int btnId, int matchRole, const QVariant& matchData);
+
+ int buttonDisplayColumn(int btnId) const;
+ void setButtonDisplayColumn(int btnId, int col = -1);
+
+ int buttonItemSide(int btnId) const;
+ void setButtonItemSide(int btnId, ItemSide side);
+
+ DisplayModes buttonDisplayModes(int btnId) const;
+ void setButtonDisplayModes(int btnId, DisplayModes modes);
+
+ QIcon buttonIcon(int btnId) const;
+ void setButtonIcon(int btnId, const QIcon& icon);
+
+ QSize buttonIconSize(int btnId) const;
+ void setButtonIconSize(int btnId, const QSize& size);
+
+ QString buttonToolTip(int btnId) const;
+ void setButtonToolTip(int btnId, const QString& toolTip);
+
+ // Delegates
+ void installDefaultItemDelegate();
+ QStyledItemDelegate* createProxyItemDelegate(
+ QStyledItemDelegate *sourceDelegate,
+ QObject* parent = NULL) const;
+
+signals:
+ void buttonClicked(int btnId, const QModelIndex& index);
+
+public slots:
+ void reset();
+
+protected:
+ virtual int buttonAtModelIndex(const QModelIndex& index) const;
+
+private:
+ class Private;
+ friend class Private;
+ Private* const d;
+};
+
+} // namespace qtgui
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(qtgui::ItemViewButtons::DisplayModes)
diff --git a/src/fougtools/qttools/gui/item_view_utils.cpp b/src/3rdparty/fougtools/qttools/gui/item_view_utils.cpp
similarity index 96%
rename from src/fougtools/qttools/gui/item_view_utils.cpp
rename to src/3rdparty/fougtools/qttools/gui/item_view_utils.cpp
index 2cbcd7f2..f4483129 100644
--- a/src/fougtools/qttools/gui/item_view_utils.cpp
+++ b/src/3rdparty/fougtools/qttools/gui/item_view_utils.cpp
@@ -38,7 +38,7 @@ namespace qtgui {
QVector ItemViewUtils::selectedRows(const QAbstractItemView* view, int col)
{
const QItemSelectionModel* itemSelModel = view->selectionModel();
- if (itemSelModel == NULL || !itemSelModel->hasSelection())
+ if (itemSelModel == nullptr || !itemSelModel->hasSelection())
return QVector();
const QModelIndexList selIndexes = itemSelModel->selectedIndexes();
QVector result;
@@ -57,7 +57,7 @@ void ItemViewUtils::selectRows(QAbstractItemView* view, const QVector& rows
{
const QAbstractItemModel* model = view->model();
QItemSelectionModel* selModel = view->selectionModel();
- if (model == NULL || selModel == NULL)
+ if (model == nullptr || selModel == nullptr)
return;
const QItemSelectionModel::SelectionFlags selFlags =
QItemSelectionModel::ToggleCurrent | QItemSelectionModel::Rows;
diff --git a/src/fougtools/qttools/gui/item_view_utils.h b/src/3rdparty/fougtools/qttools/gui/item_view_utils.h
similarity index 96%
rename from src/fougtools/qttools/gui/item_view_utils.h
rename to src/3rdparty/fougtools/qttools/gui/item_view_utils.h
index 3f1c86f1..b4af80fd 100644
--- a/src/fougtools/qttools/gui/item_view_utils.h
+++ b/src/3rdparty/fougtools/qttools/gui/item_view_utils.h
@@ -22,8 +22,7 @@ class QSortFilterProxyModel;
namespace qtgui {
-class QTTOOLS_GUI_EXPORT ItemViewUtils
-{
+class QTTOOLS_GUI_EXPORT ItemViewUtils {
public:
static QVector selectedRows(const QAbstractItemView* view, int col = -1);
static void selectRows(QAbstractItemView* view, const QVector& rows);
diff --git a/src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.cpp b/src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.cpp
new file mode 100644
index 00000000..8acfbe13
--- /dev/null
+++ b/src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+** FougTools
+** Copyright Fougue (30 Mar. 2015)
+** contact@fougue.pro
+**
+** This software is a computer program whose purpose is to provide utility
+** tools for the C++ language and the Qt toolkit.
+**
+** This software is governed by the CeCILL-C license under French law and
+** abiding by the rules of distribution of free software. You can use,
+** modify and/ or redistribute the software under the terms of the CeCILL-C
+** license as circulated by CEA, CNRS and INRIA at the following URL
+** "http://www.cecill.info".
+****************************************************************************/
+
+#include "proxy_styled_item_delegate.h"
+
+namespace qtgui {
+
+/*!
+ * \class ProxyStyledItemDelegate
+ * \brief Convenience class that simplifies dynamically overriding QStyledItemDelegate
+ *
+ * QStyledItemDelegate protected functions cannot be overriden through proxy
+ * technique, this is a limitation that applies to :
+ * \li QStyledItemDelegate::initStyleOption()
+ * \li QStyledItemDelegate::eventFilter()
+ * \li QStyledItemDelegate::editorEvent()
+ *
+ * \headerfile proxy_styled_item_delegate.h
+ * \ingroup qttools_gui
+ *
+ */
+
+ProxyStyledItemDelegate::ProxyStyledItemDelegate(QObject *parent)
+ : QStyledItemDelegate(parent),
+ m_sourceDelegate(NULL)
+{
+
+}
+
+ProxyStyledItemDelegate::ProxyStyledItemDelegate(
+ QStyledItemDelegate *srcDelegate,
+ QObject* parent)
+ : QStyledItemDelegate(parent),
+ m_sourceDelegate(srcDelegate)
+{
+}
+
+QStyledItemDelegate *ProxyStyledItemDelegate::sourceDelegate() const
+{
+ return m_sourceDelegate;
+}
+
+void ProxyStyledItemDelegate::setSourceDelegate(QStyledItemDelegate *srcDelegate)
+{
+ m_sourceDelegate = srcDelegate;
+}
+
+void ProxyStyledItemDelegate::paint(
+ QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (m_sourceDelegate != NULL)
+ m_sourceDelegate->paint(painter, option, index);
+ else
+ QStyledItemDelegate::paint(painter, option, index);
+}
+
+QSize ProxyStyledItemDelegate::sizeHint(
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (m_sourceDelegate != NULL)
+ return m_sourceDelegate->sizeHint(option, index);
+ return QStyledItemDelegate::sizeHint(option, index);
+}
+
+QString ProxyStyledItemDelegate::displayText(
+ const QVariant &value, const QLocale &locale) const
+{
+ if (m_sourceDelegate != NULL)
+ return m_sourceDelegate->displayText(value, locale);
+ return QStyledItemDelegate::displayText(value, locale);
+}
+
+QWidget *ProxyStyledItemDelegate::createEditor(
+ QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (m_sourceDelegate != NULL)
+ return m_sourceDelegate->createEditor(parent, option, index);
+ return QStyledItemDelegate::createEditor(parent, option, index);
+}
+
+void ProxyStyledItemDelegate::setEditorData(
+ QWidget *editor, const QModelIndex &index) const
+{
+ if (m_sourceDelegate != NULL)
+ m_sourceDelegate->setEditorData(editor, index);
+ else
+ QStyledItemDelegate::setEditorData(editor, index);
+}
+
+void ProxyStyledItemDelegate::setModelData(
+ QWidget *editor,
+ QAbstractItemModel *model,
+ const QModelIndex &index) const
+{
+ if (m_sourceDelegate != NULL)
+ m_sourceDelegate->setModelData(editor, model, index);
+ else
+ QStyledItemDelegate::setModelData(editor, model, index);
+}
+
+void ProxyStyledItemDelegate::updateEditorGeometry(
+ QWidget *editor,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (m_sourceDelegate != NULL)
+ m_sourceDelegate->updateEditorGeometry(editor, option, index);
+ else
+ QStyledItemDelegate::updateEditorGeometry(editor, option, index);
+}
+
+} // namespace qtgui
diff --git a/src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.h b/src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.h
new file mode 100644
index 00000000..0f998eae
--- /dev/null
+++ b/src/3rdparty/fougtools/qttools/gui/proxy_styled_item_delegate.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+** FougTools
+** Copyright Fougue (30 Mar. 2015)
+** contact@fougue.pro
+**
+** This software is a computer program whose purpose is to provide utility
+** tools for the C++ language and the Qt toolkit.
+**
+** This software is governed by the CeCILL-C license under French law and
+** abiding by the rules of distribution of free software. You can use,
+** modify and/ or redistribute the software under the terms of the CeCILL-C
+** license as circulated by CEA, CNRS and INRIA at the following URL
+** "http://www.cecill.info".
+****************************************************************************/
+
+#pragma once
+
+#include "gui.h"
+
+// QtWidgets
+#include
+
+namespace qtgui {
+
+class QTTOOLS_GUI_EXPORT ProxyStyledItemDelegate : public QStyledItemDelegate
+{
+public:
+ ProxyStyledItemDelegate(QObject* parent = NULL);
+ ProxyStyledItemDelegate(QStyledItemDelegate* srcDelegate, QObject* parent = NULL);
+
+ QStyledItemDelegate* sourceDelegate() const;
+ void setSourceDelegate(QStyledItemDelegate* srcDelegate);
+
+ void paint(
+ QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const Q_DECL_OVERRIDE;
+ QSize sizeHint(
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const Q_DECL_OVERRIDE;
+ QString displayText(
+ const QVariant &value,
+ const QLocale &locale) const Q_DECL_OVERRIDE;
+
+ QWidget *createEditor(
+ QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const Q_DECL_OVERRIDE;
+ void setEditorData(
+ QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
+ void setModelData(
+ QWidget *editor,
+ QAbstractItemModel *model,
+ const QModelIndex &index) const Q_DECL_OVERRIDE;
+ void updateEditorGeometry(
+ QWidget *editor,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+private:
+ QStyledItemDelegate* m_sourceDelegate;
+};
+
+} // namespace qtgui
diff --git a/src/fougtools/qttools/gui/qwidget_utils.cpp b/src/3rdparty/fougtools/qttools/gui/qwidget_utils.cpp
similarity index 72%
rename from src/fougtools/qttools/gui/qwidget_utils.cpp
rename to src/3rdparty/fougtools/qttools/gui/qwidget_utils.cpp
index 06bf74dd..e4474279 100644
--- a/src/fougtools/qttools/gui/qwidget_utils.cpp
+++ b/src/3rdparty/fougtools/qttools/gui/qwidget_utils.cpp
@@ -33,19 +33,17 @@ namespace qtgui {
* \ingroup qttools_gui
*/
-/*! \brief Make \p widget the central widget of \p dialog
- *
- * \p dialog should be empty for this function to work.\n
- * wrapWidgetInDialog() will try to find if \p widget contains a
- * QDialogButtonBox, if so
- * then it connects to \p dialog 's accept()/reject() slots.
- */
+//! Make 'widget' the central widget of 'dialog'
+//!
+//! 'dialog' should be empty for this function to work.\n
+//! wrapWidgetInDialog() will try to find if 'widget' contains a
+//! QDialogButtonBox, if so then it connects to dialog's accept()/reject() slots.
void QWidgetUtils::wrapWidgetInDialog(QWidget *widget, QDialog *dialog)
{
- if (widget != NULL && dialog != NULL) {
+ if (widget != nullptr && dialog != nullptr) {
dialog->setWindowTitle(widget->windowTitle());
widget->setParent(dialog);
- if (dialog->layout() != NULL) {
+ if (dialog->layout() != nullptr) {
dialog->layout()->addWidget(widget);
}
else {
@@ -55,7 +53,7 @@ void QWidgetUtils::wrapWidgetInDialog(QWidget *widget, QDialog *dialog)
}
auto btnBox = widget->findChild();
- if (btnBox != NULL) {
+ if (btnBox != nullptr) {
QObject::connect(
btnBox, &QDialogButtonBox::accepted,
dialog, &QDialog::accept);
@@ -66,16 +64,15 @@ void QWidgetUtils::wrapWidgetInDialog(QWidget *widget, QDialog *dialog)
}
}
-/*! Add \p contentsWidget to \p containerWidget
- *
- * If \p containerWidget is empty, a QBoxLayout is created to receive
- * \p contentsWidget
- */
+//! Add 'contentsWidget' to 'containerWidget'
+//!
+//! If 'containerWidget' is empty, a QBoxLayout is created to receive
+//! 'contentsWidget'
void QWidgetUtils::addContentsWidget(
QWidget *containerWidget, QWidget *contentsWidget)
{
- if (containerWidget != NULL && contentsWidget != NULL) {
- if (containerWidget->layout() == NULL) {
+ if (containerWidget != nullptr && contentsWidget != nullptr) {
+ if (containerWidget->layout() == nullptr) {
containerWidget->setLayout(new QVBoxLayout);
containerWidget->layout()->setContentsMargins(0, 0, 0, 0);
}
@@ -84,13 +81,12 @@ void QWidgetUtils::addContentsWidget(
}
}
-/*! Returns the global position of a widget corner
- *
- * \returns Null point (ie. with coordinates (0, 0)) if \p widget is null
- */
+//! Returns the global position of a widget corner
+//!
+//! \returns nullptr point (ie. with coordinates (0, 0)) if 'widget' is nullptr
QPoint QWidgetUtils::globalPos(const QWidget *widget, Qt::Corner widgetCorner)
{
- if (widget != NULL) {
+ if (widget != nullptr) {
const QRect geom = widget->frameGeometry();
switch (widgetCorner) {
case Qt::TopLeftCorner:
@@ -106,34 +102,31 @@ QPoint QWidgetUtils::globalPos(const QWidget *widget, Qt::Corner widgetCorner)
return QPoint(0, 0);
}
-/*! Move position of \p widget so it's displayed stuck to the right of \p nextTo
- */
-void QWidgetUtils::moveWidgetRightTo(QWidget* widget, const QWidget* nextTo)
+//! Move position of 'widget' so it's displayed stuck to the right of 'nextTo'
+void QWidgetUtils::moveWidgetRightTo(
+ QWidget* widget, const QWidget* nextTo, int margin)
{
const QRect frameGeom = nextTo->frameGeometry();
- widget->move(nextTo->mapToGlobal(QPoint(frameGeom.width(), 0)));
+ widget->move(nextTo->mapToGlobal(QPoint(frameGeom.width() + margin, 0)));
}
-/*! Move position of \p widget so it's displayed stuck to the left of \p nextTo
- */
-void QWidgetUtils::moveWidgetLeftTo(QWidget* widget, const QWidget* nextTo)
+//! Move position of 'widget' so it's displayed stuck to the left of 'nextTo'
+void QWidgetUtils::moveWidgetLeftTo(
+ QWidget* widget, const QWidget* nextTo, int margin)
{
- //const QRect nextToFrameGeom = nextTo->frameGeometry();
- const QRect widgetFrameGeom = widget->frameGeometry();
- widget->move(nextTo->mapToGlobal(QPoint(-widgetFrameGeom.width(), 0)));
+ const QRect frameGeom = widget->frameGeometry();
+ widget->move(nextTo->mapToGlobal(QPoint(-frameGeom.width() - margin, 0)));
}
-/*! Current slide positions of the horizontal and vertical scroll bars
- */
+//! Current slide positions of the horizontal and vertical scroll bars
QPair QWidgetUtils::horizAndVertScrollValue(const QAbstractScrollArea* area)
{
return qMakePair(area->horizontalScrollBar()->value(),
area->verticalScrollBar()->value());
}
-/*! Set the current slide positions of the horizontal and vertical scroll bars
- * to \p values
- */
+//! Set the current slide positions of the horizontal and vertical scroll bars
+//! to 'values'
void QWidgetUtils::setHorizAndVertScrollValue(
QAbstractScrollArea* area, const QPair& values)
{
@@ -141,11 +134,10 @@ void QWidgetUtils::setHorizAndVertScrollValue(
area->verticalScrollBar()->setValue(values.second);
}
-/*! Executes \p dialog asynchronously */
+//! Executes 'dialog' asynchronously
void QWidgetUtils::asyncDialogExec(QDialog *dialog)
{
- if (dialog != NULL) {
- dialog->setModal(true);
+ if (dialog) {
QObject::connect(
dialog, &QDialog::finished,
dialog, &QObject::deleteLater,
@@ -154,16 +146,16 @@ void QWidgetUtils::asyncDialogExec(QDialog *dialog)
}
}
-/*! Executes \p menu asynchronously */
+//! Executes 'menu' asynchronously
void QWidgetUtils::asyncMenuExec(QMenu *menu, const QPoint &pos)
{
- if (menu != NULL) {
+ if (menu != nullptr) {
QObject::connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
menu->popup(pos);
}
}
-/*! Executes message box information asynchronously */
+//! Executes message box information asynchronously
QMessageBox* QWidgetUtils::asyncMsgBoxInfo(
QWidget* parent,
const QString& title,
@@ -176,7 +168,7 @@ QMessageBox* QWidgetUtils::asyncMsgBoxInfo(
return msgBox;
}
-/*! Executes message box warning asynchronously */
+//! Executes message box warning asynchronously
QMessageBox* QWidgetUtils::asyncMsgBoxWarning(
QWidget *parent,
const QString &title,
@@ -189,7 +181,7 @@ QMessageBox* QWidgetUtils::asyncMsgBoxWarning(
return msgBox;
}
-/*! Executes message box critical asynchronously */
+//! Executes message box critical asynchronously
QMessageBox* QWidgetUtils::asyncMsgBoxCritical(
QWidget* parent,
const QString& title,
diff --git a/src/fougtools/qttools/gui/qwidget_utils.h b/src/3rdparty/fougtools/qttools/gui/qwidget_utils.h
similarity index 88%
rename from src/fougtools/qttools/gui/qwidget_utils.h
rename to src/3rdparty/fougtools/qttools/gui/qwidget_utils.h
index 1b54ce93..d23d859a 100644
--- a/src/fougtools/qttools/gui/qwidget_utils.h
+++ b/src/3rdparty/fougtools/qttools/gui/qwidget_utils.h
@@ -27,8 +27,7 @@ class QWidget;
namespace qtgui {
-class QTTOOLS_GUI_EXPORT QWidgetUtils
-{
+class QTTOOLS_GUI_EXPORT QWidgetUtils {
public:
template
static PARENT_WIDGET* findFirstParentWidget(QWidget* widget);
@@ -41,8 +40,8 @@ class QTTOOLS_GUI_EXPORT QWidgetUtils
QWidget* containerWidget, QWidget* contentsWidget);
static QPoint globalPos(const QWidget* widget, Qt::Corner widgetCorner);
- static void moveWidgetRightTo(QWidget* widget, const QWidget* nextTo);
- static void moveWidgetLeftTo(QWidget* widget, const QWidget* nextTo);
+ static void moveWidgetRightTo(QWidget* widget, const QWidget* nextTo, int margin = 0);
+ static void moveWidgetLeftTo(QWidget* widget, const QWidget* nextTo, int margin = 0);
static QPair horizAndVertScrollValue(const QAbstractScrollArea* area);
static void setHorizAndVertScrollValue(
@@ -78,29 +77,31 @@ class QTTOOLS_GUI_EXPORT QWidgetUtils
namespace qtgui {
-//! Searches up in the direct parents of \p widget the first ancestor being of type \c PARENT_WIDGET
+//! Searches up in the direct parents of \p widget the first ancestor being of
+//! type \c PARENT_WIDGET
template
PARENT_WIDGET* QWidgetUtils::findFirstParentWidget(QWidget* widget)
{
- PARENT_WIDGET* foundParentWidget = NULL;
+ PARENT_WIDGET* foundParentWidget = nullptr;
QWidget* iteratorWidget = widget;
- while (iteratorWidget != NULL && foundParentWidget == NULL) {
+ while (iteratorWidget != nullptr && foundParentWidget == nullptr) {
iteratorWidget = iteratorWidget->parentWidget();
foundParentWidget = qobject_cast(iteratorWidget);
}
return foundParentWidget;
}
-//! Searches up in the direct parents of \p widget the last ancestor being of type \c PARENT_WIDGET
+//! Searches up in the direct parents of \p widget the last ancestor being of
+//! type \c PARENT_WIDGET
template
PARENT_WIDGET* QWidgetUtils::findLastParentWidget(QWidget* widget)
{
- PARENT_WIDGET* foundParentWidget = NULL;
+ PARENT_WIDGET* foundParentWidget = nullptr;
QWidget* iteratorWidget = widget;
- while (iteratorWidget != NULL) {
+ while (iteratorWidget != nullptr) {
iteratorWidget = iteratorWidget->parentWidget();
PARENT_WIDGET* currParentWidget = qobject_cast(iteratorWidget);
- if (currParentWidget != NULL)
+ if (currParentWidget != nullptr)
foundParentWidget = currParentWidget;
}
return foundParentWidget;
diff --git a/src/fougtools/qttools/task/base_runner.cpp b/src/3rdparty/fougtools/qttools/task/base_runner.cpp
similarity index 100%
rename from src/fougtools/qttools/task/base_runner.cpp
rename to src/3rdparty/fougtools/qttools/task/base_runner.cpp
diff --git a/src/fougtools/qttools/task/base_runner.h b/src/3rdparty/fougtools/qttools/task/base_runner.h
similarity index 100%
rename from src/fougtools/qttools/task/base_runner.h
rename to src/3rdparty/fougtools/qttools/task/base_runner.h
diff --git a/src/fougtools/qttools/task/base_runner_signals.cpp b/src/3rdparty/fougtools/qttools/task/base_runner_signals.cpp
similarity index 100%
rename from src/fougtools/qttools/task/base_runner_signals.cpp
rename to src/3rdparty/fougtools/qttools/task/base_runner_signals.cpp
diff --git a/src/fougtools/qttools/task/base_runner_signals.h b/src/3rdparty/fougtools/qttools/task/base_runner_signals.h
similarity index 100%
rename from src/fougtools/qttools/task/base_runner_signals.h
rename to src/3rdparty/fougtools/qttools/task/base_runner_signals.h
diff --git a/src/fougtools/qttools/task/manager.cpp b/src/3rdparty/fougtools/qttools/task/manager.cpp
similarity index 100%
rename from src/fougtools/qttools/task/manager.cpp
rename to src/3rdparty/fougtools/qttools/task/manager.cpp
diff --git a/src/fougtools/qttools/task/manager.h b/src/3rdparty/fougtools/qttools/task/manager.h
similarity index 98%
rename from src/fougtools/qttools/task/manager.h
rename to src/3rdparty/fougtools/qttools/task/manager.h
index da501dc2..b5e71ea0 100644
--- a/src/fougtools/qttools/task/manager.h
+++ b/src/3rdparty/fougtools/qttools/task/manager.h
@@ -80,7 +80,7 @@ class Manager : public QObject
BaseRunner* getRunner(quint64 taskId);
const BaseRunner* getRunner(quint64 taskId) const;
- std::atomic m_taskIdSeq = 0;
+ std::atomic m_taskIdSeq = {};
std::unordered_map m_taskIdToRunner;
};
diff --git a/src/fougtools/qttools/task/progress.cpp b/src/3rdparty/fougtools/qttools/task/progress.cpp
similarity index 98%
rename from src/fougtools/qttools/task/progress.cpp
rename to src/3rdparty/fougtools/qttools/task/progress.cpp
index 96532d19..c0d80e11 100644
--- a/src/fougtools/qttools/task/progress.cpp
+++ b/src/3rdparty/fougtools/qttools/task/progress.cpp
@@ -33,7 +33,7 @@ int Progress::value() const
void Progress::setValue(int pct)
{
- m_value = pct;
+ m_value.fetch_add(pct);
m_runner->qtSignals()->emitProgress(pct);
}
diff --git a/src/fougtools/qttools/task/progress.h b/src/3rdparty/fougtools/qttools/task/progress.h
similarity index 96%
rename from src/fougtools/qttools/task/progress.h
rename to src/3rdparty/fougtools/qttools/task/progress.h
index c263a5d3..b3d1161a 100644
--- a/src/fougtools/qttools/task/progress.h
+++ b/src/3rdparty/fougtools/qttools/task/progress.h
@@ -18,6 +18,7 @@
#include
#include
+#include
#include
namespace qttask {
@@ -52,7 +53,7 @@ class Progress
BaseRunner* m_runner = nullptr;
std::unordered_map m_dataHash;
- int m_value = 0;
+ std::atomic m_value = {};
QString m_step;
};
diff --git a/src/fougtools/qttools/task/qttools_task.pri b/src/3rdparty/fougtools/qttools/task/qttools_task.pri
similarity index 100%
rename from src/fougtools/qttools/task/qttools_task.pri
rename to src/3rdparty/fougtools/qttools/task/qttools_task.pri
diff --git a/src/fougtools/qttools/task/runner_current_thread.h b/src/3rdparty/fougtools/qttools/task/runner_current_thread.h
similarity index 100%
rename from src/fougtools/qttools/task/runner_current_thread.h
rename to src/3rdparty/fougtools/qttools/task/runner_current_thread.h
diff --git a/src/fougtools/qttools/task/runner_qthread.h b/src/3rdparty/fougtools/qttools/task/runner_qthread.h
similarity index 100%
rename from src/fougtools/qttools/task/runner_qthread.h
rename to src/3rdparty/fougtools/qttools/task/runner_qthread.h
diff --git a/src/fougtools/qttools/task/runner_qthreadpool.h b/src/3rdparty/fougtools/qttools/task/runner_qthreadpool.h
similarity index 100%
rename from src/fougtools/qttools/task/runner_qthreadpool.h
rename to src/3rdparty/fougtools/qttools/task/runner_qthreadpool.h
diff --git a/src/fougtools/qttools/task/runner_stdasync.h b/src/3rdparty/fougtools/qttools/task/runner_stdasync.h
similarity index 83%
rename from src/fougtools/qttools/task/runner_stdasync.h
rename to src/3rdparty/fougtools/qttools/task/runner_stdasync.h
index 1b888464..52a36043 100644
--- a/src/fougtools/qttools/task/runner_stdasync.h
+++ b/src/3rdparty/fougtools/qttools/task/runner_stdasync.h
@@ -21,19 +21,17 @@
namespace qttask {
-struct StdAsync { };
+struct StdAsync {};
-/*! \brief Task runner based on std::async()
- */
-template<>
-class Runner : public BaseRunner
+//! Task runner based on std::async()
+template<> class Runner : public BaseRunner
{
public:
Runner(const Manager* mgr, std::launch policy = std::launch::async)
: BaseRunner(mgr),
m_isAbortRequested(false),
m_policy(policy)
- { }
+ {}
protected:
bool isAbortRequested() override
@@ -43,11 +41,14 @@ class Runner : public BaseRunner
{ m_isAbortRequested = true; }
void launch() override
- { std::async(m_policy, [=] { this->execRunnableFunc(); } ); }
+ {
+ m_future = std::async(m_policy, [=]{ this->execRunnableFunc(); });
+ }
private:
bool m_isAbortRequested;
std::launch m_policy;
+ std::future m_future;
};
} // namespace qttask
diff --git a/src/3rdparty/gsl/gsl_algorithm b/src/3rdparty/gsl/gsl_algorithm
new file mode 100644
index 00000000..710792fb
--- /dev/null
+++ b/src/3rdparty/gsl/gsl_algorithm
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_ALGORITHM_H
+#define GSL_ALGORITHM_H
+
+#include // for Expects
+#include // for dynamic_extent, span
+
+#include // for copy_n
+#include // for ptrdiff_t
+#include // for is_assignable
+
+#ifdef _MSC_VER
+#pragma warning(push)
+
+// turn off some warnings that are noisy about our Expects statements
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4996) // unsafe use of std::copy_n
+
+// blanket turn off warnings from CppCoreCheck for now
+// so people aren't annoyed by them when running the tool.
+// more targeted suppressions will be added in a future update to the GSL
+#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
+#endif // _MSC_VER
+
+namespace gsl
+{
+
+template
+void copy(span src, span dest)
+{
+ static_assert(std::is_assignable::value,
+ "Elements of source span can not be assigned to elements of destination span");
+ static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
+ (SrcExtent <= DestExtent),
+ "Source range is longer than target range");
+
+ Expects(dest.size() >= src.size());
+ std::copy_n(src.data(), src.size(), dest.data());
+}
+
+} // namespace gsl
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+#endif // GSL_ALGORITHM_H
diff --git a/src/3rdparty/gsl/gsl_assert b/src/3rdparty/gsl/gsl_assert
new file mode 100644
index 00000000..131fa8b1
--- /dev/null
+++ b/src/3rdparty/gsl/gsl_assert
@@ -0,0 +1,145 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_CONTRACTS_H
+#define GSL_CONTRACTS_H
+
+#include
+#include // for logic_error
+
+//
+// Temporary until MSVC STL supports no-exceptions mode.
+// Currently terminate is a no-op in this mode, so we add termination behavior back
+//
+#if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
+#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
+#endif
+
+//
+// There are three configuration options for this GSL implementation's behavior
+// when pre/post conditions on the GSL types are violated:
+//
+// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default)
+// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
+// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens
+//
+#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) || \
+ defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
+#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
+#endif
+
+#define GSL_STRINGIFY_DETAIL(x) #x
+#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
+
+#if defined(__clang__) || defined(__GNUC__)
+#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
+#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define GSL_LIKELY(x) (!!(x))
+#define GSL_UNLIKELY(x) (!!(x))
+#endif
+
+//
+// GSL_ASSUME(cond)
+//
+// Tell the optimizer that the predicate cond must hold. It is unspecified
+// whether or not cond is actually evaluated.
+//
+#ifdef _MSC_VER
+#define GSL_ASSUME(cond) __assume(cond)
+#elif defined(__GNUC__)
+#define GSL_ASSUME(cond) ((cond) ? static_cast(0) : __builtin_unreachable())
+#else
+#define GSL_ASSUME(cond) static_cast((cond) ? 0 : 0)
+#endif
+
+//
+// GSL.assert: assertions
+//
+
+namespace gsl
+{
+struct fail_fast : public std::logic_error
+{
+ explicit fail_fast(char const* const message) : std::logic_error(message) {}
+};
+
+namespace details
+{
+#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+
+ typedef void (__cdecl *terminate_handler)();
+
+ inline gsl::details::terminate_handler& get_terminate_handler() noexcept
+ {
+ static terminate_handler handler = &abort;
+ return handler;
+ }
+
+#endif
+
+ [[noreturn]] inline void terminate() noexcept
+ {
+#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+ (*gsl::details::get_terminate_handler())();
+#else
+ std::terminate();
+#endif
+ }
+
+#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
+
+ template
+ [[noreturn]] void throw_exception(Exception&&)
+ {
+ gsl::details::terminate();
+ }
+
+#else
+
+ template
+ [[noreturn]] void throw_exception(Exception&& exception)
+ {
+ throw std::forward(exception);
+ }
+
+#endif
+
+} // namespace details
+} // namespace gsl
+
+#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
+
+#define GSL_CONTRACT_CHECK(type, cond) \
+ (GSL_LIKELY(cond) ? static_cast(0) \
+ : gsl::details::throw_exception(gsl::fail_fast( \
+ "GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__))))
+
+#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
+
+#define GSL_CONTRACT_CHECK(type, cond) \
+ (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate())
+
+#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
+
+#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)
+
+#endif
+
+#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
+#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
+
+#endif // GSL_CONTRACTS_H
diff --git a/src/3rdparty/gsl/gsl_byte b/src/3rdparty/gsl/gsl_byte
new file mode 100644
index 00000000..e8611733
--- /dev/null
+++ b/src/3rdparty/gsl/gsl_byte
@@ -0,0 +1,181 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_BYTE_H
+#define GSL_BYTE_H
+
+#include
+
+#ifdef _MSC_VER
+
+#pragma warning(push)
+
+// don't warn about function style casts in byte related operators
+#pragma warning(disable : 26493)
+
+#ifndef GSL_USE_STD_BYTE
+// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
+#if defined(_HAS_STD_BYTE) && _HAS_STD_BYTE
+
+#define GSL_USE_STD_BYTE 1
+
+#else // defined(_HAS_STD_BYTE) && _HAS_STD_BYTE
+
+#define GSL_USE_STD_BYTE 0
+
+#endif // defined(_HAS_STD_BYTE) && _HAS_STD_BYTE
+#endif // GSL_USE_STD_BYTE
+
+#else // _MSC_VER
+
+#ifndef GSL_USE_STD_BYTE
+// this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte
+#if defined(__cplusplus) && (__cplusplus >= 201703L)
+
+#define GSL_USE_STD_BYTE 1
+#include
+
+#else // defined(__cplusplus) && (__cplusplus >= 201703L)
+
+#define GSL_USE_STD_BYTE 0
+
+#endif //defined(__cplusplus) && (__cplusplus >= 201703L)
+#endif // GSL_USE_STD_BYTE
+
+#endif // _MSC_VER
+
+// Use __may_alias__ attribute on gcc and clang
+#if defined __clang__ || (__GNUC__ > 5)
+#define byte_may_alias __attribute__((__may_alias__))
+#else // defined __clang__ || defined __GNUC__
+#define byte_may_alias
+#endif // defined __clang__ || defined __GNUC__
+
+namespace gsl
+{
+#if GSL_USE_STD_BYTE
+
+
+using std::byte;
+using std::to_integer;
+
+#else // GSL_USE_STD_BYTE
+
+// This is a simple definition for now that allows
+// use of byte within span<> to be standards-compliant
+enum class byte_may_alias byte : unsigned char
+{
+};
+
+template ::value>>
+constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
+{
+ return b = byte(static_cast(b) << shift);
+}
+
+template ::value>>
+constexpr byte operator<<(byte b, IntegerType shift) noexcept
+{
+ return byte(static_cast(b) << shift);
+}
+
+template ::value>>
+constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
+{
+ return b = byte(static_cast(b) >> shift);
+}
+
+template ::value>>
+constexpr byte operator>>(byte b, IntegerType shift) noexcept
+{
+ return byte(static_cast(b) >> shift);
+}
+
+constexpr byte& operator|=(byte& l, byte r) noexcept
+{
+ return l = byte(static_cast(l) | static_cast(r));
+}
+
+constexpr byte operator|(byte l, byte r) noexcept
+{
+ return byte(static_cast(l) | static_cast(r));
+}
+
+constexpr byte& operator&=(byte& l, byte r) noexcept
+{
+ return l = byte(static_cast(l) & static_cast(r));
+}
+
+constexpr byte operator&(byte l, byte r) noexcept
+{
+ return byte(static_cast(l) & static_cast(r));
+}
+
+constexpr byte& operator^=(byte& l, byte r) noexcept
+{
+ return l = byte(static_cast(l) ^ static_cast(r));
+}
+
+constexpr byte operator^(byte l, byte r) noexcept
+{
+ return byte(static_cast(l) ^ static_cast(r));
+}
+
+constexpr byte operator~(byte b) noexcept { return byte(~static_cast(b)); }
+
+template ::value>>
+constexpr IntegerType to_integer(byte b) noexcept
+{
+ return static_cast(b);
+}
+
+#endif // GSL_USE_STD_BYTE
+
+template
+constexpr byte to_byte_impl(T t) noexcept
+{
+ static_assert(
+ E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
+ "If you are calling to_byte with an integer contant use: gsl::to_byte() version.");
+ return static_cast(t);
+}
+template <>
+constexpr byte to_byte_impl(unsigned char t) noexcept
+{
+ return byte(t);
+}
+
+template
+constexpr byte to_byte(T t) noexcept
+{
+ return to_byte_impl::value, T>(t);
+}
+
+template
+constexpr byte to_byte() noexcept
+{
+ static_assert(I >= 0 && I <= 255,
+ "gsl::byte only has 8 bits of storage, values must be in range 0-255");
+ return static_cast(I);
+}
+
+} // namespace gsl
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+#endif // GSL_BYTE_H
diff --git a/src/3rdparty/gsl/gsl_util b/src/3rdparty/gsl/gsl_util
new file mode 100644
index 00000000..373ee791
--- /dev/null
+++ b/src/3rdparty/gsl/gsl_util
@@ -0,0 +1,158 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_UTIL_H
+#define GSL_UTIL_H
+
+#include "gsl_assert" // for Expects
+
+#include
+#include // for ptrdiff_t, size_t
+#include // for exception
+#include // for initializer_list
+#include // for is_signed, integral_constant
+#include // for forward
+
+#if defined(_MSC_VER)
+
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+
+#if _MSC_VER < 1910
+#pragma push_macro("constexpr")
+#define constexpr /*constexpr*/
+#endif // _MSC_VER < 1910
+#endif // _MSC_VER
+
+namespace gsl
+{
+//
+// GSL.util: utilities
+//
+
+// index type for all container indexes/subscripts/sizes
+using index = std::ptrdiff_t;
+
+// final_action allows you to ensure something gets run at the end of a scope
+template
+class final_action
+{
+public:
+ explicit final_action(F f) noexcept : f_(std::move(f)) {}
+
+ final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_)
+ {
+ other.invoke_ = false;
+ }
+
+ final_action(const final_action&) = delete;
+ final_action& operator=(const final_action&) = delete;
+ final_action& operator=(final_action&&) = delete;
+
+ ~final_action() noexcept
+ {
+ if (invoke_) f_();
+ }
+
+private:
+ F f_;
+ bool invoke_ {true};
+};
+
+// finally() - convenience function to generate a final_action
+template
+
+final_action finally(const F& f) noexcept
+{
+ return final_action(f);
+}
+
+template
+final_action finally(F&& f) noexcept
+{
+ return final_action(std::forward(f));
+}
+
+// narrow_cast(): a searchable way to do narrowing casts of values
+template
+constexpr T narrow_cast(U&& u) noexcept
+{
+ return static_cast(std::forward(u));
+}
+
+struct narrowing_error : public std::exception
+{
+};
+
+namespace details
+{
+ template
+ struct is_same_signedness
+ : public std::integral_constant::value == std::is_signed::value>
+ {
+ };
+}
+
+// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
+template
+T narrow(U u)
+{
+ T t = narrow_cast(u);
+ if (static_cast(t) != u) gsl::details::throw_exception(narrowing_error());
+ if (!details::is_same_signedness::value && ((t < T{}) != (u < U{})))
+ gsl::details::throw_exception(narrowing_error());
+ return t;
+}
+
+//
+// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
+//
+template
+constexpr T& at(T (&arr)[N], const index i)
+{
+ Expects(i >= 0 && i < narrow_cast(N));
+ return arr[static_cast(i)];
+}
+
+template
+constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
+{
+ Expects(i >= 0 && i < narrow_cast(cont.size()));
+ using size_type = decltype(cont.size());
+ return cont[static_cast(i)];
+}
+
+template
+constexpr T at(const std::initializer_list cont, const index i)
+{
+ Expects(i >= 0 && i < narrow_cast(cont.size()));
+ return *(cont.begin() + i);
+}
+
+} // namespace gsl
+
+#if defined(_MSC_VER)
+#if _MSC_VER < 1910
+#undef constexpr
+#pragma pop_macro("constexpr")
+
+#endif // _MSC_VER < 1910
+
+#pragma warning(pop)
+
+#endif // _MSC_VER
+
+#endif // GSL_UTIL_H
diff --git a/src/3rdparty/gsl/multi_span b/src/3rdparty/gsl/multi_span
new file mode 100644
index 00000000..65e65a11
--- /dev/null
+++ b/src/3rdparty/gsl/multi_span
@@ -0,0 +1,2228 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_MULTI_SPAN_H
+#define GSL_MULTI_SPAN_H
+
+#include // for Expects
+#include // for byte
+#include // for narrow_cast
+
+#include // for transform, lexicographical_compare
+#include // for array
+#include
+#include // for ptrdiff_t, size_t, nullptr_t
+#include // for PTRDIFF_MAX
+#include // for divides, multiplies, minus, negate, plus
+#include // for initializer_list
+#include // for iterator, random_access_iterator_tag
+#include // for numeric_limits
+#include
+#include
+#include
+#include // for basic_string
+#include // for enable_if_t, remove_cv_t, is_same, is_co...
+#include
+
+#ifdef _MSC_VER
+
+// turn off some warnings that are noisy about our Expects statements
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4702) // unreachable code
+
+#if _MSC_VER < 1910
+#pragma push_macro("constexpr")
+#define constexpr /*constexpr*/
+
+#endif // _MSC_VER < 1910
+#endif // _MSC_VER
+
+#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
+#define GSL_NOEXCEPT /*noexcept*/
+#else
+#define GSL_NOEXCEPT noexcept
+#endif // GSL_THROW_ON_CONTRACT_VIOLATION
+
+namespace gsl
+{
+
+/*
+** begin definitions of index and bounds
+*/
+namespace details
+{
+ template
+ struct SizeTypeTraits
+ {
+ static const SizeType max_value = std::numeric_limits::max();
+ };
+
+ template
+ class are_integral : public std::integral_constant
+ {
+ };
+
+ template
+ class are_integral
+ : public std::integral_constant::value && are_integral::value>
+ {
+ };
+}
+
+template
+class multi_span_index final
+{
+ static_assert(Rank > 0, "Rank must be greater than 0!");
+
+ template
+ friend class multi_span_index;
+
+public:
+ static const std::size_t rank = Rank;
+ using value_type = std::ptrdiff_t;
+ using size_type = value_type;
+ using reference = std::add_lvalue_reference_t;
+ using const_reference = std::add_lvalue_reference_t>;
+
+ constexpr multi_span_index() GSL_NOEXCEPT {}
+
+ constexpr multi_span_index(const value_type (&values)[Rank]) GSL_NOEXCEPT
+ {
+ std::copy(values, values + Rank, elems);
+ }
+
+ template ::value>>
+ constexpr multi_span_index(Ts... ds) GSL_NOEXCEPT : elems{narrow_cast(ds)...}
+ {
+ }
+
+ constexpr multi_span_index(const multi_span_index& other) GSL_NOEXCEPT = default;
+
+ constexpr multi_span_index& operator=(const multi_span_index& rhs) GSL_NOEXCEPT = default;
+
+ // Preconditions: component_idx < rank
+ constexpr reference operator[](std::size_t component_idx)
+ {
+ Expects(component_idx < Rank); // Component index must be less than rank
+ return elems[component_idx];
+ }
+
+ // Preconditions: component_idx < rank
+ constexpr const_reference operator[](std::size_t component_idx) const GSL_NOEXCEPT
+ {
+ Expects(component_idx < Rank); // Component index must be less than rank
+ return elems[component_idx];
+ }
+
+ constexpr bool operator==(const multi_span_index& rhs) const GSL_NOEXCEPT
+ {
+ return std::equal(elems, elems + rank, rhs.elems);
+ }
+
+ constexpr bool operator!=(const multi_span_index& rhs) const GSL_NOEXCEPT { return !(*this == rhs); }
+
+ constexpr multi_span_index operator+() const GSL_NOEXCEPT { return *this; }
+
+ constexpr multi_span_index operator-() const GSL_NOEXCEPT
+ {
+ multi_span_index ret = *this;
+ std::transform(ret, ret + rank, ret, std::negate{});
+ return ret;
+ }
+
+ constexpr multi_span_index operator+(const multi_span_index& rhs) const GSL_NOEXCEPT
+ {
+ multi_span_index ret = *this;
+ ret += rhs;
+ return ret;
+ }
+
+ constexpr multi_span_index operator-(const multi_span_index& rhs) const GSL_NOEXCEPT
+ {
+ multi_span_index ret = *this;
+ ret -= rhs;
+ return ret;
+ }
+
+ constexpr multi_span_index& operator+=(const multi_span_index& rhs) GSL_NOEXCEPT
+ {
+ std::transform(elems, elems + rank, rhs.elems, elems, std::plus{});
+ return *this;
+ }
+
+ constexpr multi_span_index& operator-=(const multi_span_index& rhs) GSL_NOEXCEPT
+ {
+ std::transform(elems, elems + rank, rhs.elems, elems, std::minus{});
+ return *this;
+ }
+
+ constexpr multi_span_index operator*(value_type v) const GSL_NOEXCEPT
+ {
+ multi_span_index ret = *this;
+ ret *= v;
+ return ret;
+ }
+
+ constexpr multi_span_index operator/(value_type v) const GSL_NOEXCEPT
+ {
+ multi_span_index ret = *this;
+ ret /= v;
+ return ret;
+ }
+
+ friend constexpr multi_span_index operator*(value_type v, const multi_span_index& rhs) GSL_NOEXCEPT
+ {
+ return rhs * v;
+ }
+
+ constexpr multi_span_index& operator*=(value_type v) GSL_NOEXCEPT
+ {
+ std::transform(elems, elems + rank, elems,
+ [v](value_type x) { return std::multiplies{}(x, v); });
+ return *this;
+ }
+
+ constexpr multi_span_index& operator/=(value_type v) GSL_NOEXCEPT
+ {
+ std::transform(elems, elems + rank, elems,
+ [v](value_type x) { return std::divides{}(x, v); });
+ return *this;
+ }
+
+private:
+ value_type elems[Rank] = {};
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1910
+
+struct static_bounds_dynamic_range_t
+{
+ template ::value>>
+ constexpr operator T() const GSL_NOEXCEPT
+ {
+ return narrow_cast(-1);
+ }
+};
+
+constexpr bool operator==(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) GSL_NOEXCEPT
+{
+ return true;
+}
+
+constexpr bool operator!=(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) GSL_NOEXCEPT
+{
+ return false;
+}
+
+template ::value>>
+constexpr bool operator==(static_bounds_dynamic_range_t, T other) GSL_NOEXCEPT
+{
+ return narrow_cast(-1) == other;
+}
+
+template ::value>>
+constexpr bool operator==(T left, static_bounds_dynamic_range_t right) GSL_NOEXCEPT
+{
+ return right == left;
+}
+
+template ::value>>
+constexpr bool operator!=(static_bounds_dynamic_range_t, T other) GSL_NOEXCEPT
+{
+ return narrow_cast(-1) != other;
+}
+
+template ::value>>
+constexpr bool operator!=(T left, static_bounds_dynamic_range_t right) GSL_NOEXCEPT
+{
+ return right != left;
+}
+
+constexpr static_bounds_dynamic_range_t dynamic_range{};
+#else
+const std::ptrdiff_t dynamic_range = -1;
+#endif
+
+struct generalized_mapping_tag
+{
+};
+struct contiguous_mapping_tag : generalized_mapping_tag
+{
+};
+
+namespace details
+{
+
+ template
+ struct LessThan
+ {
+ static const bool value = Left < Right;
+ };
+
+ template
+ struct BoundsRanges
+ {
+ using size_type = std::ptrdiff_t;
+ static const size_type Depth = 0;
+ static const size_type DynamicNum = 0;
+ static const size_type CurrentRange = 1;
+ static const size_type TotalSize = 1;
+
+ // TODO : following signature is for work around VS bug
+ template
+ BoundsRanges(const OtherRange&, bool /* firstLevel */)
+ {
+ }
+
+ BoundsRanges(const std::ptrdiff_t* const) {}
+ BoundsRanges() = default;
+
+ template
+ void serialize(T&) const
+ {
+ }
+
+ template
+ size_type linearize(const T&) const
+ {
+ return 0;
+ }
+
+ template
+ size_type contains(const T&) const
+ {
+ return -1;
+ }
+
+ size_type elementNum(std::size_t) const GSL_NOEXCEPT { return 0; }
+
+ size_type totalSize() const GSL_NOEXCEPT { return TotalSize; }
+
+ bool operator==(const BoundsRanges&) const GSL_NOEXCEPT { return true; }
+ };
+
+ template
+ struct BoundsRanges : BoundsRanges
+ {
+ using Base = BoundsRanges;
+ using size_type = std::ptrdiff_t;
+ static const std::size_t Depth = Base::Depth + 1;
+ static const std::size_t DynamicNum = Base::DynamicNum + 1;
+ static const size_type CurrentRange = dynamic_range;
+ static const size_type TotalSize = dynamic_range;
+
+ private:
+ size_type m_bound;
+
+ public:
+ BoundsRanges(const std::ptrdiff_t* const arr)
+ : Base(arr + 1), m_bound(*arr * this->Base::totalSize())
+ {
+ Expects(0 <= *arr);
+ }
+
+ BoundsRanges() : m_bound(0) {}
+
+ template
+ BoundsRanges(const BoundsRanges& other,
+ bool /* firstLevel */ = true)
+ : Base(static_cast&>(other), false)
+ , m_bound(other.totalSize())
+ {
+ }
+
+ template
+ void serialize(T& arr) const
+ {
+ arr[Dim] = elementNum();
+ this->Base::template serialize(arr);
+ }
+
+ template
+ size_type linearize(const T& arr) const
+ {
+ const size_type index = this->Base::totalSize() * arr[Dim];
+ Expects(index < m_bound);
+ return index + this->Base::template linearize(arr);
+ }
+
+ template
+ size_type contains(const T& arr) const
+ {
+ const ptrdiff_t last = this->Base::template contains(arr);
+ if (last == -1) return -1;
+ const ptrdiff_t cur = this->Base::totalSize() * arr[Dim];
+ return cur < m_bound ? cur + last : -1;
+ }
+
+ size_type totalSize() const GSL_NOEXCEPT { return m_bound; }
+
+ size_type elementNum() const GSL_NOEXCEPT { return totalSize() / this->Base::totalSize(); }
+
+ size_type elementNum(std::size_t dim) const GSL_NOEXCEPT
+ {
+ if (dim > 0)
+ return this->Base::elementNum(dim - 1);
+ else
+ return elementNum();
+ }
+
+ bool operator==(const BoundsRanges& rhs) const GSL_NOEXCEPT
+ {
+ return m_bound == rhs.m_bound &&
+ static_cast(*this) == static_cast(rhs);
+ }
+ };
+
+ template
+ struct BoundsRanges : BoundsRanges
+ {
+ using Base = BoundsRanges;
+ using size_type = std::ptrdiff_t;
+ static const std::size_t Depth = Base::Depth + 1;
+ static const std::size_t DynamicNum = Base::DynamicNum;
+ static const size_type CurrentRange = CurRange;
+ static const size_type TotalSize =
+ Base::TotalSize == dynamic_range ? dynamic_range : CurrentRange * Base::TotalSize;
+
+ BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr) {}
+ BoundsRanges() = default;
+
+ template
+ BoundsRanges(const BoundsRanges& other,
+ bool firstLevel = true)
+ : Base(static_cast&>(other), false)
+ {
+ (void) firstLevel;
+ }
+
+ template
+ void serialize(T& arr) const
+ {
+ arr[Dim] = elementNum();
+ this->Base::template serialize(arr);
+ }
+
+ template
+ size_type linearize(const T& arr) const
+ {
+ Expects(arr[Dim] >= 0 && arr[Dim] < CurrentRange); // Index is out of range
+ return this->Base::totalSize() * arr[Dim] +
+ this->Base::template linearize(arr);
+ }
+
+ template
+ size_type contains(const T& arr) const
+ {
+ if (arr[Dim] >= CurrentRange) return -1;
+ const size_type last = this->Base::template contains(arr);
+ if (last == -1) return -1;
+ return this->Base::totalSize() * arr[Dim] + last;
+ }
+
+ size_type totalSize() const GSL_NOEXCEPT { return CurrentRange * this->Base::totalSize(); }
+
+ size_type elementNum() const GSL_NOEXCEPT { return CurrentRange; }
+
+ size_type elementNum(std::size_t dim) const GSL_NOEXCEPT
+ {
+ if (dim > 0)
+ return this->Base::elementNum(dim - 1);
+ else
+ return elementNum();
+ }
+
+ bool operator==(const BoundsRanges& rhs) const GSL_NOEXCEPT
+ {
+ return static_cast(*this) == static_cast(rhs);
+ }
+ };
+
+ template
+ struct BoundsRangeConvertible
+ : public std::integral_constant= TargetType::TotalSize ||
+ TargetType::TotalSize == dynamic_range ||
+ SourceType::TotalSize == dynamic_range ||
+ TargetType::TotalSize == 0)>
+ {
+ };
+
+ template
+ struct TypeListIndexer
+ {
+ const TypeChain& obj_;
+ TypeListIndexer(const TypeChain& obj) : obj_(obj) {}
+
+ template
+ const TypeChain& getObj(std::true_type)
+ {
+ return obj_;
+ }
+
+ template
+ auto getObj(std::false_type)
+ -> decltype(TypeListIndexer(static_cast(obj_)).template get())
+ {
+ return TypeListIndexer(static_cast(obj_)).template get();
+ }
+
+ template
+ auto get() -> decltype(getObj(std::integral_constant()))
+ {
+ return getObj(std::integral_constant());
+ }
+ };
+
+ template
+ TypeListIndexer createTypeListIndexer(const TypeChain& obj)
+ {
+ return TypeListIndexer(obj);
+ }
+
+ template 1),
+ typename Ret = std::enable_if_t>>
+ constexpr Ret shift_left(const multi_span_index& other) GSL_NOEXCEPT
+ {
+ Ret ret{};
+ for (std::size_t i = 0; i < Rank - 1; ++i) {
+ ret[i] = other[i + 1];
+ }
+ return ret;
+ }
+}
+
+template
+class bounds_iterator;
+
+template
+class static_bounds
+{
+public:
+ static_bounds(const details::BoundsRanges&) {}
+};
+
+template
+class static_bounds
+{
+ using MyRanges = details::BoundsRanges;
+
+ MyRanges m_ranges;
+ constexpr static_bounds(const MyRanges& range) : m_ranges(range) {}
+
+ template
+ friend class static_bounds;
+
+public:
+ static const std::size_t rank = MyRanges::Depth;
+ static const std::size_t dynamic_rank = MyRanges::DynamicNum;
+ static const std::ptrdiff_t static_size = MyRanges::TotalSize;
+
+ using size_type = std::ptrdiff_t;
+ using index_type = multi_span_index